Breakout strategy in Python
Breakout strategies buy when price escapes its recent range, here is one in Python, backtested honestly on the Rust core.
What is breakout?
A breakout strategy enters when price pushes beyond a recent high or range, on the theory that a decisive break signals the start of a new move. It is a close cousin of momentum, focused on the moment of expansion rather than sustained strength.
Breakouts capture big trends but suffer from false breaks, moves that poke past the range then immediately reverse. The defense is to stay engaged only while price holds the upper part of its range and to exit quickly when it fails back inside.
The logic
We build a 20-bar Donchian channel from the rolling high and low, then compute where the current close sits within it. A value near 1 means price is at the top of its recent range; near 0 means the bottom.
The rule stays long while the close holds in the top fifth of the range and steps aside otherwise, so it rides genuine breakouts and exits on failure back into the range.
breakout in Python
Here is the full strategy in the Manifold-BT expression DSL. It imports manifoldbt, builds the signal, configures realistic execution, and runs the backtest against Rust.
import manifoldbt as mbt
from manifoldbt.indicators import close, high, low
from manifoldbt.helpers import time_range, Slippage, Interval
# 20-bar Donchian channel and the close's position within it
upper = high.rolling_max(20)
lower = low.rolling_min(20)
pos_in_range = (close - lower) / (upper - lower)
# Long while price holds in the top fifth of its recent range
strategy = (
mbt.Strategy.create("breakout")
.signal("upper", upper)
.signal("lower", lower)
.size(mbt.when(pos_in_range > 0.8, 1.0, 0.0))
.stop_loss(pct=5.0)
)
start, end = time_range("2021-01-01", "2026-01-01")
config = mbt.BacktestConfig(
universe={"binance": ["BTCUSDT"]},
time_range_start=start,
time_range_end=end,
bar_interval=Interval.hours(4),
initial_capital=10_000,
fees=mbt.FeeConfig.binance_perps(),
slippage=Slippage.fixed_bps(2),
warmup_bars=20,
)
store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1,
interval="4h", start="2021-01-01T00:00:00Z",
end="2026-01-01T00:00:00Z")
result = mbt.run(strategy, config, store)
print(result.summary())
mbt.plot.tearsheet(result, show=True)Backtest it with Manifold-BT
Four-hour BTC bars balance signal frequency against noise. Breakout strategies are sensitive to slippage because they buy into fast-moving prices, so the two-basis-point model here is conservative but realistic.
Vary the channel length and the range threshold to find a stable plateau. Tightening the threshold catches more breakouts but also more false ones, the sweep makes that trade-off visible.
| Universe | {"binance": ["BTCUSDT"]} |
| Bar interval | 4h |
| Fees | FeeConfig.binance_perps() |
| Slippage | fixed 2 bps |
| Warmup | 20 bars |
| Total return | +52.6% |
| Sharpe | 0.98 |
| Max drawdown | -21.8% |
| Win rate | 41% |
| Trades | 188 |
Keep reading
Run your first backtest
Install Manifold-BT and reproduce the backtest above in seconds. The Rust core runs years of bars sub-second so you can sweep parameters instead of waiting.