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 (Cerebroclass) 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:
- Instantiation –
cerebro = bt.Cerebro()creates aCerebroobject, initializing internal containers for strategies, data feeds, broker, and analyzers. - Registration – Calls such as
cerebro.addstrategy(MyStrat),cerebro.adddata(feed), andcerebro.addanalyzer(bt.analyzers.Sharpe)store class objects in theCerebroinstance. - Run –
cerebro.run()delegates toCerebro._run(), which builds aBTRunobject frombacktrader/btrun/btrun.py. - Engine Loop –
BTRun.run()creates aStrategyinstance, attaches the selected broker (backtrader/brokers/bbroker.pyby default), and steps through the market data series. Each tick triggersStrategy.next(), order creation, and broker order matching. - Data Flow – Data feeds are subclasses of
backtrader.feed.DataBasedefined infeeds/. They expose anext()method that pushes OHLCV values into the engine’sDataBaseobjects. - Broker Interaction – When a strategy issues an order,
bbroker.pyvalidates it, applies slippage/commission (commissions/), and updates the portfolio cash/position. - Analysis – After the loop finishes,
Cerebroiterates over registered analyzers (analyzers/*.py), each receiving the finalStrategyandBrokerstate 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:
- Pull the repository, install with
pip install -e .. - Run
pytest -q(tests are undertests/). - 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 –
LICENSEfile included, no ambiguity. - Low – Documentation limited – Only three doc files (
README.rst, docstrings, and a smalldoc/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.