kalmanGrid

kalmanGrid — Fixes

ENGINEERING COMPLETEAudited 2026-09-12· hand-written (no shared engine) engine· quantroduction· spot

Every defect the audit found and how it was repaired — the same measurements as the engineering record, without the code.

4 issues found and repaired — 2 defects, 2 warnings.

# Issue Severity Surface
1 The three Kalman filter settings in the GUI were wired to nothing DEFECT user inputs
2 The header called a long-only spot grid "Delta-Neutral" WARNING documentation
3 Any setting typed as 0 was silently ignored — including the harness's own DEFECT user inputs
4 A stray colour and an unaligned framework log line WARNING palette

Every fix was verified by re-running the full backtest across all 7 markets and comparing the result record against the pre-fix baseline. Where a fix is stated to change no behaviour, the two records are identical to the byte.


The three Kalman filter settings in the GUI were wired to nothing

Severity DEFECT · Surface user inputs · Sites 7

A Kalman filter is defined by its noise parameters: process noise on each state, and observation noise. This strategy exposes all three in the Gunbot GUI as KG_KF_Q_PRICE, KG_KF_Q_VEL and KG_KF_R, and prints them in its own settings readout. The filter read KG_Q_PRICE, KG_Q_VEL and KG_R. Setting any of the three from the GUI did nothing at all.

Why it matters. These are not peripheral settings — they are the parameters the entire strategy is built on. Process and observation noise determine how tightly the filter tracks price, which determines where the grid rungs sit, which determines whether it trades. An operator tuning them from the GUI would have seen the readout change and the behaviour not change.

Worse, three sources disagreed on the values. The GUI editor, the strategy's own readout, and the live filter each carried a different default for observation noise:

The same three settings, as described in three places

Parameter GUI editor settings readout live filter name the filter read
Process noise, price KG_KF_Q_PRICE = 0.001 KG_KF_Q_PRICE = 0.05 0.001 KG_Q_PRICE
Process noise, velocity KG_KF_Q_VEL = 0.0001 KG_KF_Q_VEL = 0.005 0.0001 KG_Q_VEL
Observation noise KG_KF_R = 0.01 KG_KF_R = 0.05 0.3 KG_R

Three values for observation noise — 0.01, 0.05 and 0.3 — across the control the operator turns, the readout they check, and the code that runs. Only the last one was in force, and no GUI input could reach it.

The fix. The filter now reads the GUI names first and falls back to the unprefixed legacy names, so a GUI setting takes effect while anyone who had set the undocumented KG_* form keeps working. The settings readout was changed to the same expression and the same defaults, so it reports what is actually in force. The editor's KG_KF_R default was corrected from 0.01 to 0.3 to match the filter, and its range widened to cover it.

The GUI knob's effect on LINK, 3 years — it had none before, and a large one now

Setting buys sells return
unset (default R = 0.3) 32 37 20.44%
KG_KF_R = 3.0 — the GUI name 9 5 -0.68%
KG_R = 3.0 — the legacy name 9 5 -0.68%

Effect on live behaviour. None at the shipped defaults — the full 3-year, 7-market run is byte-identical before and after, because neither name is set by default. The change is visible only to an operator who sets one of the three, which previously did nothing.

Scope beyond this strategy. Found by diffing this file's own settings-readout block against its live P block. The same class of mismatch cannot currently be detected automatically on any of the 79 Quantroduction strategies — see the note at the end.


The header called a long-only spot grid "Delta-Neutral"

Severity WARNING · Surface documentation · Sites 1

The second header line described the strategy as "Gunbot Custom Strategy for Spot Markets (Delta-Neutral)".

Why it matters. It is a long-only spot grid. It can be long or flat — never short, never hedged — so its delta is greater than or equal to zero by construction and is never neutralised. Delta-neutral describes a position whose directional exposure has been deliberately cancelled, which is not what this does.

What the measurement does show is more interesting and more useful: exposure is 0.1% of bars, so the strategy is almost always flat. That is a real and notable property, and it is not the same claim.

Measured exposure, 3 years x 7 markets

value
Median time in a position 0.1% of bars
Round trips per market 1 to 37
Direction ever taken long or flat only

The fix. Removed "Delta-Neutral" from the title line, replaced it with "long-only", and recorded why in place rather than deleting the claim silently.

Effect on live behaviour. None. Comments only.

Scope beyond this strategy. The same claim was on volHarvester and was corrected there. Worth checking on every strategy whose header carries it.


Any setting typed as 0 was silently ignored — including the harness's own

Severity DEFECT · Surface user inputs · Sites 40

Every numeric setting was read through a fallback idiom meaning use the operator's value, or the baked default. Zero is falsy in JavaScript, so a setting of zero was replaced by the baked default with no warning.

Why it matters. Zero is a meaningful value for most of these and the only way to turn several of them off. The same bug was also discarding the backtest harness's WARMUP_CYCLES: 0, which it passes because the engine already withholds a 2,600-bar warmup — so the harness had been asking for no warmup and this strategy used 10.

Why the measured numbers moved — BTCUSDT, 3 years, warmup isolated

Run buys sells return
original, harness asks warmup=0 (ignored → 10) 9 4 0.0080%
fixed, harness asks warmup=0 (honoured) 1 1 -0.0067%
fixed, warmup forced to 10 9 4 0.0080%

The fixed file at warmup=10 reproduces the original exactly, which proves the warmup setting was the whole difference and nothing else in this fix altered behaviour.

The fix. Replaced the idiom with a reader that separates "not set" from "set to zero", returning the default only for undefined, null, "" and a non-numeric value.

Effect on live behaviour. Identical at every setting that previously worked; the measured numbers move only for the isolated warmup reason above.

Scope beyond this strategy. Pack-wide: 1,743 sites across 70 files. This file has the most of any audited so far.


A stray colour and an unaligned framework log line

Severity WARNING · Surface palette · Sites 4

Six uses of #888, which is not one of the eight canonical palette colours, and one [Q×G] framework log line emitting without the pack's separator so it did not line up in the terminal.

Why it matters. The palette exists so one meaning has one colour everywhere — the terminal, the side panel and the chart. A stray grey breaks that, and an unaligned log line breaks the column an operator scans down.

The fix. The #888 sites were not all the same meaning, which is why the automatic hue mapper was not left to decide alone: two were the bid/ask reference lines, which became MUTED grey to stay visually distinct from the strategy's own computed levels, and one was a KG paused (no funds) marker, which became WARN amber — the palette reserves amber for exactly that, a strategy that wanted to act and could not. The framework log line keeps its [Q×G] identity and gains the separator, rather than being routed through the strategy emitter which would misattribute it.

Effect on live behaviour. None. Colours and log text. Verified by re-running the full 3-year, 7-market backtest and diffing the result record — identical to the byte.

Scope beyond this strategy. The [Q×G] framework block is in 33 files with 17 such call sites, none of which was aligned. The fixer now handles them.