use rag analysis for new stocks
Browse files
agents/new_investment_recommender.py
CHANGED
@@ -63,6 +63,7 @@ Consider the following when making recommendations:
|
|
63 |
3. Prioritize stocks that have been evaluated as good fits for the portfolio
|
64 |
4. Consider the user's risk tolerance and investment goals
|
65 |
5. Focus on stocks that complement the existing portfolio and improve diversification
|
|
|
66 |
|
67 |
Provide clear, actionable recommendations with detailed reasoning.
|
68 |
|
@@ -92,6 +93,7 @@ Portfolio Fit Evaluation:
|
|
92 |
|
93 |
Please provide specific recommendations for new investments that would complement my existing portfolio.
|
94 |
Only recommend stocks that have been properly analyzed and evaluated for portfolio fit.
|
|
|
95 |
""")
|
96 |
])
|
97 |
|
|
|
63 |
3. Prioritize stocks that have been evaluated as good fits for the portfolio
|
64 |
4. Consider the user's risk tolerance and investment goals
|
65 |
5. Focus on stocks that complement the existing portfolio and improve diversification
|
66 |
+
6. Pay close attention to the RAG interpretations
|
67 |
|
68 |
Provide clear, actionable recommendations with detailed reasoning.
|
69 |
|
|
|
93 |
|
94 |
Please provide specific recommendations for new investments that would complement my existing portfolio.
|
95 |
Only recommend stocks that have been properly analyzed and evaluated for portfolio fit.
|
96 |
+
Pay special attention to the RAG interpretations in the new stock analysis.
|
97 |
""")
|
98 |
])
|
99 |
|
agents/new_stock_analyzer.py
CHANGED
@@ -3,6 +3,7 @@ import numpy as np
|
|
3 |
import pandas as pd
|
4 |
from typing import Dict, Any, List
|
5 |
from .state import AgentState
|
|
|
6 |
|
7 |
def calculate_rsi(prices, period=14):
|
8 |
"""Calculate Relative Strength Index."""
|
@@ -148,13 +149,90 @@ def new_stock_analyzer(state: AgentState) -> AgentState:
|
|
148 |
print(f"Error analyzing {ticker}: {str(e)}")
|
149 |
analysis_results[ticker] = {"error": str(e)}
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
# Update state with new stock analysis
|
152 |
state["new_stock_analysis"] = analysis_results
|
153 |
|
154 |
# Add message to communication
|
|
|
155 |
state["messages"] = state.get("messages", []) + [{
|
156 |
"role": "ai",
|
157 |
-
"content": f"[NewStockAnalyzer] I've calculated technical indicators
|
158 |
}]
|
159 |
|
160 |
return state
|
|
|
3 |
import pandas as pd
|
4 |
from typing import Dict, Any, List
|
5 |
from .state import AgentState
|
6 |
+
from .rag_analyzer import batch_analysis_chain
|
7 |
|
8 |
def calculate_rsi(prices, period=14):
|
9 |
"""Calculate Relative Strength Index."""
|
|
|
149 |
print(f"Error analyzing {ticker}: {str(e)}")
|
150 |
analysis_results[ticker] = {"error": str(e)}
|
151 |
|
152 |
+
# Add RAG interpretation for new stocks
|
153 |
+
risk_level = state.get("risk_level", 5)
|
154 |
+
investment_goals = state.get("investment_goals", "Growth")
|
155 |
+
|
156 |
+
# Prepare batch analysis data for new stocks
|
157 |
+
stocks_data = ""
|
158 |
+
for ticker, data in analysis_results.items():
|
159 |
+
if "error" not in data:
|
160 |
+
stocks_data += f"Stock: {ticker}\n"
|
161 |
+
stocks_data += f"Current Price: ${data['current_price']:.2f}\n"
|
162 |
+
stocks_data += "Technical Indicators:\n"
|
163 |
+
for key, value in data['technical_indicators'].items():
|
164 |
+
stocks_data += f" {key}: {value}\n"
|
165 |
+
stocks_data += "Fundamental Data:\n"
|
166 |
+
for key, value in data['fundamental_data'].items():
|
167 |
+
if value is not None:
|
168 |
+
stocks_data += f" {key}: {value}\n"
|
169 |
+
stocks_data += "\n---\n\n"
|
170 |
+
|
171 |
+
# Only make the batch analysis call if we have stocks to analyze
|
172 |
+
if stocks_data:
|
173 |
+
try:
|
174 |
+
# Get batch analysis for all new stocks in one call
|
175 |
+
batch_analysis_result = batch_analysis_chain.invoke({
|
176 |
+
"stocks_data": stocks_data,
|
177 |
+
"risk_level": risk_level,
|
178 |
+
"investment_goals": investment_goals
|
179 |
+
})
|
180 |
+
|
181 |
+
# Try to parse as JSON first
|
182 |
+
try:
|
183 |
+
import json
|
184 |
+
import re
|
185 |
+
|
186 |
+
# Try to find JSON-like content in the response using regex
|
187 |
+
json_match = re.search(r'\{[\s\S]*\}', batch_analysis_result)
|
188 |
+
if json_match:
|
189 |
+
json_str = json_match.group(0)
|
190 |
+
analysis_data = json.loads(json_str)
|
191 |
+
|
192 |
+
# Update analysis_results with the parsed JSON
|
193 |
+
for ticker, analysis in analysis_data.items():
|
194 |
+
if ticker in analysis_results:
|
195 |
+
analysis_results[ticker]["rag_interpretation"] = analysis
|
196 |
+
else:
|
197 |
+
# Fallback to text parsing approach
|
198 |
+
current_ticker = None
|
199 |
+
current_analysis = []
|
200 |
+
|
201 |
+
for line in batch_analysis_result.split('\n'):
|
202 |
+
if ':' in line and line.split(':')[0].strip() in analysis_results:
|
203 |
+
# If we have a previous ticker, save its analysis
|
204 |
+
if current_ticker is not None and current_ticker in analysis_results:
|
205 |
+
analysis_results[current_ticker]["rag_interpretation"] = '\n'.join(current_analysis).strip()
|
206 |
+
current_analysis = []
|
207 |
+
|
208 |
+
# Start new ticker
|
209 |
+
current_ticker = line.split(':')[0].strip()
|
210 |
+
current_analysis.append(line.split(':', 1)[1].strip())
|
211 |
+
elif current_ticker is not None:
|
212 |
+
current_analysis.append(line)
|
213 |
+
|
214 |
+
# Add the last ticker's analysis
|
215 |
+
if current_ticker is not None and current_ticker in analysis_results:
|
216 |
+
analysis_results[current_ticker]["rag_interpretation"] = '\n'.join(current_analysis).strip()
|
217 |
+
|
218 |
+
except (json.JSONDecodeError, Exception) as json_err:
|
219 |
+
print(f"Error parsing JSON response for new stocks: {str(json_err)}")
|
220 |
+
print(f"Raw response: {batch_analysis_result}")
|
221 |
+
|
222 |
+
except Exception as e:
|
223 |
+
# Log any errors but continue execution
|
224 |
+
import traceback
|
225 |
+
print(f"Error in batch analysis for new stocks: {str(e)}")
|
226 |
+
print(traceback.format_exc())
|
227 |
+
|
228 |
# Update state with new stock analysis
|
229 |
state["new_stock_analysis"] = analysis_results
|
230 |
|
231 |
# Add message to communication
|
232 |
+
num_with_rag = sum(1 for ticker in analysis_results if "rag_interpretation" in analysis_results[ticker])
|
233 |
state["messages"] = state.get("messages", []) + [{
|
234 |
"role": "ai",
|
235 |
+
"content": f"[NewStockAnalyzer] I've calculated technical indicators, gathered fundamental data, and added RAG-based interpretations for {num_with_rag} of {len(analysis_results)} new high-ranked stocks."
|
236 |
}]
|
237 |
|
238 |
return state
|