feat(028-strategy-signals-contrib): wire strategy signals into analyst prompts
- Add strategy_signals field to AgentState (list of StrategySignal dicts) - Compute signals once in Propagator.create_initial_state() with graceful fallback - Add strategy_utils.get_signal_section() helper for role-based formatting - Inject signals into all 4 analyst nodes (market, fundamentals, news, social) - Inject signals into bull/bear researchers and research manager - Inject signals into all 3 risk debators (aggressive, conservative, neutral) - Inject signals into portfolio manager and trader - Log strategy_signals in state output JSON
This commit is contained in:
parent
4e97302e22
commit
99815917c7
|
|
@ -8,6 +8,7 @@ from tradingagents.agents.utils.agent_utils import (
|
||||||
get_insider_transactions,
|
get_insider_transactions,
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
)
|
)
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
from tradingagents.dataflows.config import get_config
|
from tradingagents.dataflows.config import get_config
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -15,6 +16,7 @@ def create_fundamentals_analyst(llm):
|
||||||
def fundamentals_analyst_node(state):
|
def fundamentals_analyst_node(state):
|
||||||
current_date = state["trade_date"]
|
current_date = state["trade_date"]
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
signal_section = get_signal_section(state, "fundamentals")
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
get_fundamentals,
|
get_fundamentals,
|
||||||
|
|
@ -41,7 +43,7 @@ def create_fundamentals_analyst(llm):
|
||||||
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
||||||
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
||||||
" You have access to the following tools: {tool_names}.\n{system_message}"
|
" You have access to the following tools: {tool_names}.\n{system_message}"
|
||||||
"For your reference, the current date is {current_date}. {instrument_context}",
|
"For your reference, the current date is {current_date}. {instrument_context}{signal_section}",
|
||||||
),
|
),
|
||||||
MessagesPlaceholder(variable_name="messages"),
|
MessagesPlaceholder(variable_name="messages"),
|
||||||
]
|
]
|
||||||
|
|
@ -51,6 +53,7 @@ def create_fundamentals_analyst(llm):
|
||||||
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
||||||
prompt = prompt.partial(current_date=current_date)
|
prompt = prompt.partial(current_date=current_date)
|
||||||
prompt = prompt.partial(instrument_context=instrument_context)
|
prompt = prompt.partial(instrument_context=instrument_context)
|
||||||
|
prompt = prompt.partial(signal_section=signal_section)
|
||||||
|
|
||||||
chain = prompt | llm.bind_tools(tools)
|
chain = prompt | llm.bind_tools(tools)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from tradingagents.agents.utils.agent_utils import (
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
get_stock_data,
|
get_stock_data,
|
||||||
)
|
)
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
from tradingagents.dataflows.config import get_config
|
from tradingagents.dataflows.config import get_config
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,6 +14,7 @@ def create_market_analyst(llm):
|
||||||
def market_analyst_node(state):
|
def market_analyst_node(state):
|
||||||
current_date = state["trade_date"]
|
current_date = state["trade_date"]
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
signal_section = get_signal_section(state, "market")
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
get_stock_data,
|
get_stock_data,
|
||||||
|
|
@ -60,7 +62,7 @@ Volume-Based Indicators:
|
||||||
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
||||||
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
||||||
" You have access to the following tools: {tool_names}.\n{system_message}"
|
" You have access to the following tools: {tool_names}.\n{system_message}"
|
||||||
"For your reference, the current date is {current_date}. {instrument_context}",
|
"For your reference, the current date is {current_date}. {instrument_context}{signal_section}",
|
||||||
),
|
),
|
||||||
MessagesPlaceholder(variable_name="messages"),
|
MessagesPlaceholder(variable_name="messages"),
|
||||||
]
|
]
|
||||||
|
|
@ -70,6 +72,7 @@ Volume-Based Indicators:
|
||||||
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
||||||
prompt = prompt.partial(current_date=current_date)
|
prompt = prompt.partial(current_date=current_date)
|
||||||
prompt = prompt.partial(instrument_context=instrument_context)
|
prompt = prompt.partial(instrument_context=instrument_context)
|
||||||
|
prompt = prompt.partial(signal_section=signal_section)
|
||||||
|
|
||||||
chain = prompt | llm.bind_tools(tools)
|
chain = prompt | llm.bind_tools(tools)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from tradingagents.agents.utils.agent_utils import (
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
get_news,
|
get_news,
|
||||||
)
|
)
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
from tradingagents.dataflows.config import get_config
|
from tradingagents.dataflows.config import get_config
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,6 +13,7 @@ def create_news_analyst(llm):
|
||||||
def news_analyst_node(state):
|
def news_analyst_node(state):
|
||||||
current_date = state["trade_date"]
|
current_date = state["trade_date"]
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
signal_section = get_signal_section(state, "news")
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
get_news,
|
get_news,
|
||||||
|
|
@ -35,7 +37,7 @@ def create_news_analyst(llm):
|
||||||
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
||||||
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
||||||
" You have access to the following tools: {tool_names}.\n{system_message}"
|
" You have access to the following tools: {tool_names}.\n{system_message}"
|
||||||
"For your reference, the current date is {current_date}. {instrument_context}",
|
"For your reference, the current date is {current_date}. {instrument_context}{signal_section}",
|
||||||
),
|
),
|
||||||
MessagesPlaceholder(variable_name="messages"),
|
MessagesPlaceholder(variable_name="messages"),
|
||||||
]
|
]
|
||||||
|
|
@ -45,6 +47,7 @@ def create_news_analyst(llm):
|
||||||
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
||||||
prompt = prompt.partial(current_date=current_date)
|
prompt = prompt.partial(current_date=current_date)
|
||||||
prompt = prompt.partial(instrument_context=instrument_context)
|
prompt = prompt.partial(instrument_context=instrument_context)
|
||||||
|
prompt = prompt.partial(signal_section=signal_section)
|
||||||
|
|
||||||
chain = prompt | llm.bind_tools(tools)
|
chain = prompt | llm.bind_tools(tools)
|
||||||
result = chain.invoke(state["messages"])
|
result = chain.invoke(state["messages"])
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction, get_news
|
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction, get_news
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
from tradingagents.dataflows.config import get_config
|
from tradingagents.dataflows.config import get_config
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7,6 +8,7 @@ def create_social_media_analyst(llm):
|
||||||
def social_media_analyst_node(state):
|
def social_media_analyst_node(state):
|
||||||
current_date = state["trade_date"]
|
current_date = state["trade_date"]
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
signal_section = get_signal_section(state, "social")
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
get_news,
|
get_news,
|
||||||
|
|
@ -29,7 +31,7 @@ def create_social_media_analyst(llm):
|
||||||
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
|
||||||
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
|
||||||
" You have access to the following tools: {tool_names}.\n{system_message}"
|
" You have access to the following tools: {tool_names}.\n{system_message}"
|
||||||
"For your reference, the current date is {current_date}. {instrument_context}",
|
"For your reference, the current date is {current_date}. {instrument_context}{signal_section}",
|
||||||
),
|
),
|
||||||
MessagesPlaceholder(variable_name="messages"),
|
MessagesPlaceholder(variable_name="messages"),
|
||||||
]
|
]
|
||||||
|
|
@ -39,6 +41,7 @@ def create_social_media_analyst(llm):
|
||||||
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
|
||||||
prompt = prompt.partial(current_date=current_date)
|
prompt = prompt.partial(current_date=current_date)
|
||||||
prompt = prompt.partial(instrument_context=instrument_context)
|
prompt = prompt.partial(instrument_context=instrument_context)
|
||||||
|
prompt = prompt.partial(signal_section=signal_section)
|
||||||
|
|
||||||
chain = prompt | llm.bind_tools(tools)
|
chain = prompt | llm.bind_tools(tools)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction
|
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_portfolio_manager(llm, memory):
|
def create_portfolio_manager(llm, memory):
|
||||||
def portfolio_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"])
|
||||||
|
signal_section = get_signal_section(state, "risk")
|
||||||
|
|
||||||
history = state["risk_debate_state"]["history"]
|
history = state["risk_debate_state"]["history"]
|
||||||
risk_debate_state = state["risk_debate_state"]
|
risk_debate_state = state["risk_debate_state"]
|
||||||
|
|
@ -52,7 +54,8 @@ def create_portfolio_manager(llm, memory):
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Be decisive and ground every conclusion in specific evidence from the analysts.{get_language_instruction()}"""
|
Be decisive and ground every conclusion in specific evidence from the analysts.{get_language_instruction()}
|
||||||
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_research_manager(llm, memory):
|
def create_research_manager(llm, memory):
|
||||||
def research_manager_node(state) -> dict:
|
def research_manager_node(state) -> dict:
|
||||||
instrument_context = build_instrument_context(state["company_of_interest"])
|
instrument_context = build_instrument_context(state["company_of_interest"])
|
||||||
|
signal_section = get_signal_section(state, "researcher")
|
||||||
history = state["investment_debate_state"].get("history", "")
|
history = state["investment_debate_state"].get("history", "")
|
||||||
market_research_report = state["market_report"]
|
market_research_report = state["market_report"]
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
|
|
@ -38,7 +40,8 @@ Here are your past reflections on mistakes:
|
||||||
|
|
||||||
Here is the debate:
|
Here is the debate:
|
||||||
Debate History:
|
Debate History:
|
||||||
{history}"""
|
{history}
|
||||||
|
{signal_section}"""
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
new_investment_debate_state = {
|
new_investment_debate_state = {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_bear_researcher(llm, memory):
|
def create_bear_researcher(llm, memory):
|
||||||
def bear_node(state) -> dict:
|
def bear_node(state) -> dict:
|
||||||
investment_debate_state = state["investment_debate_state"]
|
investment_debate_state = state["investment_debate_state"]
|
||||||
|
|
@ -11,6 +14,7 @@ def create_bear_researcher(llm, memory):
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
news_report = state["news_report"]
|
news_report = state["news_report"]
|
||||||
fundamentals_report = state["fundamentals_report"]
|
fundamentals_report = state["fundamentals_report"]
|
||||||
|
signal_section = get_signal_section(state, "researcher")
|
||||||
|
|
||||||
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
|
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
|
||||||
past_memories = memory.get_memories(curr_situation, n_matches=2)
|
past_memories = memory.get_memories(curr_situation, n_matches=2)
|
||||||
|
|
@ -39,7 +43,7 @@ Conversation history of the debate: {history}
|
||||||
Last bull argument: {current_response}
|
Last bull argument: {current_response}
|
||||||
Reflections from similar situations and lessons learned: {past_memory_str}
|
Reflections from similar situations and lessons learned: {past_memory_str}
|
||||||
Use this information to deliver a compelling bear argument, refute the bull's claims, and engage in a dynamic debate that demonstrates the risks and weaknesses of investing in the stock. You must also address reflections and learn from lessons and mistakes you made in the past.
|
Use this information to deliver a compelling bear argument, refute the bull's claims, and engage in a dynamic debate that demonstrates the risks and weaknesses of investing in the stock. You must also address reflections and learn from lessons and mistakes you made in the past.
|
||||||
"""
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_bull_researcher(llm, memory):
|
def create_bull_researcher(llm, memory):
|
||||||
def bull_node(state) -> dict:
|
def bull_node(state) -> dict:
|
||||||
investment_debate_state = state["investment_debate_state"]
|
investment_debate_state = state["investment_debate_state"]
|
||||||
|
|
@ -11,6 +14,7 @@ def create_bull_researcher(llm, memory):
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
news_report = state["news_report"]
|
news_report = state["news_report"]
|
||||||
fundamentals_report = state["fundamentals_report"]
|
fundamentals_report = state["fundamentals_report"]
|
||||||
|
signal_section = get_signal_section(state, "researcher")
|
||||||
|
|
||||||
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
|
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
|
||||||
past_memories = memory.get_memories(curr_situation, n_matches=2)
|
past_memories = memory.get_memories(curr_situation, n_matches=2)
|
||||||
|
|
@ -37,7 +41,7 @@ Conversation history of the debate: {history}
|
||||||
Last bear argument: {current_response}
|
Last bear argument: {current_response}
|
||||||
Reflections from similar situations and lessons learned: {past_memory_str}
|
Reflections from similar situations and lessons learned: {past_memory_str}
|
||||||
Use this information to deliver a compelling bull argument, refute the bear's concerns, and engage in a dynamic debate that demonstrates the strengths of the bull position. You must also address reflections and learn from lessons and mistakes you made in the past.
|
Use this information to deliver a compelling bull argument, refute the bear's concerns, and engage in a dynamic debate that demonstrates the strengths of the bull position. You must also address reflections and learn from lessons and mistakes you made in the past.
|
||||||
"""
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_aggressive_debator(llm):
|
def create_aggressive_debator(llm):
|
||||||
def aggressive_node(state) -> dict:
|
def aggressive_node(state) -> dict:
|
||||||
risk_debate_state = state["risk_debate_state"]
|
risk_debate_state = state["risk_debate_state"]
|
||||||
|
|
@ -13,6 +16,7 @@ def create_aggressive_debator(llm):
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
news_report = state["news_report"]
|
news_report = state["news_report"]
|
||||||
fundamentals_report = state["fundamentals_report"]
|
fundamentals_report = state["fundamentals_report"]
|
||||||
|
signal_section = get_signal_section(state, "risk")
|
||||||
|
|
||||||
trader_decision = state["trader_investment_plan"]
|
trader_decision = state["trader_investment_plan"]
|
||||||
|
|
||||||
|
|
@ -28,7 +32,8 @@ Latest World Affairs Report: {news_report}
|
||||||
Company Fundamentals Report: {fundamentals_report}
|
Company Fundamentals Report: {fundamentals_report}
|
||||||
Here is the current conversation history: {history} Here are the last arguments from the conservative analyst: {current_conservative_response} Here are the last arguments from the neutral analyst: {current_neutral_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
Here is the current conversation history: {history} Here are the last arguments from the conservative analyst: {current_conservative_response} Here are the last arguments from the neutral analyst: {current_neutral_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
||||||
|
|
||||||
Engage actively by addressing any specific concerns raised, refuting the weaknesses in their logic, and asserting the benefits of risk-taking to outpace market norms. Maintain a focus on debating and persuading, not just presenting data. Challenge each counterpoint to underscore why a high-risk approach is optimal. Output conversationally as if you are speaking without any special formatting."""
|
Engage actively by addressing any specific concerns raised, refuting the weaknesses in their logic, and asserting the benefits of risk-taking to outpace market norms. Maintain a focus on debating and persuading, not just presenting data. Challenge each counterpoint to underscore why a high-risk approach is optimal. Output conversationally as if you are speaking without any special formatting.
|
||||||
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_conservative_debator(llm):
|
def create_conservative_debator(llm):
|
||||||
def conservative_node(state) -> dict:
|
def conservative_node(state) -> dict:
|
||||||
risk_debate_state = state["risk_debate_state"]
|
risk_debate_state = state["risk_debate_state"]
|
||||||
|
|
@ -13,6 +16,7 @@ def create_conservative_debator(llm):
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
news_report = state["news_report"]
|
news_report = state["news_report"]
|
||||||
fundamentals_report = state["fundamentals_report"]
|
fundamentals_report = state["fundamentals_report"]
|
||||||
|
signal_section = get_signal_section(state, "risk")
|
||||||
|
|
||||||
trader_decision = state["trader_investment_plan"]
|
trader_decision = state["trader_investment_plan"]
|
||||||
|
|
||||||
|
|
@ -28,7 +32,8 @@ Latest World Affairs Report: {news_report}
|
||||||
Company Fundamentals Report: {fundamentals_report}
|
Company Fundamentals Report: {fundamentals_report}
|
||||||
Here is the current conversation history: {history} Here is the last response from the aggressive analyst: {current_aggressive_response} Here is the last response from the neutral analyst: {current_neutral_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
Here is the current conversation history: {history} Here is the last response from the aggressive analyst: {current_aggressive_response} Here is the last response from the neutral analyst: {current_neutral_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
||||||
|
|
||||||
Engage by questioning their optimism and emphasizing the potential downsides they may have overlooked. Address each of their counterpoints to showcase why a conservative stance is ultimately the safest path for the firm's assets. Focus on debating and critiquing their arguments to demonstrate the strength of a low-risk strategy over their approaches. Output conversationally as if you are speaking without any special formatting."""
|
Engage by questioning their optimism and emphasizing the potential downsides they may have overlooked. Address each of their counterpoints to showcase why a conservative stance is ultimately the safest path for the firm's assets. Focus on debating and critiquing their arguments to demonstrate the strength of a low-risk strategy over their approaches. Output conversationally as if you are speaking without any special formatting.
|
||||||
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_neutral_debator(llm):
|
def create_neutral_debator(llm):
|
||||||
def neutral_node(state) -> dict:
|
def neutral_node(state) -> dict:
|
||||||
risk_debate_state = state["risk_debate_state"]
|
risk_debate_state = state["risk_debate_state"]
|
||||||
|
|
@ -13,6 +16,7 @@ def create_neutral_debator(llm):
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
news_report = state["news_report"]
|
news_report = state["news_report"]
|
||||||
fundamentals_report = state["fundamentals_report"]
|
fundamentals_report = state["fundamentals_report"]
|
||||||
|
signal_section = get_signal_section(state, "risk")
|
||||||
|
|
||||||
trader_decision = state["trader_investment_plan"]
|
trader_decision = state["trader_investment_plan"]
|
||||||
|
|
||||||
|
|
@ -28,7 +32,8 @@ Latest World Affairs Report: {news_report}
|
||||||
Company Fundamentals Report: {fundamentals_report}
|
Company Fundamentals Report: {fundamentals_report}
|
||||||
Here is the current conversation history: {history} Here is the last response from the aggressive analyst: {current_aggressive_response} Here is the last response from the conservative analyst: {current_conservative_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
Here is the current conversation history: {history} Here is the last response from the aggressive analyst: {current_aggressive_response} Here is the last response from the conservative analyst: {current_conservative_response}. If there are no responses from the other viewpoints yet, present your own argument based on the available data.
|
||||||
|
|
||||||
Engage actively by analyzing both sides critically, addressing weaknesses in the aggressive and conservative arguments to advocate for a more balanced approach. Challenge each of their points to illustrate why a moderate risk strategy might offer the best of both worlds, providing growth potential while safeguarding against extreme volatility. Focus on debating rather than simply presenting data, aiming to show that a balanced view can lead to the most reliable outcomes. Output conversationally as if you are speaking without any special formatting."""
|
Engage actively by analyzing both sides critically, addressing weaknesses in the aggressive and conservative arguments to advocate for a more balanced approach. Challenge each of their points to illustrate why a moderate risk strategy might offer the best of both worlds, providing growth potential while safeguarding against extreme volatility. Focus on debating rather than simply presenting data, aiming to show that a balanced view can lead to the most reliable outcomes. Output conversationally as if you are speaking without any special formatting.
|
||||||
|
{signal_section}"""
|
||||||
|
|
||||||
response = llm.invoke(prompt)
|
response = llm.invoke(prompt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
from tradingagents.agents.utils.agent_utils import build_instrument_context
|
||||||
|
from tradingagents.agents.utils.strategy_utils import get_signal_section
|
||||||
|
|
||||||
|
|
||||||
def create_trader(llm, memory):
|
def create_trader(llm, memory):
|
||||||
def trader_node(state, name):
|
def trader_node(state, name):
|
||||||
company_name = state["company_of_interest"]
|
company_name = state["company_of_interest"]
|
||||||
instrument_context = build_instrument_context(company_name)
|
instrument_context = build_instrument_context(company_name)
|
||||||
|
signal_section = get_signal_section(state, "researcher")
|
||||||
investment_plan = state["investment_plan"]
|
investment_plan = state["investment_plan"]
|
||||||
market_research_report = state["market_report"]
|
market_research_report = state["market_report"]
|
||||||
sentiment_report = state["sentiment_report"]
|
sentiment_report = state["sentiment_report"]
|
||||||
|
|
@ -31,7 +33,8 @@ def create_trader(llm, memory):
|
||||||
messages = [
|
messages = [
|
||||||
{
|
{
|
||||||
"role": "system",
|
"role": "system",
|
||||||
"content": f"""You are a trading agent analyzing market data to make investment decisions. Based on your analysis, provide a specific recommendation to buy, sell, or hold. End with a firm decision and always conclude your response with 'FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**' to confirm your recommendation. Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str}""",
|
"content": f"""You are a trading agent analyzing market data to make investment decisions. Based on your analysis, provide a specific recommendation to buy, sell, or hold. End with a firm decision and always conclude your response with 'FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**' to confirm your recommendation. Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str}
|
||||||
|
{signal_section}""",
|
||||||
},
|
},
|
||||||
context,
|
context,
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Annotated
|
from typing import Annotated, Any
|
||||||
from typing_extensions import TypedDict
|
from typing_extensions import TypedDict
|
||||||
from langgraph.graph import MessagesState
|
from langgraph.graph import MessagesState
|
||||||
|
|
||||||
|
|
@ -70,3 +70,6 @@ class AgentState(MessagesState):
|
||||||
RiskDebateState, "Current state of the debate on evaluating risk"
|
RiskDebateState, "Current state of the debate on evaluating risk"
|
||||||
]
|
]
|
||||||
final_trade_decision: Annotated[str, "Final decision made by the Risk Analysts"]
|
final_trade_decision: Annotated[str, "Final decision made by the Risk Analysts"]
|
||||||
|
|
||||||
|
# Quantitative strategy signals (computed once, consumed by all nodes)
|
||||||
|
strategy_signals: Annotated[list[dict[str, Any]], "Deterministic strategy signals from the strategies framework"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
"""Utility to extract formatted strategy signals from agent state."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def get_signal_section(state: dict[str, Any], role: str) -> str:
|
||||||
|
"""Return a formatted strategy signals section for *role*, or empty string."""
|
||||||
|
signals = state.get("strategy_signals")
|
||||||
|
if not signals:
|
||||||
|
return ""
|
||||||
|
try:
|
||||||
|
from tradingagents.strategies import format_signals_for_role
|
||||||
|
section = format_signals_for_role(signals, role)
|
||||||
|
return f"\n\n{section}" if section else ""
|
||||||
|
except Exception:
|
||||||
|
return ""
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# TradingAgents/graph/propagation.py
|
# TradingAgents/graph/propagation.py
|
||||||
|
|
||||||
|
import logging
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from tradingagents.agents.utils.agent_states import (
|
from tradingagents.agents.utils.agent_states import (
|
||||||
AgentState,
|
AgentState,
|
||||||
|
|
@ -7,6 +8,8 @@ from tradingagents.agents.utils.agent_states import (
|
||||||
RiskDebateState,
|
RiskDebateState,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Propagator:
|
class Propagator:
|
||||||
"""Handles state initialization and propagation through the graph."""
|
"""Handles state initialization and propagation through the graph."""
|
||||||
|
|
@ -19,6 +22,14 @@ class Propagator:
|
||||||
self, company_name: str, trade_date: str
|
self, company_name: str, trade_date: str
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Create the initial state for the agent graph."""
|
"""Create the initial state for the agent graph."""
|
||||||
|
# Compute strategy signals once up-front
|
||||||
|
strategy_signals: list[dict[str, Any]] = []
|
||||||
|
try:
|
||||||
|
from tradingagents.strategies import compute_signals
|
||||||
|
strategy_signals = compute_signals(company_name, str(trade_date))
|
||||||
|
except Exception:
|
||||||
|
logger.warning("Strategy signal computation failed; continuing without signals", exc_info=True)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"messages": [("human", company_name)],
|
"messages": [("human", company_name)],
|
||||||
"company_of_interest": company_name,
|
"company_of_interest": company_name,
|
||||||
|
|
@ -51,6 +62,7 @@ class Propagator:
|
||||||
"fundamentals_report": "",
|
"fundamentals_report": "",
|
||||||
"sentiment_report": "",
|
"sentiment_report": "",
|
||||||
"news_report": "",
|
"news_report": "",
|
||||||
|
"strategy_signals": strategy_signals,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_graph_args(self, callbacks: Optional[List] = None) -> Dict[str, Any]:
|
def get_graph_args(self, callbacks: Optional[List] = None) -> Dict[str, Any]:
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,7 @@ class TradingAgentsGraph:
|
||||||
},
|
},
|
||||||
"investment_plan": final_state["investment_plan"],
|
"investment_plan": final_state["investment_plan"],
|
||||||
"final_trade_decision": final_state["final_trade_decision"],
|
"final_trade_decision": final_state["final_trade_decision"],
|
||||||
|
"strategy_signals": final_state.get("strategy_signals", []),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Save to file
|
# Save to file
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue