mirror of
https://github.com/TauricResearch/TradingAgents.git
synced 2026-05-01 14:33:10 +03:00
refactor: standardize portfolio manager, five-tier rating scale, fix analyst status tracking
This commit is contained in:
13
cli/main.py
13
cli/main.py
@@ -800,9 +800,11 @@ ANALYST_REPORT_MAP = {
|
|||||||
|
|
||||||
|
|
||||||
def update_analyst_statuses(message_buffer, chunk):
|
def update_analyst_statuses(message_buffer, chunk):
|
||||||
"""Update all analyst statuses based on current report state.
|
"""Update analyst statuses based on accumulated report state.
|
||||||
|
|
||||||
Logic:
|
Logic:
|
||||||
|
- Store new report content from the current chunk if present
|
||||||
|
- Check accumulated report_sections (not just current chunk) for status
|
||||||
- Analysts with reports = completed
|
- Analysts with reports = completed
|
||||||
- First analyst without report = in_progress
|
- First analyst without report = in_progress
|
||||||
- Remaining analysts without reports = pending
|
- Remaining analysts without reports = pending
|
||||||
@@ -817,11 +819,16 @@ def update_analyst_statuses(message_buffer, chunk):
|
|||||||
|
|
||||||
agent_name = ANALYST_AGENT_NAMES[analyst_key]
|
agent_name = ANALYST_AGENT_NAMES[analyst_key]
|
||||||
report_key = ANALYST_REPORT_MAP[analyst_key]
|
report_key = ANALYST_REPORT_MAP[analyst_key]
|
||||||
has_report = bool(chunk.get(report_key))
|
|
||||||
|
# Capture new report content from current chunk
|
||||||
|
if chunk.get(report_key):
|
||||||
|
message_buffer.update_report_section(report_key, chunk[report_key])
|
||||||
|
|
||||||
|
# Determine status from accumulated sections, not just current chunk
|
||||||
|
has_report = bool(message_buffer.report_sections.get(report_key))
|
||||||
|
|
||||||
if has_report:
|
if has_report:
|
||||||
message_buffer.update_agent_status(agent_name, "completed")
|
message_buffer.update_agent_status(agent_name, "completed")
|
||||||
message_buffer.update_report_section(report_key, chunk[report_key])
|
|
||||||
elif not found_active:
|
elif not found_active:
|
||||||
message_buffer.update_agent_status(agent_name, "in_progress")
|
message_buffer.update_agent_status(agent_name, "in_progress")
|
||||||
found_active = True
|
found_active = True
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from .risk_mgmt.conservative_debator import create_conservative_debator
|
|||||||
from .risk_mgmt.neutral_debator import create_neutral_debator
|
from .risk_mgmt.neutral_debator import create_neutral_debator
|
||||||
|
|
||||||
from .managers.research_manager import create_research_manager
|
from .managers.research_manager import create_research_manager
|
||||||
from .managers.risk_manager import create_risk_manager
|
from .managers.portfolio_manager import create_portfolio_manager
|
||||||
|
|
||||||
from .trader.trader import create_trader
|
from .trader.trader import create_trader
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ __all__ = [
|
|||||||
"create_neutral_debator",
|
"create_neutral_debator",
|
||||||
"create_news_analyst",
|
"create_news_analyst",
|
||||||
"create_aggressive_debator",
|
"create_aggressive_debator",
|
||||||
"create_risk_manager",
|
"create_portfolio_manager",
|
||||||
"create_conservative_debator",
|
"create_conservative_debator",
|
||||||
"create_social_media_analyst",
|
"create_social_media_analyst",
|
||||||
"create_trader",
|
"create_trader",
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import time
|
|
||||||
import json
|
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
||||||
|
|
||||||
|
|
||||||
def create_risk_manager(llm, memory):
|
def create_portfolio_manager(llm, memory):
|
||||||
def risk_manager_node(state) -> dict:
|
def portfolio_manager_node(state) -> dict:
|
||||||
|
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
|
||||||
@@ -24,7 +21,7 @@ def create_risk_manager(llm, memory):
|
|||||||
for i, rec in enumerate(past_memories, 1):
|
for i, rec in enumerate(past_memories, 1):
|
||||||
past_memory_str += rec["recommendation"] + "\n\n"
|
past_memory_str += rec["recommendation"] + "\n\n"
|
||||||
|
|
||||||
prompt = f"""As the Risk Management Judge, evaluate the debate between the Aggressive, Neutral, and Conservative analysts and deliver a final trading decision.
|
prompt = f"""As the Portfolio Manager, synthesize the risk analysts' debate and deliver the final trading decision.
|
||||||
|
|
||||||
{instrument_context}
|
{instrument_context}
|
||||||
|
|
||||||
@@ -37,19 +34,18 @@ def create_risk_manager(llm, memory):
|
|||||||
- **Underweight**: Reduce exposure, take partial profits
|
- **Underweight**: Reduce exposure, take partial profits
|
||||||
- **Sell**: Exit position or avoid entry
|
- **Sell**: Exit position or avoid entry
|
||||||
|
|
||||||
**Guidelines:**
|
**Context:**
|
||||||
1. Extract the strongest points from each analyst, focusing on relevance to the current context.
|
- Trader's proposed plan: **{trader_plan}**
|
||||||
2. Start with the trader's original plan: **{trader_plan}**, and refine it based on the analysts' insights.
|
- Lessons from past decisions: **{past_memory_str}**
|
||||||
3. Apply lessons from past decisions to strengthen this analysis: **{past_memory_str}**
|
|
||||||
|
|
||||||
**Required Output Structure:**
|
**Required Output Structure:**
|
||||||
1. **Rating**: State one of Buy / Overweight / Hold / Underweight / Sell.
|
1. **Rating**: State one of Buy / Overweight / Hold / Underweight / Sell.
|
||||||
2. **Executive Summary**: A concise action plan covering entry strategy, position sizing, key risk levels, and time horizon. Keep this brief and actionable.
|
2. **Executive Summary**: A concise action plan covering entry strategy, position sizing, key risk levels, and time horizon.
|
||||||
3. **Investment Thesis**: Detailed reasoning anchored in the debate and past reflections.
|
3. **Investment Thesis**: Detailed reasoning anchored in the analysts' debate and past reflections.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Analysts Debate History:**
|
**Risk Analysts Debate History:**
|
||||||
{history}
|
{history}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -76,4 +72,4 @@ Be decisive and ground every conclusion in specific evidence from the analysts."
|
|||||||
"final_trade_decision": response.content,
|
"final_trade_decision": response.content,
|
||||||
}
|
}
|
||||||
|
|
||||||
return risk_manager_node
|
return portfolio_manager_node
|
||||||
@@ -59,7 +59,7 @@ class ConditionalLogic:
|
|||||||
if (
|
if (
|
||||||
state["risk_debate_state"]["count"] >= 3 * self.max_risk_discuss_rounds
|
state["risk_debate_state"]["count"] >= 3 * self.max_risk_discuss_rounds
|
||||||
): # 3 rounds of back-and-forth between 3 agents
|
): # 3 rounds of back-and-forth between 3 agents
|
||||||
return "Risk Judge"
|
return "Portfolio Manager"
|
||||||
if state["risk_debate_state"]["latest_speaker"].startswith("Aggressive"):
|
if state["risk_debate_state"]["latest_speaker"].startswith("Aggressive"):
|
||||||
return "Conservative Analyst"
|
return "Conservative Analyst"
|
||||||
if state["risk_debate_state"]["latest_speaker"].startswith("Conservative"):
|
if state["risk_debate_state"]["latest_speaker"].startswith("Conservative"):
|
||||||
|
|||||||
@@ -110,12 +110,12 @@ Adhere strictly to these instructions, and ensure your output is detailed, accur
|
|||||||
)
|
)
|
||||||
invest_judge_memory.add_situations([(situation, result)])
|
invest_judge_memory.add_situations([(situation, result)])
|
||||||
|
|
||||||
def reflect_risk_manager(self, current_state, returns_losses, risk_manager_memory):
|
def reflect_portfolio_manager(self, current_state, returns_losses, portfolio_manager_memory):
|
||||||
"""Reflect on risk manager's decision and update memory."""
|
"""Reflect on portfolio manager's decision and update memory."""
|
||||||
situation = self._extract_current_situation(current_state)
|
situation = self._extract_current_situation(current_state)
|
||||||
judge_decision = current_state["risk_debate_state"]["judge_decision"]
|
judge_decision = current_state["risk_debate_state"]["judge_decision"]
|
||||||
|
|
||||||
result = self._reflect_on_component(
|
result = self._reflect_on_component(
|
||||||
"RISK JUDGE", judge_decision, situation, returns_losses
|
"PORTFOLIO MANAGER", judge_decision, situation, returns_losses
|
||||||
)
|
)
|
||||||
risk_manager_memory.add_situations([(situation, result)])
|
portfolio_manager_memory.add_situations([(situation, result)])
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class GraphSetup:
|
|||||||
bear_memory,
|
bear_memory,
|
||||||
trader_memory,
|
trader_memory,
|
||||||
invest_judge_memory,
|
invest_judge_memory,
|
||||||
risk_manager_memory,
|
portfolio_manager_memory,
|
||||||
conditional_logic: ConditionalLogic,
|
conditional_logic: ConditionalLogic,
|
||||||
):
|
):
|
||||||
"""Initialize with required components."""
|
"""Initialize with required components."""
|
||||||
@@ -34,7 +34,7 @@ class GraphSetup:
|
|||||||
self.bear_memory = bear_memory
|
self.bear_memory = bear_memory
|
||||||
self.trader_memory = trader_memory
|
self.trader_memory = trader_memory
|
||||||
self.invest_judge_memory = invest_judge_memory
|
self.invest_judge_memory = invest_judge_memory
|
||||||
self.risk_manager_memory = risk_manager_memory
|
self.portfolio_manager_memory = portfolio_manager_memory
|
||||||
self.conditional_logic = conditional_logic
|
self.conditional_logic = conditional_logic
|
||||||
|
|
||||||
def setup_graph(
|
def setup_graph(
|
||||||
@@ -101,8 +101,8 @@ class GraphSetup:
|
|||||||
aggressive_analyst = create_aggressive_debator(self.quick_thinking_llm)
|
aggressive_analyst = create_aggressive_debator(self.quick_thinking_llm)
|
||||||
neutral_analyst = create_neutral_debator(self.quick_thinking_llm)
|
neutral_analyst = create_neutral_debator(self.quick_thinking_llm)
|
||||||
conservative_analyst = create_conservative_debator(self.quick_thinking_llm)
|
conservative_analyst = create_conservative_debator(self.quick_thinking_llm)
|
||||||
risk_manager_node = create_risk_manager(
|
portfolio_manager_node = create_portfolio_manager(
|
||||||
self.deep_thinking_llm, self.risk_manager_memory
|
self.deep_thinking_llm, self.portfolio_manager_memory
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create workflow
|
# Create workflow
|
||||||
@@ -124,7 +124,7 @@ class GraphSetup:
|
|||||||
workflow.add_node("Aggressive Analyst", aggressive_analyst)
|
workflow.add_node("Aggressive Analyst", aggressive_analyst)
|
||||||
workflow.add_node("Neutral Analyst", neutral_analyst)
|
workflow.add_node("Neutral Analyst", neutral_analyst)
|
||||||
workflow.add_node("Conservative Analyst", conservative_analyst)
|
workflow.add_node("Conservative Analyst", conservative_analyst)
|
||||||
workflow.add_node("Risk Judge", risk_manager_node)
|
workflow.add_node("Portfolio Manager", portfolio_manager_node)
|
||||||
|
|
||||||
# Define edges
|
# Define edges
|
||||||
# Start with the first analyst
|
# Start with the first analyst
|
||||||
@@ -176,7 +176,7 @@ class GraphSetup:
|
|||||||
self.conditional_logic.should_continue_risk_analysis,
|
self.conditional_logic.should_continue_risk_analysis,
|
||||||
{
|
{
|
||||||
"Conservative Analyst": "Conservative Analyst",
|
"Conservative Analyst": "Conservative Analyst",
|
||||||
"Risk Judge": "Risk Judge",
|
"Portfolio Manager": "Portfolio Manager",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
workflow.add_conditional_edges(
|
workflow.add_conditional_edges(
|
||||||
@@ -184,7 +184,7 @@ class GraphSetup:
|
|||||||
self.conditional_logic.should_continue_risk_analysis,
|
self.conditional_logic.should_continue_risk_analysis,
|
||||||
{
|
{
|
||||||
"Neutral Analyst": "Neutral Analyst",
|
"Neutral Analyst": "Neutral Analyst",
|
||||||
"Risk Judge": "Risk Judge",
|
"Portfolio Manager": "Portfolio Manager",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
workflow.add_conditional_edges(
|
workflow.add_conditional_edges(
|
||||||
@@ -192,11 +192,11 @@ class GraphSetup:
|
|||||||
self.conditional_logic.should_continue_risk_analysis,
|
self.conditional_logic.should_continue_risk_analysis,
|
||||||
{
|
{
|
||||||
"Aggressive Analyst": "Aggressive Analyst",
|
"Aggressive Analyst": "Aggressive Analyst",
|
||||||
"Risk Judge": "Risk Judge",
|
"Portfolio Manager": "Portfolio Manager",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
workflow.add_edge("Risk Judge", END)
|
workflow.add_edge("Portfolio Manager", END)
|
||||||
|
|
||||||
# Compile and return
|
# Compile and return
|
||||||
return workflow.compile()
|
return workflow.compile()
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class TradingAgentsGraph:
|
|||||||
self.bear_memory = FinancialSituationMemory("bear_memory", self.config)
|
self.bear_memory = FinancialSituationMemory("bear_memory", self.config)
|
||||||
self.trader_memory = FinancialSituationMemory("trader_memory", self.config)
|
self.trader_memory = FinancialSituationMemory("trader_memory", self.config)
|
||||||
self.invest_judge_memory = FinancialSituationMemory("invest_judge_memory", self.config)
|
self.invest_judge_memory = FinancialSituationMemory("invest_judge_memory", self.config)
|
||||||
self.risk_manager_memory = FinancialSituationMemory("risk_manager_memory", self.config)
|
self.portfolio_manager_memory = FinancialSituationMemory("portfolio_manager_memory", self.config)
|
||||||
|
|
||||||
# Create tool nodes
|
# Create tool nodes
|
||||||
self.tool_nodes = self._create_tool_nodes()
|
self.tool_nodes = self._create_tool_nodes()
|
||||||
@@ -117,7 +117,7 @@ class TradingAgentsGraph:
|
|||||||
self.bear_memory,
|
self.bear_memory,
|
||||||
self.trader_memory,
|
self.trader_memory,
|
||||||
self.invest_judge_memory,
|
self.invest_judge_memory,
|
||||||
self.risk_manager_memory,
|
self.portfolio_manager_memory,
|
||||||
self.conditional_logic,
|
self.conditional_logic,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -283,8 +283,8 @@ class TradingAgentsGraph:
|
|||||||
self.reflector.reflect_invest_judge(
|
self.reflector.reflect_invest_judge(
|
||||||
self.curr_state, returns_losses, self.invest_judge_memory
|
self.curr_state, returns_losses, self.invest_judge_memory
|
||||||
)
|
)
|
||||||
self.reflector.reflect_risk_manager(
|
self.reflector.reflect_portfolio_manager(
|
||||||
self.curr_state, returns_losses, self.risk_manager_memory
|
self.curr_state, returns_losses, self.portfolio_manager_memory
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_signal(self, full_signal):
|
def process_signal(self, full_signal):
|
||||||
|
|||||||
Reference in New Issue
Block a user