MS
0
← Back to home

Systematic BTC Strategies

Python, Backtesting, MEXC Futures, Flask

The idea

This started as a much bigger, messier project: a bot that followed trade signals from a Telegram channel. That version never goes public, not the code, not even in its git history, since it's tied to a real trading account. What's here is a clean extraction of the part that actually stands on its own: five rules-based BTC strategies sharing one indicator library and one backtest engine, no external signals, no discretionary input, just OHLCV candles in and trades out.

Only one of the five, BB Channel Rider, has been through full validation and runs live in paper mode. The other four exist to build and test ideas, not to be trusted as-is, and I'm upfront about that distinction rather than presenting all five as equally proven.

The bot

BB Channel Rider is a mean-reversion strategy on BTC/USDT perpetual futures, 15-minute candles, 10x leverage, 25% of capital per trade. It enters when price touches a Bollinger Band (20-period, 3.0 standard deviations) in the direction confirmed by an EMA-150 trend filter, then manages the position with a dual stop-loss (a stop-limit plus a market backstop in case price gaps through it), a stop that snaps to breakeven and then trails in the profitable direction as price moves, and a take-profit at the opposite band. When take-profit hits and price is still sitting at the band, the bot immediately flips into the opposite position instead of sitting idle. The full spec was frozen on 2026-05-10 and hasn't changed since.

It runs as a systemd service on an Oracle Cloud VPS with automatic restart, alongside a Flask dashboard for backtesting any of the five strategies and watching live status. The API key is read-only and locked to the server's IP, and paper mode never sends an order to the exchange, it only reads live prices.

Live record

Running since August 2026, a handful of closed trades so far on a $1,000 paper balance, currently in profit. Far too few to conclude anything, which is exactly why it stays running. This is the number I'd want judged in a year, not the backtest. The live figures are on the dashboard, linked below.

What the backtest says

The backtest is the tool that configured the bot, not the product. Over the year of real 15-minute data following the spec freeze, charging the fees the bot actually pays: 311 trades, 60.5% win rate, +$730.45 on a $1,000 start, 20.1% maximum drawdown.

Fees dominate. The same year with fees switched off returns +$3,078, so roughly three quarters of the gross edge goes to the exchange. At 10x leverage a round trip costs about 1.2% of margin, which means a take-profit on a small move can close at a net loss even though price moved the right way. One did, on 9 August, and finding it is what prompted re-deriving all of these numbers.

Two validation gates. A 16,200-combination parameter grid search found 67.5% of combinations profitable, which says the strategy family isn't balanced on a knife edge. But the frozen parameter set ranks 14th of those 16,200 on the same window it was chosen from, so that ranking is a selection, not independent evidence, and I'd be fooling myself to present it as confirmation. The honest test is the period after the freeze, which the parameters never saw: 66 trades, 65.2% win rate, +$359.73, 10.1% maximum drawdown. It held up.

Known limitations

Paper mode uses real prices and models fees, but assumes zero slippage and instant fills, so live trading would run somewhat below these numbers. The backtest can't distinguish a stop-limit fill from the market backstop, so stop-loss exits are costed at the cheaper maker rate. The other four strategies share the same engine but haven't been through this validation.

These figures replace an earlier set (290 trades, 63.8%, +$10,348) that I published and later found to be wrong. The audit script had drifted from the deployed strategy on five counts, each flattering, and was measuring a configuration that never ran. It now imports the live strategy module directly, so the two cannot diverge again.

Explore it

Live dashboard ↗  ·  Source code ↗