On 22 July 2026 gold moved $27 in an hour. Our broker disabled algorithmic trading during the episode.
Every close order our system sent was rejected.
The reasoning failure
When you design protections for an automated system, the default mental model is: "if X happens, I close". You write the condition, you write the close call, you test it, it works.
What that model silently assumes is that the close call can always execute. And that assumption is exactly the one that fails at the moment the protection matters.
It is not a rare case. It is a correlated one: the broker restricts execution precisely when the market moves hard, which is when your stop needs to fire. Your protection and its unavailability share a cause.
The three layers, and which one survives
Cerberus has three nets. It is worth looking at them by where they live:
1. Daily-loss cutout — lives in our code. Closes everything and pauses. Does not execute if the broker rejects orders.
2. Per-basket stop — lives in our code. Cuts the group of positions past a limit. Also does not execute.
3. Mirrored broker-side stop — lives on the broker's server, as a resting SL order on every position. Executes.
The third one is the only one that survived that episode. The first two are smarter, more configurable and easier to reason about. And that day they were worth zero.
Why we do not keep only the third
A resting order on the server is dumb: it is a price, and that is all. It knows nothing about the day's accumulated loss, nothing about how many positions you hold or how they relate, and it cannot pause the system until you come back.
So the layers are not redundant, they are complementary in failure mode:
- Logic in your code is smart but depends on you being able to act.
- The order on the server is dumb but executes no matter what.
The mistake is having only one of the two. Most systems have only the first, because that is the one that is comfortable to program.
The detail that nearly cost us
There is a subtler version of the same problem. We had a code-side exit that closed a position when profit retraced past a margin. On one tick jump, a position armed at +15.8 pips closed at −14.9. Between the code evaluating the condition and the order reaching the server, price was already somewhere else.
We replaced it with an order that rests at the broker and rides up with price. Now it executes at the level, not at the level plus the delay.
The rule we took away
If a protection only exists while your process runs and your connection responds, then it does not cover the scenario where your process or your connection is part of the problem.
That applies far beyond trading. A retry that lives in the client does not cover you when the client is what went down. A spend cap evaluated by your service does not cover you when your service is wedged. A timeout in your code does not cover you when your code never gets to run.
The useful question is not "what does my protection do when X happens?". It is "where does my protection live, and is it still alive when X happens?"
From building Cerberus at Tuurt Labs. High-risk instrument: trading leveraged CFDs can cost you your entire capital. This is not investment advice.