Strategy Package Manual

This repository stores Backtrader strategy modules in the strategies/ package and runs them through run_backtest.py, run_all.bat, and build_dashboard.py.

Package Layout

backtrader_strategy_library/
  strategies/
    __init__.py
    <StrategyName>.py
    _catalog_talib_strategy.py
  run_backtest.py
  run_all.bat
  build_dashboard.py
  results/

strategies/ should contain strategy modules only. A strategy module should be import-safe: importing it must not download data, run Cerebro, create plots, write files, or start a backtest.

Strategy File Rules

Each runnable strategy file should expose at least one bt.Strategy subclass.

Preferred convention:

import backtrader as bt


class ExampleStrategy(bt.Strategy):
    params = (
        ("printlog", False),
    )

    def __init__(self):
        ...

    def next(self):
        ...

Rules:

Shared Generated Strategy Base

strategies/_catalog_talib_strategy.py contains the shared TA-Lib-backed base used by generated catalog strategies.

Files that subclass it normally look like:

from strategies._catalog_talib_strategy import CatalogTalibStrategy


class SomeCatalogStrategy(CatalogTalibStrategy):
    params = (
        ("profile", "trend"),
        ("stop_atr_mult", 2.0),
        ("allow_short", True),
        ("printlog", False),
    )

The leading underscore means it is a helper module and is skipped by run_backtest.py.

Running All Strategies

Use:

run_all.bat

Current batch defaults:

set ASSETS=BTC-USD
set PERIOD=1y
set INTERVAL=1d
set BENCHMARK=BTC-USD
set FAST=1
set /a WORKERS=%NUMBER_OF_PROCESSORS%-1

FAST=1 uses the fast worker pool path. It is much faster than fully isolated mode because it avoids launching a new Python process for every strategy.

Set FAST=0 if you need maximum isolation for debugging a bad or hanging strategy.

Fast Mode

Direct fast run:

python run_backtest.py --fast --workers 8 --symbol BTC-USD --period 1y --interval 1d --benchmark BTC-USD --strategies strategies --out results

Fast mode does this:

Fast mode tradeoff:

Equity Plots

Dashboard Equity Plots means the number of strategy folders containing:

equity_vs_benchmark.png

Fast mode skips these by default for speed.

To create plots in fast mode:

python run_backtest.py --fast --fast-plots --fast-equity --workers 8 --symbol BTC-USD --period 1y --interval 1d --benchmark BTC-USD --strategies strategies --out results

Add --fast-plots --fast-equity to the fast command in run_all.bat if you want full plot output every run.

Targeted Runs

Run only matching strategy files:

python run_backtest.py --fast --strategy-filter macd --workers 4 --symbol BTC-USD --period 1y --interval 1d --benchmark BTC-USD

Smoke test first N matching files:

python run_backtest.py --fast --limit 5 --workers 2 --symbol BTC-USD --period 6mo --interval 1d --benchmark BTC-USD

Force a fresh data download:

python run_backtest.py --fast --refresh-data --symbol BTC-USD --period 1y --interval 1d --benchmark BTC-USD

Results

For asset BTC-USD, outputs are under:

results/BTC-USD/

Important files:

results/BTC-USD/run.log
results/BTC-USD/run_progress.json
results/BTC-USD/run_summary.json
results/BTC-USD/all_metrics.csv
results/BTC-USD/skipped_strategies.csv
results/BTC-USD/dashboard.html
results/BTC-USD/<StrategyName>/metrics.csv

If plots are enabled:

results/BTC-USD/<StrategyName>/equity_vs_benchmark.png
results/BTC-USD/<StrategyName>/drawdown_vs_benchmark.png
results/BTC-USD/<StrategyName>/daily_returns_hist.png
results/BTC-USD/<StrategyName>/rolling_return_vs_benchmark.png
results/BTC-USD/<StrategyName>/equity.csv

Dashboard

Build dashboards after a run:

python build_dashboard.py --results results --mode assets

The asset dashboard is written to:

results/<ASSET>/dashboard.html

For BTC:

results/BTC-USD/dashboard.html

Metrics

Key metric columns:

Column Meaning
total_return_pct Strategy return over the test period.
benchmark_return_pct Benchmark return over the same dates.
asset_buy_hold_return_pct Buy-and-hold return for the tested asset.
excess_return_vs_benchmark_pct Strategy return minus benchmark return.
sharpe Annualized Sharpe based on equity curve returns.
max_drawdown_pct Maximum drawdown from the strategy equity curve.
total_trades Closed plus still-open trades reported by Backtrader.
closed_trades Trades that fully closed before the end of the backtest.
open_trades Trades still open at the final bar.
won / lost Closed winning/losing trades.
win_rate_pct Win rate based on closed trades only.

Important: a strategy can show non-zero return with closed_trades = 0 if it has open_trades > 0. That means it entered a position and held it through the end of the backtest. The final value includes mark-to-market value of that open position.

Adding A New Strategy

  1. Create strategies/NewStrategy.py.
  2. Define class NewStrategy(bt.Strategy).
  3. Keep the file import-safe.
  4. Avoid root-level yf.download, bt.Cerebro(), cerebro.run(), plotting, or optimization code.
  5. Run a smoke test:
python run_backtest.py --fast --strategy-filter NewStrategy --symbol BTC-USD --period 1y --interval 1d --benchmark BTC-USD
  1. Rebuild the dashboard:
python build_dashboard.py --results results --mode assets

Maintenance Checks

Compile all strategy files:

python -m compileall strategies

Find accidental main blocks:

rg "if __name__\\s*==" strategies

Find accidental import-time backtest code:

rg "^\\s*(cerebro\\.run\\(|yf\\.download\\(|plt\\.show\\(|cerebro\\.plot\\()" strategies

Strategy files should pass these checks cleanly.