The Problem

Quant developers need a deterministic, pure‑Python backtesting engine that can be scripted, extended, and run offline without a heavyweight broker SDK. They also want a single library that supplies data adapters, order simulation, and a suite of performance analyzers.

What This Does

backtrader supplies a full backtesting and live‑trading framework. Core objects live in backtrader/:

  • cerebro.py – the orchestrator (Cerebro class) that registers strategies, data feeds, brokers, and runs the simulation.
  • btrun/btrun.py – the low‑level engine that steps through the market calendar, calls strategy hooks, and drives the order‑matching logic.
  • feeds/ – adapters for CSV, Yahoo, Quandl, Oanda, etc. (YahooFinanceData, GenericCSVData, …).
  • brokers/ – simulated broker implementations (bbroker.py, ibbroker.py, …).
  • analyzers/ – ready‑made performance metrics (Sharpe, DrawDown, SQN, …).

The library is pure Python (345 source files) and ships with 96 test modules and a Travis CI config (.travis.yml).

How It Is Wired

Execution begins in user code that imports the package (import backtrader as bt). The typical entry point is the Cerebro class in backtrader/cerebro.py:

  1. Instantiation – cerebro = bt.Cerebro() creates a Cerebro object, initializing internal containers for strategies, data feeds, broker, and analyzers.
  2. Registration – Calls such as cerebro.addstrategy(MyStrat), cerebro.adddata(feed), and cerebro.addanalyzer(bt.analyzers.Sharpe) store class objects in the Cerebro instance.
  3. Run – cerebro.run() delegates to Cerebro._run(), which builds a BTRun object from backtrader/btrun/btrun.py.
  4. Engine Loop – BTRun.run() creates a Strategy instance, attaches the selected broker (backtrader/brokers/bbroker.py by default), and steps through the market data series. Each tick triggers Strategy.next(), order creation, and broker order matching.
  5. Data Flow – Data feeds are subclasses of backtrader.feed.DataBase defined in feeds/. They expose a next() method that pushes OHLCV values into the engine’s DataBase objects.
  6. Broker Interaction – When a strategy issues an order, bbroker.py validates it, applies slippage/commission (commissions/), and updates the portfolio cash/position.
  7. Analysis – After the loop finishes, Cerebro iterates over registered analyzers (analyzers/*.py), each receiving the final Strategy and Broker state to compute metrics.

The only external side‑effects are optional live‑feed modules (e.g., ibbroker.py for Interactive Brokers) that open network sockets; the core simulation stays file‑ and memory‑bound. The call graph is shallow: user → Cerebro → BTRun → Strategy / Broker → Analyzer. No circular imports are present, making the core easy to isolate for unit testing.

How To Use It

# Clone and install in editable mode
git clone https://github.com/moses-y/backtrader
cd backtrader
pip install -e .   # reads setup.py for dependencies

No additional configuration files are required for the basic backtest. Example from the README:

from datetime import datetime
import backtrader as bt

class SmaCross(bt.SignalStrategy):
    def __init__(self):
        sma1 = bt.ind.SMA(period=10)
        sma2 = bt.ind.SMA(period=30)
        self.signal_add(bt.SIGNAL_LONG, bt.ind.CrossOver(sma1, sma2))

cerebro = bt.Cerebro()
cerebro.addstrategy(SmaCross)

data = bt.feeds.YahooFinanceData(
    dataname='MSFT',
    fromdate=datetime(2011, 1, 1),
    todate=datetime(2012, 12, 31)
)
cerebro.adddata(data)

cerebro.run()
cerebro.plot()

Save the script (e.g., run_sma.py) and execute python run_sma.py. For live trading, swap the data feed and broker classes with IBData/IBBroker or Oanda equivalents and supply API credentials as per each module’s docstring.

Real‑World Use

A quant team can embed the library in a CI pipeline to validate new strategy code nightly. The pipeline would:

  1. Pull the repository, install with pip install -e ..
  2. Run pytest -q (tests are under tests/).
  3. Execute a headless backtest script that writes performance CSVs to an artifacts bucket.

The output can be consumed by downstream reporting tools or fed into pyfolio (deprecated) for deeper risk analysis.

Code Health & Issues

  • Low – No failing tests – 96 test files are present; CI status is tracked by .travis.yml.
  • Low – License present – LICENSE file included, no ambiguity.
  • Low – Documentation limited – Only three doc files (README.rst, docstrings, and a small doc/ folder); API reference is external to the repo.
  • Low – No explicit type hints – The codebase is Python 2/3 compatible but lacks modern typing, which may increase refactor risk.

No structural red flags detected; the repository contains expected CI, licensing, and lockfiles.

The Bottom Line

backtrader offers a mature, well‑tested Python backtesting engine with a clear separation between strategy logic, data feeds, and broker simulation. It is suitable for teams that need a pure‑Python solution and are comfortable extending the library for custom data sources or live‑trading integrations. The lack of built‑in type hints and limited in‑repo documentation suggest a modest onboarding cost, but the extensive test suite and stable API mitigate long‑term maintenance risk.