Skip to content
Back to skills

Backtrader

ASecurity

Event-driven backtesting with bar-by-bar execution, complex order types, multiple analyzers, and custom indicators

  • 19 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 2, 2026
ai-agentspythonbashrailstestingapiperformance

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 5 files and shows the line behind each finding

Scanned September 2, 2026

npx -y skills add Serennity007/awesome-stock-quant-skills --skill backtrader --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Backtrader?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Backtrader
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/serennity007-backtrader/badge)](https://www.skillsdirectory.com/skills/serennity007-backtrader)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: backtrader
description: Event-driven backtesting with bar-by-bar execution, complex order types, multiple analyzers, and custom indicators
---

# 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.

## Event-Driven vs Vectorized

| Aspect | Backtrader (event-driven) | vectorbt (vectorized) |
|---|---|---|
| Execution model | Bar-by-bar callbacks | Whole-array operations |
| Speed | Slower (Python loop) | Fast (NumPy/Numba) |
| Order types | Market, limit, stop, stop-limit, bracket, OCO | Market only (native) |
| Realism | Built-in broker with commission, slippage, margin | Manual slippage modeling |
| Multi-timeframe | Native resampledata | Manual alignment |
| Best for | Complex strategies, bracket orders, portfolio | Fast 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

---

## Core Concepts

Backtrader has five core objects that interact through an event loop:

### 1. Cerebro (the engine)

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()
```

### 2. Strategy (your logic)

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()
```

### 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
)
```

### 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

# Cheat-on-open: execute at the open of the signal bar (avoids lookahead)
cerebro.broker.set_coo(True)
```

### 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()
```

---

## Order Types

Backtrader supports complex order types critical for realistic crypto backtesting.

### Market Order

```python
self.buy()  # market buy
self.sell()  # market sell
self.close()  # close current position
```

### Limit Order

```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
```

### 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)
```

### 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.

---

## Position Sizing (Sizers)

Sizers determine how many units to buy/sell per order.

```python
# Fixed size
cerebro.addsizer(bt.sizers.FixedSize, stake=100)

# Percent of portfolio
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)
```

---

## Crypto Considerations

### 24/7 Markets

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.

### 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
```

### Fractional Sizing

Crypto allows fractional units. Backtrader supports this natively -- no special config needed.

### 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
```

### Volatile Data

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

---

## 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)

# Resample 1h to daily
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
```

---

## 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
```

---

## 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)
```

---

## 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`.

---

## 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

### 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

---

## Quick Start

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

Files in this skill

  • SKILL.md9.6 KB
  • references/api_guide.md7.7 KB
  • references/strategy_patterns.md8 KB
  • scripts/backtest_strategy.py14.5 KB
  • scripts/bracket_orders.py15.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.