Skip to main content

Bull/Bear Debate Agent

The debate feature uses two independent LLM agents to argue opposing sides before every trade. This eliminates the confirmation bias that occurs when a single agent naturally gravitates toward a direction.

Academic Basis​

Paper: TradingAgents (arXiv:2412.20138)

Key finding: Multi-agent frameworks comprehensively outperform single-agent baselines across all tested metrics in trading decision tasks.

How It Works​

Market Data
↓ ↓
BullAgent BearAgent
(forced (forced
bullish) bearish)
↓ ↓
3 arguments 3 arguments
+ confidence + confidence
↓
Debate Summary
↓
Injected into main
decision prompt as
{{ debate_summary }}

BullAgent​

Receives the same market data as the main agent but is forced to argue bullish. It must:

  • Provide exactly 3 arguments supporting a long position
  • Assign a confidence score to its bull case
  • Cite specific data points (indicator values, price levels)

BearAgent​

Receives the same data but is forced to argue bearish. It must:

  • Provide exactly 3 counter-arguments supporting a short or hold
  • Assign a confidence score to its bear case
  • Cite specific data points

Summary Injection​

The combined output is summarized and injected into the main decision prompt at {{ debate_summary }}. The main agent then uses this in Step 3 (Sentiment Check) of the FinCoT chain.

Enabling the Debate​

# config.yaml
debate:
enabled: true # adds 2 extra LLM calls per decision cycle
Token Cost

When debate is enabled, each decision cycle makes 3 LLM calls total:

  1. BullAgent
  2. BearAgent
  3. Main decision agent

Budget accordingly if you're on a metered API plan.

Example Debate Output​

=== Bull Arguments (confidence: 0.68) ===
1. RSI at 58 shows momentum building without overbought conditions.
Clear room to run to 70 before mean reversion pressure.

2. Funding rate at +0.008% — well below the +0.03% threshold that
historically signals crowded longs. No squeeze risk.

3. Binance spot CVD positive for 4 consecutive hours, indicating
net buyer accumulation at current levels.

=== Bear Arguments (confidence: 0.44) ===
1. Price rejected the $43,500 resistance level twice in 6 hours.
Third test rarely breaks cleanly without consolidation.

2. 4H MACD histogram shrinking — momentum deceleration before
the daily trend has fully turned bullish.

3. BTC dominance rising (+0.3% today) suggests altcoin rotation
away, reducing ETH's relative strength.

=== Summary ===
Bulls present moderate conviction with funding and CVD support.
Bears flag resistance rejection and momentum deceleration.
Net sentiment: Cautiously bullish with reduced position sizing recommended.

Why Forced Arguments?​

Without the forced constraint, a single LLM asked to "consider both sides" will:

  1. Generate a weak straw-man counterargument
  2. Immediately dismiss it
  3. Confirm its initial bias

By using two separate agents with mandatory position constraints, each side is argued with full effort.

Core Code​

The debate logic lives in src/agent/debate.py:

async def run_bull_bear_debate(
market_data: dict,
symbol: str,
llm_client: BaseLLM,
) -> DebateResult:
bull_result = await run_bull_agent(market_data, symbol, llm_client)
bear_result = await run_bear_agent(market_data, symbol, llm_client)
return summarize_debate(bull_result, bear_result)

Interaction with Other Features​

FeatureInteraction
FinCoTDebate summary feeds into Step 3 (Sentiment Check)
Regime AdaptiveIn trending regimes, the bull/bear confidence delta is used to amplify the regime signal
Market MonitorDebate is still run for volatility-triggered decisions (same cost applies)

When Debate Adds the Most Value​

  • Choppy / ranging markets — prevents over-committing to a direction
  • Near key resistance/support — forces explicit argument about rejection probability
  • After a losing streak — counters the human-like tendency to reverse-bias after losses (the review system can exhibit this)

Next Steps​