Skip to content

fix(api): wire ML pipeline into live recommendation path (#5)#42

Open
bradsmithmba wants to merge 4 commits into
cloudtrainerwork:masterfrom
bradsmithmba:fix/wire-ml-pipeline
Open

fix(api): wire ML pipeline into live recommendation path (#5)#42
bradsmithmba wants to merge 4 commits into
cloudtrainerwork:masterfrom
bradsmithmba:fix/wire-ml-pipeline

Conversation

@bradsmithmba

Copy link
Copy Markdown
Contributor

Summary

  • get_actionable_recommendations() now calls _detect_regime() which tries to load the most recent checkpoints/regime_detector*.pt checkpoint, runs the 48D feature vector through RegimeDetector, and returns the predicted regime index.
  • When no checkpoint exists (the common case before training), it falls back to _heuristic_regime() which maps the existing SMA-crossover sentiment to a RegimeType int — identical behavior to before, but now explicit and testable.
  • StrategyFactory.get_recommended_strategies(regime) drives the strategy loop, replacing the hardcoded ['bullish_call_spread', 'bearish_put_spread', 'iron_condor', 'covered_call'] list.
  • A _BUILDER_MAP dispatches each StrategyType to the appropriate contract-construction method. Types with no builder are skipped gracefully.
  • _generate_strategy_recommendation() and _find_support_resistance() removed as dead code.
  • ScoringEngine not wired yet: it requires real NN probability outputs to be meaningful, and those only exist once the model is trained with the corrected features from Critical: 7 of 11 volatility features are hardcoded constants with no live signal #2.

Closes

Closes #5.

Test plan

  • TestHeuristicRegime: verifies SMA sentiment → RegimeType mapping
  • TestDetectRegime: verifies heuristic fallback when no checkpoint / on ML failure
  • TestGetActionableRecommendations: verifies StrategyFactory.get_recommended_strategies is called with the detected regime, replacing the hardcoded loop

🤖 Generated with Claude Code

bradsmithmba and others added 2 commits June 24, 2026 10:43
…loudtrainerwork#2)

VIX level and VIX percentile now come from ^VIX history aligned to the
price data date index. implied_volatility, iv_rank, and iv_percentile
are derived from rolling HV20 (proxy until a historical options chain
source is available — labeled with ponytail: comments).

term_structure_slope and put_call_skew remain 0.0: historical options
chain data is not available from yfinance and cannot be back-filled.

Closes cloudtrainerwork#2. Also resolves cloudtrainerwork#3 (regime classifier blind to vol signal) since
the neural net now receives varying volatility features instead of constants.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rwork#5)

EnhancedStrategyRecommender.get_actionable_recommendations() now routes
through RegimeDetector → StrategyFactory for strategy selection instead
of a hardcoded list of four strategy types.

- _detect_regime(): loads the most recent checkpoint in checkpoints/ and
  runs RegimeStateVector → RegimeDetector.predict_regime(). Falls back to
  the existing SMA-crossover heuristic when no checkpoint exists or the
  pipeline raises — preserving full backward compatibility.
- _heuristic_regime(): maps SMA sentiment ('bullish'/'bearish'/'neutral')
  to RegimeType ints; keeps the fallback logic explicit and testable.
- StrategyFactory.get_recommended_strategies(regime) now drives the
  strategy loop; the builder map dispatches each StrategyType to the
  appropriate contract-construction method.
- _generate_strategy_recommendation() and _find_support_resistance()
  removed (dead after the refactor).
- StrategyFactory imported at module level so it is patchable in tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bradsmithmba and others added 2 commits June 24, 2026 12:42
…erwork#43, cloudtrainerwork#44, cloudtrainerwork#45, cloudtrainerwork#46)

Three bugs caused _detect_regime() to silently fall back to heuristic
every time, even when a trained checkpoint existed:

- cloudtrainerwork#43: _find_checkpoint() glob patterns never matched any file the
  trainer produces; updated to match models/checkpoints/ and
  training_runs/*/checkpoints/ with correct filenames.

- cloudtrainerwork#44: load_state_dict() received the full checkpoint dict instead of
  the nested state dict; now unpacks model_state_dict (trainer format)
  or state_dict (inference export format) before loading.

- cloudtrainerwork#45: RegimeStateVector().calculate() returned 21 features by default;
  RegimeDetector expects 48. Fixed by passing include_extended=True.

- cloudtrainerwork#46: _BUILDER_MAP class-level cache stored instance-bound methods,
  causing wrong method bindings on a second instance. Removed class
  cache; _get_builder_map() now returns a fresh dict per call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… layers

Training correctness (cloudtrainerwork#47):
- Remove F.softmax from RegimeDetector._forward_impl — forward() now returns raw
  logits so CrossEntropyLoss receives pre-softmax values (was double-softmaxing)
- Remove undocumented confidence-logit contamination of regime logits
- Fix calculate_uncertainty to apply softmax before entropy computation
- Fix compute_loss confidence pseudo-target to use softmax of logits, not raw logits
- Update stale tests that assumed softmax output from forward()

Regime labeling (cloudtrainerwork#48, cloudtrainerwork#49):
- Remove BULL_VOLATILE=2 and SIDEWAYS_LOW_VOL=3 from RegimeType — they were
  IntEnum aliases for HIGH_VOLATILITY and LOW_VOLATILITY, making list(RegimeType)
  return 6 members instead of 8
- Fix vol_high_pct threshold from 30 to 0.30 — was comparing decimal volatility
  against integer 30, making the HIGH_VOLATILITY branch unreachable

Training loop (cloudtrainerwork#50):
- Initialize val_metrics=None before the epoch loop to prevent UnboundLocalError
  when checkpoint_frequency < validation_frequency

Feature engineering (cloudtrainerwork#52, cloudtrainerwork#53, cloudtrainerwork#54, cloudtrainerwork#12):
- EventFeatures: skip minmax standardization for constant columns (was producing
  all-NaN in 3 of 48 input dimensions)
- Stochastic %K: replace inf with NaN then fill 50.0 (flat price guard)
- ADX: guard zero denominator in DX calculation with np.where
- OBV: fill NaN volume with 0 before accumulation loop

Data layer (cloudtrainerwork#55):
- batch_get_prices: pass 2-year default start date; was silently returning ~20
  rows due to yfinance default 1-month period

Recommendation engine (cloudtrainerwork#51):
- position_size typed Optional[float] — kelly sizing explicitly returns None
  when history is absent; callers doing arithmetic were hitting TypeError

Enhanced recommender (cloudtrainerwork#57, cloudtrainerwork#56, cloudtrainerwork#58, cloudtrainerwork#60, cloudtrainerwork#61):
- _find_checkpoint: anchor glob to Path(__file__).parents[3] so it works from
  any process cwd, not just repo root
- _calculate_probability_above: return 0.5 for ATM at expiry (was returning 0.0)
- _days_to_expiration: compare .date() not datetime — eliminates time-of-day
  off-by-one that misfired at 3pm on expiration day
- Iron condor max_loss: use max(call_wing, put_wing) — was ignoring put wing
- BUTTERFLY removed from builder map; was silently returning iron condor payload

Co-Authored-By: Claude Sonnet 4.6 <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.

Architecture: Live recommendation path bypasses the ML pipeline entirely

1 participant