Backtrader
backtrader is a powerful and flexible Python framework for backtesting trading strategies, analyzing financial data, and live trading. It provides a robust engine for simulating market conditions, managing portfolios, and executing trades based on defined rules. The current stable version is 1.9.78.123, with a major 2.x release under active development that introduces significant changes. Its release cadence is sporadic but active, with bug fixes and minor features released as needed.
Common errors
-
AttributeError: 'module' object has no attribute 'Cerebro'
cause Attempting to access a backtrader component directly (e.g., `backtrader.Cerebro`) without importing backtrader with the standard alias.fixAlways use `import backtrader as bt` and then refer to components as `bt.Cerebro`, `bt.Strategy`, etc. -
ModuleNotFoundError: No module named 'matplotlib'
cause The `cerebro.plot()` method was called, but the `matplotlib` library is not installed.fixInstall `matplotlib`: `pip install matplotlib` or `pip install backtrader[plotting]`. -
ValueError: No data points left to run a strategy (fromdate/todate problem?) TypeError: object of type 'NoneType' has no len()
cause This usually indicates that the data feed could not be loaded correctly, or the specified `fromdate`/`todate` range for the data is empty/invalid. Common reasons include incorrect file path, wrong `datetimeformat`, or an empty data file.fixVerify the `dataname` path, `datetimeformat` string, and ensure the `fromdate`/`todate` range correctly overlaps with available data. Check the content of your data file for correctness and headers. -
FileNotFoundError: [Errno 2] No such file or directory: 'your_data.csv'
cause The path provided to a data feed (e.g., `bt.feeds.CSVData(dataname='your_data.csv')`) is incorrect or the file does not exist at that location.fixDouble-check the file path. Ensure it's either an absolute path or a path relative to where your script is being run. Use `os.path.abspath()` for debugging if unsure.
Warnings
- breaking The upcoming backtrader 2.0 release (currently in pre-release/beta) introduces significant breaking changes, including module restructuring and API renames (e.g., `bt.Cerebro` moves to `bt.core.Cerebro`).
- gotcha backtrader internally processes all datetime objects as UTC. If your input data feed contains timezone-aware datetimes or is in a local timezone, ensure you convert it to UTC or set the correct timezone conversion parameters in your data feed (`dtformat`, `tz`, `tzislocal`).
- gotcha Calling `cerebro.plot()` will raise a `ModuleNotFoundError` or similar error if `matplotlib` is not installed in your environment.
- gotcha Strategy and indicator parameters must be defined within a `params` tuple in the class, not as instance attributes in `__init__`.
Install
-
pip install backtrader -
pip install backtrader[plotting,pandas]
Imports
- bt
import backtrader as bt
- Cerebro
from backtrader import Cerebro
import backtrader as bt cerebro = bt.Cerebro()
- Strategy
from backtrader.strategy import Strategy
import backtrader as bt class MyStrategy(bt.Strategy):
- CSVData
from backtrader.feeds import CSVData
import backtrader as bt data = bt.feeds.CSVData(...)
Quickstart
import backtrader as bt
import datetime
import os
# Dummy CSV data for demonstration. In a real scenario, this would be a file.
dummy_csv_content = (
"Date,Open,High,Low,Close,Volume,OpenInterest\n"
"2020-01-01,100,102,99,101,1000,0\n"
"2020-01-02,101,103,100,102,1200,0\n"
"2020-01-03,102,104,101,103,1100,0\n"
"2020-01-06,103,105,102,104,1300,0\n"
)
# Create a dummy CSV file
dummy_csv_path = 'dummy_data.csv'
with open(dummy_csv_path, 'w') as f:
f.write(dummy_csv_content)
class SmaCross(bt.Strategy):
params = (('fast_period', 10), ('slow_period', 30),)
def __init__(self):
self.sma_fast = bt.indicators.SMA(self.data.close, period=self.p.fast_period)
self.sma_slow = bt.indicators.SMA(self.data.close, period=self.p.slow_period)
self.crossover = bt.indicators.CrossOver(self.sma_fast, self.sma_slow)
def next(self):
if not self.position: # Not in the market
if self.crossover > 0: # fast crosses slow upwards
self.buy()
elif self.crossover < 0: # fast crosses slow downwards
self.close()
cerebro = bt.Cerebro()
cerebro.addstrategy(SmaCross)
# Add data feed
data = bt.feeds.CSVData(
dataname=dummy_csv_path,
datetimeformat='%Y-%m-%d',
fromdate=datetime.datetime(2020, 1, 1),
todate=datetime.datetime(2020, 1, 31)
)
cerebro.adddata(data)
cerebro.broker.setcash(100000.0)
cerebro.broker.setcommission(commission=0.001)
print(f'Starting Portfolio Value: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'Final Portfolio Value: {cerebro.broker.getvalue():.2f}')
# Clean up dummy file
os.remove(dummy_csv_path)
# To plot results (requires matplotlib):
# cerebro.plot()