Scalping strategy in Python
Scalping takes many small, fast trades, here is a scalping strategy in Python on one-minute bars, backtested with real costs.
What is scalping?
Scalping is high-frequency-of-trades, not necessarily high-frequency-tech: many quick trades that each aim for a small profit, holding seconds to minutes. The thesis is that lots of small edges compound, if costs stay below the edge.
That last condition is everything. At a scalper's trade count, fees and slippage are the dominant term, a rule that looks profitable on close prices can be a guaranteed loser once realistic costs are applied. This is exactly where a faithful execution model earns its keep.
The logic
We use a fast 9/21 EMA crossover on one-minute bars to catch short bursts of momentum. The signal is intentionally simple, the interesting part of scalping is the cost and risk control, not the entry.
Tight risk management defines the style: a 0.5% stop-loss and a 0.8% take-profit keep each trade small and quick, exactly the asymmetry a scalper wants.
scalping 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, ema
from manifoldbt.helpers import time_range, Slippage, Interval
# Fast 9 / 21 EMA crossover for short momentum bursts
fast = ema(close, 9)
slow = ema(close, 21)
strategy = (
mbt.Strategy.create("scalper")
.signal("fast", fast)
.signal("slow", slow)
.size(mbt.when(fast > slow, 1.0, 0.0))
.stop_loss(pct=0.5)
.take_profit(pct=0.8)
)
start, end = time_range("2024-06-01", "2026-01-01")
config = mbt.BacktestConfig(
universe={"binance": ["BTCUSDT"]},
time_range_start=start,
time_range_end=end,
bar_interval=Interval.minutes(1),
initial_capital=10_000,
fees=mbt.FeeConfig.binance_perps(),
slippage=Slippage.fixed_bps(1),
warmup_bars=21,
)
store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1,
interval="1m", start="2024-06-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
One-minute bars produce thousands of trades, so the result is hypersensitive to the cost model. Try setting slippage to zero and watch the edge evaporate, that gap is the lesson of scalping.
Because turnover is so high, the only honest way to judge a scalper is with realistic fees, slippage, and ideally finer-grained data. Manifold-BT runs the whole minute-level history on Rust in well under a second, so you can iterate fast.
| Universe | {"binance": ["BTCUSDT"]} |
| Bar interval | 1m |
| Fees | FeeConfig.binance_perps() |
| Slippage | fixed 1 bps |
| Warmup | 21 bars |
| Total return | +11.2% |
| Sharpe | 0.71 |
| Max drawdown | -15.4% |
| Win rate | 39% |
| Trades | 6,431 |
Frequently asked questions
Is scalping profitable after fees?
Often not. Scalping's high trade count makes fees and slippage the dominant cost, so a strategy must clear that hurdle by a wide margin. A realistic backtest is the only way to know before risking capital.
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.