164 lines
5.1 KiB
Python
164 lines
5.1 KiB
Python
import time
|
|
import json
|
|
|
|
|
|
def create_research_manager(llm, memory):
|
|
def research_manager_node(state) -> dict:
|
|
history = state["investment_debate_state"].get("history", "")
|
|
market_research_report = state["market_report"]
|
|
sentiment_report = state["sentiment_report"]
|
|
news_report = state["news_report"]
|
|
fundamentals_report = state["fundamentals_report"]
|
|
|
|
investment_debate_state = state["investment_debate_state"]
|
|
|
|
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
|
|
|
|
if memory:
|
|
past_memories = memory.get_memories(curr_situation, n_matches=2)
|
|
else:
|
|
past_memories = []
|
|
|
|
|
|
if past_memories:
|
|
past_memory_str = "### Past Lessons Applied\\n**Reflections from Similar Situations:**\\n"
|
|
for i, rec in enumerate(past_memories, 1):
|
|
past_memory_str += rec["recommendation"] + "\\n\\n"
|
|
past_memory_str += "\\n\\n**How I'm Using These Lessons:**\\n"
|
|
past_memory_str += "- [Specific adjustment based on past mistake/success]\\n"
|
|
past_memory_str += "- [Impact on current conviction level]\\n"
|
|
else:
|
|
past_memory_str = "" # Don't include placeholder when no memories
|
|
|
|
prompt = f"""You are the Portfolio Manager judging the Bull vs Bear debate. Make a definitive SHORT-TERM decision: BUY, SELL, or HOLD (rare).
|
|
|
|
## YOUR MISSION
|
|
Analyze the debate objectively and make a decisive SHORT-TERM (1-2 week) trading decision backed by evidence.
|
|
|
|
## DECISION FRAMEWORK
|
|
|
|
### Score Each Side (0-10)
|
|
Evaluate both Bull and Bear arguments:
|
|
|
|
**Bull Score:**
|
|
- Evidence Strength: [0-10] (hard data vs speculation)
|
|
- Logic: [0-10] (sound reasoning?)
|
|
- Short-Term Relevance: [0-10] (matters in 1-2 weeks?)
|
|
- **Total Bull: [X]/30**
|
|
|
|
**Bear Score:**
|
|
- Evidence Strength: [0-10] (hard data vs speculation)
|
|
- Logic: [0-10] (sound reasoning?)
|
|
- Short-Term Relevance: [0-10] (matters in 1-2 weeks?)
|
|
- **Total Bear: [X]/30**
|
|
|
|
### Decision Matrix
|
|
|
|
**BUY if:**
|
|
- Bull score > Bear score by 3+ points
|
|
- Clear short-term catalyst (next 1-2 weeks)
|
|
- Risk/reward ratio >2:1
|
|
- Technical setup supports entry
|
|
- Past lessons don't show pattern failure
|
|
|
|
**SELL if:**
|
|
- Bear score > Bull score by 3+ points
|
|
- Significant near-term risks
|
|
- Catalyst already priced in
|
|
- Risk/reward ratio <1:1
|
|
- Technical breakdown evident
|
|
|
|
**HOLD if (ALL must apply - should be RARE):**
|
|
- Scores within 2 points (truly balanced)
|
|
- Major catalyst imminent (1-3 days away)
|
|
- Waiting provides significant option value
|
|
- Current position is optimal
|
|
|
|
## OUTPUT STRUCTURE (MANDATORY)
|
|
|
|
### Debate Scorecard
|
|
| Criterion | Bull | Bear | Winner |
|
|
|-----------|------|------|--------|
|
|
| Evidence | [X]/10 | [Y]/10 | [Bull/Bear] |
|
|
| Logic | [X]/10 | [Y]/10 | [Bull/Bear] |
|
|
| Short-Term | [X]/10 | [Y]/10 | [Bull/Bear] |
|
|
| **TOTAL** | **[X]** | **[Y]** | **[Winner] +[Diff]** |
|
|
|
|
### Decision Summary
|
|
**DECISION: BUY / SELL / HOLD**
|
|
**Conviction: High / Medium / Low**
|
|
**Time Horizon: [X] days (typically 5-14 days)**
|
|
**Recommended Position Size: [X]% of capital**
|
|
|
|
### Winning Arguments
|
|
- **Bull's Strongest:** [Quote best Bull point if buying]
|
|
- **Bear's Strongest:** [Quote best Bear point even if buying - acknowledge risk]
|
|
- **Decisive Factor:** [What tipped the scale]
|
|
|
|
### Investment Plan for Trader
|
|
**Execution Strategy:**
|
|
- Entry: [When and at what price]
|
|
- Stop Loss: [Specific level and % risk]
|
|
- Target: [Specific level and % gain]
|
|
- Risk/Reward: [Ratio]
|
|
- Time Limit: [Max holding period]
|
|
|
|
**If BUY:**
|
|
- Why Bull won the debate
|
|
- Key catalyst timeline
|
|
- Exit strategy (both profit and loss)
|
|
|
|
**If SELL:**
|
|
- Why Bear won the debate
|
|
- Key risk timeline
|
|
- When to reassess
|
|
|
|
**If HOLD (rare):**
|
|
- Why waiting is optimal
|
|
- What event we're waiting for (date)
|
|
- Decision trigger (when to reassess)
|
|
|
|
## QUALITY RULES
|
|
- ✅ Be decisive (avoid fence-sitting)
|
|
- ✅ Score objectively with numbers
|
|
- ✅ Quote specific arguments from debate
|
|
- ✅ Focus on 1-2 week horizon
|
|
- ✅ Learn from past mistakes
|
|
- ❌ Don't default to HOLD to avoid deciding
|
|
- ❌ Don't ignore strong opposing arguments
|
|
- ❌ Don't make long-term arguments
|
|
""" + (f"""
|
|
## PAST LESSONS
|
|
Here are reflections on past mistakes - apply these lessons:
|
|
{past_memory_str}
|
|
|
|
**Learning Check:** How are you adjusting based on these past situations?
|
|
""" if past_memory_str else "") + f"""
|
|
---
|
|
|
|
**DEBATE TO JUDGE:**
|
|
{history}
|
|
|
|
**MARKET DATA:**
|
|
Technical: {market_research_report}
|
|
Sentiment: {sentiment_report}
|
|
News: {news_report}
|
|
Fundamentals: {fundamentals_report}"""
|
|
response = llm.invoke(prompt)
|
|
|
|
new_investment_debate_state = {
|
|
"judge_decision": response.content,
|
|
"history": investment_debate_state.get("history", ""),
|
|
"bear_history": investment_debate_state.get("bear_history", ""),
|
|
"bull_history": investment_debate_state.get("bull_history", ""),
|
|
"current_response": response.content,
|
|
"count": investment_debate_state["count"],
|
|
}
|
|
|
|
return {
|
|
"investment_debate_state": new_investment_debate_state,
|
|
"investment_plan": response.content,
|
|
}
|
|
|
|
return research_manager_node
|