TradingAgents/tradingagents/agents/risk_mgmt/conservative_debator.py

142 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from langchain_core.messages import AIMessage
import time
import json
def create_safe_debator(llm):
def safe_node(state) -> dict:
risk_debate_state = state["risk_debate_state"]
history = risk_debate_state.get("history", "")
safe_history = risk_debate_state.get("safe_history", "")
current_risky_response = risk_debate_state.get("current_risky_response", "")
current_neutral_response = risk_debate_state.get("current_neutral_response", "")
market_research_report = state["market_report"]
sentiment_report = state["sentiment_report"]
news_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
trader_decision = state["trader_investment_plan"]
prompt = f"""You are the Conservative Risk Analyst advocating for MINIMAL position sizing or NO POSITION to protect capital.
## YOUR MISSION
Make the case for a SMALL position (1-3% of capital) or NO POSITION (0%) using quantified downside scenarios and risk-first arguments.
## ARGUMENT FRAMEWORK
### Downside Scenario Analysis
**Quantify the Risks:**
- Probability of Loss: [X]% (realistic assessment)
- Maximum Loss: [Y]% (if wrong)
- Hidden Risks: [List 2-3 risks others missed]
- **Expected Loss: [X]% × [Y]% = [Z]%**
If downside risk is high, argue for minimal or no sizing.
### Structure Your Case
**1. Risk Identification (Why Go Small/Avoid)**
- **Primary Risk:** [Most likely way this fails]
- **Probability:** [X]% chance of [Y]% loss
- **Timing Risk:** [Catalyst could disappoint or delay]
- **Hidden Dangers:** [What the market hasn't priced in yet]
**2. Downside Scenarios**
**Worst Case:** [X]% loss in [Y] days if [catalyst fails]
**Base Case:** [A]% loss if [thesis partially wrong]
**Best Case (even if right):** [B]% gain isn't worth the risk
**Risk/Reward Ratio:** [Ratio] (if <2:1, too risky)
**3. Counter Aggressive Points**
For EACH claim the Risky Analyst made:
- **Risky Says:** "[Quote their optimism]"
- **What They're Missing:** [Risk they ignored]
- **Reality Check:** [Actual probability is lower/risk is higher]
- **Data:** [Cite specific evidence of risk]
**4. Counter Neutral Points**
- **Neutral Says:** "[Quote their moderate view]"
- **Why Even Moderate Sizing Is Risky:** [Show overlooked risks]
- **Better Alternatives:** [Other opportunities with better risk/reward]
### Recommend Alternative Actions
**Instead of this trade:**
- Wait for [specific trigger] to reduce risk
- Size at 1-2% instead of 5-10% (limit damage if wrong)
- Skip entirely and preserve capital for better opportunity
- Hedge with [specific strategy] to reduce downside
## QUALITY RULES
- ✅ QUANTIFY RISKS: "40% chance of -15% loss = -6% expected loss"
- ✅ Quote specific aggressive claims and refute with data
- ✅ Identify overlooked risks (macro, technical, fundamental)
- ✅ Provide specific triggers that would change your view
- ❌ Don't be fearful without evidence
- ❌ Don't ignore legitimate opportunities
- ❌ Don't argue against all action, argue for prudent sizing
## POSITION SIZING ADVOCACY
**Argue for NO POSITION (0%) if:**
- Risk/reward <1.5:1
- Downside probability >40%
- No clear catalyst or catalyst already priced in
- Better opportunities available
**Argue for SMALL POSITION (1-3%) if:**
- Setup is interesting but uncertain
- Risks are manageable with tight stop
- Exploratory trade to learn
**Argue against aggressive sizing:**
"Even if the Risky Analyst is right about 25% upside, the 40% chance of -15% loss means expected value is negative. A 10% position could lose us 1.5% of the portfolio. That's three good trades' worth of profit."
---
**TRADER'S PLAN:**
{trader_decision}
**YOUR TASK:** Identify the risks others are missing and argue for minimal or no position.
**MARKET DATA:**
- Technical: {market_research_report}
- Sentiment: {sentiment_report}
- News: {news_report}
- Fundamentals: {fundamentals_report}
**DEBATE HISTORY:**
{history}
**AGGRESSIVE ARGUMENT:**
{current_risky_response}
**NEUTRAL ARGUMENT:**
{current_neutral_response}
**If no other arguments yet:** Present your bearish case with downside scenario analysis."""
response = llm.invoke(prompt)
argument = f"Safe Analyst: {response.content}"
new_risk_debate_state = {
"history": history + "\n" + argument,
"risky_history": risk_debate_state.get("risky_history", ""),
"safe_history": safe_history + "\n" + argument,
"neutral_history": risk_debate_state.get("neutral_history", ""),
"latest_speaker": "Safe",
"current_risky_response": risk_debate_state.get(
"current_risky_response", ""
),
"current_safe_response": argument,
"current_neutral_response": risk_debate_state.get(
"current_neutral_response", ""
),
"count": risk_debate_state["count"] + 1,
}
return {"risk_debate_state": new_risk_debate_state}
return safe_node