Zhiyong_AI
Home / Guides / Automated Trading Failure Modes

Three Ways Automated Trading Fails: Disconnects, Rate Limits and Parameter Drift

By Qin ShenUpdated 2026-09-02About 9 min read
Zhiyong AI site cover image; this guide covers three ways automated trading programs fail at runtime

Hand a strategy over to a program and run it automatically, and the place it really costs you is often not the strategy itself but the runtime: the program is still running, but it has stopped doing what you think it's doing. These problems cluster in three places — disconnects, rate limits and parameter drift. The first two throw errors; the third doesn't, which is exactly why the third is the most expensive. Below we take them apart one at a time, then finish with three operating rules you can put to use straight away.

Whether a strategy is right and how a program dies are two separate things

A backtest has no network. No request timeouts, no API turning you away, no "this stretch of the market looks nothing like the one you tuned your parameters on." Live trading has all three.

So the failures of a trading program can be looked at in three layers:

  • Strategy-level errors — the idea never held up in the first place. A backtest can catch part of this layer.
  • Execution-level errors — the order didn't go out, went out at the wrong price, or slipped more than expected. This layer at least leaves a trace you can find in the logs.
  • Runtime breakdowns — the program is alive, the process hasn't exited, the logs are still scrolling, but its state, its request quota and its parameters have come loose from the real world.

The third layer is the hardest, because it doesn't look like a fault. This article covers only the third layer.

Disconnects: the orders are still there, the thing making decisions is gone

First, the point that's easiest to get mixed up: orders already resting on the platform don't disappear because you went offline. They sit in the platform's matching system, not in your program. If the price gets there they still fill; if a condition triggers, it still triggers. That lets a lot of people breathe a sigh of relief — about the wrong thing.

Because what a disconnect really cuts off is the other half: your program can't receive fill reports, can't send new instructions and can't compute new signals. So one line is worth remembering — "the position is safe" and "the strategy is safe" are two different things. The position may be sitting there perfectly fine the whole time, but the brain managing it has gone offline.

The worst setup is a stop-loss written into your own program — the program watches the price and then sends a closing order — instead of one placed on the platform in advance. In that case a disconnect means the stop simply vanishes, and when the market moves against you there's nothing there to catch it. Any protective order that can be placed on the platform shouldn't be left in local logic.

There's another trap after reconnecting. The program is back, but the state in its memory is frozen at the moment before the disconnect: it thinks an order hasn't filled when it filled long ago; it thinks it's flat when it already holds a position. Then it carries on placing orders on that wrong premise, without a single error along the way.

From experience

The incident that stuck with me most wasn't a strategy losing money. A program lost its connection to the API for a short stretch in the middle of the night, and after reconnecting it went on sending orders based on the stale state in its memory. The logs showed nothing unusual and every request succeeded; the only problem was that the position it believed it held no longer matched the real position in the account. Since then I've given every trading program the same startup step: the first thing it does after reconnecting is pull the real positions and open orders again, and if they don't match, it stops and waits for a human instead of guessing its way forward.

Rate limits: the most common way to go down is running yourself into them

Every API caps how often you can call it. Go over, and at best your requests get rejected; at worst you're temporarily blocked. The exact number of calls, the time window they're counted over, how weight is split across endpoints — all of this differs from platform to platform, and between endpoints on the same platform. Go by the API documentation you're actually using, and don't copy numbers from someone else's article; that kind of number goes out of date fast.

In normal operation, though, hitting a rate limit is less common than you'd think. What really runs people into it is what happens after an error: a request fails, the program retries immediately, it fails again, it retries immediately again… a loop like that can burn through the whole quota in a few seconds. Then, at the very moment you most need to cancel an order, you find the cancel request can't get out either.

What makes this path so dangerous is that it amplifies: what started as a brief network blip gets turned by the retry logic into a complete loss of contact. A small glitch escalates into an incident, and the step in between is the rate limit.

The proper approach is retrying with backoff. The key points:

  • Don't retry immediately after a failure; wait a short while first.
  • Stretch the wait when failures keep coming; a common approach is to double the interval each time.
  • Add a little random jitter to the interval, so several programs or loops don't lock into the same rhythm, retrying together and failing together again.
  • Set a ceiling: after a certain number of consecutive failures, stop and raise an alert for a human to handle — don't retry forever.

Also give your requests priorities. A failed market-data query can back off slowly, but "lifeline" requests such as cancelling orders and closing positions need headroom kept in reserve. Don't let a loop that polls prices at high frequency eat up the bit of quota you'll need at the critical moment.

Parameter drift: no errors, it just quietly stops fitting

A grid's upper and lower bounds and its spacing, the period length of a trend strategy, the percentage used for a stop-loss — every one of these parameters was tuned on a particular stretch of the market. The assumption you made while tuning, without ever saying it out loud, was: volatility from here on will be roughly what it was then.

Once the market shifts into a different state, that assumption no longer holds. But nothing will tell you. The program throws no errors, the API returns everything as normal, the logs are spotless; it just keeps placing orders with a set of parameters that no longer fits. The two failures above at least send a signal — disconnects throw errors, rate limits come back as rejections — while drift sends none at all.

The way it shows itself is usually subtle, and you only see it if you go looking:

  • Fill frequency is clearly out of line with what you expected when you set the parameters: either nothing happens for ages, or it churns back and forth like mad.
  • In a range-type strategy, the price hugs one side for a long time and the grid levels on the other side never get used at all.
  • The profit-to-loss ratio per trade is getting worse: you're still making money, but the ratio between what you make and what you lose isn't what it used to be.

The fix isn't to "repair" but to "review". Set yourself a fixed schedule, and when it comes round, pull the actual fills for that period and line them up against the assumptions you made when you set the parameters: Has the size of the swings changed? Has fill frequency changed? Is the price still inside the range you drew?

As for how often to review, strategies run at such different paces that there's no universal number to copy. What matters is that someone actually does it, instead of it sitting forever on the "when I get a moment" list.

Put the three side by side: the difference is whether there's a signal

Line the three failures up and you'll see that what really decides how hard each one is isn't the size of the consequences but whether it tells you on its own:

Failure modeThrows an error?How you find outWorst case
DisconnectYesLogs stop, the heartbeat times out, no fill reports come backThe local stop-loss stops working and the position is left unprotected; after reconnecting, it keeps trading on stale state
Rate limitYesRequests are rejected and error codes come backYou can't cancel when you most need to; a small blip escalates into an incident
Parameter driftNoOnly by actively reviewing your fill historySlow, quiet losses over a long period; by the time you notice, you've already been losing for a while

The first two can be contained with engineering: add heartbeats, add alerts, add backoff. The third has no engineering fix; it only gets caught by a person who regularly sits down and looks. That's also why plenty of people with solidly written programs still come unstuck on the third — the first two come with a reminder, the third doesn't.

One more thing in passing: these three failures share an upstream problem, which is that the market data your program sees may itself be wrong. Different data sources, different price definitions, different latency — at any one moment there can be several "current prices". A program working from the wrong definition is making decisions on a skewed basis, even if nothing at all goes wrong at runtime. That's a subject of its own and isn't covered here.

Three operating rules

None of them is complicated, but they have to be in place before you start running; patching them in afterwards is usually too late.

Put these three in place before you start:
· Before opening a trade, ask: "If I disconnect right now, what happens to this order?" If you can't answer, don't open it yet. The answer usually points straight to one action: place the protective order on the platform instead of leaving it in local logic.
· Give your automation a switch that stops it in one step. The requirement is that within a few seconds it stops and sends no new orders — not "edit the config and redeploy". When something really does go wrong, you won't be in the mood to edit code.
· Regularly review whether the parameters still fit. Make it a fixed task and put it in your calendar; don't wait until you've lost money to remember. Parameter drift won't come knocking.

One more habit that isn't a rule but saves a lot of trouble: have the program regularly write its key state to disk, or push it somewhere you can see — current position, number of open orders, and the time of the last successful request. With those three numbers, one glance tells you which kind of failure you're dealing with in most cases. Without them, all you can do is dig through the logs and guess.

A reminder while we're here: if the idea behind your strategy, or the skeleton of your code, came from an AI, the parameters and thresholds it gave you are a starting point, not a conclusion.

One last thought

The biggest upside of automation is that it doesn't get tired, doesn't fumble, and doesn't chase trades on emotion in the middle of the night. The price is that it also never senses that something is off. A person watching the market will instinctively stop when things start to look wrong; a program won't. It will go on executing last month's thinking indefinitely.

So when you judge whether a piece of automation can be trusted, don't just look at the backtest curve. Look at three questions: what happens when it disconnects, what happens when it hits an error, and who notices when its parameters go stale. Once you can answer all three, then talk about returns.

Read next: for where the price a script reads comes from and how stale it can be, see Data Sources, Latency and Price References. If you'd like to switch topics and look at something hands-on, try Can You Buy US Stocks with USDT? and No Brokerage Account? How to Buy Apple and Tesla Stock With a Crypto Wallet.

This page contains no referral links and no invite code. Wherever it says "the platform" or "the one you use", that's generic and doesn't point to any specific platform. For this site's disclosure policy and risk disclaimer, see Disclosure and Risk Notice.