← back to the showcase

TAKT showcase: backtrader optstrategy, the same results, 2.2–5.2× faster

The numbers below are measured. The TAKT build itself is not included (see "Availability"); this package holds the scripts, the strategies and every reading.

Not affiliated with backtrader. TAKT is not affiliated with, endorsed or sanctioned by the backtrader project or its author. The name backtrader is used only to identify the software we measured.

backtrader (GPL-3.0) is a Python backtesting framework. Its cerebro.optstrategy runs the same strategy once for every combination of parameter values (a grid search) and returns, for every combination, the parameters and the output of the attached analyzers.

We ran the same optimization script twice on the same machine, data and grid: once with unchanged backtrader (A) and once with the TAKT build loaded into the same backtrader process (C). The script, the strategy and backtrader itself are the same; C returns the same result for every parameter set, byte for byte: every analyzer's output, every order and trade notification, the final portfolio value, cash and positions.

Main result (100 parameter sets, 7 interleaved rounds, one CPU). Same result in every round and on both machines (result SHA-256 3e5e1fcc3532…, results/stdout/main_smacross_100.stdout.txt).

Machine A: backtrader C: with TAKT Wall-time factor (95% CI) cycles:u factor (95% CI)
AMD Ryzen 9 7950X3D (Zen 4) 128.7 s 27.10 s 4.75× (4.72–4.98) 4.83× (4.79–5.04)
AMD Threadripper PRO 5975WX (Zen 3) 224.0 s 42.79 s 5.23× (5.16–5.41) 5.35× (5.24–5.41)

The run includes Python start-up, reading the CSV data, all 100 backtests and canonicalising the result.

What was measured

Label Command What it is
A python bt_opt.py ... backtrader 1.9.78.123 (the current PyPI release, identical to git b853d7c), unchanged.
C python takt-backtrader bt_opt.py ... the same backtrader with the TAKT build loaded; same script, same arguments.

Workload. - Strategy: SmaCross, the moving-average crossover from backtrader's documentation ("Hello Algotrading!"), unchanged (tools/strats_bt_docs.py): buy when the fast SMA crosses above the slow one, close when it crosses below. - Grid: pfast 5, 10, ..., 50 and pslow 20, 40, ..., 200 (100 parameter sets, tools/main_grid.json). - Data: Binance spot BTC/USDT, 1-hour candles, 2023-10-01 to 2026-09-30 (26,304 bars), from data.binance.vision (tools/fetch_data.sh, tools/prep_data.py), loaded with backtrader's GenericCSVData. - Broker: 10,000 USDT, 0.1% commission, PercentSizer 95%. - Cerebro defaults (stdstats=True, runonce=True, preload=True, optdatas=True, optreturn=True), maxcpus=1. - Analyzers: TradeAnalyzer, DrawDown, SharpeRatio, Returns, SQN, Transactions, TimeReturn (days), plus three recording analyzers of ours that keep every order notification, every trade notification and the final broker state (tools/bt_opt.py).

Stands. - AMD Ryzen 9 7950X3D (Zen 4, AVX-512), Debian 13, Python 3.13.5; both commands pinned to one CPU (taskset -c 1), takt-harness itself to another (CPU 0). The host ran other work during the measurement. - AMD Ryzen Threadripper PRO 5975WX (Zen 3), Ubuntu 24.04, Python 3.12.3; both commands pinned to one CPU (taskset -c 36), takt-harness itself to another (CPU 37). The machine was shared with other jobs during the measurement (other CPUs sharing the same L3 cache ran other work at times).

Tool. takt-harness 0.2.1: interleaved rounds after one warm-up, median taken. It measures the wall time of the whole process and counts user-mode cycles:u of the process and its children. 95% CIs are bootstrap intervals of the factor. Raw readings are in results/zen4/ and results/zen3/.

Each measured run prints one line: the SHA-256 of the whole optimization result (for every parameter set: the parameters, the output of every analyzer, every order notification with its created and executed parts, every trade notification, final value, cash and positions; tools/bt_opt.py), the counts and the best parameter set. The line of every workload is in results/stdout/; its SHA-256 is the stdout hash in the readings.

Equivalence

Other workloads

Five more workloads, 5 interleaved rounds after one warm-up each, one CPU per workload (two workloads at a time, on the two CPUs named above; takt-harness of each on the other one). Same result in every round of every workload, and on both machines.

Workload Parameter sets Closed trades per run
MacdAtr (backtrader sample macd-settings: MACD cross, SMA direction, ATR trailing stop), BNB/USDT 1 h; macd1 × macd2 × atrdist 18 8,744
SmaCross on 5-minute candles, ETH/USDT 2025-10-01 to 2026-09-30 (105,120 bars) 6 6,057
EmpSmaCross (empenoso/backtrader-quickstart-template, MIT): SMA cross on five pairs at once, run in backtrader's default mode 9 18,171
BBADX (jasgin/backtrader-backtests, MIT): Bollinger bands and ADX, long and short with stop orders, XRP/USDT 1 h 16 16,838
TestStrategy (backtrader Quickstart, final version, logging off): 1,000 cash, no commission, 10-unit stake, SOL/USDT 1 h; maperiod 10–30 21 30,075
Workload Zen 4: A Zen 4: C Zen 4 wall-time factor (95% CI) Zen 4 cycles:u factor Zen 3: A Zen 3: C Zen 3 wall-time factor (95% CI) Zen 3 cycles:u factor
MacdAtr 25.97 s 6.920 s 3.75× (3.39–3.84) 3.86× 46.78 s 11.91 s 3.93× (3.86–4.01) 3.99×
SmaCross 5 m 30.60 s 8.052 s 3.80× (3.54–4.05) 3.89× 55.05 s 14.03 s 3.92× (3.86–4.08) 3.99×
EmpSmaCross 47.32 s 16.84 s 2.81× (2.49–3.11) 2.83× 72.24 s 26.13 s 2.76× (2.70–2.90) 2.81×
BBADX 27.52 s 11.29 s 2.44× (2.32–2.51) 2.48× 49.63 s 19.78 s 2.51× (2.45–2.57) 2.52×
TestStrategy 37.35 s 16.33 s 2.29× (2.22–2.34) 2.31× 64.05 s 28.54 s 2.24× (2.19–2.28) 2.27×

cycles:u factors are medians; their 95% CIs are in the readings (results/zen*/sec_*.log and .json).

On Zen 4, EmpSmaCross and SmaCross 5 m were measured a second time, one at a time (CPU 1, takt-harness on CPU 0): during the first reading, other work on the host raised the cycle counts of both A and C by about a third from the second round on, and the intervals of the wall-time factor were 1.91–4.12 and 2.55–5.10. The table shows the second reading; the first one is kept in results/zen4/first_disturbed/.

Where the result applies

Availability

The TAKT build is not distributed: backtrader is GPL-3.0. Instead we run your optimization on our machines with it and return the same result backtrader would produce, with its run time. On your first run we also run unchanged backtrader, so you see both timings. Send your script, strategy and data description: https://taktcycles.com/?src=showcase-backtrader#start. This is TAKT's own service, not an official or sanctioned backtrader service.

The first 20 core-hours are free. After that, $0.10 per core-hour of our machine time, paid from your dashboard balance.

Reproducing A

python3.12 -m venv venv && venv/bin/pip install backtrader==1.9.78.123
tools/fetch_data.sh downloads                      # Binance klines (new, empty directory)
venv/bin/python -I tools/prep_data.py downloads data
mkdir work && cp tools/bt_opt.py tools/strats*.py tools/run_opt.sh tools/main_grid.json work/
BT_HOME=$PWD work/run_opt.sh orig --strategy SmaCross --grid "$(cat work/main_grid.json)" --data BTCUSDT-1h

The last command prints the digest line of results/stdout/main_smacross_100.stdout.txt. The equivalence matrix is tools/matrix.py (it needs the TAKT launcher for C).

Contents

Source text: README.md

Telegram