← Item page
Mission Control / Link Triage Explainer

Backtesting.py

A mature Python framework for event-style backtesting of trading strategies on OHLC candlestick data. The useful thing here is not “a trading bot”; it is a compact research sandbox for testing rules, visualizing equity curves, and learning why naive strategies usually fail.

Source: kernc.github.io/backtesting.py Repo: kernc/backtesting.py Language: Python License: AGPL-3.0 Explainer written: 2026-06-01

Verdict for Ananth / Dab

Worth keeping as an explainer-ready research/tool link. Backtesting.py is a credible, well-used Python package for fast single-asset strategy experiments. It is best for learning, prototyping, and producing evidence cards; it is not a production trading stack, broker integration layer, portfolio optimizer, or guarantee that any strategy works live.

  • Best use: quick experiments like moving-average crossovers, breakout rules, risk sizing ideas, and parameter sweeps.
  • Mission Control fit: could power a future “strategy lab” artifact where Dab takes a hypothesis, runs a transparent historical test, and outputs charts + caveats.
  • Main caution: backtests are easy to overfit. Treat every result as a falsification aid, not a buy/sell recommendation.

What it does

Backtesting.py lets you define a strategy class with two key methods:

  • init(): declare indicators, e.g. moving averages, RSI, features from TA-Lib/pandas/numpy.
  • next(): receive each new bar and decide whether to buy, sell, close, or hold.

Then Backtest(...).run() simulates orders over historical OHLCV data and returns a metrics object: return, annualized return, volatility, Sharpe/Sortino/Calmar, drawdowns, win rate, trade list, equity curve, and more. bt.plot() creates an interactive visualization.

What it is not

  • Not a live trading/execution system.
  • Not a multi-asset institutional portfolio simulator by default.
  • Not a source of market data; you bring data frames with the right columns.
  • Not a magic anti-overfitting layer; parameter optimization can make false confidence worse if used casually.
  • AGPL-licensed, so embedding it in distributed/proprietary services needs license care.

Core workflow map

1. Prepare candles
Pandas DataFrame with Open, High, Low, Close, optionally Volume. Any instrument works if it can be represented as candles.
2. Write Strategy subclass
Declare indicators in init(); implement bar-by-bar trade logic in next().
3. Run Backtest
Configure cash, commission, exclusivity/hedging behavior, margin assumptions, and order rules.
4. Inspect evidence
Stats, trades table, equity curve, drawdown periods, parameter sensitivity, and plots.

Source map

PathRole
backtesting/backtesting.pyMain engine: Backtest, Strategy, broker/order/trade/position primitives.
backtesting/lib.pyHelpers: crossover/cross, resampling aggregation, heatmaps, composable strategy utilities.
backtesting/_stats.pyPerformance metric calculation.
backtesting/_plotting.pyInteractive Bokeh plotting and visual output.
doc/examples/Quick start, multiple time frames, optimization and heatmap examples.

Minimal use pattern

from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from backtesting.test import SMA, GOOG

class SmaCross(Strategy):
    def init(self):
        price = self.data.Close
        self.ma1 = self.I(SMA, price, 10)
        self.ma2 = self.I(SMA, price, 20)

    def next(self):
        if crossover(self.ma1, self.ma2):
            self.buy()
        elif crossover(self.ma2, self.ma1):
            self.sell()

bt = Backtest(GOOG, SmaCross, commission=.002, exclusive_orders=True)
stats = bt.run()
bt.plot()

Interesting capabilities

  • Indicator-agnostic: indicators can come from plain functions, NumPy, pandas, TA-Lib, Tulipy, or custom feature code.
  • Built-in optimization: strategy parameters can be swept and visualized; the docs include parameter heatmap examples.
  • Interactive plots: useful for quickly seeing if a strategy only wins during one market regime.
  • Composable utilities: helpers for crossovers, resampling, multi-timeframe workflows, and heatmaps reduce boilerplate.
  • Fast enough for iteration: intended for quick local research rather than huge distributed simulations.

Risk and quality notes

  • Maturity: high adoption, clear docs, CI badges, PyPI package, and active repository history.
  • Model risk: strategy results depend heavily on data cleanliness, execution assumptions, commissions, slippage, survivorship bias, and look-ahead bias.
  • Optimization risk: heatmaps are helpful, but repeated parameter search can overfit historical noise.
  • License: AGPL-3.0 is fine for local experiments, but check obligations before wrapping it in a networked/commercial service.

How Dab could use it

  1. Hypothesis testing: convert a plain-language trading idea into a Strategy class and run it against a known dataset.
  2. Evidence artifact: generate a small HTML report: hypothesis, assumptions, chart, metrics, drawdown periods, trade table excerpts, and reasons not to trust it yet.
  3. Learning lane: use it to teach backtesting concepts: leakage, regime dependence, transaction costs, position sizing, and why Sharpe is fragile.
  4. Podcast/research feed: if a market idea appears in Daily Podcast Creator or Link Triage, Dab can backtest a toy version and include caveats.

Consumption path

  1. Skim the project homepage.
  2. Read the Quick Start example.
  3. Run the SMA crossover example locally.
  4. Then inspect parameter heatmaps and multiple-timeframe examples.

If this becomes a Mission Control project

A sensible first build would be a local-only Strategy Lab: input a ticker/data CSV + plain-English rule, let Claude/Dab draft a Strategy class, run Backtesting.py, and write a static report under Mission Control. Acceptance criteria should require explicit assumptions, no live trading, no financial advice language, and visible warnings about overfitting.