mirror of
https://github.com/TauricResearch/TradingAgents.git
synced 2026-09-19 11:15:24 +03:00
fix(agents): ground the Trader in the technical market report
- the Trader received only the digested investment plan, so its entry / stop / sizing levels were not anchored to real price structure (ATR, support and resistance, current price) - inject the market report and instruct the Trader to take concrete price levels from it and direction/strategy from the plan; when the market analyst was not selected the report is empty, so the section and grounding note are omitted #1167
This commit is contained in:
@@ -52,6 +52,7 @@ def test_trader_prompt_states_constraint():
|
|||||||
create_trader(llm)({
|
create_trader(llm)({
|
||||||
"company_of_interest": "NVDA",
|
"company_of_interest": "NVDA",
|
||||||
"investment_plan": "**Recommendation**: Buy",
|
"investment_plan": "**Recommendation**: Buy",
|
||||||
|
"market_report": "Current price $189.5; ATR 4.2.",
|
||||||
})
|
})
|
||||||
assert NO_EXTERNAL_TOOLS in _prompt_text(captured["prompt"])
|
assert NO_EXTERNAL_TOOLS in _prompt_text(captured["prompt"])
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ def _make_trader_state():
|
|||||||
return {
|
return {
|
||||||
"company_of_interest": "NVDA",
|
"company_of_interest": "NVDA",
|
||||||
"investment_plan": "**Recommendation**: Buy\n**Rationale**: ...\n**Strategic Actions**: ...",
|
"investment_plan": "**Recommendation**: Buy\n**Rationale**: ...\n**Strategic Actions**: ...",
|
||||||
|
"market_report": "Current price $189.5; 14-day ATR 4.2; support $178, resistance $196.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -200,6 +201,31 @@ class TestTraderAgent:
|
|||||||
prompt = captured["prompt"]
|
prompt = captured["prompt"]
|
||||||
assert any("Proposed Investment Plan" in m["content"] for m in prompt)
|
assert any("Proposed Investment Plan" in m["content"] for m in prompt)
|
||||||
|
|
||||||
|
def test_prompt_includes_market_report_for_price_levels(self):
|
||||||
|
# #1167: the Trader must see the technical market report so entry/stop
|
||||||
|
# levels are grounded in real price structure, not just the digested plan.
|
||||||
|
captured = {}
|
||||||
|
trader = create_trader(_structured_trader_llm(captured))
|
||||||
|
trader(_make_trader_state())
|
||||||
|
user = " ".join(m["content"] for m in captured["prompt"] if m["role"] == "user")
|
||||||
|
system = " ".join(m["content"] for m in captured["prompt"] if m["role"] == "system")
|
||||||
|
assert "Technical Market Report:" in user
|
||||||
|
assert "14-day ATR 4.2" in user # the actual report content reached the Trader
|
||||||
|
assert "support $178, resistance $196" in user
|
||||||
|
assert "Ground concrete price levels" in system
|
||||||
|
|
||||||
|
def test_empty_market_report_omits_the_section_and_grounding(self):
|
||||||
|
# #1167: when the market analyst wasn't selected the report is empty, so
|
||||||
|
# don't tell the Trader to ground levels in a report it doesn't have.
|
||||||
|
captured = {}
|
||||||
|
state = _make_trader_state()
|
||||||
|
state["market_report"] = ""
|
||||||
|
create_trader(_structured_trader_llm(captured))(state)
|
||||||
|
text = " ".join(m["content"] for m in captured["prompt"])
|
||||||
|
assert "Technical Market Report:" not in text
|
||||||
|
assert "Ground concrete price levels" not in text
|
||||||
|
assert "Proposed Investment Plan" in text # still present
|
||||||
|
|
||||||
def test_falls_back_to_freetext_when_structured_unavailable(self):
|
def test_falls_back_to_freetext_when_structured_unavailable(self):
|
||||||
plain_response = (
|
plain_response = (
|
||||||
"**Action**: Sell\n\nGuidance cut hits margins.\n\n"
|
"**Action**: Sell\n\nGuidance cut hits margins.\n\n"
|
||||||
|
|||||||
@@ -25,6 +25,23 @@ def create_trader(llm):
|
|||||||
company_name = state["company_of_interest"]
|
company_name = state["company_of_interest"]
|
||||||
instrument_context = get_instrument_context_from_state(state)
|
instrument_context = get_instrument_context_from_state(state)
|
||||||
investment_plan = state["investment_plan"]
|
investment_plan = state["investment_plan"]
|
||||||
|
# The research plan digests the debate but loses exact price structure;
|
||||||
|
# give the Trader the technical market report so entry/stop levels are
|
||||||
|
# grounded in real ATR / support-resistance / current price (#1167). The
|
||||||
|
# report is empty when the user did not select the market analyst, so
|
||||||
|
# only offer it (and the grounding instruction) when it has content.
|
||||||
|
market_report = (state["market_report"] or "").strip()
|
||||||
|
|
||||||
|
if market_report:
|
||||||
|
grounding = (
|
||||||
|
"Ground concrete price levels (entry, stop-loss, position sizing) in the technical "
|
||||||
|
"market report's price structure -- current price, support/resistance, ATR, and "
|
||||||
|
"volatility -- and use the research plan for direction and strategy. "
|
||||||
|
)
|
||||||
|
report_section = f"Technical Market Report:\n{market_report}\n\n"
|
||||||
|
else:
|
||||||
|
grounding = ""
|
||||||
|
report_section = ""
|
||||||
|
|
||||||
messages = [
|
messages = [
|
||||||
{
|
{
|
||||||
@@ -32,7 +49,7 @@ def create_trader(llm):
|
|||||||
"content": (
|
"content": (
|
||||||
"You are a trading agent analyzing market data to make investment decisions. "
|
"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. "
|
"Based on your analysis, provide a specific recommendation to buy, sell, or hold. "
|
||||||
"Anchor your reasoning in the analysts' reports and the research plan. "
|
+ grounding
|
||||||
+ NO_EXTERNAL_TOOLS
|
+ NO_EXTERNAL_TOOLS
|
||||||
+ get_language_instruction()
|
+ get_language_instruction()
|
||||||
),
|
),
|
||||||
@@ -40,12 +57,11 @@ def create_trader(llm):
|
|||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": (
|
"content": (
|
||||||
f"Based on a comprehensive analysis by a team of analysts, here is an investment "
|
f"Here is the research team's investment plan for {company_name}. "
|
||||||
f"plan tailored for {company_name}. {instrument_context} This plan incorporates "
|
f"{instrument_context}\n\n"
|
||||||
f"insights from current technical market trends, macroeconomic indicators, and "
|
f"{report_section}"
|
||||||
f"social media sentiment. Use this plan as a foundation for evaluating your next "
|
f"Proposed Investment Plan:\n{investment_plan}\n\n"
|
||||||
f"trading decision.\n\nProposed Investment Plan: {investment_plan}\n\n"
|
f"Make an informed, strategic trading decision."
|
||||||
f"Leverage these insights to make an informed and strategic decision."
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user