Building a Mean-Reversion Bot Step by Step
This is the implementation companion to the mean-reversion concept. The idea is old and simple: measure how far price has stretched from a baseline, bet on the snap back, and get out when it reverts. This post builds that as a working bot for prediction markets, where the mechanics differ from equities in one important way.
The difference: a prediction market contract is a bounded probability, not an unbounded asset. On Kalshi and Polymarket, each contract is priced between $0.01 and $0.99 and pays out $1.00 if the outcome happens or nothing if it does not, so the price works as the market's estimate of how likely that outcome is. That bound changes both your signal math and your risk math, as we will see.
Step 1: Define the baseline and the deviation
Mean reversion needs a mean. The standard move is a rolling window: define the mean, measure distance from it, and wait for a snap-back signal. Compute a z-score of price against a moving average: z equals current price minus the N-period mean, divided by the N-period standard deviation. A common quantitative rule is z = (current price - 50-period mean) / 50-period standard deviation.
For a prediction market, use the mid price (halfway between best bid and best ask) as your price input, not the last trade. Last trade prints on thin books are noisy. And keep the window short. These contracts have a fixed resolution date, so a 200-period lookback that makes sense on a stock is meaningless on a contract that resolves in three days.
Step 2: Entry rules
The textbook entry is a threshold on the z-score. Professional mean-reversion algorithms often enter when z exceeds +2 or falls below -2, and some use a tighter ±1.5 to catch more signals at a lower win rate. The tradeoff is direct: the aggressive approach generates more signals but a lower win rate, while the conservative approach misses some opportunities but offers higher probability per trade.
Do not fade blindly. Two filters matter more on prediction markets than on forex:
- Spread check. Tight spreads of 1 to 2 cents mean the market is liquid and well-traded; wide spreads of 5 cents or more signal thin liquidity, uncertainty, or both. If the spread is wide, your z-score is built on a fuzzy mid and your fill will be bad. Skip it.
- Distance from the bounds. Order books near the price extremes behave differently: spreads widen, depth thins out, and the bid-ask dynamics shift to account for the catastrophic loss scenario. A contract at 3 cents is not 'oversold', it is a market pricing in near-certain zero. Fading it is not mean reversion, it is betting against resolution.
The last point is why you never treat a prediction-market contract like an oscillating stock. Below a floor and above a ceiling, the reversion assumption breaks because the underlying event is close to settled.
Step 3: Exit rules
The target is the mean. Most mean-reversion traders exit when price returns to the middle of the range, and a clean rule is to exit at the z-score crossing back through zero. Do not hold for a full reversion to the opposite extreme. Mean reversion is not about catching the entire move, it is about capturing the high-probability portion back to average.
You also need two non-price exits. First, a stop for when the thesis is simply wrong: a common rule is a hard stop when the z-score reaches -3, a statistical breakdown of the reversion assumption. Second, a time stop. Because these contracts resolve on a date, model your hold like a half-life: most mean-reversion trades should exit within 2 to 3 times the half-life, and if the position has not reverted by then the initial thesis is likely wrong. Force-flatten well before resolution regardless.
Step 4: Position sizing
Size off a fixed fraction of capital, not gut feel. A standard baseline is to limit risk to 1 to 2 percent per trade. On a binary contract the 'risk' is unusually concrete: contracts settle at either $0 or $1, so any unbalanced inventory carries the risk of total loss. Your worst case on a long is the full price you paid per contract, so size against that number directly rather than a stop distance.
Then check the book can actually absorb your size. Actionable liquidity is the depth within about 3 cents of the inside; anything beyond that is too far from the current price to matter for immediate execution. If your intended size is larger than that near-touch depth, you will walk the book and give back your edge in slippage. Cut the size or split the order.
Step 5: Wire in hard risk limits
Signal logic decides what to trade. Risk limits decide what you are allowed to lose. Keep them separate and make the limits declarative, so a bug in your signal cannot override them. A minimum set:
- Per-trade cap: maximum dollars committed to any single position.
- Daily loss stop: flatten everything and stop trading for the day past a realized-loss threshold.
- Max open positions: a ceiling on concurrent contracts, since correlated markets can move together.
- Kill switch: one command that halts new orders and cancels resting ones.
This is exactly the split Banger enforces. You write the signal as a banger.Strategy in Python, and the risk envelope (per-trade cap, daily loss stop, max open positions, kill switch) sits outside your code as configuration the runtime enforces on every order. Banger never custodies funds; you bring your own venue keys.
Step 6: Paper trade before you fund anything
Backtesting and statistical validation are critical, and a backtest on a static price series will always flatter a mean-reversion strategy because it ignores spread, slippage, and whether your size would have filled. Run against the live order book in paper mode first. That surfaces the real killers: fills you assumed but would not have gotten, and z-score signals that evaporate once you account for the spread.
pip install bangertrades
banger run strategy.py --paperThe honest caveats
Mean reversion has clear entry and exit points and works well in range-bound markets, but it struggles in trending markets and is sensitive to news and economic shocks. On prediction markets the trend is often news: a contract 'stretched' from its mean may be repricing on real information about the event, and it will not revert. Your spread filter, your distance-from-bounds filter, and your z = -3 stop are what keep a one-sided repricing from turning into a full loss on a contract that settles at zero. Build those first, then tune the signal.
Sources
- Kalshi vs Polymarket 2026: Fees, Markets and US Legality
- Mean Reversion Strategies for Algorithmic Trading
- Mean Reversion Trading in Forex: Strategy Guide for 2026
- Mean Reversion Trading 2026 - Complete Strategy Guide
- Mean Reversion Trading Strategy: How to Build and Test
- Mean Reversion Trading: Understanding Strategies and Indicators
- How Prediction Market Order Books Work on Kalshi and Polymarket
- Prediction market orderbook analysis: depth, spread, liquidity
- Market Making in Prediction Markets: How Liquidity Providers Trade