Skip to content

Latest commit

 

History

History
353 lines (287 loc) · 13.3 KB

File metadata and controls

353 lines (287 loc) · 13.3 KB

backTestingTraderBot

A full-featured Python backtesting framework for options and equities trading strategies. Supports pluggable signal systems, multi-broker live paper trading, Monte Carlo simulation, and comprehensive performance analytics with visualizations.

Built over 30+ agentic coding sessions — see journal/ for the full development narrative.

Features

  • Multi-instrument Trading: Trade equities, options (calls/puts), or both separately
  • Pluggable Signal Systems:
    • indicator_pair — any two indicators with configurable sync windows
    • ema_233 — EMA crossover on resampled bars
    • armed_mode — arm/fire logic for indicator pairs (prevents signal stacking)
    • trigger_chain — sequential trigger chain with N indicators
  • Options Greeks Calculation: Compute and track delta, theta, gamma, vega for options positions
  • Portfolio Management: Track multiple concurrent positions with P&L calculation including costs/slippage
  • Flexible Exit Logic: Profit target, stop loss, opposite signal, EOD close, and options expiration
  • Monte Carlo Simulation: Bootstrap trade P&Ls to produce equity curve distributions and percentile bands
  • Live Paper Trading: Multi-broker support — Alpaca paper orders and IBKR paper orders via separate live runners
  • Comprehensive Metrics: Sharpe, Sortino, max drawdown, win rate, profit factor, Probabilistic Sharpe Ratio, Deflated Sharpe Ratio, and more
  • Visualization: Equity curves, drawdown charts, and signal overlays on price
  • YAML Configuration: Adjust all strategy parameters without code changes
  • IS/OOS Split: In-sample / out-of-sample evaluation built into the backtest engine
  • Trade Logging: Detailed CSV output of all trades with entry/exit reasons
  • Streamlit Dashboard: Interactive 4-view results browser

Project Structure

backTestingTraderBot/
├── requirements.txt
├── config/
│   └── strategy_params.example.yaml  # Example strategy parameters
├── data/
│   ├── Alpaca/equities/SYMBOL/[1min|5min]/[YYYY]/
│   ├── DataBento/equities/SYMBOL/[1min|5min]/[YYYY]/
│   ├── DataBento/options/SYMBOL/1min/
│   └── TV/equities/SYMBOL/5min/
├── main_runner/
│   ├── run_backtest_db.py            # Databento backtest entry point
│   ├── run_backtest_with_alpaca.py   # Alpaca backtest entry point
│   ├── run_backtest_tv.py            # TradingView backtest entry point
│   └── run_monte_carlo.py            # Monte Carlo post-processor
├── live_runner/
│   ├── run_live_db.py                # Databento stream → Alpaca paper orders
│   └── run_live_ibkr.py              # IBKR stream → IBKR paper orders
├── scripts_bash/
│   ├── run_backtest_db.sh
│   ├── run_backtest_alpaca.sh
│   ├── run_backtest_tv.sh
│   └── run_mc.sh
├── scripts_py/
│   ├── dashboard.py                  # Streamlit results dashboard
│   ├── download_and_aggregate_databento.py
│   ├── download_options_databento.py # Options cache pre-warmer
│   └── armed_mode_comparison.py
├── src/
│   ├── data/
│   │   ├── alpaca_loader.py
│   │   ├── databento_loader.py
│   │   ├── aggregator.py             # 1-min → 5-min resampler
│   │   └── tradingview_loader.py
│   ├── indicators/
│   │   ├── base.py                   # Shared primitives (rolling_high_low, double_ema_smooth)
│   │   ├── smi.py
│   │   ├── williams_r.py
│   │   ├── ema.py
│   │   ├── rsi.py
│   │   ├── macd.py
│   │   └── vwap.py
│   ├── signals/
│   │   ├── strategy.py               # SignalStrategy ABC + factory + concrete classes
│   │   └── indicator_pair_pipeline.py # Unified signal generation for all systems
│   ├── options/
│   │   ├── greeks.py
│   │   ├── option_pricer.py
│   │   ├── strike_selector.py
│   │   ├── entry_logic.py
│   │   ├── exit_rules.py
│   │   ├── utils.py
│   │   └── position.py
│   ├── backtest/
│   │   ├── engine.py
│   │   ├── trade_logic.py
│   │   └── portfolio.py
│   ├── analysis/
│   │   ├── metrics.py
│   │   ├── monte_carlo.py
│   │   └── visualize.py
│   ├── live/
│   │   ├── live_engine.py
│   │   ├── alpaca_trader.py
│   │   ├── ibkr_trader.py
│   │   ├── databento_streamer.py
│   │   ├── ibkr_streamer.py
│   │   └── broker_protocol.py
│   └── utils/
│       └── logging_config.py
├── journal/
│   ├── INDEX.md
│   ├── log/                          # Chronological dev log
│   ├── decisions/                    # Key design rationale docs
│   ├── runbooks/                     # Operational how-to guides
│   ├── concepts/                     # Reference / educational docs
│   ├── tutorials/                    # Multi-part crash courses
│   └── docs/                         # _state.md, _modules.md (living state)
├── tests/
│   ├── test_indicators.py
│   ├── test_greeks.py
│   ├── test_signals.py
│   ├── test_portfolio.py
│   └── ...                           # 900+ tests total
└── results/
    ├── db/                           # Databento results
    ├── alpaca/                       # Alpaca results
    ├── tv/                           # TradingView results
    └── others/                       # Comparison reports

Installation

  1. Clone and navigate to the project:

    git clone https://github.com/Jaggia/backTestingTraderBot.git
    cd backTestingTraderBot
  2. Create a virtual environment (recommended):

    python3 -m venv venv
    source venv/bin/activate  # macOS/Linux
    # or
    venv\Scripts\activate  # Windows
  3. Install dependencies:

    pip install -r requirements.txt
  4. Set up environment variables (if using live data sources):

    Export these in ~/.zshrc or equivalent:

    export DATA_BENTO_PW=your_databento_api_key_here
    export ALPACA_UN=your_alpaca_api_key_here
    export ALPACA_PW=your_alpaca_secret_key_here

Quick Start

1. Configure Your Strategy

Copy the example config and edit to your needs:

cp config/strategy_params.example.yaml config/strategy_params.yaml

Key configurable sections:

strategy:
  timeframe: "5min"              # 1min or 5min bars
  trade_mode: "equities"         # equities or options
  signal_system: "indicator_pair" # indicator_pair, ema_233, armed_mode, trigger_chain
  initial_capital: 100000        # Starting portfolio value

signals:
  # Indicator parameters vary by signal system — see strategy_params.example.yaml
  # sync_window: X               # Bars to synchronize indicator events
  # vwap_filter: true/false      # Optional VWAP filter

options:
  target_dte: X                  # Days to expiration
  strike_selection: "ATM"        # ATM, 1_ITM, 1_OTM, target_delta

exits:
  profit_target_pct: XX.X        # Take profit at +XX%
  stop_loss_pct: XX.X            # Stop loss at -XX%
  eod_close: false               # Close all positions at market close
  opposite_signal: true          # Exit on opposite signal

position:
  sizing_mode: "percent_of_equity"  # fixed or percent_of_equity
  sizing_pct: XX                    # % of equity per trade
  max_concurrent_positions: X

costs:
  commission_per_contract: X.XX  # Per contract commission
  slippage_pct: X.XX             # Slippage as % of price

2. Run a Backtest

Data Source Selection

Databento Data (Default):

./scripts_bash/run_backtest_db.sh
# Or directly:
python main_runner/run_backtest_db.py START_DATE END_DATE

Alpaca Data:

./scripts_bash/run_backtest_alpaca.sh
# Or directly:
python main_runner/run_backtest_with_alpaca.py START_DATE END_DATE

TradingView Data:

./scripts_bash/run_backtest_tv.sh
# Or directly:
python main_runner/run_backtest_tv.py START_DATE END_DATE

Data Source Comparison

Source Timeframe Instrument Best For
Databento 1min → 5min (aggregated) Equities + Options Production, closest to IB
Alpaca 1min, 5min Equities Testing, development
TradingView 5min Equities Chart validation

3. Review Results

After backtesting, check results/{db,alpaca,tv}/{date_range}/{mode}/{timeframe}/:

  • backtest.csv: Detailed trade log with entry/exit prices, P&L, and exit reasons
  • report.md: Summary of strategy configuration and performance metrics
  • config.yaml: Full config snapshot at run time
  • equity_curve.png: Portfolio value over time
  • drawdown.png: Underwater plot showing drawdown periods
  • signals.png: Price chart with entry/exit signals overlaid
  • equity_data.csv: Equity curve data used by the interactive dashboard

4. Launch the Dashboard

streamlit run scripts_py/dashboard.py

Browse results across data sources and dates with 4 views:

  • Overview: Metric cards, charts, config used, full report
  • Trade Explorer: Interactive table with filters, P&L histogram, cumulative P&L
  • Comparison: Armed mode comparison tables
  • Cross-Run: Metrics across all runs plotted over time

Signal Systems

System Config Value Description
Indicator Pair indicator_pair Two indicators with configurable sync windows. Supports any combination from the indicator library.
EMA 233 ema_233 EMA crossover on resampled higher-timeframe bars. Uses intrabar-cross detection for precise fills.
Armed Mode armed_mode First indicator arms the system; second fires and disarms. Prevents stacking signals from a single event.
Trigger Chain trigger_chain Sequential N-indicator trigger chain with ordered execution.

All signal systems share the same backtest engine, exit logic, and portfolio management. Switch between them via strategy.signal_system in config — no code changes needed.

Position Management

Position Sizing

  • fixed: Trade a fixed number of contracts per trade
  • percent_of_equity: Size each trade as a % of current portfolio value

Exit Rules

  1. Profit Target: Close when position reaches +X% gain
  2. Stop Loss: Close when position reaches -X% loss
  3. Opposite Signal: Close when opposite trading signal fires
  4. End-of-Day: Auto-close all positions at market close (if enabled)
  5. Expiration: Options automatically closed at expiration

Options Greeks

For options trades, the system calculates delta, theta, gamma, and vega. Realized P&L includes time decay for accurate options P&L.

Data Sources

Source Timeframe Instrument Format
Alpaca API 1min, 5min Equities OHLCV
TradingView 5min Equities OHLCV
Databento 1min (aggregated to 5min) Equities OHLCV
Databento API 1min Options OHLCV

CSV caching: All data is cached locally to avoid repeated API calls.

Performance Metrics

The backtest engine computes:

  • Win Rate (%): % of trades that finished with profit
  • Sharpe Ratio: Risk-adjusted return (annualized)
  • Probabilistic Sharpe Ratio: Corrects for sample size, skewness, and kurtosis
  • Deflated Sharpe Ratio: Multiple-testing-corrected PSR
  • Max Drawdown (%): Largest peak-to-trough decline
  • Profit Factor: Gross profit / gross loss
  • Average Win/Loss: Mean profit/loss per trade
  • Total P&L: Sum of all trade P&L
  • Total Return (%): Final equity / initial capital - 1

Monte Carlo Simulation

Bootstrap trade P&Ls to get a distribution of equity curve outcomes:

# Inline — runs automatically after the backtest
python main_runner/run_backtest_db.py START END --mc

# Post-hoc — run on any existing results folder
python main_runner/run_monte_carlo.py results/db/RUN_PATH/equities/5min
python main_runner/run_monte_carlo.py results/db/RUN_PATH/equities/5min --n 2000

Live Paper Trading

Two broker integrations for forward-testing:

Alpaca (via Databento data):

python live_runner/run_live_db.py

IBKR (via IB Gateway):

python live_runner/run_live_ibkr.py

Both use the same signal pipeline and exit logic as backtesting. Live bars and trades are automatically logged for later analysis.

Testing

pytest tests/                        # All tests (900+)
pytest tests/test_indicators.py -v   # Single test file
pytest --cov=src tests/              # With coverage

Contributing

To extend the system:

  1. New Indicators: Add to src/indicators/ and register in src/indicators/base.py
  2. New Signal Systems: Implement a concrete class in src/signals/strategy.py and register in _STRATEGY_MAP
  3. New Exit Rules: Update check_exit() in src/backtest/trade_logic.py
  4. New Metrics: Add to compute_metrics() in src/analysis/metrics.py

Always add tests in tests/ for new functionality.

License

This project is provided as-is for educational and research purposes.