TradingAgents/examples/crypto_backtest_examples.py

283 lines
9.5 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

"""
Example strategies for crypto backtesting
Demonstrates various trading strategies and agent integration
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from datetime import datetime, timedelta
from tradingagents.backtesting import CryptoBacktestEngine, OrderType
from tradingagents.backtesting.crypto_data_loader import CryptoDataLoader
from tradingagents.backtesting.crypto_strategy_evaluator import CryptoStrategyEvaluator, AgentDecision
# ============================================================================
# EXAMPLE 1: Buy and Hold Strategy
# ============================================================================
def buy_and_hold_strategy(timestamp, row, engine):
"""
Simple buy and hold strategy.
Buy once at the start, hold until end.
"""
if len(engine.positions) == 0:
return OrderType.BUY, "Initial buy - Buy and Hold"
return OrderType.HOLD, "Holding position"
# ============================================================================
# EXAMPLE 2: Moving Average Crossover
# ============================================================================
class MovingAverageCrossover:
"""MA crossover strategy with state."""
def __init__(self, short_window=50, long_window=200):
self.short_window = short_window
self.long_window = long_window
self.prices = []
def __call__(self, timestamp, row, engine):
"""Execute strategy."""
self.prices.append(row['close'])
if len(self.prices) < self.long_window:
return OrderType.HOLD, "Warming up indicators"
# Calculate MAs
short_ma = sum(self.prices[-self.short_window:]) / self.short_window
long_ma = sum(self.prices[-self.long_window:]) / self.long_window
# Golden cross (buy signal)
if short_ma > long_ma and len(engine.positions) == 0:
return OrderType.BUY, f"Golden cross: MA{self.short_window} > MA{self.long_window}"
# Death cross (sell signal)
elif short_ma < long_ma and len(engine.positions) > 0:
return OrderType.SELL, f"Death cross: MA{self.short_window} < MA{self.long_window}"
return OrderType.HOLD, "No crossover signal"
# ============================================================================
# EXAMPLE 3: RSI Mean Reversion
# ============================================================================
class RSIMeanReversion:
"""RSI-based mean reversion strategy."""
def __init__(self, period=14, oversold=30, overbought=70):
self.period = period
self.oversold = oversold
self.overbought = overbought
self.prices = []
def calculate_rsi(self):
"""Calculate RSI."""
if len(self.prices) < self.period + 1:
return 50 # Neutral
gains = []
losses = []
for i in range(1, self.period + 1):
change = self.prices[-i] - self.prices[-i-1]
if change > 0:
gains.append(change)
losses.append(0)
else:
gains.append(0)
losses.append(abs(change))
avg_gain = sum(gains) / self.period
avg_loss = sum(losses) / self.period
if avg_loss == 0:
return 100
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return rsi
def __call__(self, timestamp, row, engine):
"""Execute strategy."""
self.prices.append(row['close'])
rsi = self.calculate_rsi()
# Oversold - buy signal
if rsi < self.oversold and len(engine.positions) == 0:
return OrderType.BUY, f"RSI oversold: {rsi:.1f}"
# Overbought - sell signal
elif rsi > self.overbought and len(engine.positions) > 0:
return OrderType.SELL, f"RSI overbought: {rsi:.1f}"
return OrderType.HOLD, f"RSI neutral: {rsi:.1f}"
# ============================================================================
# EXAMPLE 4: Simulated Agent Strategy
# ============================================================================
def simulated_agent_strategy(timestamp, row, engine):
"""
Simulated crypto agent decision-making.
Mimics multi-signal analysis from agents.
"""
price = row['close']
# Simulate technical analysis
sma_50 = row.get('sma_50', price)
technical_signal = 1 if price > sma_50 else -1
# Simulate fundamental analysis (price-based proxy)
fundamental_signal = 1 if price < 42000 else -1 # Undervalued below 42k
# Simulate on-chain sentiment (mock)
onchain_signal = 1 # Assume bullish on-chain
# Aggregate signals
total_signal = technical_signal + fundamental_signal + onchain_signal
confidence = abs(total_signal) / 3.0
# Make decision
if total_signal >= 2 and len(engine.positions) == 0:
return OrderType.BUY, f"Agent BUY: {total_signal}/3 bullish signals (conf: {confidence:.0%})"
elif total_signal <= -2 and len(engine.positions) > 0:
return OrderType.SELL, f"Agent SELL: {total_signal}/3 bearish signals (conf: {confidence:.0%})"
return OrderType.HOLD, f"Agent HOLD: Mixed signals {total_signal}/3"
# ============================================================================
# EXAMPLE 5: Volatility Breakout
# ============================================================================
class VolatilityBreakout:
"""Trade breakouts based on volatility."""
def __init__(self, lookback=20, std_multiplier=2.0):
self.lookback = lookback
self.std_multiplier = std_multiplier
self.prices = []
def __call__(self, timestamp, row, engine):
"""Execute strategy."""
self.prices.append(row['close'])
if len(self.prices) < self.lookback:
return OrderType.HOLD, "Building history"
recent_prices = self.prices[-self.lookback:]
mean_price = sum(recent_prices) / len(recent_prices)
# Calculate standard deviation
variance = sum((p - mean_price) ** 2 for p in recent_prices) / len(recent_prices)
std = variance ** 0.5
upper_band = mean_price + (std * self.std_multiplier)
lower_band = mean_price - (std * self.std_multiplier)
current_price = row['close']
# Breakout above upper band
if current_price > upper_band and len(engine.positions) == 0:
return OrderType.BUY, f"Breakout above ${upper_band:.0f}"
# Breakdown below lower band
elif current_price < lower_band and len(engine.positions) > 0:
return OrderType.SELL, f"Breakdown below ${lower_band:.0f}"
return OrderType.HOLD, f"Price in range ${lower_band:.0f}-${upper_band:.0f}"
# ============================================================================
# EXAMPLE 6: Example Agent Function (for agent_backtest)
# ============================================================================
def example_agent_function(timestamp, row):
"""
Example agent function that returns AgentDecision.
This would be replaced by actual agent calls.
"""
price = row['close']
# Simple logic for demonstration
if price < 40000:
return AgentDecision(
signal="BUY",
confidence=0.8,
reasoning="Price below key support at $40k. Strong buying opportunity."
)
elif price > 48000:
return AgentDecision(
signal="SELL",
confidence=0.75,
reasoning="Price approaching resistance at $48k. Take profits."
)
else:
return AgentDecision(
signal="HOLD",
confidence=0.6,
reasoning="Price in consolidation range. Wait for clearer signal."
)
# ============================================================================
# RUNNING EXAMPLES
# ============================================================================
def run_example_backtest():
"""Run example backtests with different strategies."""
print("\n" + "=" * 80)
print(" CRYPTO BACKTESTING EXAMPLES")
print("=" * 80)
# Setup
print("\n📊 Setting up backtest environment...")
engine = CryptoBacktestEngine(initial_capital=10000)
loader = CryptoDataLoader(exchange_id='binance')
evaluator = CryptoStrategyEvaluator(engine, loader)
print("✅ Environment ready\n")
# Define test period
start_date = datetime(2024, 1, 1)
end_date = datetime(2024, 6, 1)
symbol = 'BTC/USDT'
print(f"Backtest Configuration:")
print(f" Symbol: {symbol}")
print(f" Period: {start_date.date()} to {end_date.date()}")
print(f" Initial Capital: ${engine.initial_capital:,.2f}")
print(f" Commission: {engine.commission_rate:.2%}")
print(f" Slippage: {engine.slippage_rate:.2%}\n")
# Available strategies
strategies = {
'1. Buy and Hold': buy_and_hold_strategy,
'2. MA Crossover (50/200)': MovingAverageCrossover(50, 200),
'3. RSI Mean Reversion': RSIMeanReversion(14, 30, 70),
'4. Simulated Agent': simulated_agent_strategy,
'5. Volatility Breakout': VolatilityBreakout(20, 2.0),
}
print("📋 Available Strategies:")
for name in strategies.keys():
print(f" {name}")
print("\n To run full backtest with real data:")
print(" 1. Ensure CCXT is installed: pip install ccxt")
print(" 2. Ensure internet connection")
print(" 3. Run: evaluator.run_backtest(symbol, start_date, end_date, strategy)")
print("\n✅ Example strategies loaded and ready to test\n")
if __name__ == "__main__":
run_example_backtest()