Expand description
ML Feature Engineering Polars layer (ta.features.*)
Wires the rich Rust feature extractors from quantwave_core::features into
the .ta. namespace on LazyFrame, following the exact patterns from
quantwave-polars/src/lib.rs (UDF map closures + StructChunked::from_series
for rich multi-outputs + with_columns for lazy exprs).
This delivers the minimal locked surface required for the cross-epic deliverable (ML Features → Realistic Backtest with Rich Metadata) that closes quantwave-4ps + quantwave-gwx.
The canonical executable demonstration + parity verification is the notebook: docs/examples/notebooks/ml_feature_backtest_parity.py (uses this surface in documented Rust batch path + equivalent Python streaming generators
- FeatureToSignal adapter + full rich metadata preservation in trades).
LOCKED SURFACE (per quantwave-4ps notes, “DETAILED WLX SURFACE REQUIRED…” section, 2026-05-31 IST):
- .ta.features.hurst(period) -> column “hurst_{period}” (f64 persistence)
- .ta.features.cyber_cycle(length) -> Struct column “cyber_cycle” with fields [cycle, trigger, momentum, signal]
- .ta.features.griffiths_dominant_cycle(lower, upper, length) -> column “griffiths_dc” (f64)
- .ta.features.regime_features() -> column “regime_label” (u32, from HMM bull_bear for MVP usability)
- .ta.features.instantaneous_trendline() -> Struct “itl” {trend, strength}
- .ta.features.regime_probs() -> Struct “regime_probs” {prob_bull, prob_bear, prob_steady, prob_crisis, prob_other}
- .ta.features.trendflex(length) -> column “trendflex_{length}”
- .ta.features.ehlers_autocorrelation(length, num_lags) -> Struct {dominant_lag, max_correlation}
All are lazy (exprs built with with_columns + map UDFs; execution deferred to collect).
All delegate directly to the Next
Sources recorded (per AGENTS.md + 4ps spec):
- quantwave-core/src/features/hurst.rs (HurstFeatureExtractor + HurstFeatures; wraps indicators/hurst.rs)
- quantwave-core/src/features/cyber_cycle.rs (CyberCycleFeatureExtractor + CyberCycleFeatures; primary source indicators/cyber_cycle.rs:35 per Ehlers “Cybernetic Analysis…”)
- quantwave-core/src/features/griffiths_dominant_cycle.rs (GriffithsDominantCycleFeatureExtractor + …Features; wraps indicators/griffiths_dominant_cycle.rs)
- quantwave-core/src/features/regime.rs + regimes/hmm.rs (regime_to_features + HMM::bull_bear for label; MarketRegime)
- quantwave-core/src/features/mod.rs (wlx prep note 2026-05-30 + AsFeatures skeleton + proptest parity contract)
- quantwave-4ps epic (parent) + wlx child design notes (this surface is the exact contract for the “smoking gun” notebook)
- Existing .ta. patterns in quantwave-polars/src/lib.rs (macd/bbands/supertrend/gap_momentum struct returns, adosc etc. stateful maps, regimes_conditioned_metrics)
- gw7s notebook (docs/examples/notebooks/ml_feature_stability.py) + quantwave-4ub research (P0 feature list)
- quantwave-backtest (future consumer of the metadata columns from these exprs)
Decision: CyberCycle uses Struct (matches all rich outputs in this crate on Polars 0.46; users .unnest(“cyber_cycle”) if needed). Regime uses simple but real HMM label (usable in MVP notebook/backtester filters) rather than pure placeholder.
Structs§
- TaFeatures
Namespace - Sub-namespace returned by .ta().features(). Methods here implement the exact locked surface for the 4ps/gwx cross-epic deliverable.