DEV Community

Cover image for The Gap Between "It Works on Paper" and "It Works on Monday Morning"
turboline-ai
turboline-ai

Posted on

The Gap Between "It Works on Paper" and "It Works on Monday Morning"

Most trading bot tutorials follow the same arc. You learn how to fetch OHLCV data, wire up a moving average crossover, call create_order(), and paper trade for a week. The tutorial ends. You feel ready.

Then you connect to a live exchange and something breaks within the first hour. An order gets stuck in a pending state. A WebSocket drops silently. Your position sizing logic buys ten times what it should because you forgot to account for the decimal precision on a particular pair.

The paper trading phase taught you none of that. Here is what the actual stack looks like when you build something you can trust with real capital in 2026.

Four Layers That Have to Work Together

A production bot is not a script. It is four distinct systems that need to cooperate, and weaknesses in any one of them will cost you money.

Layer 1: The signal pipeline

Your signals need to be backtestable before they ever touch live data. That means writing them against a framework like vectorbt where you can run the same logic over historical data and verify it behaves the way you think it does. If your signal generation code cannot be tested in isolation, you will never know whether a bad trade was a signal problem, a data problem, or an execution problem.

Layer 2: Signal scoring

A raw signal is binary. A scored signal is more useful. In practice this means taking a confirmed crossover or momentum indicator and running it through a secondary layer that asks: how strong is this signal in context? One approach gaining traction is injecting an LLM-assisted scoring step here, where a model provides a confidence modifier based on broader context. The important word is "non-critical." This layer should influence position size, not trigger or block trades on its own. If the scoring layer fails, your bot should degrade gracefully, not halt.

Layer 3: Position sizing

Kelly Criterion is the right framework here, not fixed lot sizes and not gut feel. The formula outputs a theoretically optimal fraction of capital to risk on a given trade based on your historical win rate and average payoff ratio. In practice you want to use a fractional Kelly (typically half-Kelly) to account for estimation error in those inputs. This alone separates a systematic approach from one that just picks arbitrary sizes.

def kelly_fraction(win_rate: float, avg_win: float, avg_loss: float) -> float:
    if avg_loss == 0:
        return 0.0
    b = avg_win / avg_loss
    q = 1 - win_rate
    kelly = (b * win_rate - q) / b
    return max(0.0, kelly * 0.5)  # half-Kelly
Enter fullscreen mode Exit fullscreen mode

Layer 4: Execution and state management

CCXT handles the exchange connectivity and gives you WebSocket access to real-time order books and price feeds on exchanges like Binance or OKX. But connection management is where most bots quietly fail. WebSocket connections drop. They drop without sending a close frame. They drop and reconnect but miss three seconds of data. Your execution layer needs reconnection logic, a local state store that tracks open positions independently of what the exchange reports, and reconciliation logic that periodically compares the two.

Risk Controls Are Not Optional

This is the part that separates systematic trading from handing an API key to a random number generator.

Before any live order hits the wire, three controls need to be in place:

Max drawdown kill switch. Pick a threshold, say 8% of starting capital for the session. If you cross it, the bot stops placing new orders and alerts you. This is not a feature you add later. It is the first thing you build.

Per-trade stop losses. Every open position needs a defined exit if it moves against you. Hard-coded, not dynamically adjusted. Dynamic stops are fine to research, but in production you want a hard floor that does not move.

Daily loss limits. Separate from the max drawdown kill switch. This is a rolling 24-hour cap. If the strategy has three losing trades in a row before noon, it should reduce size or pause entirely, not keep firing at full size because the weekly drawdown is still acceptable.

Without these three, you are not running a trading system. You are running a bet with automation.

The Part Nobody Puts in the Tutorial

The first thing that will actually go wrong is not your signal logic. It will be an exchange rate limit you did not know existed. Or a fill that comes back with a status you did not handle. Or a network timeout that leaves an order in a state your code cannot interpret.

Production readiness means building for the failure modes, not the happy path. That means logging every order state transition. It means having a separate process that checks open positions every 60 seconds and compares them to what your bot thinks it holds. It means treating the exchange as an unreliable external system, because it is.

The bot you paper traded was a prototype. The bot you run live is infrastructure. Those are different things, and they deserve to be built differently from the start.

Top comments (0)