merge upstream main into crypto-analysis-mvp

This commit is contained in:
CadeYu committed 2026-04-18 21:07:54 +08:00
commit 99ec63f966
52 files changed
+1170 -669

No files matched your search

+1 -1
View File
@@ -59,7 +59,7 @@ class ConditionalLogic:
if (
state["risk_debate_state"]["count"] >= 3 * self.max_risk_discuss_rounds
): # 3 rounds of back-and-forth between 3 agents
return "Risk Judge"
return "Portfolio Manager"
if state["risk_debate_state"]["latest_speaker"].startswith("Aggressive"):
return "Conservative Analyst"
if state["risk_debate_state"]["latest_speaker"].startswith("Conservative"):
+6 -7
View File
@@ -1,13 +1,12 @@
# TradingAgents/graph/reflection.py
from typing import Dict, Any
from langchain_openai import ChatOpenAI
from typing import Any, Dict
class Reflector:
"""Handles reflection on decisions and updating memory."""
def __init__(self, quick_thinking_llm: ChatOpenAI):
def __init__(self, quick_thinking_llm: Any):
"""Initialize the reflector with an LLM."""
self.quick_thinking_llm = quick_thinking_llm
self.reflection_system_prompt = self._get_reflection_prompt()
@@ -110,12 +109,12 @@ Adhere strictly to these instructions, and ensure your output is detailed, accur
)
invest_judge_memory.add_situations([(situation, result)])
def reflect_risk_manager(self, current_state, returns_losses, risk_manager_memory):
"""Reflect on risk manager's decision and update memory."""
def reflect_portfolio_manager(self, current_state, returns_losses, portfolio_manager_memory):
"""Reflect on portfolio manager's decision and update memory."""
situation = self._extract_current_situation(current_state)
judge_decision = current_state["risk_debate_state"]["judge_decision"]
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)])
+13 -14
View File
@@ -1,8 +1,7 @@
# TradingAgents/graph/setup.py
from typing import Dict, Any
from langchain_openai import ChatOpenAI
from langgraph.graph import END, StateGraph, START
from typing import Any, Dict
from langgraph.graph import END, START, StateGraph
from langgraph.prebuilt import ToolNode
from tradingagents.agents import *
@@ -16,14 +15,14 @@ class GraphSetup:
def __init__(
self,
quick_thinking_llm: ChatOpenAI,
deep_thinking_llm: ChatOpenAI,
quick_thinking_llm: Any,
deep_thinking_llm: Any,
tool_nodes: Dict[str, ToolNode],
bull_memory,
bear_memory,
trader_memory,
invest_judge_memory,
risk_manager_memory,
portfolio_manager_memory,
conditional_logic: ConditionalLogic,
):
"""Initialize with required components."""
@@ -34,7 +33,7 @@ class GraphSetup:
self.bear_memory = bear_memory
self.trader_memory = trader_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
def setup_graph(
@@ -101,8 +100,8 @@ class GraphSetup:
aggressive_analyst = create_aggressive_debator(self.quick_thinking_llm)
neutral_analyst = create_neutral_debator(self.quick_thinking_llm)
conservative_analyst = create_conservative_debator(self.quick_thinking_llm)
risk_manager_node = create_risk_manager(
self.deep_thinking_llm, self.risk_manager_memory
portfolio_manager_node = create_portfolio_manager(
self.deep_thinking_llm, self.portfolio_manager_memory
)
# Create workflow
@@ -124,7 +123,7 @@ class GraphSetup:
workflow.add_node("Aggressive Analyst", aggressive_analyst)
workflow.add_node("Neutral Analyst", neutral_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
# Start with the first analyst
@@ -176,7 +175,7 @@ class GraphSetup:
self.conditional_logic.should_continue_risk_analysis,
{
"Conservative Analyst": "Conservative Analyst",
"Risk Judge": "Risk Judge",
"Portfolio Manager": "Portfolio Manager",
},
)
workflow.add_conditional_edges(
@@ -184,7 +183,7 @@ class GraphSetup:
self.conditional_logic.should_continue_risk_analysis,
{
"Neutral Analyst": "Neutral Analyst",
"Risk Judge": "Risk Judge",
"Portfolio Manager": "Portfolio Manager",
},
)
workflow.add_conditional_edges(
@@ -192,11 +191,11 @@ class GraphSetup:
self.conditional_logic.should_continue_risk_analysis,
{
"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
return workflow.compile()
+6 -4
View File
@@ -1,12 +1,12 @@
# TradingAgents/graph/signal_processing.py
from langchain_openai import ChatOpenAI
from typing import Any
class SignalProcessor:
"""Processes trading signals to extract actionable decisions."""
def __init__(self, quick_thinking_llm: ChatOpenAI):
def __init__(self, quick_thinking_llm: Any):
"""Initialize with an LLM for processing."""
self.quick_thinking_llm = quick_thinking_llm
@@ -18,12 +18,14 @@ class SignalProcessor:
full_signal: Complete trading signal text
Returns:
Extracted decision (BUY, SELL, or HOLD)
Extracted rating (BUY, OVERWEIGHT, HOLD, UNDERWEIGHT, or SELL)
"""
messages = [
(
"system",
"You are an efficient assistant designed to analyze paragraphs or financial reports provided by a group of analysts. Your task is to extract the investment decision: SELL, BUY, or HOLD. Provide only the extracted decision (SELL, BUY, or HOLD) as your output, without adding any additional text or information.",
"You are an efficient assistant that extracts the trading decision from analyst reports. "
"Extract the rating as exactly one of: BUY, OVERWEIGHT, HOLD, UNDERWEIGHT, SELL. "
"Output only the single rating word, nothing else.",
),
("human", full_signal),
]
+15 -15
View File
@@ -66,10 +66,8 @@ class TradingAgentsGraph:
set_config(self.config)
# Create necessary directories
os.makedirs(
os.path.join(self.config["project_dir"], "dataflows/data_cache"),
exist_ok=True,
)
os.makedirs(self.config["data_cache_dir"], exist_ok=True)
os.makedirs(self.config["results_dir"], exist_ok=True)
# Initialize LLMs with provider-specific thinking configuration
llm_kwargs = self._get_provider_kwargs()
@@ -99,7 +97,7 @@ class TradingAgentsGraph:
self.bear_memory = FinancialSituationMemory("bear_memory", self.config)
self.trader_memory = FinancialSituationMemory("trader_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
self.tool_nodes = self._create_tool_nodes()
@@ -117,7 +115,7 @@ class TradingAgentsGraph:
self.bear_memory,
self.trader_memory,
self.invest_judge_memory,
self.risk_manager_memory,
self.portfolio_manager_memory,
self.conditional_logic,
)
@@ -148,6 +146,11 @@ class TradingAgentsGraph:
if reasoning_effort:
kwargs["reasoning_effort"] = reasoning_effort
elif provider == "anthropic":
effort = self.config.get("anthropic_effort")
if effort:
kwargs["effort"] = effort
return kwargs
def _create_tool_nodes(self) -> Dict[str, ToolNode]:
@@ -254,15 +257,12 @@ class TradingAgentsGraph:
}
# Save to file
directory = Path(f"eval_results/{self.ticker}/TradingAgentsStrategy_logs/")
directory = Path(self.config["results_dir"]) / self.ticker / "TradingAgentsStrategy_logs"
directory.mkdir(parents=True, exist_ok=True)
with open(
f"eval_results/{self.ticker}/TradingAgentsStrategy_logs/full_states_log_{trade_date}.json",
"w",
encoding="utf-8",
) as f:
json.dump(self.log_states_dict, f, indent=4)
log_path = directory / f"full_states_log_{trade_date}.json"
with open(log_path, "w", encoding="utf-8") as f:
json.dump(self.log_states_dict[str(trade_date)], f, indent=4)
def reflect_and_remember(self, returns_losses):
"""Reflect on decisions and update memory based on returns."""
@@ -278,8 +278,8 @@ class TradingAgentsGraph:
self.reflector.reflect_invest_judge(
self.curr_state, returns_losses, self.invest_judge_memory
)
self.reflector.reflect_risk_manager(
self.curr_state, returns_losses, self.risk_manager_memory
self.reflector.reflect_portfolio_manager(
self.curr_state, returns_losses, self.portfolio_manager_memory
)
def process_signal(self, full_signal):