backtrader

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Backtrader

Backtrader

Backtrader is a Python event-driven backtesting framework that processes data bar-by-bar, simulating realistic execution with a built-in broker, order management, and position tracking. Unlike vectorized frameworks (vectorbt, pandas), backtrader walks through history one bar at a time, firing callbacks that let you implement complex order logic that depends on previous fills, partial executions, and conditional brackets.
Backtrader是一款基于Python的事件驱动回测框架,它逐K线处理数据,通过内置的经纪商、订单管理和仓位跟踪功能模拟真实交易执行。与向量化框架(vectorbt、pandas)不同,Backtrader会逐根遍历历史K线,触发回调函数,让你能够实现依赖于之前成交、部分执行和条件括号单的复杂订单逻辑。

Event-Driven vs Vectorized

事件驱动 vs 向量化

AspectBacktrader (event-driven)vectorbt (vectorized)
Execution modelBar-by-bar callbacksWhole-array operations
SpeedSlower (Python loop)Fast (NumPy/Numba)
Order typesMarket, limit, stop, stop-limit, bracket, OCOMarket only (native)
RealismBuilt-in broker with commission, slippage, marginManual slippage modeling
Multi-timeframeNative resampledataManual alignment
Best forComplex strategies, bracket orders, portfolioFast parameter sweeps, simple signals
Use backtrader when you need:
  • Bracket orders (entry + stop loss + take profit as a unit)
  • Stop-limit or trailing stop orders
  • Order-dependent logic (scale in after first fill, cancel if not filled in N bars)
  • Multi-timeframe strategies (daily signals, hourly execution)
  • Realistic commission and slippage modeling
Use vectorbt when you need:
  • Fast parameter optimization over thousands of combinations
  • Simple long/short signals without complex order management
  • Quick prototyping and statistical analysis of results

维度Backtrader(事件驱动)vectorbt(向量化)
执行模型逐K线回调全数组运算
速度较慢(Python循环)较快(NumPy/Numba)
订单类型市价单、限价单、止损单、止损限价单、括号单、OCO单仅支持市价单(原生)
真实性内置经纪商,支持佣金、滑点、保证金模拟需手动模拟滑点
多时间框架原生支持数据重采样需手动对齐数据
适用场景复杂策略、括号单、组合投资快速参数扫描、简单信号策略
当你需要以下功能时选择Backtrader:
  • 括号单(入场+止损+止盈为一个整体单元)
  • 止损限价单或追踪止损单
  • 依赖订单状态的逻辑(首次成交后加仓、N根K线未成交则取消订单)
  • 多时间框架策略(日线信号、小时线执行)
  • 真实的佣金与滑点模拟
当你需要以下功能时选择vectorbt:
  • 针对数千种组合的快速参数优化
  • 无需复杂订单管理的简单多空信号
  • 快速原型开发与结果统计分析

Core Concepts

核心概念

Backtrader has five core objects that interact through an event loop:
Backtrader包含五个核心对象,它们通过事件循环交互:

1. Cerebro (the engine)

1. Cerebro(引擎)

The central orchestrator. You add strategies, data feeds, analyzers, and sizers to Cerebro, then call
run()
.
python
import backtrader as bt

cerebro = bt.Cerebro()
cerebro.addstrategy(MyStrategy, fast_period=10, slow_period=30)
cerebro.adddata(data_feed)
cerebro.broker.setcash(100_000)
cerebro.broker.setcommission(commission=0.003)  # 0.3%
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe")
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
cerebro.run()
核心协调器。你可以向Cerebro添加策略、数据馈源、分析器和仓位计算器,然后调用
run()
启动回测。
python
import backtrader as bt

cerebro = bt.Cerebro()
cerebro.addstrategy(MyStrategy, fast_period=10, slow_period=30)
cerebro.adddata(data_feed)
cerebro.broker.setcash(100_000)
cerebro.broker.setcommission(commission=0.003)  # 0.3%
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe")
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
cerebro.run()

2. Strategy (your logic)

2. Strategy(策略逻辑)

A Strategy subclass contains all trading logic. Key methods:
  • __init__()
    — Define indicators. Runs once before backtesting starts.
  • next()
    — Called on every bar. Place orders here.
  • notify_order(order)
    — Called when order status changes (submitted, accepted, completed, canceled, margin, expired).
  • notify_trade(trade)
    — Called when a trade opens or closes. Access P&L here.
python
class EMACrossover(bt.Strategy):
    params = (
        ("fast_period", 10),
        ("slow_period", 30),
    )

    def __init__(self) -> None:
        self.ema_fast = bt.ind.EMA(period=self.p.fast_period)
        self.ema_slow = bt.ind.EMA(period=self.p.slow_period)
        self.crossover = bt.ind.CrossOver(self.ema_fast, self.ema_slow)

    def next(self) -> None:
        if not self.position:
            if self.crossover > 0:
                self.buy()
        elif self.crossover < 0:
            self.close()
Strategy子类包含所有交易逻辑。关键方法:
  • __init__()
    — 定义指标,在回测开始前运行一次。
  • next()
    — 每根K线都会被调用,在此处下达订单。
  • notify_order(order)
    — 订单状态变化时调用(已提交、已接受、已完成、已取消、保证金不足、已过期)。
  • notify_trade(trade)
    — 交易开仓或平仓时调用,在此处获取盈亏数据。
python
class EMACrossover(bt.Strategy):
    params = (
        ("fast_period", 10),
        ("slow_period", 30),
    )

    def __init__(self) -> None:
        self.ema_fast = bt.ind.EMA(period=self.p.fast_period)
        self.ema_slow = bt.ind.EMA(period=self.p.slow_period)
        self.crossover = bt.ind.CrossOver(self.ema_fast, self.ema_slow)

    def next(self) -> None:
        if not self.position:
            if self.crossover > 0:
                self.buy()
        elif self.crossover < 0:
            self.close()

3. Data Feed

3. Data Feed(数据馈源)

Backtrader data feeds provide OHLCV lines. The most common approach is loading from a pandas DataFrame:
python
import pandas as pd

df = pd.DataFrame({
    "open": [...], "high": [...], "low": [...],
    "close": [...], "volume": [...],
}, index=pd.DatetimeIndex([...]))

data = bt.feeds.PandasData(dataname=df)
cerebro.adddata(data)
For CSV files:
python
data = bt.feeds.GenericCSVData(
    dataname="ohlcv.csv",
    dtformat="%Y-%m-%d",
    openinterest=-1,  # no open interest column
)
Backtrader的数据馈源提供OHLCV数据。最常用的方式是从pandas DataFrame加载:
python
import pandas as pd

df = pd.DataFrame({
    "open": [...], "high": [...], "low": [...],
    "close": [...], "volume": [...],
}, index=pd.DatetimeIndex([...]))

data = bt.feeds.PandasData(dataname=df)
cerebro.adddata(data)
加载CSV文件:
python
data = bt.feeds.GenericCSVData(
    dataname="ohlcv.csv",
    dtformat="%Y-%m-%d",
    openinterest=-1,  # 无持仓兴趣列
)

4. Broker

4. Broker(经纪商)

The built-in broker simulates order execution with configurable cash, commission, and slippage.
python
cerebro.broker.setcash(100_000)
cerebro.broker.setcommission(commission=0.003)  # 0.3% per trade
内置经纪商可模拟订单执行,支持配置初始资金、佣金和滑点。
python
cerebro.broker.setcash(100_000)
cerebro.broker.setcommission(commission=0.003)  # 每笔交易0.3%

Cheat-on-open: execute at the open of the signal bar (avoids lookahead)

开盘价成交:在信号K线的开盘价执行订单(避免前瞻偏差)

cerebro.broker.set_coo(True)
undefined
cerebro.broker.set_coo(True)
undefined

5. Analyzers

5. Analyzers(分析器)

Analyzers compute performance metrics after the backtest completes.
python
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe",
                    riskfreerate=0.0, annualize=True, timeframe=bt.TimeFrame.Days)
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="trades")
cerebro.addanalyzer(bt.analyzers.Returns, _name="returns")

results = cerebro.run()
strat = results[0]

sharpe = strat.analyzers.sharpe.get_analysis()
dd = strat.analyzers.drawdown.get_analysis()
trades = strat.analyzers.trades.get_analysis()

分析器在回测完成后计算绩效指标。
python
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe",
                    riskfreerate=0.0, annualize=True, timeframe=bt.TimeFrame.Days)
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="trades")
cerebro.addanalyzer(bt.analyzers.Returns, _name="returns")

results = cerebro.run()
strat = results[0]

sharpe = strat.analyzers.sharpe.get_analysis()
dd = strat.analyzers.drawdown.get_analysis()
trades = strat.analyzers.trades.get_analysis()

Order Types

订单类型

Backtrader supports complex order types critical for realistic crypto backtesting.
Backtrader支持对真实加密货币回测至关重要的复杂订单类型。

Market Order

市价单

python
self.buy()  # market buy
self.sell()  # market sell
self.close()  # close current position
python
self.buy()  # 市价买入
self.sell()  # 市价卖出
self.close()  # 平仓

Limit Order

限价单

python
self.buy(exectype=bt.Order.Limit, price=95.0)
self.sell(exectype=bt.Order.Limit, price=105.0)
python
self.buy(exectype=bt.Order.Limit, price=95.0)
self.sell(exectype=bt.Order.Limit, price=105.0)

Stop Order

止损单

Triggers a market order when price reaches the stop level:
python
self.sell(exectype=bt.Order.Stop, price=90.0)  # stop loss
价格达到止损位时触发市价单:
python
self.sell(exectype=bt.Order.Stop, price=90.0)  # 止损

Stop-Limit Order

止损限价单

Triggers a limit order when price reaches the stop level:
python
self.buy(exectype=bt.Order.StopLimit, price=100.0, plimit=101.0)
价格达到止损位时触发限价单:
python
self.buy(exectype=bt.Order.StopLimit, price=100.0, plimit=101.0)

Bracket Order

括号单

Entry + stop loss + take profit as an atomic unit. If the stop fills, the take profit is canceled (and vice versa).
python
self.buy_bracket(
    price=100.0,           # entry limit
    stopprice=95.0,        # stop loss
    limitprice=110.0,      # take profit
    exectype=bt.Order.Limit,
    stopexec=bt.Order.Stop,
    limitexec=bt.Order.Limit,
)
See
references/strategy_patterns.md
for bracket order patterns with ATR-based stops.

入场+止损+止盈为一个原子单元。如果止损单成交,止盈单会被取消(反之亦然)。
python
self.buy_bracket(
    price=100.0,           # 入场限价
    stopprice=95.0,        # 止损
    limitprice=110.0,      # 止盈
    exectype=bt.Order.Limit,
    stopexec=bt.Order.Stop,
    limitexec=bt.Order.Limit,
)
如需基于ATR止损的括号单模式,请查看
references/strategy_patterns.md

Position Sizing (Sizers)

仓位管理(Sizers)

Sizers determine how many units to buy/sell per order.
python
undefined
仓位计算器决定每笔订单的买卖数量。
python
undefined

Fixed size

固定数量

cerebro.addsizer(bt.sizers.FixedSize, stake=100)
cerebro.addsizer(bt.sizers.FixedSize, stake=100)

Percent of portfolio

占组合比例

cerebro.addsizer(bt.sizers.PercentSizer, percents=95)
cerebro.addsizer(bt.sizers.PercentSizer, percents=95)

All available cash

全仓买入

cerebro.addsizer(bt.sizers.AllInSizer, percents=95)

Custom sizer:

```python
class RiskSizer(bt.Sizer):
    params = (("risk_pct", 0.02),)

    def _getsizing(self, comminfo, cash, data, isbuy):
        risk_amount = cash * self.p.risk_pct
        atr = self.strategy.atr[0]
        if atr <= 0:
            return 0
        size = risk_amount / atr
        return int(size)

cerebro.addsizer(bt.sizers.AllInSizer, percents=95)

自定义仓位计算器:

```python
class RiskSizer(bt.Sizer):
    params = (("risk_pct", 0.02),)

    def _getsizing(self, comminfo, cash, data, isbuy):
        risk_amount = cash * self.p.risk_pct
        atr = self.strategy.atr[0]
        if atr <= 0:
            return 0
        size = risk_amount / atr
        return int(size)

Crypto Considerations

加密货币适配要点

24/7 Markets

7×24小时市场

Crypto trades around the clock. When using daily bars, there are no weekends to skip. Set the session times or use
sessionstart
/
sessionend
if analyzing specific windows.
加密货币全天候交易。使用日线数据时无需跳过周末。如需分析特定时段,可设置交易时段或使用
sessionstart
/
sessionend

High Fees

高额手续费

DEX swaps on Solana typically cost 0.25-0.30% per trade. Set commission accordingly:
python
cerebro.broker.setcommission(commission=0.003)  # 0.3% round trip per side
Solana上的DEX交易手续费通常为每笔0.25-0.30%,需相应设置佣金:
python
cerebro.broker.setcommission(commission=0.003)  # 单边0.3%,往返合计0.6%

Fractional Sizing

fractional仓位

Crypto allows fractional units. Backtrader supports this natively -- no special config needed.
加密货币支持小数仓位,Backtrader原生支持此功能,无需额外配置。

Slippage

滑点

For realistic simulation, enable cheat-on-open and add slippage:
python
cerebro.broker.set_coo(True)
cerebro.broker.set_slippage_perc(0.001)  # 0.1% slippage
为实现真实模拟,启用开盘价成交并添加滑点:
python
cerebro.broker.set_coo(True)
cerebro.broker.set_slippage_perc(0.001)  # 0.1%滑点

Volatile Data

高波动数据

Crypto OHLCV data often has extreme wicks. Use ATR-based stops rather than fixed percentage stops to adapt to volatility.

加密货币OHLCV数据通常带有极端影线,建议使用基于ATR的止损而非固定百分比止损,以适应波动率变化。

Multi-Timeframe

多时间框架

Backtrader can resample data to multiple timeframes within a single strategy:
python
data_1h = bt.feeds.PandasData(dataname=df_1h)
cerebro.adddata(data_1h)
Backtrader可在单个策略内将数据重采样至多个时间框架:
python
data_1h = bt.feeds.PandasData(dataname=df_1h)
cerebro.adddata(data_1h)

Resample 1h to daily

将1小时数据重采样为日线数据

cerebro.resampledata(data_1h, timeframe=bt.TimeFrame.Days, compression=1)

Access in strategy:

```python
def __init__(self):
    self.ema_1h = bt.ind.EMA(self.datas[0], period=20)    # hourly
    self.ema_daily = bt.ind.EMA(self.datas[1], period=20)  # daily

cerebro.resampledata(data_1h, timeframe=bt.TimeFrame.Days, compression=1)

在策略中调用:

```python
def __init__(self):
    self.ema_1h = bt.ind.EMA(self.datas[0], period=20)    # 小时线EMA
    self.ema_daily = bt.ind.EMA(self.datas[1], period=20)  # 日线EMA

Custom Indicators

自定义指标

python
class SpreadIndicator(bt.Indicator):
    lines = ("spread", "zscore",)
    params = (("period", 20),)

    def __init__(self):
        mean = bt.ind.SMA(self.data, period=self.p.period)
        std = bt.ind.StdDev(self.data, period=self.p.period)
        self.lines.spread = self.data - mean
        self.lines.zscore = self.lines.spread / std

python
class SpreadIndicator(bt.Indicator):
    lines = ("spread", "zscore",)
    params = (("period", 20),)

    def __init__(self):
        mean = bt.ind.SMA(self.data, period=self.p.period)
        std = bt.ind.StdDev(self.data, period=self.p.period)
        self.lines.spread = self.data - mean
        self.lines.zscore = self.lines.spread / std

Plotting

绘图

Backtrader includes matplotlib-based plotting:
python
cerebro.plot(style="candlestick", volume=True)
For headless environments, save to file:
python
import matplotlib
matplotlib.use("Agg")
figs = cerebro.plot(style="candlestick")
figs[0][0].savefig("backtest_result.png", dpi=150)

Backtrader包含基于matplotlib的绘图功能:
python
cerebro.plot(style="candlestick", volume=True)
在无图形界面环境中,可保存为文件:
python
import matplotlib
matplotlib.use("Agg")
figs = cerebro.plot(style="candlestick")
figs[0][0].savefig("backtest_result.png", dpi=150)

Integration with Other Skills

与其他工具集成

  • pandas-ta: Compute indicators externally, add as data feed columns. See
    references/api_guide.md
    for adding extra lines.
  • trading-visualization: Export trade log from
    notify_trade
    and plot with the visualization skill.
  • position-sizing: Use the
    position-sizing
    skill for Kelly or volatility-targeting sizers.
  • risk-management: Apply portfolio-level guardrails from the
    risk-management
    skill as strategy filters.
  • slippage-modeling: Use slippage estimates from the
    slippage-modeling
    skill to configure
    set_slippage_perc
    .

  • pandas-ta: 外部计算指标,添加为数据馈源列。如需添加额外数据列,请查看
    references/api_guide.md
  • trading-visualization: 从
    notify_trade
    导出交易日志,使用可视化工具绘图。
  • position-sizing: 使用
    position-sizing
    工具实现凯利公式或波动率目标仓位管理。
  • risk-management: 应用
    risk-management
    工具中的组合级风控规则作为策略过滤器。
  • slippage-modeling: 使用
    slippage-modeling
    工具的滑点估算结果配置
    set_slippage_perc

Files

文件说明

References

参考文档

  • references/api_guide.md
    — Cerebro, Strategy, Broker, Analyzer, Data Feed API reference
  • references/strategy_patterns.md
    — Reusable strategy patterns: crossover, mean reversion, multi-timeframe, custom indicators
  • references/api_guide.md
    — Cerebro、Strategy、Broker、Analyzer、Data Feed的API参考
  • references/strategy_patterns.md
    — 可复用策略模式:交叉策略、均值回归、多时间框架、自定义指标

Scripts

脚本

  • scripts/backtest_strategy.py
    — Complete EMA crossover backtest with analyzers and synthetic data
  • scripts/bracket_orders.py
    — Bracket order demonstration with RSI entry and ATR-based stops

  • scripts/backtest_strategy.py
    — 完整的EMA交叉回测脚本,包含分析器和合成数据
  • scripts/bracket_orders.py
    — 括号单演示脚本,基于RSI入场和ATR止损

Quick Start

快速开始

bash
uv pip install backtrader pandas numpy matplotlib
python scripts/backtest_strategy.py --demo
python scripts/bracket_orders.py --demo
bash
uv pip install backtrader pandas numpy matplotlib
python scripts/backtest_strategy.py --demo
python scripts/bracket_orders.py --demo