kalmanGrid — Status & roadmap
Where this strategy is today
ENGINEERING COMPLETE — the code is correct, uniform and shippable. That is a statement about engineering, not about profitability; the performance verdict is separate and sits below it.
| Dimension | State |
|---|---|
| Correctness | 5 / 5 invariants pass |
| Console output | 34 tagged calls, 0 off-format |
| Side panel | 46 rows, padded to the 3-column grid |
| Chart marks | reference-levels |
| Palette | 8 / 8 canonical |
| GUI settings | 66 exposed · 0 read at runtime · 0 untunable · 0 inert |
| Deployed to a live install | Not yet — audited and staged, not yet shipped |
Performance verdict. Over three years on 7 markets it returns a median 0.3% against buy-and-hold's 39.2% — an edge of -38.5% — and is profitable on 4 of 7. On this window it is not a replacement for simply holding the asset, and nothing in these reports claims it is.
What it actually does
A spot grid whose levels are not fixed — they are anchored to a Kalman-filtered fair value that moves with the market.
The filter runs a two-state model, [price, velocity], observing the mid price. Grid rungs are placed at GRID_SPACING × ATR around the filter's price estimate rather than around the last trade, so the whole ladder drifts with the estimated fair value instead of being re-anchored by hand.
Two parts of it are more carefully built than the pack average, and both were verified against the code rather than taken from the header:
- The covariance prediction is the canonical
P⁻ = F·P·Fᵀ + Q, written out as explicit 2×2 matrix arithmetic with the transpose applied correctly. - Observation noise adapts per Mehra (1970). Mehra's relation
E[νν'] = H·P·Hᵀ + Ris rearranged to recover R from the empirical innovation variance —empiricalR = (innovVar − H·P⁻·Hᵀ) / scale— floored, then blended into the running estimate with a learning rate. The header is also honest about what is not implemented: Q is held at its configured floor, and Mehra's autocorrelation-based Q identification is absent. That caveat is accurate.
Safety: it pauses when the innovation z-score exceeds INNOV_PAUSE (6), which is the filter saying the observation no longer matches its model — a sensible condition to stop trading on.
Verified against the shipped strategy source, not its documentation.
The measured constraint
Time in market is 0.1%, over 113 round trips across all 7 markets and three years. Everything in the performance report rests on that fraction of the bars. A strategy out of the market 100% of the time is not therefore a low-risk one: the 0.3% drawdown happens entirely inside the time it is committed.
Settings, measured
This strategy does not use the engine config surface.
What to build next
Ordered by expected effect on the result, not by effort.
1. Re-tune the filter now that its settings are reachable
Highest priority
Until this audit the three parameters a Kalman filter is actually built on — process noise on price, process noise on velocity, and observation noise — could not be set from the Gunbot GUI. The GUI wrote KG_KF_Q_PRICE, KG_KF_Q_VEL and KG_KF_R; the filter read KG_Q_PRICE, KG_Q_VEL and KG_R. Turning them changed nothing.
They now work, and they matter a great deal. Raising observation noise to 3.0 on LINK takes the strategy from 32 buys and +20.4% to 9 buys and −0.7%. That sensitivity means the shipped values have never been measured against alternatives, because until now they could not be. A sweep over Q/R is the single highest-value experiment here — and because R adapts at runtime, what is being tuned is the starting R and the floor, which is a narrower and more tractable question than it first looks.
2. Work out why it almost never trades
Highest priority
Measured exposure is 0.1% of bars — across three years and seven markets it holds a position on roughly one bar in a thousand, with 1 to 37 round trips per market. The result is dominated by a single market: LINK returns 20.4% with a profit factor of 6.9, while BTC managed exactly one round trip and SOL nine.
That is not a strategy with a small edge, it is a strategy that rarely expresses one, and the median return of 0.3% is close to meaningless as a sample. Before any tuning, find out which gate is binding: the innovation-z pause at 6, the grid spacing relative to ATR, the exposure cap, or the filter simply tracking price so closely that the mid rarely sits a full rung away from fair value. The last of those is the interesting possibility — a filter tuned to follow price leaves no gap for a grid to trade inside, which would make the Q/R tuning above the direct cause and the direct remedy.
3. Judge it on LINK-like markets, not on the median
High priority
The per-market spread is the widest of any strategy audited so far: +20.4% on LINK against −0.0% on BTC, where buy-and-hold returned +130.8%. Profit factor ranges from 0.00 to 7.71 and win rate from 0% to 76%.
With one round trip on BTC the numbers there carry no information at all. The honest reading is that this strategy has conditions it suits and conditions in which it simply does not act, and the median across seven markets hides both. Worth doing: classify the markets by whether the filter's innovation stayed inside the pause threshold, and report the strategy only on markets where it actually traded enough to be measured.
4. Consider whether the ladder should ever cut a loss
Worth testing
Like the other accumulate-and-scale strategies in this pack, the sell paths require a gain. Unlike them, the win rate here is genuinely mixed (0-76%) rather than a structural 100%, which means positions are being closed at a loss somewhere — worth confirming which path does that and whether it is intended, because the design does not obviously include one.
If there is no deliberate loss-cutting path, then the mixed win rate is coming from fee drag on scratch trades rather than from risk management, and that is a different thing to know.
5. The settings measurement does not yet cover this lineage
Read before acting on the others
The audit proves which settings a strategy reads by running it with a recording proxy over its config object. That works for the 348 Gunbot Quant files, which read through one shared config accessor, and not for the 79 Quantroduction files including this one — they build a plain settings object straight from the GUI values.
The three dead Kalman knobs were found here by diffing the settings-display block against the live P block by hand. A proxy over P would have caught them automatically, and would cover all 79 files at once. This is the third strategy in a row where that gap hid a real defect, which makes it the highest-value improvement to the audit tooling itself.
Operator output, measured
Everything below was read out of the strategy file by the presentation audit, not taken from its documentation. These are the surfaces an operator actually watches: the terminal log, the side panel, the chart, and the settings the GUI offers.
- Tagged, aligned, coloured
- 34
- Raw and off-format
- 0
- Exempt (object and error dumps)
- 18
Every non-exempt line carries the strategy name, an event tag and the palette colour for that tag, so one terminal running many pairs stays readable.
- Data rows
- 46
- Section headers
- 9
- Rows with no tooltip
- 0
- Padded to the 3-column grid
- yes
- Model
- reference-levels
draws price levels into customChartTargets and no per-trade marks, so there is no intent-vs-fill distinction to get wrong
- Non-canonical colours
- 0
One colour per meaning, identical in the log, the panel and the chart — the eight canonical roles.
Settings the GUI exposes
66 settings appear in the Gunbot strategy editor for this strategy. Which of them the code reads has not yet been measured for this lineage: it does not use the shared config surface, so there is nothing to wrap with a recording proxy.
PERIODTRADING_LIMITKG_TLKG_CAPITAL_ALLOCALLOC_PCTALLOC_CONFIRMEDALLOC_SPLIT_TOLALLOC_ENFORCE_SPLITALLOC_AUTO_REBALANCEALLOC_RESERVE_PCTKG_GRIDKG_GRID_LEVELSKG_GRID_SPAN_PCTKG_GRID_SPACINGKG_GAINKG_MAX_DCAKG_DCA_DECAYKG_COMPOUNDKG_Q_PRICEKG_Q_VELKG_RKG_INNOV_PAUSEKG_CALIBKG_EM_ENABLEDKG_EM_INTERVALKG_EM_WARMUPKG_EM_LRKG_R_FLOORKG_Q_FLOORKG_MAX_EXPKG_MAX_DDKG_FEEKG_MAKER_FEEKG_SPLOG_LEVELWARMUP_CYCLESMIN_ORDER_QUOTEBE_GUARDNO_POST_ONLYKG_TRACEVERBOSE_LOGSVERBOSE_INTERVAL_MINBE_GUARD_BLOCK_MARKET_SELLSSCRATCH_LIVENESS_MINCONSEC_RESET_CYCLESDRIFT_ATR_FRACSKEW_QTY_MAXSKEW_QTY_TARGETPORTFOLIO_INCLUDEPORTFOLIO_EXP_BUDGETPAIR_EXP_BUDGETDISABLE_BREAKER_WINDDOWNTRACE_ALLKG_DCA_FROM_HOLDINGKG_KF_Q_PRICEKG_KF_Q_VELKG_KF_RKG_PERIODSTRICT_LITERATURENO_CLOSE_MARKETQUANTRODUCTION_TRACERESET_BREAKER_ONCERESET_STATS_ONCEKG_COUNT_WINDOW_CYKG_PENDING_REAP_CYSPREAD_PNL_JUMP_GUARD
Open presentation findings
- NOTE · inputs — GUI editor entry is linked by the marker `kalmangrid` rather than the filename `kalmanGrid` (case-insensitive). It resolves, but a rename of either side breaks the link silently.