8.4 KiB
8.4 KiB
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
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:
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:
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 capitalfinal_value: Ending portfolio valuetotal_return: Total return percentagetotal_trades: Number of trades executedwinning_trades: Number of profitable tradeslosing_trades: Number of losing tradeswin_rate: Win rate percentageprofit_factor: Gross profit / gross lossmax_drawdown: Maximum drawdown percentagesharpe_ratio: Sharpe ratiosortino_ratio: Sortino ratiotrades: List of BacktestTrade recordssnapshots: List of BacktestSnapshot records
Results Analyzer
AnalysisResult
Comprehensive analysis output:
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:
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
# 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:
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")