Bot Engineering

Auditing Deriv Bot Logic: A Pre-Deployment Checklist

· 8 min read

Most bot failures on Deriv are not strategy failures. They are logic failures: a state variable that survives a restart when it should not, an order whose contract ID is never reconciled, a stop rule that fires after the loss it was meant to prevent. Backtests rarely expose these because a backtest is a price simulation, not an execution simulation. This checklist gives you a structured audit of three areas that backtests systematically miss: state handling, order lifecycle, and failure modes specific to synthetic indices. Run it before every deployment, and re-run it after every logic change.

Trading involves significant risk and you can lose your entire stake. Test every strategy on a demo account first.

State Handling

State is everything the bot remembers between ticks, blocks, and sessions. Audit it by asking one question per variable: where is it initialised, where is it mutated, and what happens if the process dies between those two points?

Start with a written inventory. For each variable, record its name, its initial value, its mutation points, and whether it should survive a restart. Typical offenders are consecutive-loss counters, cumulative session P/L, the current stake (especially under any progression), and flags such as “trade open” or “cooldown active”.

Check the following explicitly:

  • Initialisation on load. Every counter must be set at start, not inferred from the first tick. A consecutive-loss counter that defaults to “undefined” and is compared with a number will silently evaluate false in some runtimes, disabling your loss limit.
  • Persistence versus reset. If the bot stores state externally, decide deliberately whether a restart resumes the session or begins a new one. Resuming a daily loss counter is safer; resuming a “trade open” flag without reconciling the actual open contract is dangerous.
  • Single source of truth. The stake used for the next trade should derive from one place. If a progression, a manual override, and a recovery rule can all write to it, you have three sources of truth and no audit trail.
  • Type discipline. Strings from API responses compared to numbers, or floats used for money, produce off-by-a-cent errors that compound. Normalise to integers in the smallest currency unit where the platform allows it, or round explicitly at one defined point.
  • Boundary conditions. Test the counter at its limit minus one, at the limit, and one past it. The stop must fire at the limit, not after it.

A minimal rule set for state, expressed as DBot-style steps:

  1. On bot start: load configuration, set all counters to defined values, set `trade_open = false`.
  2. On each tick: if `dailyloss >= dailylimit` or `consecutivelosses >= maxconsecutive` or `drawdown >= max_drawdown`, stop the bot and log the trigger.
  3. On trade entry: set `trade_open = true` and record the proposed stake and the contract parameters.
  4. On trade close: update counters from the actual contract result, set `trade_open = false`, recompute the next stake from the single stake function.
  5. On any error or disconnect: do not mutate counters; enter a reconciliation state (see below).

If your progression has no hard cap on steps and stake, add one before anything else. ORSTAC recommends against martingale; where a progression exists, the audit must show a maximum number of steps, a maximum stake, and a ruin test on demo data before any live use.

Order Lifecycle

The order lifecycle is where most silent failures live. A Deriv contract is not a fire-and-forget request: it has a proposal, a buy, an open state, and a settlement, and each transition can fail independently.

Audit the lifecycle as a state machine with these states: idle, proposal requested, proposal received, buy sent, contract open, settled, reconciled. For each transition, write down the trigger, the timeout, and the recovery action.

  • Proposal expiry. Proposals have a validity window. If your bot computes a stake, waits for a signal confirmation, then buys against a stale proposal, the buy can fail or execute on parameters you did not intend. Re-request the proposal immediately before the buy, or verify its validity field.
  • Duplicate buys. A retry loop around the buy call without an idempotency guard can open two contracts from one signal. Guard with `trade_open` and with a record of the last proposal ID bought.
  • Orphaned contracts. If the process crashes after the buy but before the response is stored, the contract exists and the bot does not know. On restart, query open contracts and reconcile before trading. Never assume “no local record” means “no open position”.
  • Settlement matching. Match settlements to entries by contract ID, not by timestamp or by sequence. Timestamps collide under latency; sequence numbers drift after reconnects.
  • Partial failure. A buy that times out is not necessarily a buy that failed. Treat unknown outcomes as open until reconciled.

A worked example makes the cost of a missing reconciliation concrete.

Worked example. Suppose a bot risks 1% of a 1,000 USD demo balance per contract, so 10 USD stake per trade, and targets a session of 100 trades. Assume, illustratively, a 50% win rate at a payout of 0.95:1, meaning a win returns 9.50 USD profit and a loss costs the 10 USD stake. Expected profit per trade is (0.5 × 9.50) − (0.5 × 10.00) = 4.75 − 5.00 = −0.25 USD. Over 100 trades the expected result is 100 × (−0.25) = −25 USD. Now suppose a duplicate-buy bug fires on 2 of those 100 trades, adding two unintended 10 USD stakes with the same odds. The added expected loss is 2 × (−0.25) = −0.50 USD, and the added variance is larger than the expected figure suggests: two extra contracts can swing the session result by up to 20 USD in stake terms. The point is not the size of the number but that the bug is invisible in a backtest, which never sends a second buy.

For Multipliers, the lifecycle adds stop-loss and take-profit by price, which are platform-side orders. Audit that your bot does not also implement a local stop that can conflict with the platform one, and that a modification request is confirmed before you assume it applied. For fixed-stake contracts, there is no price stop: risk is controlled by stake, duration, and session limits, so the lifecycle audit must confirm those limits are enforced in code, not in your intentions.

Failure Modes in Synthetic Indices

Synthetic indices are generated continuously, including on weekends, which changes the failure profile compared with forex. Audit for the following.

  • Gap-free but not behaviour-free. Synthetic indices tick continuously, so you will not see weekend gaps, but you will see regime changes in volatility. A duration or barrier calibrated on one volatility regime may behave differently in another. Log the realised volatility alongside results so you can tell whether a drawdown is strategy failure or regime change.
  • Tick versus candle logic. If your bot evaluates on candles but executes on ticks, the signal and the fill can be separated by a full candle. State this explicitly and test the delay.
  • Duration and expiry. Short durations on fast indices mean many settlements per hour, which multiplies the effect of any per-trade bug. Compute your expected number of trades per session from duration and session length, and check your limits against that count, not against a guess.
  • Digits and barrier contracts. For digit contracts, the payout structure is not symmetric around 50%. Win rate alone tells you nothing; compute the break-even rate from the actual payout before judging any result. If a contract pays 0.95:1, the break-even win rate is 10.00 / (10.00 + 9.50) = 0.5128, or 51.28%. A 51% win rate loses money at that payout.
  • Disconnects. The API connection can drop mid-contract. The contract continues on the platform. Your bot must reconnect, re-subscribe, and reconcile, not restart from scratch and trade again.
  • Clock and timezone. Daily loss limits keyed to a local day boundary can reset early or late. Define the boundary explicitly and test it.

Limitations

This checklist does not validate your edge. It catches logic and execution defects; it cannot tell you whether the strategy has positive expectancy, and a bot that passes every item here can still lose money steadily. It does not replace a demo sample: run the audited bot on a demo account, record a sample, and only then consider real money at minimum stake. It does not model platform-side latency or liquidity, which depend on settings and conditions you cannot fully observe. It does not make a progression safe; a capped martingale can still lose the cap. And it does not substitute for written rules and a change process: any fix found during the audit should be versioned, tested, and recorded, never applied straight after a loss.

Frequently Asked Questions

Can a backtest catch these bugs? No, because a backtest simulates prices, not execution, so duplicate buys, orphaned contracts, and state resets do not exist inside it. Use the backtest as a filter for strategy logic, and this checklist as the filter for bot logic.

How large a demo sample is enough before going live? There is no universal number, but the sample must be large enough that the expected number of trades in your session limit is covered several times over, and it must be recorded. If your session limit is 100 trades, a 20-trade demo proves almost nothing about how the limits behave.

Does capping a martingale make it acceptable? A cap bounds the loss; it does not create an edge. With a hard cap on steps and stake, the worst case is a defined loss, which you must size against your 1% per-contract rule and your maximum drawdown, and you should run a ruin test on demo data before any live use.

Key Takeaways

  • Audit state first: every counter needs a defined initial value, one mutation path, and a tested boundary.
  • Treat the order lifecycle as a state machine with reconciliation on every restart and every disconnect.
  • Match settlements by contract ID, and treat timed-out buys as open until proven otherwise.
  • Judge results by expectancy and break-even rate, not win rate; at a 0.95:1 payout the break-even rate is 51.28%.
  • Run the audited bot on demo first, with hard automatic limits for daily loss, drawdown, and consecutive losses.

The ORSTAC repository hosts open-source bots you can use as reference implementations for this audit, and the Deriv API documentation plus the official Deriv API libraries define the lifecycle states your code must handle. Build and test on Deriv, where a free demo account is available to run the bots, and check the synthetic indices documentation and Deriv Bot pages for platform specifics before you deploy. Bring your audit findings and edge cases to the ORSTAC Telegram group so others can check their own logic against them.

Trading involves significant risk and you can lose your entire stake. Test every strategy on a demo account first.