This commit is contained in:
LixuanMao 2025-10-20 09:38:10 +07:00 committed by GitHub
commit cdf4a5e8ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 111 additions and 16 deletions

View File

@ -72,6 +72,7 @@ class MessageBuffer:
"fundamentals_report": None,
"investment_plan": None,
"trader_investment_plan": None,
"risk_debate": None,
"final_trade_decision": None,
}
@ -113,6 +114,7 @@ class MessageBuffer:
"fundamentals_report": "Fundamentals Analysis",
"investment_plan": "Research Team Decision",
"trader_investment_plan": "Trading Team Plan",
"risk_debate": "Risk Management Team Debate",
"final_trade_decision": "Portfolio Management Decision",
}
self.current_report = (
@ -162,6 +164,11 @@ class MessageBuffer:
if self.report_sections["trader_investment_plan"]:
report_parts.append("## Trading Team Plan")
report_parts.append(f"{self.report_sections['trader_investment_plan']}")
# Risk Management Team Debate 
if self.report_sections["risk_debate"]:
report_parts.append("## Risk Management Team Debate")
report_parts.append(f"{self.report_sections['risk_debate']}")
# Portfolio Management Decision
if self.report_sections["final_trade_decision"]:
@ -520,12 +527,16 @@ def get_analysis_date():
)
def display_complete_report(final_state):
"""Display the complete analysis report with team-based panels."""
def display_complete_report(final_state, report_dir, selections):
"""Display the complete analysis report with team-based panels and save to markdown file."""
console.print("\n[bold green]Complete Analysis Report[/bold green]\n")
# Create full markdown report content
md_content = ["# Complete Analysis Report"]
# I. Analyst Team Reports
analyst_reports = []
md_content.append("## I. Analyst Team Reports")
# Market Analyst Report
if final_state.get("market_report"):
@ -537,6 +548,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Market Analyst")
md_content.append(adjust_markdown_headers(
final_state["market_report"]))
md_content.append("") # Empty line for spacing
# Social Analyst Report
if final_state.get("sentiment_report"):
@ -548,6 +563,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Social Analyst")
md_content.append(adjust_markdown_headers(
final_state["sentiment_report"]))
md_content.append("") # Empty line for spacing
# News Analyst Report
if final_state.get("news_report"):
@ -559,6 +578,9 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### News Analyst")
md_content.append(adjust_markdown_headers(final_state["news_report"]))
md_content.append("") # Empty line for spacing
# Fundamentals Analyst Report
if final_state.get("fundamentals_report"):
@ -570,6 +592,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Fundamentals Analyst")
md_content.append(adjust_markdown_headers(
final_state["fundamentals_report"]))
md_content.append("") # Empty line for spacing
if analyst_reports:
console.print(
@ -585,6 +611,7 @@ def display_complete_report(final_state):
if final_state.get("investment_debate_state"):
research_reports = []
debate_state = final_state["investment_debate_state"]
md_content.append("## II. Research Team Decision")
# Bull Researcher Analysis
if debate_state.get("bull_history"):
@ -596,6 +623,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Bull Researcher")
md_content.append(adjust_markdown_headers(
debate_state["bull_history"]))
md_content.append("") # Empty line for spacing
# Bear Researcher Analysis
if debate_state.get("bear_history"):
@ -607,6 +638,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Bear Researcher")
md_content.append(adjust_markdown_headers(
debate_state["bear_history"]))
md_content.append("") # Empty line for spacing
# Research Manager Decision
if debate_state.get("judge_decision"):
@ -618,6 +653,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Research Manager Decision")
md_content.append(adjust_markdown_headers(
debate_state["judge_decision"]))
md_content.append("") # Empty line for spacing
if research_reports:
console.print(
@ -631,6 +670,12 @@ def display_complete_report(final_state):
# III. Trading Team Reports
if final_state.get("trader_investment_plan"):
md_content.append("## III. Trading Team Plan")
md_content.append("### Trader")
md_content.append(adjust_markdown_headers(
final_state["trader_investment_plan"]))
md_content.append("") # Empty line for spacing
console.print(
Panel(
Panel(
@ -649,6 +694,7 @@ def display_complete_report(final_state):
if final_state.get("risk_debate_state"):
risk_reports = []
risk_state = final_state["risk_debate_state"]
md_content.append("## IV. Risk Management Team Decision")
# Aggressive (Risky) Analyst Analysis
if risk_state.get("risky_history"):
@ -660,6 +706,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Aggressive (Risky) Analyst")
md_content.append(adjust_markdown_headers(
risk_state["risky_history"]))
md_content.append("") # Empty line for spacing
# Conservative (Safe) Analyst Analysis
if risk_state.get("safe_history"):
@ -671,6 +721,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Conservative (Safe) Analyst")
md_content.append(adjust_markdown_headers(
risk_state["safe_history"]))
md_content.append("") # Empty line for spacing
# Neutral Analyst Analysis
if risk_state.get("neutral_history"):
@ -682,6 +736,10 @@ def display_complete_report(final_state):
padding=(1, 2),
)
)
md_content.append("### Neutral Analyst")
md_content.append(adjust_markdown_headers(
risk_state["neutral_history"]))
md_content.append("") # Empty line for spacing
if risk_reports:
console.print(
@ -695,6 +753,11 @@ def display_complete_report(final_state):
# V. Portfolio Manager Decision
if risk_state.get("judge_decision"):
md_content.append("## V. Portfolio Manager Decision")
md_content.append("### Portfolio Manager")
md_content.append(adjust_markdown_headers(
risk_state["judge_decision"]))
console.print(
Panel(
Panel(
@ -709,6 +772,12 @@ def display_complete_report(final_state):
)
)
# Write the full markdown report to file
complete_report_filename = f"complete_report_by_{selections.get('shallow_thinker')}__{selections.get('deep_thinker')}.md"
complete_report_path = report_dir / complete_report_filename
with open(complete_report_path, "w") as f:
f.write("\n".join(md_content))
def update_research_team_status(status):
"""Update status for all research team members and trader."""
@ -993,6 +1062,7 @@ def run_analysis():
# Risk Management Team - Handle Risk Debate State
if "risk_debate_state" in chunk and chunk["risk_debate_state"]:
risk_state = chunk["risk_debate_state"]
risk_debate_content = ""
# Update Risky Analyst status and report
if (
@ -1006,10 +1076,11 @@ def run_analysis():
"Reasoning",
f"Risky Analyst: {risk_state['current_risky_response']}",
)
# Update risk report with risky analyst's latest analysis only
# Update risk report with adding risky analyst's latest analysis
risk_debate_content += f"### Risky Analyst Analysis\n{risk_state['current_risky_response']}\n"
message_buffer.update_report_section(
"final_trade_decision",
f"### Risky Analyst Analysis\n{risk_state['current_risky_response']}",
"risk_debate",
risk_debate_content,
)
# Update Safe Analyst status and report
@ -1024,10 +1095,11 @@ def run_analysis():
"Reasoning",
f"Safe Analyst: {risk_state['current_safe_response']}",
)
# Update risk report with safe analyst's latest analysis only
# Update risk report with adding safe analyst's latest analysis
risk_debate_content += f"### Safe Analyst Analysis\n{risk_state['current_safe_response']}\n"
message_buffer.update_report_section(
"final_trade_decision",
f"### Safe Analyst Analysis\n{risk_state['current_safe_response']}",
"risk_debate",
risk_debate_content,
)
# Update Neutral Analyst status and report
@ -1042,10 +1114,11 @@ def run_analysis():
"Reasoning",
f"Neutral Analyst: {risk_state['current_neutral_response']}",
)
# Update risk report with neutral analyst's latest analysis only
# Update risk report with adding neutral analyst's latest analysis
risk_debate_content += f"### Neutral Analyst Analysis\n{risk_state['current_neutral_response']}\n"
message_buffer.update_report_section(
"final_trade_decision",
f"### Neutral Analyst Analysis\n{risk_state['current_neutral_response']}",
"risk_debate",
risk_debate_content,
)
# Update Portfolio Manager status and final decision
@ -1095,7 +1168,7 @@ def run_analysis():
message_buffer.update_report_section(section, final_state[section])
# Display the complete final report
display_complete_report(final_state)
display_complete_report(final_state, report_dir, selections)
update_display(layout)

View File

@ -1,6 +1,6 @@
import questionary
from typing import List, Optional, Tuple, Dict
import re
from cli.models import AnalystType
ANALYST_ORDER = [
@ -274,3 +274,23 @@ def select_llm_provider() -> tuple[str, str]:
print(f"You selected: {display_name}\tURL: {url}")
return display_name, url
def adjust_markdown_headers(markdown_text: str) -> str:
def replace_header(match):
hashes = match.group(1)
header_text = match.group(2)
header_level = len(hashes)
if header_level <= 3:
new_hashes = "####" # Force at least h4
else:
new_hashes = "#" * (header_level + 1) # Increase one #
return f"{new_hashes} {header_text}"
# Regex to match markdown headers from level 1 to 6
adjusted_text = re.sub(
r"^(#{1,6})\s+(.*)", replace_header, markdown_text, flags=re.MULTILINE
)
return adjusted_text

View File

@ -2,7 +2,6 @@ import chromadb
from chromadb.config import Settings
from openai import OpenAI
class FinancialSituationMemory:
def __init__(self, name, config):
if config["backend_url"] == "http://localhost:11434/v1":
@ -69,7 +68,7 @@ class FinancialSituationMemory:
if __name__ == "__main__":
# Example usage
matcher = FinancialSituationMemory()
matcher = FinancialSituationMemory( name="test", config={"backend_url": "https://api.openai.com/v1",})
# Example data
example_data = [

View File

@ -95,7 +95,10 @@ class TradingAgentsGraph:
self.tool_nodes = self._create_tool_nodes()
# Initialize components
self.conditional_logic = ConditionalLogic()
self.conditional_logic = ConditionalLogic(
max_debate_rounds=self.config["max_debate_rounds"],
max_risk_discuss_rounds=self.config["max_risk_discuss_rounds"]
)
self.graph_setup = GraphSetup(
self.quick_thinking_llm,
self.deep_thinking_llm,