DEV Community

finaltype
finaltype

Posted on Originally published at finaltype.github.io

Wrapping Up Notification Cleanup, a Performance Calc Error, and a Regression

Five days across a weekend — I finished cleaning up the notification system, found that paper-account performance math didn't quite match the real balance, and a day later ran into a small regression from the fix

This is the English version of a post originally written in Korean for my algorithmic trading system devlog(new tab).

Writing again after a few days. The weekend was uneventful, and the three weekdays were filled with wrapping up cleanup work, a performance calculation error I found in the process, and a small regression the following day.

Finishing up the cleanup work

First, I redefined the standard for judging cash deployment. The old standard was "is cash within the target allocation range," but that turned out not to describe the real situation well. Now it directly counts "how many buy proposals got rejected" and "how much usable limit went unused."

The notification system cleanup also entered its final stage around this time. It now has an allowlist signature, alerts sent by severity tier, quiet handling when things are normal, a daily summary, and a weekly "still alive" check-in. This is an extension of an earlier post(new tab) about process separation and reporting.

Performance math didn't match the real balance

While reviewing the performance report for the fully automated verification track, I noticed the return shown in the report didn't quite match the real account balance. It turned out the report was calculated from an internally kept trade ledger rather than the actual brokerage account, and fees and taxes weren't being properly reflected — skewing it slightly better than reality. On top of that, unsettled trades at end-of-day close were getting logged under the wrong date.

I fixed three things right away: a calculation method that properly reflects fees and taxes, a daily cross-check between the internal ledger and the real account that alerts or blocks on mismatch, and a new performance path calculated from the real account. Background on this verification track itself is in a separate post(new tab).

The same day, I caught a small bug in the ranking calculation too. The staleness check on input data wasn't wired at the per-ticker level, so on certain days some tickers were silently dropped from the model input. Fixed.

A regression the next day, but it stopped safely

The next morning, one of the previous day's fixes had subtly changed the cache-invalidation criteria, creating a timing issue where the cache got refilled at the wrong moment. That collided with an old race condition elsewhere, triggering repeated heavy recalculations — made worse by old and new code running simultaneously during an incomplete deployment.

Fortunately, the end result was just that trading safely stopped — no bad orders went out. I traced it to four spots and fixed them, and it was a good reminder of a lesson learned before: when you fix code, restart every resident process that imports that module, all at once.

Also this week

  • A backtest over a recent sharp-drop period showed good performance, but looking closer, most of the gains were concentrated in just a few crash days — too early to generalize, so I kept it as a reference only.
  • On the data-archive side, I reconsidered whether it's still worth collecting old news articles indefinitely. Decided to keep collecting, not to hunt for new signals but as insurance for future troubleshooting. Covered in more detail here(new tab).
  • Pushed the live-trading go/no-go decision point back to after August 11th, and clarified the criteria — separating "were there incidents" from "how consistently could it trade."

Two of the five days were quiet, and the other three were about confirming and re-checking whether the numbers were actually correct. Not a flashy stretch, but the kind of check I think is necessary before widening the scope of live trading.

Top comments (0)