Summary
When price is constant over the stochastic window, highest_high - lowest_low == 0. The %K formula divides by zero, producing inf (not NaN). fillna(0) does not replace inf, so infinity enters the feature tensor, causing the RegimeDetector forward pass to produce NaN activations silently.
Evidence
src/features/regime_features.py line 239:
k_percent = 100 * (close - lowest_low) / (highest_high - lowest_low)
No zero guard. When flat: 0 / 0 for the numerator case produces NaN, but non-zero / 0 produces inf.
src/features/regime_features.py line 291: fillna(0) does not replace inf.
Fix
Add: k_percent = k_percent.replace([np.inf, -np.inf], np.nan).fillna(50.0) — default to midpoint (50) for flat price, which is the economically correct neutral value.
Summary
When price is constant over the stochastic window,
highest_high - lowest_low == 0. The %K formula divides by zero, producinginf(notNaN).fillna(0)does not replaceinf, so infinity enters the feature tensor, causing theRegimeDetectorforward pass to produceNaNactivations silently.Evidence
src/features/regime_features.pyline 239:No zero guard. When flat:
0 / 0for the numerator case producesNaN, butnon-zero / 0producesinf.src/features/regime_features.pyline 291:fillna(0)does not replaceinf.Fix
Add:
k_percent = k_percent.replace([np.inf, -np.inf], np.nan).fillna(50.0)— default to midpoint (50) for flat price, which is the economically correct neutral value.