Summary
src/data/regime_labeler.py and src/strategies/factory.py use the same regime integers (0–7) but assign them completely different semantics. The neural network is trained on labels from the regime labeler, then makes inferences interpreted by the factory. The result: bull-market strategies are recommended in bear markets, and vice versa.
The mismatch
| Regime int |
Labeler (training labels) |
Factory (inference mapping) |
| 0 |
BULL_TRENDING |
Deep Bear Market ← INVERTED |
| 1 |
BEAR_TRENDING |
Bull Trending ← INVERTED |
| 2 |
HIGH_VOLATILITY |
High Volatility Trending |
| 3 |
LOW_VOLATILITY |
Uncertain/Transitional |
| 4 |
SIDEWAYS_RANGING |
Low Volatility/Sideways |
| 5 |
RECOVERY |
Moderate Bull/Sideways |
| 6 |
DISTRIBUTION |
Recovery Phase |
| 7 |
CRISIS |
High Volatility Uncertain |
| 8 |
(never produced) |
Extreme Volatility ← unreachable |
When the labeler identifies a BULL_TRENDING market (regime 0) and trains the neural net on it, the factory maps regime 0 to "Deep Bear Market" and recommends LONG_PUT, BEAR_PUT_SPREAD, BEAR_CALL_SPREAD. The model has learned to output 0 for bull markets, but the factory deploys bear strategies when it sees 0.
The inversion is not just regimes 0 and 1. Almost every regime name is misaligned: RECOVERY (5) maps to "Moderate Bull/Sideways" instead of recovery strategies; DISTRIBUTION (6) maps to "Recovery Phase"; CRISIS (7) maps to "High Volatility Uncertain" instead of crisis/defensive strategies.
Secondary bug
The factory defines 9 regime mappings (0–8), but RegimeDetector outputs exactly 8 regime probabilities (num_regimes=8). Regime 8 ("Extreme Volatility") is structurally unreachable during inference — the argmax of 8 outputs is always 0–7.
Correct fix
One of the two systems must be updated to match the other. The labeler's naming reflects standard financial terminology (BULL_TRENDING, BEAR_TRENDING, CRISIS) and was presumably designed first. The factory mapping should be updated:
# Correct factory mappings aligned with labeler RegimeType
0: [LONG_CALL, BULL_CALL_SPREAD, BULL_PUT_SPREAD], # BULL_TRENDING
1: [LONG_PUT, BEAR_PUT_SPREAD, BEAR_CALL_SPREAD], # BEAR_TRENDING
2: [LONG_STRADDLE, LONG_STRANGLE, ...], # HIGH_VOLATILITY
3: [CALENDAR_CALL, CALENDAR_PUT, SHORT_STRADDLE, ...], # LOW_VOLATILITY
4: [IRON_CONDOR, SHORT_STRANGLE, BUTTERFLY], # SIDEWAYS_RANGING
5: [BULL_CALL_SPREAD, LONG_CALL, BULL_PUT_SPREAD], # RECOVERY
6: [BEAR_CALL_SPREAD, IRON_CONDOR, ...], # DISTRIBUTION
7: [LONG_STRADDLE, LONG_PUT, BEAR_PUT_SPREAD], # CRISIS
Also reduce factory._regime_mappings to 8 entries (0–7) and remove the unreachable regime 8, or update RegimeDetector to num_regimes=9.
Any trained model weights produced under the current misalignment should be discarded — they have learned to associate features with the wrong regime integers.
Summary
src/data/regime_labeler.pyandsrc/strategies/factory.pyuse the same regime integers (0–7) but assign them completely different semantics. The neural network is trained on labels from the regime labeler, then makes inferences interpreted by the factory. The result: bull-market strategies are recommended in bear markets, and vice versa.The mismatch
When the labeler identifies a BULL_TRENDING market (regime 0) and trains the neural net on it, the factory maps regime 0 to "Deep Bear Market" and recommends
LONG_PUT,BEAR_PUT_SPREAD,BEAR_CALL_SPREAD. The model has learned to output 0 for bull markets, but the factory deploys bear strategies when it sees 0.The inversion is not just regimes 0 and 1. Almost every regime name is misaligned: RECOVERY (5) maps to "Moderate Bull/Sideways" instead of recovery strategies; DISTRIBUTION (6) maps to "Recovery Phase"; CRISIS (7) maps to "High Volatility Uncertain" instead of crisis/defensive strategies.
Secondary bug
The factory defines 9 regime mappings (0–8), but
RegimeDetectoroutputs exactly 8 regime probabilities (num_regimes=8). Regime 8 ("Extreme Volatility") is structurally unreachable during inference — the argmax of 8 outputs is always 0–7.Correct fix
One of the two systems must be updated to match the other. The labeler's naming reflects standard financial terminology (BULL_TRENDING, BEAR_TRENDING, CRISIS) and was presumably designed first. The factory mapping should be updated:
Also reduce
factory._regime_mappingsto 8 entries (0–7) and remove the unreachable regime 8, or updateRegimeDetectortonum_regimes=9.Any trained model weights produced under the current misalignment should be discarded — they have learned to associate features with the wrong regime integers.