# Backtest Module The backtest module provides comprehensive historical strategy replay with realistic slippage and commission modeling, results analysis, and report generation. ## Overview ``` tradingagents/backtest/ __init__.py # Public API exports backtest_engine.py # Core backtest engine results_analyzer.py # Metrics and trade analysis report_generator.py # PDF/HTML/JSON/Markdown reports ``` ## Quick Start ```python from tradingagents.backtest import ( BacktestEngine, BacktestConfig, ResultsAnalyzer, ReportGenerator, OHLCV, Signal, OrderSide, PercentageSlippage, PercentageCommission, ) from decimal import Decimal from datetime import datetime # Configure backtest config = BacktestConfig( initial_capital=Decimal("100000"), slippage_model=PercentageSlippage(Decimal("0.1")), # 0.1% slippage commission_model=PercentageCommission(Decimal("0.1")), # 0.1% commission ) # Create engine engine = BacktestEngine(config) # Prepare price data price_data = { "AAPL": [ OHLCV(datetime(2023, 1, 3), 130, 132, 129, 131, 1000000), OHLCV(datetime(2023, 1, 4), 131, 135, 130, 134, 1200000), OHLCV(datetime(2023, 1, 5), 134, 136, 133, 135, 1100000), ], } # Define signals signals = [ Signal(datetime(2023, 1, 3), "AAPL", OrderSide.BUY, Decimal("100")), Signal(datetime(2023, 1, 5), "AAPL", OrderSide.SELL, Decimal("100")), ] # Run backtest result = engine.run(price_data, signals) # Analyze results analyzer = ResultsAnalyzer() analysis = analyzer.analyze(result) # Generate report generator = ReportGenerator() report = generator.generate(result, analysis) ``` ## Backtest Engine ### BacktestConfig Configuration for backtest execution: | Field | Type | Default | Description | |-------|------|---------|-------------| | `initial_capital` | `Decimal` | Required | Starting capital | | `slippage_model` | `SlippageModel` | `NoSlippage()` | Slippage model | | `commission_model` | `CommissionModel` | `NoCommission()` | Commission model | | `allow_fractional` | `bool` | `True` | Allow fractional shares | | `margin_enabled` | `bool` | `False` | Enable margin trading | ### Slippage Models Built-in slippage models: ```python from tradingagents.backtest import ( NoSlippage, # No slippage FixedSlippage, # Fixed amount per share PercentageSlippage, # Percentage of price VolumeSlippage, # Volume-impact model ) # Fixed: $0.01 per share slippage = FixedSlippage(Decimal("0.01")) # Percentage: 0.1% of price slippage = PercentageSlippage(Decimal("0.1")) # Volume impact: 0.1% per 1% of daily volume slippage = VolumeSlippage( base_impact=Decimal("0.1"), volume_factor=Decimal("0.01"), ) ``` ### Commission Models Built-in commission models: ```python from tradingagents.backtest import ( NoCommission, # No commission FixedCommission, # Fixed per trade PerShareCommission, # Per share PercentageCommission, # Percentage of value TieredCommission, # Tiered by trade value ) # Fixed: $5 per trade commission = FixedCommission(Decimal("5")) # Per share: $0.005 per share, min $1, max $10 commission = PerShareCommission( per_share=Decimal("0.005"), minimum=Decimal("1"), maximum=Decimal("10"), ) # Percentage: 0.1% of trade value commission = PercentageCommission(Decimal("0.1")) # Tiered: Different rates by trade size commission = TieredCommission(tiers=[ (Decimal("10000"), Decimal("0.2")), # 0.2% for trades < $10k (Decimal("100000"), Decimal("0.1")), # 0.1% for trades < $100k (None, Decimal("0.05")), # 0.05% for larger trades ]) ``` ### BacktestResult The result contains: - `initial_capital`: Starting capital - `final_value`: Ending portfolio value - `total_return`: Total return percentage - `total_trades`: Number of trades executed - `winning_trades`: Number of profitable trades - `losing_trades`: Number of losing trades - `win_rate`: Win rate percentage - `profit_factor`: Gross profit / gross loss - `max_drawdown`: Maximum drawdown percentage - `sharpe_ratio`: Sharpe ratio - `sortino_ratio`: Sortino ratio - `trades`: List of BacktestTrade records - `snapshots`: List of BacktestSnapshot records ## Results Analyzer ### AnalysisResult Comprehensive analysis output: ```python analyzer = ResultsAnalyzer() analysis = analyzer.analyze(result) # Risk metrics print(f"Sharpe: {analysis.risk_metrics.sharpe_ratio}") print(f"Sortino: {analysis.risk_metrics.sortino_ratio}") print(f"Calmar: {analysis.risk_metrics.calmar_ratio}") print(f"VaR (95%): {analysis.risk_metrics.var_95}") print(f"CVaR (95%): {analysis.risk_metrics.cvar_95}") # Trade statistics print(f"Win rate: {analysis.trade_statistics.win_rate}%") print(f"Profit factor: {analysis.trade_statistics.profit_factor}") print(f"Max win streak: {analysis.trade_statistics.max_win_streak}") print(f"Average trade: {analysis.trade_statistics.avg_trade}") # Drawdown analysis print(f"Max drawdown: {analysis.drawdown_analysis.max_drawdown}%") print(f"Recovery time: {analysis.drawdown_analysis.max_drawdown_duration} days") # Monthly performance for breakdown in analysis.monthly_performance: print(f"{breakdown.period}: {breakdown.return_pct}%") ``` ### RiskMetrics | Metric | Description | |--------|-------------| | `sharpe_ratio` | Risk-adjusted return (vs risk-free rate) | | `sortino_ratio` | Downside risk-adjusted return | | `calmar_ratio` | Return / max drawdown | | `var_95` | 5% worst-case daily loss | | `cvar_95` | Average of 5% worst days | | `ulcer_index` | Depth and duration of drawdowns | | `max_drawdown` | Maximum peak-to-trough decline | | `max_drawdown_duration` | Longest drawdown period (days) | | `recovery_factor` | Total return / max drawdown | ### TradeStatistics | Metric | Description | |--------|-------------| | `total_trades` | Total number of trades | | `win_rate` | Percentage of winning trades | | `profit_factor` | Gross profit / gross loss | | `max_win` | Largest winning trade | | `max_loss` | Largest losing trade | | `avg_trade` | Average trade P&L | | `median_trade` | Median trade P&L | | `max_win_streak` | Longest winning streak | | `max_loss_streak` | Longest losing streak | | `avg_holding_period` | Average trade duration | ## Report Generator ### ReportConfig Configure report output: ```python from tradingagents.backtest import ( ReportGenerator, ReportConfig, ReportFormat, ReportSection, ) config = ReportConfig( format=ReportFormat.HTML, sections=[ ReportSection.SUMMARY, ReportSection.TRADES, ReportSection.PERFORMANCE, ReportSection.RISK, ReportSection.CHARTS, ], include_charts=True, color_scheme={ "primary": "#2196F3", "positive": "#4CAF50", "negative": "#F44336", }, ) generator = ReportGenerator(config) report = generator.generate(result, analysis) ``` ### Output Formats | Format | Description | |--------|-------------| | `HTML` | Interactive HTML with embedded CSS | | `PDF` | PDF document (requires WeasyPrint) | | `JSON` | Structured JSON data | | `MARKDOWN` | Plain Markdown text | ### Report Sections | Section | Content | |---------|---------| | `SUMMARY` | High-level metrics overview | | `TRADES` | Individual trade records | | `PERFORMANCE` | Monthly/yearly returns | | `RISK` | Risk metrics and analysis | | `CHARTS` | Equity curves, drawdown charts | | `POSITIONS` | Position history | ### Charts Built-in SVG charts: - **Equity Curve**: Portfolio value over time - **Drawdown Chart**: Underwater equity chart - **Monthly Returns Heatmap**: Color-coded monthly returns ```python # Get chart data charts = generator.generate_charts(result, analysis) equity_svg = charts["equity_curve"] drawdown_svg = charts["drawdown"] heatmap_svg = charts["monthly_heatmap"] ``` ## Factory Functions Convenience functions for common configurations: ```python from tradingagents.backtest import ( create_backtest_engine, create_results_analyzer, create_report_generator, ) # Create engine with common settings engine = create_backtest_engine( initial_capital=100000, slippage_pct=0.1, commission_pct=0.1, ) # Create analyzer analyzer = create_results_analyzer() # Create report generator generator = create_report_generator(format="html") ``` ## See Also - [Results Analyzer API](../api/results-analyzer.md) - [Report Generator API](../api/report-generator.md) - [Backtesting Guide](../guides/backtesting.md)