// learn ยท Data & tools
How to build a robust investing bot
We run a live market bot (Peaky Radar) and a real dYdX execution engine, so this isn't theory. This is the design that keeps a bot from quietly destroying an account, the intuitions, not the code. One day we may open the Peaky bot itself; for now, here's the blueprint we build to.
The one idea that matters: separate the brain from the hands
Every robust bot we've studied, Freqtrade, Jesse, and our own, splits into the same three pure stages. Keep them separate and you can test, swap and debug each in isolation:
- Indicators,
populate_indicators(candles): turn raw price data into a dataframe of RSI, MACD, EMAs, ATR, etc. - Signal logic, pure functions that mark buy/sell on that dataframe. No network calls, no side effects. This is where the strategy lives, and it must be unit-testable in complete isolation.
- Execution adapter, the only part that talks to the exchange:
place_market_order,place_limit_exit_order. Swap dYdX for another venue by rewriting only this layer.
If your signal logic knows what an exchange is, the design is already wrong. The brain decides; the hands act; they meet through a thin interface.
The four layers
| Layer | Job | How we do it |
|---|---|---|
| Data ingestion | Fetch candles / feeds on a schedule | Scheduled scans, dedup state, cached slow data (e.g. fundamentals) so you don't refetch what rarely changes |
| Signal logic | Decide, purely, from data | Indicator dataframe โ pure buy/sell functions โ a score |
| Execution adapter | Place & manage orders | dYdX v4 client; market entry + laddered limit exits |
| State & safety | Track reality, prevent disaster | Local order ledger, exposure caps, kill-switch, watchdog |
Safety, the part amateurs skip (and blow up on)
This is what separates a toy from something you'd trust with money. None of it is optional.
- Keep a local ledger of orders and fills. Never rely on exchange state alone, network lag and races mean the exchange's view and yours can disagree for seconds. Reconcile a local record against fills; that's how you avoid double-entering or losing track of a position.
- Hard exposure cap. A strict maximum position size and maximum number of open orders, enforced in code, not in your head.
- Emergency kill-switch (
panic_exit). One command that cancels everything and flattens. You will need it at the worst possible moment; build it first. - Heartbeat / watchdog. A separate process that checks the bot is alive and sane, and trips the kill-switch if it detects runaway behaviour or a stalled loop.
- Stop-loss / invalidation on every position. Define where the thesis is wrong before you enter, and let the bot enforce it without emotion.
Test before you trust
- Paper / dry-run mode first. Run the full pipeline against a mock executor that emulates fills, validate timing and logic under simulated latency before a single real order.
- Backtest with realistic fees and slippage. A backtest that ignores costs is a fantasy. Model both, and check drawdown through the ugly periods, not just the good ones.
- Unit-test indicators and order logic. Pure functions make this easy, that's half the reason to separate them.
- Tune parameters carefully. Optimisers (hyperopt) find great-looking settings, usually overfit to the past. Validate on data the tuning never saw.
Strategy archetypes (and when each dies)
| Strategy | Works when | Fails when |
|---|---|---|
| EMA crossover (trend) | Clear, sustained trends | Choppy ranges, whipsaws you |
| Bollinger mean-reversion | Range-bound markets | Strong breakouts, fades a runaway move |
| Momentum breakout | Volatility expansions | False breakouts in quiet markets |
| RSI / MACD hybrid | Momentum with confirmation | Lagging in fast reversals |
| Grid / DCA | Sideways, mean-reverting ranges | Strong trends, accumulates into a falling knife |
There's no strategy that works in all regimes, the skill is matching the strategy to the market, and having safety rules for when the regime changes underneath you.
Why dYdX specifically
dYdX is a decentralized perpetuals exchange: you trade from your own wallet, no custodian holds your funds. Its v4 client connects to mainnet or testnet, and the testnet has a free faucet, meaning you can run your entire bot end-to-end against real market plumbing with fake money before risking a cent. That's the ideal proving ground: real order flow, zero downside. Practise on testnet until the boring parts (reconnects, partial fills, the kill-switch) are bulletproof.
Educational content about software design, not financial advice and not a recommendation to trade with leverage. Automated systems can and do fail; perpetuals carry high risk of total loss. Do your own research.