Making something run automatically and having it actually get handled to completion turned out to be two different sentences This is the English version of a post originally written in Korean for my algorithmic trading system devlog (new tab). I designed this system to judge and trade on its own, without needing human approval for each decision. The order execution and safety-guard layer (new tab) was built around that same goal. Over the past month, though, there were three separate moments where I had to step in and act directly on the live account. Each one failed for a structurally different reason. 1. An allocation rule structurally starved one order I noticed a particular ticker had a sell plan queued for several days running, yet it never actually went out. The system kept nominating it as a sell candidate every day, but the order never reached execution. The cause was the rule that splits the daily trading budget across multiple rounds. This position's order size was consistently larger than whatever sell budget remained that day. No matter how the rounds were reordered, it could never clear. The budget cap itself was working exactly as designed. The problem was that the underlying assumption — "if it doesn't clear this time, it'll clear next time" — never held for this position. New opportunities kept arriving, but none of them was ever big enough. I executed the one blocked order by hand. It was an irreversible sell on the live account. Afterward, I reworked the allocation rule itself so the same starvation pattern couldn't recur. 2. A safety guard confused a snapshot with a cumulative reading On a different day, the opposite kind of failure happened. A guard meant to detect cumulative drawdown wrongly blocked two legitimate buy orders. The index was nearly flat that day, but the loss figure this guard was tracking read much larger. Looking closer, the guard was designed to measure "decline from peak," but the current value it compared against was an intraday snapshot. A brief intraday swing pushed the cumulative metric up, tripping the guard in a situation where it shouldn't have fired at all. A gauge meant to track cumulative state and a gauge meant to read an instant were tangled together. I judged the two blocked buys were legitimate and executed them by hand. I then changed the guard to only react to "today's close versus yesterday's close," never an intraday reading. A separate, faster guard now handles sharp intraday drops instead. 3. The intervention path itself didn't know about "buying something new" While cleaning up after the second case, a third incident happened. I used the tool built to record manually-placed orders into the ledger, and the entry silently failed to land. That tool classifies any hand-placed trade into one of three categories: selling an existing position, adding to an existing position, or a trade unrelated to the system. But this particular buy was a brand-new position — something not in the ledger before. It didn't fit any of the three categories, so the tool defaulted it to "unrelated to the system." As a result, an asset I had actually bought briefly showed up as if it sat outside the ledger entirely. This tool existed specifically to handle human intervention. But when it was designed, nobody accounted for the case of a human opening a brand-new position from scratch. The intervention path itself was missing one form of intervention. I fixed it by following the correct sequence — booking the other day's sells first, then this buy — and verification confirmed the ledger matched the live account exactly. Adding this missing case to the classification logic is still on the to-do list. Putting the three together All three showed the same gap: "built to run automatically" and "actually carried through to completion" are two different sentences. The first had a rule in place, but that rule was structurally impossible to clear for a particular input. The second had a guard in place, but what it measured — instant versus cumulative — didn't match what it was meant to measure. The third had a human-intervention path in place, but that path itself didn't know about one form of intervention. In all three cases, I didn't know in advance that automation could miss this specific case. I only found out after it already had. Generalizing This reconfirmed something for me: the more fully automated a system is meant to be, the more important it is to build in a path for a human to step in at the last moment. Not because automation is imperfect in some abstract sense, but because you can't fully know in advance where it will break. But that intervention path is itself a system component, and it can carry the same kind of design flaw as anything else. The third case made that clear. Treating a human-intervention path as "just an exception handler, doesn't need much design" turns that path into the next failure point. So when I build an intervention path now, I try to keep a few things together. Make the fact that a human intervened get recorded automatically, rather than depending on memory, and enumerate the situations where intervention might be needed in advance — cases like "opening a brand-new position" are easy to miss. When intervention was needed because of some underlying rule — an allocation rule, a time-window design — fixing that root rule instead of patching around it each time matters just as much, so the same intervention doesn't keep recurring. The goal of automation isn't removing the human entirely. It's closer to making sure that when a human does have to step in, that intervention is safe and gets recorded.

3 Cases Where Fully Automated Trading Still Needed a Human
finaltype

