A production trading bot is not a signal with a loop around it. It is a five-stage pipeline — data, signal, risk, execution, monitoring — and the stages rank in roughly reverse order of the attention they get in tutorials. Builders spend nearly all their time on the signal, which is also the stage least correlated with whether the system survives its first year live: signals fail gradually, the other stages fail all at once.
The short answer to "what do I actually need": a data store whose timestamps you trust, a signal simple enough to explain in two sentences, a risk layer that can veto anything, an execution layer that reconciles its own beliefs against the broker's, plus monitoring that pages you when the two disagree. Everything else — languages and frameworks included — is detail.
The Five Stages
Data
Everything downstream inherits this layer's flaws. The classic futures traps are contract rolls and session boundaries: a continuous back-adjusted series is fine for signals built on price differences but silently wrong for anything keyed to absolute levels, because the adjustment shifts history at every roll. Index futures trade nearly around the clock with a daily maintenance halt, so a "daily" bar is a convention — pick the session template that defines your day and encode it once.
Store raw exchange messages separately from derived series: if you only keep computed bars, every bar-builder bug fix rewrites history and old backtests stop being reproducible. Decide early between full depth of market and top-of-book — retrofitting depth into a quote-based design is a rewrite, not a patch.
Signal
A signal is a pure function: history in, position intent out. Keep it pure — no network calls, no hidden state — so it can be replayed exactly — the property every test below depends on. Inputs can be anything computable point-in-time: bar statistics, order flow imbalance, cumulative delta divergence, dealer positioning levels. The signal's job ends at intent — once it starts sizing positions or checking account state, risk logic is smeared across two layers and neither can be tested alone.
The losing side of this stage is complexity. Every added parameter is another dial an optimizer can turn toward noise; the overfitting section below is mostly a bill for decisions made here.
Risk
The risk layer sits between intent and orders and holds the only veto in the system. At minimum it enforces a hard position cap, a daily loss threshold that flattens and halts, a sanity bound on order prices, a rate limit on submissions, plus a human-reachable kill switch. These checks fire on bugs as often as on markets — a feed glitch that prints an absurd price, or a loop that re-submits a rejected order forever.
The cost of omission stays invisible for months: a missing gate costs nothing until the day it costs more than the account. That asymmetry is the argument for ranking this layer above the signal.
Execution
Backtests assume orders fill; live systems manage orders that exist in uncertain states — partially filled, rejected, cancelled in flight, or unknown during a disconnect. The core discipline is reconciliation: check the bot's internal position against the broker's reported position on a schedule, and halt trading on any mismatch instead of "correcting" automatically — correction applied to bad state is how a flat bot becomes a doubled one.
Market orders pay the spread with certainty; limit orders earn the spread when they fill — but they fill preferentially when price is trading through them, exactly when you least want the position. This adverse-selection cost never appears in a naive simulation.
Monitoring
Log every decision with its inputs: what the signal saw, what the risk layer allowed, what was sent, what came back. Heartbeats should page you when the process dies but also when it merely goes quiet — a hung process holding a position is worse than a dead one. My readiness test: if the machine caught fire mid-session, could I flatten from a phone in two minutes using only the broker's interface? Until yes, size stays at minimum.

