File size: 7,654 Bytes
c90e00d 76b5330 c90e00d dd350d1 c90e00d dd350d1 c90e00d 76b5330 c90e00d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
from typing import Dict, List
from .state import AgentState, AgentState2
def create_new_investment_recommender():
"""Create a new investment recommender using LangChain."""
# Define the function schema for structured output
function_def = {
"name": "generate_new_investment_recommendations",
"description": "Generate new investment recommendations based on analyzed high-rank stocks and portfolio fit",
"parameters": {
"type": "object",
"properties": {
"new_investment_summary": {
"type": "string",
"description": "Summary of the new investment opportunities"
},
"new_investments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Stock ticker symbol"
},
"action": {
"type": "string",
"enum": ["BUY"],
"description": "Recommended action for this stock"
},
"reasoning": {
"type": "string",
"description": "Detailed reasoning for the recommendation"
},
"priority": {
"type": "integer",
"description": "Priority level (1-5, where 1 is highest priority)",
"minimum": 1,
"maximum": 5
}
},
"required": ["ticker", "action", "reasoning", "priority"]
}
}
},
"required": ["new_investment_summary", "new_investments"]
}
}
# Create the prompt template
prompt = ChatPromptTemplate.from_messages([
("system", """You are an expert financial advisor specializing in identifying new investment opportunities.
Your task is to recommend only high-ranked stocks that have been properly analyzed and evaluated for portfolio fit.
Consider the following when making recommendations:
1. Technical analysis signals (RSI, moving averages, etc.)
2. Fundamental analysis metrics (PE ratios, debt-to-equity, growth rates, etc.)
3. Prioritize stocks that have been evaluated as good fits for the portfolio
4. Consider the user's risk tolerance and investment goals
5. Focus on stocks that complement the existing portfolio and improve diversification
6. Pay close attention to the RAG interpretations
Provide clear, actionable recommendations with detailed reasoning.
IMPORTANT: For the reasoning of each recommendation, include a more detailed technical and fundamental analysis section:
- For technical analysis: Include specific insights about RSI levels, MACD signals, moving average crossovers, and what these indicators suggest about momentum and trend direction.
- For fundamental analysis: Include specific metrics like P/E ratio compared to industry average, debt-to-equity ratio, earnings growth, and what these metrics suggest about the company's valuation and financial health.
"""),
("human", """
I need recommendations for new investments based on the following information:
User's Portfolio:
{portfolio_data}
User's Risk Tolerance: {risk_level}
User's Investment Goals: {investment_goals}
High-Ranked Stocks:
{high_rank_stocks}
New Stock Analysis:
{new_stock_analysis}
Portfolio Fit Evaluation:
{portfolio_fit}
Please provide specific recommendations for new investments that would complement my existing portfolio.
Only recommend stocks that have been properly analyzed and evaluated for portfolio fit.
Pay special attention to the RAG interpretations in the new stock analysis.
""")
])
# Create the LLM
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0.5, api_key=os.getenv("OPENAI_API_KEY"))
# Create the structured output chain
chain = prompt | llm.bind_functions(functions=[function_def], function_call={"name": "generate_new_investment_recommendations"}) | JsonOutputFunctionsParser()
return chain
def new_investment_recommender(state: AgentState2) -> AgentState2:
"""Recommends new investments based on analyzed high-rank stocks and portfolio fit evaluation."""
try:
# Get the portfolio data
portfolio = state["portfolio_data"]
# Get the high-rank stocks
high_rank_stocks = state.get("high_rank_stocks", [])
# Get the new stock analysis
new_stock_analysis = state.get("new_stock_analysis", {})
# Get the portfolio fit evaluation
portfolio_fit = state.get("portfolio_fit", {})
# If no stocks have been analyzed or evaluated, return early
if not new_stock_analysis or not portfolio_fit.get("evaluated_stocks"):
state["messages"] = state.get("messages", []) + [{
"role": "ai",
"content": "[NewInvestmentRecommender] No properly analyzed stocks to recommend."
}]
state["new_investment_summary"] = "No properly analyzed stocks to recommend."
state["new_investments"] = []
return state
# Get user preferences
risk_level = state.get("risk_level", 5)
investment_goals = state.get("investment_goals", "Growth")
# Create the recommender
recommender = create_new_investment_recommender()
# Generate recommendations
result = recommender.invoke({
"portfolio_data": portfolio,
"risk_level": risk_level,
"investment_goals": investment_goals,
"high_rank_stocks": high_rank_stocks,
"new_stock_analysis": new_stock_analysis,
"portfolio_fit": portfolio_fit
})
# Ensure we have the required fields
if "new_investment_summary" not in result:
result["new_investment_summary"] = f"Analysis of {len(high_rank_stocks)} high-ranked stocks."
if "new_investments" not in result:
result["new_investments"] = []
except Exception as e:
# Handle any errors in the recommendation engine
state["messages"] = state.get("messages", []) + [{
"role": "ai",
"content": f"[NewInvestmentRecommender] Error generating recommendations: {str(e)}"
}]
result = {
"new_investment_summary": "Error in analysis",
"new_investments": []
}
# Update state with recommendations
state["new_investment_summary"] = result.get("new_investment_summary", "")
state["new_investments"] = result.get("new_investments", [])
# Add message to communication
state["messages"] = state.get("messages", []) + [{
"role": "ai",
"content": f"[NewInvestmentRecommender] I've analyzed the properly evaluated stocks and generated {len(result.get('new_investments', []))} recommendations for new investments."
}]
return state |