Issue #102: Backtesting Framework for Historical Validation
Context & Clarification
FalconSignals generates investment recommendations (buy/hold/sell), not algorithmic trading strategies. Backtesting here means validating recommendation quality through historical analysis, not simulating portfolio returns or order execution.
Key Distinction
| What We ARE Building |
What We Are NOT Building |
| ✅ Recommendation quality validation |
❌ Portfolio return simulation |
| ✅ Signal accuracy tracking over time |
❌ Order execution modeling |
| ✅ Confidence calibration analysis |
❌ Capital allocation strategies |
| ✅ Mode comparison (LLM vs rule-based) |
❌ Multi-asset portfolio optimization |
Why Traditional Backtesting Libraries Don't Apply
Libraries like backtrader, zipline, bt, and vectorbt are designed for:
- Systematic trading strategies with deterministic entry/exit rules
- Automatic position sizing and rebalancing
- Order execution simulation (slippage, commissions)
FalconSignals is different:
- Generates human-readable recommendations requiring judgment
- Users decide when/how to act on signals
- Focus is on signal quality, not portfolio mechanics
What We Already Have
✅ Historical Analysis (analyze --date 2024-06-01)
- Generates recommendations using only historical data
- Prevents look-ahead bias
- Works in both LLM and rule-based modes
✅ Performance Tracking (track-performance)
- Fetches current prices for active recommendations
- Stores daily price snapshots
- Calculates price changes and benchmark comparison
✅ Performance Metrics (performance-report)
- Win rate, average return, median return
- Alpha vs benchmark (SPY)
- Sharpe ratio, max drawdown
- Confidence calibration error
✅ Database Infrastructure
recommendations table stores all signals
price_tracking table stores daily prices
performance_summary table caches metrics
What's Missing
1. Backtesting Orchestration
Problem: Manual iteration through dates is tedious
# Currently required
uv run python -m src.main analyze --ticker AAPL --date 2024-01-01
uv run python -m src.main analyze --ticker AAPL --date 2024-02-01
# ...repeat 50+ times
Solution: Automated backtest command
# Proposed
uv run python -m src.main backtest \
--start-date 2024-01-01 \
--end-date 2024-12-31 \
--frequency weekly \
--ticker AAPL,MSFT \
--mode rule_based
Tasks:
2. Cost Estimation & Controls
Problem: LLM backtests can be expensive (€0.50-0.80 per ticker)
Solution: Pre-calculate costs and require confirmation
uv run python -m src.main backtest \
--start-date 2024-01-01 \
--end-date 2024-12-31 \
--frequency weekly \
--ticker AAPL,MSFT,GOOGL \
--mode llm \
--dry-run
# Output:
# 📊 Backtest Plan:
# Date range: 2024-01-01 to 2024-12-31
# Frequency: weekly (52 dates)
# Tickers: 3
# Total analyses: 156
# Estimated cost (LLM): €78-125
# Estimated duration: ~2 hours
#
# Continue? [y/N]
Tasks:
3. Backtest-Specific Reports
Problem: Current performance-report shows aggregated metrics, not backtest insights
Solution: Enhanced reports with:
- Performance by signal type (strong_buy vs buy vs hold)
- Confidence calibration tables
- Mode comparison (LLM vs rule-based)
- Time-series visualizations
- CSV export for custom analysis
Example output:
# Backtest Report: 2024-01-01 to 2024-12-31
## Performance by Signal Type
| Signal | Count | Win Rate | Avg Return (30d) | Alpha vs SPY |
|-------------|-------|----------|------------------|--------------|
| strong_buy | 12 | 75.0% | +8.2% | +3.1% |
| buy | 60 | 63.3% | +4.5% | +1.2% |
| hold | 54 | 51.9% | +1.8% | -0.5% |
## Confidence Calibration
| Confidence Range | Count | Actual Win Rate | Calibration Error |
|------------------|-------|-----------------|-------------------|
| 80-100% | 23 | 78.3% | -3.7% |
| 60-80% | 89 | 61.8% | -8.2% |
## Mode Comparison
| Metric | Rule-Based | LLM Mode | Winner |
|--------------|------------|----------|---------------|
| Win Rate | 58.2% | 64.7% | LLM (+6.5%) |
| Avg Return | +3.1% | +4.8% | LLM (+1.7%) |
| Sharpe Ratio | 0.82 | 1.05 | LLM |
| Cost | €0 | €95 | Rule-Based |
Tasks:
4. Configuration Management
Problem: No centralized backtest configuration
Solution: Add to config/default.yaml:
backtesting:
# Default parameters
default_frequency: "weekly" # daily, weekly, monthly
default_period_days: 90 # Track outcomes for X days
max_concurrent_analyses: 5 # Parallel execution limit
# Cost controls
llm_cost_limit_per_backtest: 100.0 # EUR
require_confirmation: true
# Reporting
report_formats:
- markdown
- json
- csv
include_visualizations: true
Tasks:
5. Parallel Execution (Optional)
Problem: Sequential backtests are slow (50+ dates × multiple tickers)
Solution: Run analyses in parallel (careful with API rate limits)
Tasks:
6. Resumable Backtests (Optional)
Problem: Long LLM backtests may fail mid-run
Solution: Save progress and allow resuming
Tasks:
Implementation Priority
Phase 1 (Must Have)
- Core
BacktestEngine with date iteration
- Basic
backtest CLI command
- Cost estimation for LLM mode
- Reuse existing analyze/track/report logic
Phase 2 (Should Have)
- Enhanced backtest-specific reports
- Signal type comparison
- Confidence calibration analysis
- Mode comparison (LLM vs rule-based)
- CSV export
Phase 3 (Nice to Have)
- Visualizations (charts, plots)
- Parallel execution
- Resumable backtests
- Interactive HTML reports
Success Criteria
Example Workflows
Validate System Before Using
# 1. Run 3-month backtest (rule-based)
uv run python -m src.main backtest \
--start-date 2024-09-01 \
--end-date 2024-12-01 \
--frequency weekly \
--ticker AAPL,MSFT,NVDA \
--mode rule_based
# 2. Review results
uv run python -m src.main backtest-report --session-id 1
# 3. If good, test LLM on subset
uv run python -m src.main backtest \
--start-date 2024-11-01 \
--end-date 2024-12-01 \
--frequency weekly \
--ticker NVDA \
--mode llm
# 4. Compare modes
uv run python -m src.main backtest-report --session-id 1,2 --compare
Evaluate LLM ROI
# Run both modes on same data
uv run python -m src.main backtest \
--start-date 2024-06-01 \
--end-date 2024-12-01 \
--frequency weekly \
--ticker AAPL,MSFT,GOOGL,AMZN,META \
--mode both # Run both modes
# Compare cost vs performance
uv run python -m src.main backtest-report \
--session-id 3 \
--compare-modes \
--format markdown
# Decision: If LLM only adds 2% return but costs €80,
# use rule-based for daily scans, LLM for final validation
Libraries to Consider (Optional)
Potentially Useful
quantstats - For tearsheet-style reports and visualizations
plotly - For interactive charts
seaborn - For statistical visualizations
NOT Applicable
- ❌
backtrader - For algorithmic trading strategies
- ❌
zipline - For quantitative finance strategies
- ❌
bt - For portfolio optimization
- ❌
vectorbt - For vectorized backtesting
These are designed for systematic trading, not recommendation validation.
Open Questions
- Default frequency: Weekly (good balance) or monthly (faster but less data)?
- Parallel execution: Enable by default or opt-in?
- Visualizations: Which charts are most valuable?
- Cumulative returns by signal type?
- Confidence calibration curves?
- Mode comparison over time?
- Incremental analysis: Should we skip dates that already have data?
Benefits
- ✅ Validate system effectiveness before relying on recommendations
- ✅ Identify which analysis mode works best (LLM vs rule-based)
- ✅ Optimize confidence calibration
- ✅ Data-driven system improvements
- ✅ Build confidence in recommendations
Related Documentation
- See
docs/BACKTESTING_PROPOSAL.md for detailed design
- See
docs/CLI_GUIDE.md for existing commands
- See
src/data/repository.py for performance tracking logic
Issue #102: Backtesting Framework for Historical Validation
Context & Clarification
FalconSignals generates investment recommendations (buy/hold/sell), not algorithmic trading strategies. Backtesting here means validating recommendation quality through historical analysis, not simulating portfolio returns or order execution.
Key Distinction
Why Traditional Backtesting Libraries Don't Apply
Libraries like
backtrader,zipline,bt, andvectorbtare designed for:FalconSignals is different:
What We Already Have
✅ Historical Analysis (
analyze --date 2024-06-01)✅ Performance Tracking (
track-performance)✅ Performance Metrics (
performance-report)✅ Database Infrastructure
recommendationstable stores all signalsprice_trackingtable stores daily pricesperformance_summarytable caches metricsWhat's Missing
1. Backtesting Orchestration
Problem: Manual iteration through dates is tedious
Solution: Automated
backtestcommand# Proposed uv run python -m src.main backtest \ --start-date 2024-01-01 \ --end-date 2024-12-31 \ --frequency weekly \ --ticker AAPL,MSFT \ --mode rule_basedTasks:
BacktestEngineclass (src/backtesting/engine.py)analyzelogic for each datebacktestCLI command (src/cli/commands/backtest.py)2. Cost Estimation & Controls
Problem: LLM backtests can be expensive (€0.50-0.80 per ticker)
Solution: Pre-calculate costs and require confirmation
Tasks:
BacktestEngine--dry-runflag (show plan without executing)3. Backtest-Specific Reports
Problem: Current
performance-reportshows aggregated metrics, not backtest insightsSolution: Enhanced reports with:
Example output:
Tasks:
BacktestReportclass (src/backtesting/report.py)PerformanceRepositorybacktest-reportCLI command4. Configuration Management
Problem: No centralized backtest configuration
Solution: Add to
config/default.yaml:Tasks:
BacktestConfigschema tosrc/config/schemas.pyconfig/default.yaml5. Parallel Execution (Optional)
Problem: Sequential backtests are slow (50+ dates × multiple tickers)
Solution: Run analyses in parallel (careful with API rate limits)
Tasks:
BacktestEngine--max-workersCLI option6. Resumable Backtests (Optional)
Problem: Long LLM backtests may fail mid-run
Solution: Save progress and allow resuming
Tasks:
--resumeflag to continue failed backtestsImplementation Priority
Phase 1 (Must Have)
BacktestEnginewith date iterationbacktestCLI commandPhase 2 (Should Have)
Phase 3 (Nice to Have)
Success Criteria
Example Workflows
Validate System Before Using
Evaluate LLM ROI
Libraries to Consider (Optional)
Potentially Useful
quantstats- For tearsheet-style reports and visualizationsplotly- For interactive chartsseaborn- For statistical visualizationsNOT Applicable
backtrader- For algorithmic trading strategieszipline- For quantitative finance strategiesbt- For portfolio optimizationvectorbt- For vectorized backtestingThese are designed for systematic trading, not recommendation validation.
Open Questions
Benefits
Related Documentation
docs/BACKTESTING_PROPOSAL.mdfor detailed designdocs/CLI_GUIDE.mdfor existing commandssrc/data/repository.pyfor performance tracking logic