VectorBT Strategy Library

A collection of 100 auto-discovered VectorBT strategy optimizers, plus a runner that downloads Yahoo Finance data, evaluates every strategy, saves the results, and generates comparison charts. A separate script turns a completed result folder into an HTML dashboard.

Research software, not investment advice. The optimizer selects parameters on the same data used to report performance. Treat all results as in-sample research until they have survived out-of-sample testing, walk-forward validation, and realistic execution assumptions.

Contents

What this project does

For one asset and one requested history window, backtest_all_strategies.py:

  1. Downloads OHLCV data with yfinance.
  2. Normalizes it to Open, High, Low, Close, and Volume columns.
  3. Discovers every Python module in vectorbt_strategies/, except the explicitly excluded core modules.
  4. Calls each module's optimize_strategy(data, optimize_for="total_return_pct") function.
  5. Keeps the best parameter combination reported by that strategy.
  6. Records performance statistics and catches per-strategy failures.
  7. Creates an equity chart comparing each successful optimized strategy with buy-and-hold.
  8. Writes a ranked summary.csv and detailed per-strategy CSV files.

generate_results_dashboard.py then reads that result folder and creates dashboard.html.

The default initial capital is $100,000, defined by DEFAULT_INIT_CASH in vectorbt_strategies/strategy_opt_utils.py.

Project layout

VectorBT_Strategy_Library/
|-- README.md                         This manual
|-- backtest_all_strategies.py        Download data and run every strategy
|-- generate_results_dashboard.py     Build dashboard.html from a result folder
|-- run_batch_backtests.bat           Run all strategies for 42 preset symbols
|-- run_batch_dashboards.bat          Build dashboards for the preset symbols
|-- vectorbt_strategies/
|   |-- __init__.py
|   |-- strategy_opt_utils.py         Shared data, indicator, ranking, and result helpers
|   `-- *_opt.py                      Auto-discovered strategy modules
`-- sample_results/                   Previously generated example output

The runner writes new result folders relative to the current working directory, not necessarily beside the script. Run commands from the project root unless you deliberately want output elsewhere.

Installation

Python 3.11 in an isolated virtual environment is recommended. The package does not currently include pinned dependencies, so recording the installed versions is important for reproducible research.

Extract or clone the package, open a terminal in its parent directory, and change into the package directory:

VectorBT_Strategy_Library/

On Windows PowerShell:

cd VectorBT_Strategy_Library
py -3.11 -m venv .venv
& .\.venv\Scripts\Activate.ps1

python -m pip install --upgrade pip
python -m pip install numpy pandas vectorbt yfinance matplotlib plotly scikit-learn tqdm hurst TA-Lib

On macOS or Linux:

cd VectorBT_Strategy_Library
python3.11 -m venv .venv
source .venv/bin/activate

python -m pip install --upgrade pip
python -m pip install numpy pandas vectorbt yfinance matplotlib plotly scikit-learn tqdm hurst TA-Lib

If PowerShell blocks activation, either adjust its execution policy for your user or use the virtual-environment interpreter directly:

.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install numpy pandas vectorbt yfinance matplotlib plotly scikit-learn tqdm hurst TA-Lib

Dependencies and why they are needed

Package Used for
numpy Numeric arrays and calculations
pandas OHLCV tables, metrics, and CSV files
vectorbt Portfolio simulation and several indicators
yfinance Yahoo Finance downloads
matplotlib Static equity-curve PNGs
plotly Dashboard charts
TA-Lib Indicators used by several strategy modules
scikit-learn GMM and decision-tree strategies
hurst Hurst-regime strategy
tqdm Progress display in the regime-switching strategy

There is currently no requirements.txt or lock file, so a fresh install may not reproduce an older run exactly. Record package versions for any serious experiment:

python -m pip freeze > environment-used.txt

Verify the environment

python -c "import numpy, pandas, vectorbt, yfinance, matplotlib, plotly, sklearn, tqdm, hurst, talib; print('All imports succeeded')"
python backtest_all_strategies.py --help
python generate_results_dashboard.py --help

VectorBT can take a while to import on the first invocation because Numba may initialize or compile components.

Five-minute quick start

On Windows PowerShell, from the extracted or cloned package directory:

& .\.venv\Scripts\Activate.ps1

python backtest_all_strategies.py --symbol SPY --period 1y --interval 1d
python generate_results_dashboard.py --symbol SPY --period 1y
Start-Process ".\SPY-1y\dashboard.html"

On macOS or Linux:

source .venv/bin/activate

python backtest_all_strategies.py --symbol SPY --period 1y --interval 1d
python generate_results_dashboard.py --symbol SPY --period 1y
python -m webbrowser -t "SPY-1y/dashboard.html"

The first command can be computationally expensive: it runs every discovered strategy and every parameter combination defined inside each strategy.

Defaults

This is valid:

python backtest_all_strategies.py

It is equivalent to:

python backtest_all_strategies.py --symbol BTC-USD --period 1y --interval 1d

Dashboard arguments have no defaults, so both are required:

python generate_results_dashboard.py --symbol BTC-USD --period 1y

Command reference

backtest_all_strategies.py

python backtest_all_strategies.py [--symbol SYMBOL] [--period PERIOD] [--interval INTERVAL]
Option Default Meaning
--symbol BTC-USD One Yahoo Finance ticker
--period 1y History window passed to yfinance.download
--interval 1d Bar interval passed to yfinance.download

Examples:

# US stock
python backtest_all_strategies.py --symbol AAPL --period 5y --interval 1d

# Cryptocurrency
python backtest_all_strategies.py --symbol ETH-USD --period 2y --interval 1d

# Gold futures; quote symbols containing '=' in PowerShell
python backtest_all_strategies.py --symbol "GC=F" --period 1y --interval 1d

# EUR/USD
python backtest_all_strategies.py --symbol "EURUSD=X" --period 1y --interval 1d

The runner always asks strategies to optimize for total_return_pct. There is no command-line option to change the objective or select a subset of strategies.

generate_results_dashboard.py

python generate_results_dashboard.py --symbol SYMBOL --period PERIOD

It does not download data or run strategies. It requires an existing result folder and at least its summary.csv.

python generate_results_dashboard.py --symbol QQQ --period 1y
Start-Process ".\QQQ-1y\dashboard.html"

The dashboard command has no --interval argument. A result folder is identified only by symbol and period, so two runs with the same symbol and period but different intervals target the same folder and overwrite each other.

Yahoo Finance symbols, periods, and intervals

The downloader passes --symbol, --period, and --interval directly to yfinance. Common examples include:

Asset Example symbol
US equity or ETF AAPL, SPY, QQQ
Cryptocurrency BTC-USD, ETH-USD
FX EURUSD=X, GBPUSD=X, JPY=X
Futures GC=F, CL=F, BZ=F

Common period values include 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, and max. Common intervals include 1m, 5m, 15m, 30m, 60m, 1d, 1wk, and 1mo. Yahoo may limit how far back intraday intervals can be requested, and availability varies by symbol.

This runner does not support explicit start/end dates, multiple symbols in one invocation, retries, or a local download cache.

Output-folder sanitization

The backtest runner replaces characters outside A-Z, a-z, digits, _, ., and - with _. For example:

Yahoo symbol Backtest output folder
SPY SPY-1y
BTC-USD BTC-USD-1y
EURUSD=X EURUSD_X-1y
GC=F GC_F-1y

The dashboard generator does not apply the same sanitization. Until that inconsistency is fixed, use the sanitized symbol when generating a dashboard for a ticker containing =:

python backtest_all_strategies.py --symbol "GC=F" --period 1y --interval 1d
python generate_results_dashboard.py --symbol GC_F --period 1y
Start-Process ".\GC_F-1y\dashboard.html"

The dashboard title will display GC_F, but it will read the correct folder. The supplied dashboard batch file does not apply this workaround and will fail for its FX and futures tickers containing =.

Understanding the output

A successful SPY run creates:

SPY-1y/
|-- data.csv
|-- buy_and_hold_equity.csv
|-- summary.csv
|-- failures.csv
|-- <strategy>_equity_vs_buy_hold.png
|-- ...
|-- per_strategy_results/
|   |-- <strategy>_optimization_results.csv
|   `-- ...
`-- dashboard.html                    Only after dashboard generation

data.csv

The downloaded and normalized market data. It contains:

Rows with a missing close are removed. Missing OHLC values are filled from close or prior close, and missing volume is filled with zero.

yfinance is called with auto_adjust=False, and the runner uses Close, not Adj Close. Equity results therefore do not directly include dividend distributions and may be distorted by corporate actions depending on the data returned.

buy_and_hold_equity.csv

A simple benchmark starting at $100,000:

benchmark equity = 100000 * current close / first close

It does not model fees, slippage, dividend cash flows, taxes, or position constraints.

summary.csv

One row per successfully completed strategy, sorted by optimized total return from highest to lowest. Principal columns are:

Column Meaning
strategy Strategy/module name
plot Saved equity PNG path
init_cash Initial portfolio cash; currently 100000
best_* Best parameter key(s) reported by the optimizer
total_return_pct Optimized strategy return in percent
benchmark_return_pct Buy-and-hold return over the same close series
sharpe VectorBT Sharpe ratio
rank_score Strategy-provided rank score when available
max_drawdown_pct Maximum drawdown magnitude in percent
total_trades Number of completed/recorded trades
end_value Final portfolio value

Dynamic parameter fields vary by strategy. With the shared compatibility wrapper, parameter combinations may appear as best_key, best_best_key, or a tuple-like string in params.

failures.csv

One row per failed strategy:

Column Meaning
strategy Strategy that failed
error Exception message

A strategy failure does not normally stop the remaining strategies. Check this file after every run, including when the dashboard looks healthy.

per_strategy_results/<strategy>_optimization_results.csv

The detail returned by that optimizer. Depending on the strategy implementation, it may contain:

Common metric fields include total_return_pct, benchmark_return_pct, sharpe, sortino, calmar, max_drawdown_pct, total_trades, win_rate_pct, profit_factor, and end_value. The runner also appends init_cash and its own buy-and-hold return.

Do not assume every CSV has an identical schema; inspect columns before combining files.

Equity PNGs

Each successful strategy gets a static plot comparing:

Only the winning parameter combination is plotted.

The HTML dashboard

The dashboard contains:

The ranked table includes all successful strategies; the image gallery is limited to the first 24 rows of summary.csv.

The generated HTML loads Plotly JavaScript from a CDN. The static PNG gallery remains local, but interactive charts may require internet access when the page is opened.

Generate a dashboard from sample_results

Dashboards already exist in many sample folders. To regenerate one, make sample_results the working directory while invoking the script from its parent:

cd sample_results
python ..\generate_results_dashboard.py --symbol SPY --period 1y
Start-Process ".\SPY-1y\dashboard.html"

The included samples are historical artifacts and do not cover all 100 modules currently present. They should not be treated as proof that the current code and dependency versions will reproduce those exact values.

Batch processing

The supplied batch launchers are Windows .bat files. The underlying Python scripts work on Windows, macOS, and Linux, but customers on macOS or Linux must run the Python commands directly or create an equivalent shell loop.

Preset backtest batch

From Command Prompt, after changing into the package directory:

run_batch_backtests.bat

From PowerShell, after changing into the package directory:

cmd /c run_batch_backtests.bat

The batch currently uses period=1y, interval=1d, and these 42 symbols:

SPY QQQ DIA IWM EEM EFA
AAPL MSFT NVDA TSLA AMZN META
BTC-USD ETH-USD SOL-USD BNB-USD XRP-USD ADA-USD
EURUSD=X GBPUSD=X JPY=X CHF=X AUDUSD=X CAD=X
GC=F SI=F CL=F BZ=F NG=F HG=F
TLT IEF SHY HYG LQD AGG
VIXY GLD SLV VNQ XLU XLF

With 100 current strategies, that schedules up to 4,200 strategy executions, each of which may test many parameter combinations. Plan for substantial CPU time, memory use, disk output, and Yahoo requests.

Edit the period, interval, and symbol list near the top of run_batch_backtests.bat to change the batch.

Preset dashboard batch

After the backtests finish:

cmd /c run_batch_dashboards.bat

Known issue: entries containing = do not match the sanitized backtest directory names. Generate those dashboards manually with sanitized names, for example EURUSD_X and GC_F, or update the batch file.

Both batch files end with pause and are designed for interactive Windows use.

Running one strategy

There is no single-strategy CLI option. Use the Python API:

from backtest_all_strategies import download_ohlcv
from vectorbt_strategies.rsi_mean_reversion_opt import optimize_strategy

data = download_ohlcv("SPY", period="1y", interval="1d")
result = optimize_strategy(data, optimize_for="total_return_pct")

print("Strategy:", result.name)
print("Best parameters:", result.best_params)
print(result.results.head())
print(result.best_portfolio.stats())

result.results.to_csv("rsi_mean_reversion_SPY_results.csv", index=False)

Save this as a script in the project root and run it with the same environment. Importing a strategy file does not download data; data is passed explicitly to optimize_strategy.

The shared compatibility utility recognizes total_return_pct and sharpe as optimization metrics. Individual legacy strategies may have additional internal ranking behavior, so inspect the target module when changing the objective.

Using your own OHLCV data

The all-strategies runner only downloads from Yahoo Finance. To use a CSV, call strategy modules directly:

import pandas as pd

from vectorbt_strategies.macd_trend_opt import optimize_strategy

data = pd.read_csv(
    "my_ohlcv.csv",
    index_col=0,
    parse_dates=True,
)
data = data.sort_index()

result = optimize_strategy(data, optimize_for="total_return_pct")
print(result.best_params)
print(result.best_portfolio.stats())

Input expectations:

The normalizer title-cases column names. It can synthesize missing open/high/low data from close and missing volume as zero, but doing so changes strategy meaning. Volume-based strategies may produce no useful signals if volume is absent.

For reliable risk metrics, ensure VectorBT knows the real bar frequency. Many current modules explicitly use a daily frequency, which must be corrected in code before trusting results on non-daily data.

Changing settings

Initial cash

Edit:

# vectorbt_strategies/strategy_opt_utils.py
DEFAULT_INIT_CASH = 100_000

Strategies import this value. Search for hard-coded init_cash values before assuming every module honors a change:

rg -n "init_cash" .\vectorbt_strategies

Fees and slippage

Fees and slippage are set inside individual strategy modules, commonly around:

fees=0.001
slippage=0.0005

They are not global command-line settings and are not perfectly uniform across the library. To compare strategies fairly, audit and standardize every vbt.Portfolio.from_signals(...) call:

rg -n "fees=|slippage=" .\vectorbt_strategies

VectorBT normally interprets these values as fractions, so 0.001 represents 0.1% per transaction side and 0.0005 represents 0.05%, subject to the exact portfolio call.

Parameter grids

Parameter ranges are defined inside each strategy's optimize_strategy function. For example, open the relevant *_opt.py file and change its lists such as windows, thresholds, stop levels, or take-profit values.

The number of combinations is usually the product of all grid lengths. Wider grids can increase memory and runtime dramatically, especially where signals are materialized as one DataFrame column per combination.

Optimization objective

The main runner currently hard-codes:

module.optimize_strategy(data, optimize_for="total_return_pct")

Change that call to sharpe only after reviewing all strategy implementations and ensuring frequency information is correct. Optimization by total return tends to favor concentrated or high-risk outcomes; optimization by Sharpe depends strongly on correct annualization.

Run only a subset

No CLI filter exists. Practical options are:

  1. Use the single-strategy Python API shown above.
  2. Temporarily move unwanted *_opt.py modules outside vectorbt_strategies/.
  3. Add an include/exclude option to discover_strategy_modules().

Do not rename helper files to ordinary .py names inside the strategy directory unless they also implement optimize_strategy; the discovery code imports every non-core .py file and later tries to call that function.

Adding a strategy

Create a uniquely named file under vectorbt_strategies/, normally ending in _opt.py. Use this minimal interface:

"""Example auto-discovered strategy optimizer."""

STRATEGY_NAME = "my_strategy_opt"


def optimize_strategy(data, optimize_for="total_return_pct"):
    import pandas as pd
    import vectorbt as vbt

    from .strategy_opt_utils import (
        DEFAULT_INIT_CASH,
        finish_optimization_result,
        normalize_ohlcv,
    )

    data = normalize_ohlcv(data)
    close = data["Close"]

    windows = [10, 20, 50]
    entries = {}
    exits = {}

    for window in windows:
        ma = close.rolling(window).mean()
        entries[(window,)] = (close > ma) & (close.shift(1) <= ma.shift(1))
        exits[(window,)] = (close < ma) & (close.shift(1) >= ma.shift(1))

    entries = pd.DataFrame(entries)
    exits = pd.DataFrame(exits)

    pf = vbt.Portfolio.from_signals(
        close,
        entries=entries,
        exits=exits,
        init_cash=DEFAULT_INIT_CASH,
        fees=0.001,
        slippage=0.0005,
        freq="1D",
    )

    return finish_optimization_result(
        STRATEGY_NAME,
        locals(),
        optimize_for=optimize_for,
    )

Contract requirements:

Prefer strategy-specific optional imports inside optimize_strategy. A top-level import failure occurs during discovery and can abort the entire suite before per-strategy error handling begins.

Test a new strategy directly before running the full suite. Confirm signals do not use future data, parameter columns align with price data, at least one trade occurs, and fees/slippage/frequency are explicit.

Strategy catalog

The current library contains these 100 auto-discovered strategy modules. The _opt suffix indicates that the module searches a parameter grid or otherwise selects a best configuration.

adaptive_ema_volatility_opt
adaptive_momentum_squeeze_opt
adaptive_vortex_trend_opt
adx_range_trend_filter_opt
anchored_vwap_trend_opt
aroon_trend_opt
atr_channel_reversion_opt
atr_percentile_trend_opt
autocorrelation_momentum_opt
awesome_oscillator_divergence_opt
body_range_strength_opt
bollinger_bandwidth_expansion_opt
bollinger_regime_adaptive_opt
bollinger_squeeze_breakout_opt
cci_trend_pullback_opt
chaikin_money_flow_trend_opt
chandelier_exit_breakout_opt
coppock_curve_opt
decision_tree_ema_ml_opt
dema_macd_trend_opt
donchian_breakout_opt
donchian_midline_reversion_opt
drawdown_recovery_opt
elder_ray_trend_opt
ema_adx_cross_opt
ema_atr_adx_opt
ema_cross_bb_width_filter_opt
ema_cross_resistance_breakouts_opt
ema_cross_with_sizing_and_stop_opt
ema_ppo_volume_trend_opt
ema_stop_target_grid_opt
entropy_volatility_regime_opt
fisher_transform_reversal_opt
force_index_momentum_opt
fractal_breakout_opt
gap_reversal_opt
gmm_regime_filter_opt
hammer_candle_reversal_opt
heikin_ashi_trend_opt
hilbert_bollinger_stop_target_opt
hma_trend_following_opt
hurst_regime_ema_cross_opt
ichimoku_cloud_opt
inside_bar_breakout_opt
intraday_volatility_breakout_opt
kama_trend_pullback_opt
keltner_breakout_trend_opt
keltner_mean_reversion_opt
kst_momentum_opt
linear_regression_slope_opt
ma_envelope_reversion_opt
macd_histogram_reversal_opt
macd_trend_opt
median_breakout_filter_opt
mfi_volume_reversion_opt
micro_pullback_breakout_opt
momentum_atr_trailing_stop_opt
moving_average_crossover_grid_opt
moving_average_slope_stop_opt
n_day_high_low_stop_opt
obv_momentum_stop_target_opt
open_close_momentum_opt
outside_bar_reversal_opt
percentile_channel_breakout_opt
pivot_range_breakout_opt
pivot_stochastic_atr_opt
ppo_signal_cross_opt
price_efficiency_ratio_opt
price_volume_surge_opt
quantile_mean_reversion_opt
range_expansion_close_opt
realized_volatility_breakout_opt
regime_switching_trend_opt
return_percentile_momentum_opt
roc_acceleration_opt
rolling_skew_reversion_opt
rsi_bollinger_reversion_opt
rsi_mean_reversion_opt
rsi_trend_confirmation_opt
stochastic_rsi_reversal_opt
stochastic_trend_opt
supertrend_atr_opt
tema_crossover_atr_stop_opt
trend_momentum_volume_rsi_opt
trend_strength_volatility_breakout_opt
trend_volatility_breakout_opt
triple_ema_sl_tp_opt
tsi_momentum_opt
ulcer_index_recovery_opt
ultimate_oscillator_trend_opt
vol_cluster_reversion_opt
volatility_contraction_expansion_opt
volatility_cooling_atr_opt
volatility_scaled_breakout_opt
volume_dryup_breakout_opt
volume_price_trend_opt
vortex_cross_trend_opt
vwap_deviation_reversion_opt
williams_r_breakout_opt
zscore_mean_reversion_opt

The strategy filename is the authoritative place to inspect exact indicators, entry/exit logic, position direction, sizing, stops, costs, frequency, and parameter ranges. These details are not normalized across the collection.

Known limitations and important warnings

Existing result folders are deleted

Before a run starts, the runner recursively deletes an existing folder with the same sanitized SYMBOL-PERIOD name:

SPY + 1y -> SPY-1y

This happens without confirmation. Back up valuable results or use a separate working directory before rerunning. The interval is not part of the folder name.

Optimization is in-sample

Parameter selection and reported performance use the same downloaded period. There is no train/test split, cross-validation, walk-forward analysis, multiple-testing correction, or holdout evaluation in the main runner. The winning return is therefore biased upward as an estimate of future performance.

Strategy assumptions differ

The modules are not a single standardized experimental framework. They vary in:

Ranking unlike strategies by total return is convenient, but not automatically an apples-to-apples comparison.

--interval is not propagated consistently

The CLI interval controls the Yahoo download only. Many strategies pass freq="1d" or freq="1D" directly to VectorBT. Consequently, annualized Sharpe/Sortino/Calmar metrics—and sometimes time-based behavior—can be wrong for intraday, weekly, or monthly runs. Audit and parameterize every strategy's freq before trusting non-daily results.

Raw close is used

The downloader specifies auto_adjust=False and keeps Close. The benchmark and strategies do not explicitly account for dividends. Corporate actions, roll behavior in futures, and data-provider revisions can materially affect conclusions.

Results are not execution-ready

The system does not model order-book depth, spread variation, partial fills, borrow availability/cost, funding, taxes, market impact, exchange outages, delistings, or live-order latency. Some strategies do include fixed fees/slippage, but assumptions vary.

No caching, resume, or run manifest

Each run downloads data again. There is no checkpoint/resume system, random-seed manifest, code revision field, dependency snapshot, or configuration file saved automatically. An interrupted process can leave a partial output directory.

Sample results are not current validation

The sample_results folders were generated by an earlier state of the project. They include fewer successful strategies than the current 100-module catalog. Across the included failure logs, adx_range_trend_filter_opt and moving_average_crossover_grid_opt repeatedly reported missing index-frequency errors. Current behavior should be established with a fresh, version-recorded run.

Troubleshooting

ModuleNotFoundError

Install the named dependency into the same interpreter that runs the scripts:

python -m pip install PACKAGE_NAME
python -c "import sys; print(sys.executable)"

Common mappings:

Import error Install command
No module named 'vectorbt' python -m pip install vectorbt
No module named 'yfinance' python -m pip install yfinance
No module named 'talib' python -m pip install TA-Lib
No module named 'sklearn' python -m pip install scikit-learn
No module named 'hurst' python -m pip install hurst
No module named 'tqdm' python -m pip install tqdm

If TA-Lib installation fails, confirm you are using a supported Python/Windows architecture and an up-to-date pip. A strategy needing an unavailable optional package will normally be listed in failures.csv because most strategy-specific imports occur inside optimize_strategy.

No data returned for SYMBOL

Check:

Try a simple daily request first:

python backtest_all_strategies.py --symbol SPY --period 1y --interval 1d

Missing <folder>\summary.csv

The dashboard was run before a successful backtest, from the wrong working directory, or with a symbol spelling that does not match the output folder. Change to the directory that contains the result folder and retry.

For = symbols, use the sanitized dashboard argument:

python generate_results_dashboard.py --symbol EURUSD_X --period 1y

Index frequency is None

VectorBT cannot infer annualization from the index. This is a known failure in some included sample runs. Ensure the data has a sorted DatetimeIndex, then pass the real frequency explicitly to vbt.Portfolio.from_signals, for example freq="1D" for daily bars. Do not use 1D for intraday data.

The process appears frozen

Some parameter grids are large and VectorBT/Numba may compile code on first use. Watch CPU and memory, and wait for the next Backtesting ... console message. Test a single strategy with a smaller grid before launching the 42-symbol batch.

Out-of-memory errors

Reduce parameter-list sizes inside the failing strategy, shorten the data period, use a coarser interval, and run one strategy at a time. Vectorized grids can allocate full time-series arrays for every parameter combination.

A strategy shows no trades or NaN metrics

Possible causes include:

Inspect the strategy's detail CSV and failures.csv; then test the module directly with a longer history.

The dashboard opens without interactive charts

The generated page loads Plotly from https://cdn.plot.ly. Check internet access, browser content restrictions, and the developer console. The local PNG gallery should still display if the image files remain beside dashboard.html.

Batch files use the wrong Python

The batch scripts call python, which may resolve outside your virtual environment. Activate the environment before running the batch, or edit both .bat files to call:

.venv\Scripts\python.exe

Cloud-synced or network-folder problems

Large batches create many CSV and PNG files while repeatedly deleting and recreating result folders. If file locking or performance becomes a problem, run the package from a local working directory and copy only completed results to the shared or synchronized location.

Reproducible research checklist

Before treating a result as evidence:

  1. Save the exact downloaded data.csv.
  2. Save python -m pip freeze output.
  3. Record Python version, command, symbol, period, interval, and run timestamp.
  4. Preserve the source-code revision and parameter grids.
  5. Review failures.csv.
  6. Standardize fees, slippage, sizing, direction, and frequency across compared strategies.
  7. Separate training/optimization data from test data.
  8. Use walk-forward or rolling out-of-sample evaluation.
  9. Compare against a correctly adjusted benchmark.
  10. Stress-test parameters and costs instead of trusting a single optimum.
  11. Validate fills and constraints in a more realistic execution model.
  12. Paper-trade before considering live deployment.

Typical workflow summary

& .\.venv\Scripts\Activate.ps1

# 1. Run all 100 strategies for one symbol
python backtest_all_strategies.py --symbol SPY --period 1y --interval 1d

# 2. Always inspect failures
Import-Csv .\SPY-1y\failures.csv | Format-Table -AutoSize

# 3. Inspect the ranking
Import-Csv .\SPY-1y\summary.csv |
    Select-Object -First 10 strategy,total_return_pct,benchmark_return_pct,sharpe,max_drawdown_pct,total_trades |
    Format-Table -AutoSize

# 4. Build and open the dashboard
python generate_results_dashboard.py --symbol SPY --period 1y
Start-Process .\SPY-1y\dashboard.html

# 5. Preserve the environment for reproducibility
python -m pip freeze > .\SPY-1y\environment-used.txt