Kalman Grid — Patch Update
Audit / Issue Found
The grid strategy was booking every buy rung and every sell rung as a completed trade the moment it placed the order, before the exchange had actually filled anything. Because these rungs are post-only and may sit on the book for a long time, or get cancelled when price moves away, the bot's stats and its internal "what do I own at what average price" record were running ahead of reality.
Before the patch
Trade count went up every time the bot placed a rung, even if the rung never filled. The internal cost-basis list grew with phantom buys, which then dragged the calculated average entry price away from the truth. Sell rungs immediately credited profit to the running total even if they sat unfilled and were later cancelled. Win and loss tallies were based on the fictional profit-and-loss, not on what actually happened.
After the patch
Placement now only records "I placed a rung at price X for size Y" as a pending intent. None of the stats move. The bot still uses the same resting-rung logic to avoid double-placing on the same level.
A balance detector then watches the actual asset balance on the exchange. When the balance goes up, that is a real buy fill: the detector walks the pending-buy queue oldest-first, takes the matching size out, adds the actual filled rung to the cost-basis list, recomputes the true average entry price, and bumps the trade count and grid-buy count by one. When the balance goes down, that is a real sell fill: the detector calculates realized profit from the cost-basis-minus-fees, updates the running profit total, ticks the win or loss column accordingly, and if the position is essentially gone resets the entry accounting.
A safety reaper prunes pending rungs that have been sitting around for more than thirty cycles without filling, so they cannot pile up forever.
The emergency stop-loss still books its own profit-and-loss immediately so nothing is lost if the exchange clears the position before the next cycle. A per-cycle tag tells the detector to skip the duplicate when it sees the same drop.
Bottom line
Stats now reflect what the exchange did, not what the bot tried to do. The internal "what I bought at what price" record is honest, so the sell logic that depends on it is making decisions on real fills instead of phantom ones.
Follow-up correctness audit, same day
Two real issues were found and fixed in a deeper review of the new fill detector.
First, orphan buy fills. The detector matches an observed balance increase against the queue of placed-but-not-yet-filled rungs. If the queue is empty when a buy hits, for example because the safety reaper already dropped the matching rung after waiting too long, or because cash was added externally, the bot used to count the trade but never recorded the buy in its average-cost ledger. That meant the next sell would calculate profit against a stale average. The fix detects this remainder, anchors it at the current mid price as a synthetic entry, bumps a separate external-buys counter, and warns in the log so you can see it happened. From this point on, sells price their profit against an honest average.
Second, the carry-over window between a stop-loss and the detector was only one cycle. On a slow exchange or a market order that fills in pieces over several ticks, any straggler would be double-counted as a fresh sell. The window is now five cycles by default, tunable per pair, so stragglers are absorbed correctly.
Five other findings were checked. Three were false positives. Two were minor logging or display concerns that did not warrant code changes.