The last stretch of live-trading prep was too hectic to write day by day, but these two days packed in a data bug and this project's first real trade
This is the English version of a post originally written in Korean for my algorithmic trading system devlog(new tab).
Bundling two days into one post. The final stretch of live-trading prep was too hectic to write day by day. Even so, quite a few important things happened in this project over these two days, so I'm writing them up together.
What I thought was a "hallucination" turned out to be a bug
I was in the middle of swapping out one price-data source for another. After the swap, something strange started happening — even before market open, price indicators would occasionally show values from several days earlier.
I'd seen a similar symptom before, so at first I assumed "the AI is making up weird prices again" and moved on. This time I actually dug in, and the cause turned out to be completely different.
The new data source was returning values oldest-first instead of most-recent-first, and the code hadn't noticed — it was trusting the first value in the list as "the most recent." It was just a reversed order, but on the surface it looked exactly like the AI insisting a days-old price was today's price.
A slightly embarrassing but useful lesson: check the data ordering before doubting the AI's judgment. Fixed it to explicitly verify and sort the order.
Automated trading stopped for half a day
The same day, a small code change elsewhere unintentionally touched the paper-trading (simulated funds) auto-trading loop. From that morning on, every order had quietly been getting rejected.
The cause was a marker that needed to be set in several places, missing from a few of them. Fortunately this was paper trading, not the live account, and things recovered on their own from the next trading cycle.
Patched the missing markers back in. This is the kind of mistake that would have been much more serious on a live account, so it was fortunate this surfaced on paper trading first.
Locked down the retired brokerage's live-order path for good
I'd mentioned a few days ago that I decided to switch brokerages, and I finished the cleanup that day. Locked the old brokerage's live-order path behind three separate layers, so no real order could accidentally go out through it.
Leaving an already-retired path loosely open is a lesson this project has learned the hard way more than once — it always causes trouble eventually. This time I handled it right away instead of putting it off.
And the next day, the first real order went out
Put a very small amount of money into the live account, bought one stock, and immediately sold it back. It was a single round-trip trade meant to confirm that the path I'd only ever verified with paper trading works end to end on the live account too.
The order, went out, filled, and showed up correctly in the ledger — the whole process went exactly as planned. Since it was a round trip, the resulting P&L was just a tiny amount equal to trading costs, and making money was never the point of this trade.
All the doubting of the safeguards and bug-hunting from the day before turned out to be in service of this one trade. The fact that the door to live trading is now actually open is the real result of these two days.
Two more bugs caught just before
Before placing the real order, I ran a read-only check against the live account (no orders placed, just inspection) first. It turned up two real problems.
One was that the code for checking balance, holdings, and order status was still sending requests in the paper-trading format even against the live account, so the live server was rejecting all of them. Fixed it to branch the request format by live vs. paper trading.
The other was that the fill-confirmation logic only checked one trading path. Orders filled through a path outside regular trading hours were an entirely invisible blind spot — left alone, that could have caused the same order to be misjudged as "unfilled" and resubmitted. Fixed it to check both paths.
Both were the kind of problem that could only really be caught right before real money was on the line, so I'm glad they surfaced when they did.
Set down the last piece of a weeks-long cleanup
The last piece of a structural cleanup that had been running in parallel with live-trading prep also wrapped up that day. It was the piece deliberately saved for last because it was judged the highest-risk part.
Once I actually opened it up, the live-trading path was already safe enough. The old remaining path didn't need to be rebuilt urgently, so I decided not to rush it. Rather than rushing to fix something risky, I chose to confirm it wasn't risky and set it aside with room to spare.
Also this stretch
- Upgraded one monitoring device that used to just alert on anomalies to one that takes action directly — a decision made only after it passed several rehearsals.
- Opened one more intraday order-flow data collection channel on the data archive(new tab) side.
- Rehearsed several scenarios on paper trading — a network disconnect, a duplicate order about to go out, a sharp-drop trading halt — and everything behaved as intended.
- Changed the allocation policy to pre-set the split between the two exchange boards, so a single market can't monopolize allocation purely on score.
- Reviewed splitting a single position purchase into multiple tranches, but decided against building it — at the current scale, the added complexity outweighed the benefit.
Looking back, these two days held two opposite feelings at once. One day was the embarrassment of doubting the AI's judgment only to find out it was a data problem; the next was the satisfaction of seeing something long-prepared actually work.
Top comments (0)