TradingAgents/examples/backtest_example.py

375 lines
10 KiB
Python
Executable File

"""
Complete example of using the TradingAgents backtesting framework.
This example demonstrates:
1. Basic backtesting with built-in strategies
2. Custom strategy implementation
3. Performance analysis
4. Monte Carlo simulation
5. Report generation
"""
from decimal import Decimal
from datetime import datetime
from typing import Dict, List
import pandas as pd
# Import backtesting framework
from tradingagents.backtest import (
Backtester,
BacktestConfig,
BaseStrategy,
Signal,
Position,
BuyAndHoldStrategy,
SimpleMovingAverageStrategy,
compare_strategies,
)
def example_1_basic_backtest():
"""Example 1: Run a basic backtest with buy-and-hold strategy."""
print("=" * 80)
print("Example 1: Basic Backtest")
print("=" * 80)
# Create configuration
config = BacktestConfig(
initial_capital=Decimal('100000.00'),
start_date='2020-01-01',
end_date='2023-12-31',
commission=Decimal('0.001'), # 0.1%
slippage=Decimal('0.0005'), # 0.05%
benchmark='SPY',
)
# Create strategy
strategy = BuyAndHoldStrategy()
# Create backtester
backtester = Backtester(config)
# Run backtest
print("\nRunning backtest...")
results = backtester.run(
strategy=strategy,
tickers=['AAPL', 'MSFT'],
)
# Print results
print("\nBacktest Results:")
print(f"Total Return: {results.total_return:+.2%}")
print(f"Annualized Return: {results.metrics.annualized_return:+.2%}")
print(f"Sharpe Ratio: {results.sharpe_ratio:.2f}")
print(f"Max Drawdown: {results.max_drawdown:.2%}")
print(f"Win Rate: {results.win_rate:.2%}")
print(f"Total Trades: {results.metrics.total_trades}")
# Generate HTML report
print("\nGenerating HTML report...")
results.generate_report('backtest_report_example1.html')
print("Report saved to: backtest_report_example1.html")
# Export to CSV
print("\nExporting to CSV...")
results.export_to_csv('backtest_results_example1')
print("Results exported to: backtest_results_example1/")
return results
def example_2_sma_strategy():
"""Example 2: Backtest with SMA crossover strategy."""
print("\n" + "=" * 80)
print("Example 2: SMA Crossover Strategy")
print("=" * 80)
config = BacktestConfig(
initial_capital=Decimal('100000.00'),
start_date='2020-01-01',
end_date='2023-12-31',
commission=Decimal('0.001'),
slippage=Decimal('0.0005'),
benchmark='SPY',
)
# Create SMA strategy
strategy = SimpleMovingAverageStrategy(
short_window=50,
long_window=200,
)
backtester = Backtester(config)
print("\nRunning backtest with SMA crossover...")
results = backtester.run(
strategy=strategy,
tickers=['AAPL'],
)
print("\nResults:")
print(f"Total Return: {results.total_return:+.2%}")
print(f"Sharpe Ratio: {results.sharpe_ratio:.2f}")
print(f"Max Drawdown: {results.max_drawdown:.2%}")
return results
class MomentumStrategy(BaseStrategy):
"""
Example custom momentum strategy.
Buys stocks with positive momentum (returns over lookback period).
"""
def __init__(self, lookback_days: int = 20):
"""Initialize momentum strategy."""
super().__init__(name="Momentum")
self.lookback_days = lookback_days
def generate_signals(
self,
timestamp: datetime,
data: Dict[str, pd.DataFrame],
positions: Dict[str, Position],
portfolio_value: Decimal,
) -> List[Signal]:
"""Generate momentum-based signals."""
signals = []
for ticker, df in data.items():
if len(df) < self.lookback_days:
continue
# Calculate momentum (returns over lookback period)
recent_prices = df['close'].tail(self.lookback_days)
momentum = (recent_prices.iloc[-1] / recent_prices.iloc[0]) - 1
current_position = positions.get(ticker)
# Buy if positive momentum and not holding
if momentum > 0.05 and (not current_position or current_position.is_flat):
signals.append(Signal(
ticker=ticker,
timestamp=timestamp,
action='buy',
confidence=min(float(momentum) * 5, 1.0),
))
# Sell if negative momentum and holding
elif momentum < -0.02 and current_position and not current_position.is_flat:
signals.append(Signal(
ticker=ticker,
timestamp=timestamp,
action='sell',
confidence=0.8,
))
return signals
def example_3_custom_strategy():
"""Example 3: Custom momentum strategy."""
print("\n" + "=" * 80)
print("Example 3: Custom Momentum Strategy")
print("=" * 80)
config = BacktestConfig(
initial_capital=Decimal('100000.00'),
start_date='2020-01-01',
end_date='2023-12-31',
commission=Decimal('0.001'),
slippage=Decimal('0.0005'),
)
strategy = MomentumStrategy(lookback_days=20)
backtester = Backtester(config)
print("\nRunning backtest with momentum strategy...")
results = backtester.run(
strategy=strategy,
tickers=['AAPL', 'MSFT', 'GOOGL'],
)
print("\nResults:")
print(f"Total Return: {results.total_return:+.2%}")
print(f"Sharpe Ratio: {results.sharpe_ratio:.2f}")
print(f"Max Drawdown: {results.max_drawdown:.2%}")
return results
def example_4_compare_strategies():
"""Example 4: Compare multiple strategies."""
print("\n" + "=" * 80)
print("Example 4: Strategy Comparison")
print("=" * 80)
strategies = {
'Buy & Hold': BuyAndHoldStrategy(),
'SMA (50/200)': SimpleMovingAverageStrategy(50, 200),
'SMA (20/50)': SimpleMovingAverageStrategy(20, 50),
'Momentum': MomentumStrategy(20),
}
print("\nComparing strategies...")
comparison = compare_strategies(
strategies=strategies,
tickers=['AAPL'],
start_date='2020-01-01',
end_date='2023-12-31',
initial_capital=100000.0,
)
print("\nComparison Results:")
print(comparison)
return comparison
def example_5_monte_carlo():
"""Example 5: Monte Carlo simulation."""
print("\n" + "=" * 80)
print("Example 5: Monte Carlo Simulation")
print("=" * 80)
# First run a backtest
config = BacktestConfig(
initial_capital=Decimal('100000.00'),
start_date='2020-01-01',
end_date='2023-12-31',
commission=Decimal('0.001'),
)
strategy = SimpleMovingAverageStrategy()
backtester = Backtester(config)
print("\nRunning initial backtest...")
results = backtester.run(strategy=strategy, tickers=['AAPL'])
# Run Monte Carlo simulation
print("\nRunning Monte Carlo simulation...")
from tradingagents.backtest import MonteCarloConfig
mc_config = MonteCarloConfig(
n_simulations=10000,
method='resample_returns',
)
mc_results = results.monte_carlo(mc_config)
print("\nMonte Carlo Results:")
print(f"Mean Final Value: ${mc_results.mean_final_value:,.2f}")
print(f"Median Final Value: ${mc_results.median_final_value:,.2f}")
print(f"Probability of Profit: {mc_results.probability_of_profit:.2%}")
print("\nConfidence Intervals:")
for level, (lower, upper) in mc_results.confidence_intervals.items():
print(f" {level:.0%}: ${lower:,.2f} - ${upper:,.2f}")
return mc_results
def example_6_walk_forward():
"""Example 6: Walk-forward analysis."""
print("\n" + "=" * 80)
print("Example 6: Walk-Forward Analysis")
print("=" * 80)
from tradingagents.backtest import WalkForwardConfig
config = BacktestConfig(
initial_capital=Decimal('100000.00'),
start_date='2020-01-01',
end_date='2023-12-31',
commission=Decimal('0.001'),
)
# Define strategy factory
def strategy_factory(short_window, long_window):
"""Create SMA strategy with given parameters."""
return SimpleMovingAverageStrategy(short_window, long_window)
# Define parameter grid
param_grid = {
'short_window': [20, 50],
'long_window': [100, 200],
}
# Create walk-forward config
wf_config = WalkForwardConfig(
in_sample_months=12,
out_sample_months=3,
optimization_metric='sharpe',
)
backtester = Backtester(config)
print("\nRunning walk-forward analysis...")
print("(This may take a while...)")
wf_results = backtester.walk_forward_analysis(
strategy_factory=strategy_factory,
param_grid=param_grid,
tickers=['AAPL'],
wf_config=wf_config,
)
print("\nWalk-Forward Results:")
print(f"Number of Windows: {len(wf_results.windows)}")
print(f"WF Efficiency Ratio: {wf_results.efficiency_ratio:.2f}")
print(f"Overfitting Score: {wf_results.overfitting_score:.2f}")
print("\nWindow Summary:")
print(wf_results.summary())
return wf_results
def main():
"""Run all examples."""
print("\n" + "=" * 80)
print("TradingAgents Backtesting Framework Examples")
print("=" * 80)
# Run examples
try:
example_1_basic_backtest()
except Exception as e:
print(f"Example 1 failed: {e}")
try:
example_2_sma_strategy()
except Exception as e:
print(f"Example 2 failed: {e}")
try:
example_3_custom_strategy()
except Exception as e:
print(f"Example 3 failed: {e}")
try:
example_4_compare_strategies()
except Exception as e:
print(f"Example 4 failed: {e}")
try:
example_5_monte_carlo()
except Exception as e:
print(f"Example 5 failed: {e}")
# Walk-forward is slow, so commented out by default
# try:
# example_6_walk_forward()
# except Exception as e:
# print(f"Example 6 failed: {e}")
print("\n" + "=" * 80)
print("Examples Complete!")
print("=" * 80)
if __name__ == '__main__':
main()