Skip to content

fix(strategies): align factory regime numbering with training labeler (#15)#18

Open
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/regime-numbering-alignment
Open

fix(strategies): align factory regime numbering with training labeler (#15)#18
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/regime-numbering-alignment

Conversation

@bradsmithmba

Copy link
Copy Markdown

Summary

StrategyFactory and the training-time RegimeType labeler (src/data/regime_labeler.py) used the same regime integers (0–7) to mean different things. The neural net is trained on labels from the labeler, then its predictions are interpreted by the factory. Because the two numberings were misaligned, the system recommended bull-market strategies in bear markets and vice versa across nearly every regime.

Closes #15.

The misalignment (before this PR)

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 tagged a market BULL_TRENDING (0) and the model learned to output 0, the factory mapped 0 to "Deep Bear Market" and recommended LONG_PUT / BEAR_PUT_SPREAD / BEAR_CALL_SPREAD.

Changes

  • src/strategies/factory.py

    • _build_regime_mappings() realigned to RegimeType semantics (0=BULL_TRENDING … 7=CRISIS)
    • Removed the unreachable regime 8 (RegimeDetector emits 8 classes, indices 0–7)
    • _assess_expected_performance() performance map realigned
    • _assess_risk_for_regime() high_risk_regimes corrected to [1, 2, 6, 7] (BEAR_TRENDING, HIGH_VOLATILITY, DISTRIBUTION, CRISIS)
    • Docstring now names RegimeType as the source of truth
  • tests/strategies/test_factory.py

    • Fixed fixtures and tests that had encoded the inverted numbering as expected behavior (this is why the bug was never caught — the tests asserted the bug was correct)
    • Added test_regime_mappings_match_labeler_numbering: a regression guard that fails if the factory and labeler diverge again
  • tests/strategies/test_integration.py

    • Corrected stale regime comments and condition data to match the canonical numbering

Why the bug survived

The pre-existing test_factory.py asserted that regime 0 should produce bearish strategies and regime 1 bullish — i.e. it validated the inverted mapping. Passing tests that encode a bug make the bug permanent. The new regression test ties the factory's directional output back to the documented RegimeType numbering so this cannot silently re-invert.

Required follow-up: retraining

This is a code fix, not a full remediation. Any model checkpoint trained before this change learned feature → wrong-regime-integer associations and must be discarded and retrained after merge. No checkpoints are committed to the repo, so there is nothing to delete here — this is a heads-up for anyone holding local/remote weights.

Two upstream issues should be resolved before a useful retrain, since they corrupt the training input itself:

Testing

$ pytest tests/strategies/ -q
141 passed

Verification was scoped to tests/strategies/ because the rest of the suite currently fails to collect due to unrelated, separately-filed issues (#1 missing src.data providers, #6 sys.exit at import, #7 missing gym). This PR touches none of those paths.

🤖 Generated with Claude Code

Regime integers in StrategyFactory used different semantics than
RegimeType in regime_labeler.py, which produces the training labels.
Regime 0 meant BULL_TRENDING to the labeler but "Deep Bear Market" to
the factory, so the model recommended bearish strategies in bull
markets (and vice versa) across nearly every regime.

Realign the factory mapping, performance map, and risk classification
to RegimeType. Remove the unreachable regime 8 (detector emits 8
classes, 0-7). Update tests that had encoded the inverted numbering as
expected behavior, and add a regression guard tying the factory to the
labeler's numbering.

Note: any model checkpoints trained before this change learned the
inverted associations and must be retrained after merge.

Closes cloudtrainerwork#15

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regime numbering is inverted between training labeler and inference factory — bull strategies recommended in bear markets

1 participant