quantwave 0.4.0__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. {quantwave-0.4.0 → quantwave-0.5.1}/Cargo.lock +21 -6
  2. {quantwave-0.4.0 → quantwave-0.5.1}/Cargo.toml +5 -4
  3. {quantwave-0.4.0 → quantwave-0.5.1}/PKG-INFO +1 -1
  4. {quantwave-0.4.0 → quantwave-0.5.1}/python/quantwave/__init__.py +15 -1
  5. quantwave-0.5.1/quantwave-core/README.md +101 -0
  6. quantwave-0.5.1/quantwave-core/proptest-regressions/features/mod.txt +7 -0
  7. quantwave-0.5.1/quantwave-core/src/features/cyber_cycle.rs +76 -0
  8. quantwave-0.5.1/quantwave-core/src/features/ehlers_autocorrelation.rs +63 -0
  9. quantwave-0.5.1/quantwave-core/src/features/griffiths_dominant_cycle.rs +53 -0
  10. quantwave-0.5.1/quantwave-core/src/features/hurst.rs +108 -0
  11. quantwave-0.5.1/quantwave-core/src/features/instantaneous_trendline.rs +39 -0
  12. quantwave-0.5.1/quantwave-core/src/features/mod.rs +135 -0
  13. quantwave-0.5.1/quantwave-core/src/features/regime.rs +50 -0
  14. quantwave-0.5.1/quantwave-core/src/features/regime_probs.rs +48 -0
  15. quantwave-0.5.1/quantwave-core/src/features/trendflex.rs +51 -0
  16. quantwave-0.5.1/quantwave-core/src/indicators/kinematic_kalman.rs +207 -0
  17. quantwave-0.5.1/quantwave-core/src/indicators/market_structure.rs +410 -0
  18. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/mod.rs +2 -0
  19. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/lib.rs +4 -0
  20. quantwave-0.5.1/quantwave-core/tests/test_ml_feature_validation.rs +318 -0
  21. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-python/src/lib.rs +239 -0
  22. quantwave-0.4.0/quantwave-python/README.md +0 -62
  23. {quantwave-0.4.0 → quantwave-0.5.1}/LICENSE +0 -0
  24. {quantwave-0.4.0 → quantwave-0.5.1}/README.md +0 -0
  25. {quantwave-0.4.0 → quantwave-0.5.1}/pyproject.toml +0 -0
  26. {quantwave-0.4.0 → quantwave-0.5.1}/python/quantwave/polars.py +0 -0
  27. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/Cargo.toml +0 -0
  28. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/proptest-regressions/indicators/bandpass.txt +0 -0
  29. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/proptest-regressions/indicators/oc_price_rsi.txt +0 -0
  30. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/proptest-regressions/indicators/overlap.txt +0 -0
  31. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/proptest-regressions/indicators/rocket_rsi.txt +0 -0
  32. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/bin/bench_complex.rs +0 -0
  33. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/bin/bench_ema.rs +0 -0
  34. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/bin/bench_rust.rs +0 -0
  35. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/bin/bench_sma.rs +0 -0
  36. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/adaptive_ema.rs +0 -0
  37. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/alligator.rs +0 -0
  38. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/alma.rs +0 -0
  39. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/amfm.rs +0 -0
  40. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/atr_ts.rs +0 -0
  41. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/autotune.rs +0 -0
  42. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/bandpass.rs +0 -0
  43. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/butterworth.rs +0 -0
  44. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/cg.rs +0 -0
  45. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/channel_cycle.rs +0 -0
  46. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/choppiness_index.rs +0 -0
  47. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/classic_laguerre.rs +0 -0
  48. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/continuation_index.rs +0 -0
  49. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/correlation_cycle.rs +0 -0
  50. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/correlation_trend.rs +0 -0
  51. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/cyber_cycle.rs +0 -0
  52. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/cybernetic_oscillator.rs +0 -0
  53. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/cycle.rs +0 -0
  54. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/cycle_trend_analytics.rs +0 -0
  55. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/dmh.rs +0 -0
  56. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/donchian.rs +0 -0
  57. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/dsma.rs +0 -0
  58. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ehlers_autocorrelation.rs +0 -0
  59. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ehlers_filter.rs +0 -0
  60. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ehlers_loops.rs +0 -0
  61. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ehlers_stochastic.rs +0 -0
  62. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ehlers_ultimate_oscillator.rs +0 -0
  63. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/emd.rs +0 -0
  64. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/exp_dev_bands.rs +0 -0
  65. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/fisher.rs +0 -0
  66. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/fisher_high_pass.rs +0 -0
  67. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/fourier_series.rs +0 -0
  68. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/fourier_transform.rs +0 -0
  69. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/fractals.rs +0 -0
  70. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/frama.rs +0 -0
  71. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/gap_momentum.rs +0 -0
  72. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/gaussian.rs +0 -0
  73. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/generalized_laguerre.rs +0 -0
  74. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/griffiths_dominant_cycle.rs +0 -0
  75. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/griffiths_predictor.rs +0 -0
  76. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/griffiths_spectrum.rs +0 -0
  77. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/hamming.rs +0 -0
  78. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/hann.rs +0 -0
  79. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/harrington_adx.rs +0 -0
  80. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/heikin_ashi.rs +0 -0
  81. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/high_pass.rs +0 -0
  82. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/hilbert_transform.rs +0 -0
  83. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/hma.rs +0 -0
  84. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/homodyne_discriminator.rs +0 -0
  85. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/hurst.rs +0 -0
  86. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ichimoku.rs +0 -0
  87. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/instantaneous_trendline.rs +0 -0
  88. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/inverse_fisher.rs +0 -0
  89. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/just_ignore_them.rs +0 -0
  90. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/kalman.rs +0 -0
  91. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/kama.rs +0 -0
  92. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/keltner.rs +0 -0
  93. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/laguerre_filter.rs +0 -0
  94. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/laguerre_oscillator.rs +0 -0
  95. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/laguerre_rsi.rs +0 -0
  96. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/mad.rs +0 -0
  97. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/madh.rs +0 -0
  98. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/mama.rs +0 -0
  99. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/market_state.rs +0 -0
  100. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/math.rs +0 -0
  101. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/mesa_stochastic.rs +0 -0
  102. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/metadata.rs +0 -0
  103. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/momentum.rs +0 -0
  104. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/my_rsi.rs +0 -0
  105. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/noise_elimination.rs +0 -0
  106. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/obvm.rs +0 -0
  107. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/oc_price_rsi.rs +0 -0
  108. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/one_euro_filter.rs +0 -0
  109. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/overlap.rs +0 -0
  110. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/pairs_rotation.rs +0 -0
  111. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/pattern.rs +0 -0
  112. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/phasor.rs +0 -0
  113. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/pivot_points.rs +0 -0
  114. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/pma.rs +0 -0
  115. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/precision_trend.rs +0 -0
  116. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/price_transform.rs +0 -0
  117. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/recursive_median.rs +0 -0
  118. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/reflex.rs +0 -0
  119. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/reverse_ema.rs +0 -0
  120. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/reversion_index.rs +0 -0
  121. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/robustness.rs +0 -0
  122. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/rocket_rsi.rs +0 -0
  123. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/rodc.rs +0 -0
  124. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/roofing_filter.rs +0 -0
  125. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/rsih.rs +0 -0
  126. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/rsmk.rs +0 -0
  127. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/sdo.rs +0 -0
  128. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/simple_predictor.rs +0 -0
  129. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/sine_wave.rs +0 -0
  130. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/smoothing.rs +0 -0
  131. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/statistics.rs +0 -0
  132. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/stc.rs +0 -0
  133. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/super_smoother.rs +0 -0
  134. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/supertrend.rs +0 -0
  135. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/sve_volatility_bands.rs +0 -0
  136. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/swiss_army_knife.rs +0 -0
  137. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/synthetic_oscillator.rs +0 -0
  138. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/system_evaluator.rs +0 -0
  139. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/talib_wrapper.rs +0 -0
  140. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/tema.rs +0 -0
  141. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/tradj_ema.rs +0 -0
  142. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/trendflex.rs +0 -0
  143. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/triangle.rs +0 -0
  144. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/truncated_bandpass.rs +0 -0
  145. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ttm_squeeze.rs +0 -0
  146. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ultimate_bands.rs +0 -0
  147. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ultimate_channel.rs +0 -0
  148. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/ultimate_smoother.rs +0 -0
  149. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/universal_oscillator.rs +0 -0
  150. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/usi.rs +0 -0
  151. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/vfi.rs +0 -0
  152. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/volatility.rs +0 -0
  153. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/volume.rs +0 -0
  154. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/volume_profile.rs +0 -0
  155. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/vortex.rs +0 -0
  156. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/voss_predictor.rs +0 -0
  157. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/vpn.rs +0 -0
  158. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/vwap.rs +0 -0
  159. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/wavetrend.rs +0 -0
  160. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/indicators/zero_lag.rs +0 -0
  161. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/options_india/black_scholes.rs +0 -0
  162. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/options_india/chain_analytics.rs +0 -0
  163. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/options_india/india.rs +0 -0
  164. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/options_india/iv_solver.rs +0 -0
  165. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/options_india/mod.rs +0 -0
  166. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/analytics.rs +0 -0
  167. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/ensemble.rs +0 -0
  168. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/gmm.rs +0 -0
  169. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/hmm.rs +0 -0
  170. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/hmm_gas.rs +0 -0
  171. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/hsmm.rs +0 -0
  172. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/india.rs +0 -0
  173. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/mod.rs +0 -0
  174. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/ms_garch.rs +0 -0
  175. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/multi_asset.rs +0 -0
  176. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/pelt.rs +0 -0
  177. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/tar.rs +0 -0
  178. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/regimes/volatility_clustering.rs +0 -0
  179. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/test_utils.rs +0 -0
  180. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/src/traits.rs +0 -0
  181. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/alma_9_085_6.json +0 -0
  182. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/atr_ts_14_25.json +0 -0
  183. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/cycle_trend_analytics.json +0 -0
  184. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/donchian_5.json +0 -0
  185. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/ehlers_autocorrelation.json +0 -0
  186. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/ehlers_loops.json +0 -0
  187. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/ehlers_stochastic.json +0 -0
  188. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/fractals.json +0 -0
  189. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/heikin_ashi.json +0 -0
  190. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/hma_14.json +0 -0
  191. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/ichimoku.json +0 -0
  192. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/keltner_20_20_15.json +0 -0
  193. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/mad.json +0 -0
  194. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/mesa_stochastic.json +0 -0
  195. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/oc_price_rsi.json +0 -0
  196. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/pivot_points.json +0 -0
  197. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/rsih.json +0 -0
  198. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/sma_5.json +0 -0
  199. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/supertrend_10_3.json +0 -0
  200. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/tema_14.json +0 -0
  201. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/ttm_squeeze_20_2_15.json +0 -0
  202. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/vortex_14.json +0 -0
  203. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/voss_predictor.json +0 -0
  204. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/gold_standard/wavetrend_10_21_4.json +0 -0
  205. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-core/tests/test_wrapper.rs +0 -0
  206. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-python/.gitignore +0 -0
  207. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-python/Cargo.toml +0 -0
  208. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-python/LICENSE +0 -0
  209. {quantwave-0.4.0/quantwave-core → quantwave-0.5.1/quantwave-python}/README.md +0 -0
  210. {quantwave-0.4.0 → quantwave-0.5.1}/quantwave-python/build.rs +0 -0
@@ -2125,15 +2125,30 @@ dependencies = [
2125
2125
 
2126
2126
  [[package]]
2127
2127
  name = "quantwave"
2128
- version = "0.4.0"
2128
+ version = "0.5.1"
2129
2129
  dependencies = [
2130
2130
  "quantwave-core",
2131
2131
  "quantwave-polars",
2132
2132
  ]
2133
2133
 
2134
+ [[package]]
2135
+ name = "quantwave-backtest"
2136
+ version = "0.5.1"
2137
+ dependencies = [
2138
+ "approx",
2139
+ "chrono",
2140
+ "polars",
2141
+ "proptest",
2142
+ "quantwave-core",
2143
+ "rand 0.8.6",
2144
+ "serde",
2145
+ "serde_json",
2146
+ "thiserror 1.0.69",
2147
+ ]
2148
+
2134
2149
  [[package]]
2135
2150
  name = "quantwave-core"
2136
- version = "0.4.0"
2151
+ version = "0.5.1"
2137
2152
  dependencies = [
2138
2153
  "approx",
2139
2154
  "chrono",
@@ -2151,7 +2166,7 @@ dependencies = [
2151
2166
 
2152
2167
  [[package]]
2153
2168
  name = "quantwave-plugins"
2154
- version = "0.4.0"
2169
+ version = "0.5.1"
2155
2170
  dependencies = [
2156
2171
  "polars",
2157
2172
  "polars-arrow",
@@ -2162,7 +2177,7 @@ dependencies = [
2162
2177
 
2163
2178
  [[package]]
2164
2179
  name = "quantwave-polars"
2165
- version = "0.4.0"
2180
+ version = "0.5.1"
2166
2181
  dependencies = [
2167
2182
  "polars",
2168
2183
  "quantwave-core",
@@ -2172,7 +2187,7 @@ dependencies = [
2172
2187
 
2173
2188
  [[package]]
2174
2189
  name = "quantwave-python"
2175
- version = "0.4.0"
2190
+ version = "0.5.1"
2176
2191
  dependencies = [
2177
2192
  "paste",
2178
2193
  "quantwave-core",
@@ -2181,7 +2196,7 @@ dependencies = [
2181
2196
 
2182
2197
  [[package]]
2183
2198
  name = "quantwave-xtask"
2184
- version = "0.4.0"
2199
+ version = "0.5.1"
2185
2200
  dependencies = [
2186
2201
  "anyhow",
2187
2202
  "quick-xml",
@@ -3,7 +3,7 @@ members = ["quantwave-core", "quantwave-python"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.4.0"
6
+ version = "0.5.1"
7
7
  edition = "2024"
8
8
  license = "MIT"
9
9
  repository = "https://github.com/lavs9/quantwave"
@@ -30,9 +30,10 @@ thiserror = "1.0"
30
30
  chrono = { version = "0.4", features = ["serde"] }
31
31
  nalgebra = { version = "0.33", features = ["serde-serialize"] }
32
32
  statrs = "0.18"
33
- quantwave-core = { path = "quantwave-core", version = "0.4.0" }
34
- quantwave-polars = { path = "quantwave-polars", version = "0.4.0" }
35
- quantwave-plugins = { path = "quantwave-plugins", version = "0.4.0" }
33
+ quantwave-core = { path = "quantwave-core", version = "0.5.1" }
34
+ quantwave-polars = { path = "quantwave-polars", version = "0.5.1" }
35
+ quantwave-plugins = { path = "quantwave-plugins", version = "0.5.1" }
36
+ quantwave-backtest = { path = "quantwave-backtest", version = "0.5.1" }
36
37
 
37
38
  [profile.dev]
38
39
  opt-level = 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantwave
3
- Version: 0.4.0
3
+ Version: 0.5.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Financial and Insurance Industry
@@ -125,6 +125,16 @@ class ta:
125
125
  rocket_rsi = rocketrsi
126
126
  trendflex = trendflex
127
127
  truncated_bandpass = truncatedbandpass
128
+ # ML features (gw7s notebook + harness + 4ps/gwx cross-epic deliverable)
129
+ cyber_cycle_feature_extractor = CyberCycleFeatureExtractor
130
+ hurst_feature_extractor = HurstFeatureExtractor
131
+ instantaneous_trendline_feature_extractor = InstantaneousTrendlineFeatureExtractor
132
+ trendflex_feature_extractor = TrendflexFeatureExtractor
133
+ regime_to_features = regime_to_features
134
+ # Newly wired for the E2E notebook (trivial parallel to above; completes the locked .ta.features.* surface in Python)
135
+ griffiths_dominant_cycle_feature_extractor = GriffithsDominantCycleFeatureExtractor
136
+ bull_bear_hmm = BullBearHMM
137
+ griffiths_dominant_cycle_features = griffiths_dominant_cycle_features # batch helper
128
138
  volume_profile = volumeprofile
129
139
 
130
140
  class options_india:
@@ -170,5 +180,9 @@ __all__ = [
170
180
  "HtDcPeriod", "HtPhasor", "HtDcPhase", "HtSine", "HtTrendMode",
171
181
  "HurstExponent", "KalmanFilter", "MarketState", "RecursiveMedian",
172
182
  "RecursiveMedianOscillator", "Reflex", "RocketRsi", "Trendflex",
173
- "TruncatedBandpass", "VolumeProfile"
183
+ "TruncatedBandpass", "VolumeProfile",
184
+ # ML feature toolkit (quantwave-gw7s)
185
+ "CyberCycleFeatureExtractor", "HurstFeatureExtractor",
186
+ "InstantaneousTrendlineFeatureExtractor", "TrendflexFeatureExtractor",
187
+ "regime_to_features"
174
188
  ]
@@ -0,0 +1,101 @@
1
+ # QuantWave
2
+
3
+ **High-performance, Polars-native technical analysis — in Python and Rust**
4
+
5
+ 150+ indicators · Full Ehlers DSP suite · Regime Detection · Complete Options India stack · Bit-identical streaming & batch
6
+
7
+ **Python** `pip install quantwave` **Rust** `cargo add quantwave`
8
+
9
+ [📖 Documentation](https://lavs9.github.io/quantwave/) • [⭐ GitHub](https://github.com/lavs9/quantwave) • [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/lavs9/quantwave)
10
+
11
+ **150+ indicators • Polars-native • Streaming & batch parity • MIT licensed**
12
+
13
+ ---
14
+
15
+ ## Why QuantWave?
16
+
17
+ Most quantitative libraries force an uncomfortable compromise.
18
+
19
+ **Python-first libraries** (pandas-ta, TA-Lib Python wrappers, etc.) are convenient but fall apart on large datasets, recursive indicators, or live streaming — often becoming 10-100x slower than native code.
20
+
21
+ **Pure Rust libraries** are fast, but they rarely integrate cleanly with modern Polars-based research pipelines and lack the breadth of advanced techniques (Ehlers DSP, regime detection, full Options India analytics).
22
+
23
+ **QuantWave removes the tradeoff.**
24
+
25
+ It delivers **institutional-grade Rust performance** through zero-copy Polars expressions, while offering a first-class, productive experience in both Python and Rust. Every indicator is built on a single mathematical source of truth — the `Next<T>` trait — guaranteeing that batch results (Polars) and real-time streaming results are **bit-identical**.
26
+
27
+ ### How We Compare
28
+
29
+ | Approach | Speed on large data | Polars-native | Streaming parity | Breadth (Ehlers + Regimes + Options) |
30
+ |---------------------------|---------------------|---------------|------------------|--------------------------------------|
31
+ | pandas-ta / TA-Lib (Python) | Poor–Average | Partial | Rare | Limited |
32
+ | Other Rust TA crates | Excellent | Poor | Rare | Limited |
33
+ | **QuantWave** | **Excellent** | **Native** | **Guaranteed** | **Strong** |
34
+
35
+ ## What We’ve Built
36
+
37
+ QuantWave is no longer early-stage. It ships with production-ready depth across several domains:
38
+
39
+ - **150+ Technical Indicators** with TA-Lib parity and extensive Ehlers DSP coverage
40
+ - **Full Regime Detection Suite** (HMM, GMM, PELT, clustering, conditioned risk metrics)
41
+ - **Complete Options India Stack** — Black-Scholes Greeks, IV solvers, chain analytics (Max Pain, PCR, GEX, OI Zones), and NSE utilities, all exposed as native Polars expressions
42
+ - **Streaming & Batch Parity** — The same mathematical logic powers both high-speed Polars pipelines and low-latency streaming via the universal `Next<T>` trait
43
+ - **Gold-Standard Validation** — Every indicator is tested against reference implementations for correctness
44
+
45
+ ## Core Strengths
46
+
47
+ - **Performance** — Rust core with zero-copy Polars expressions
48
+ - **Correctness** — Validated against gold-standard reference vectors
49
+ - **Parity** — Bit-identical results between batch and streaming
50
+ - **Breadth** — Classic indicators + advanced Ehlers DSP + regime detection + Options India
51
+ - **Developer Experience** — Clean Python API (`from quantwave import ta`) and idiomatic Rust
52
+
53
+ ## Real-World Performance
54
+
55
+ We don’t just claim to be fast — here’s what the numbers show on 1 million rows of realistic OHLCV data:
56
+
57
+ - **SuperTrend**: 7.4 ms (QuantWave) vs >200 ms (Pandas) → **~27× faster**
58
+ - **CyberCycle** (Ehlers): 5.0 ms vs >500 ms (Pandas) → **~100× faster**
59
+ - **Instantaneous Trendline**: 74 ms vs >2,000 ms (Pandas) → **~27× faster**
60
+ - **Memory footprint** on realistic multi-ticker data: **2–5× lower** than Pandas
61
+
62
+ Complex recursive indicators (the ones that matter most for real strategies) are where the gap becomes dramatic.
63
+
64
+ → [Full benchmarks & methodology](https://lavs9.github.io/quantwave/benchmarks/)
65
+
66
+ ## Quickstart (Python)
67
+
68
+ ```bash
69
+ pip install quantwave
70
+ ```
71
+
72
+ ```python
73
+ import polars as pl
74
+ from quantwave import ta
75
+
76
+ df = pl.read_parquet("ohlcv.parquet")
77
+
78
+ df = df.with_columns(
79
+ ta.rsi("close", 14).alias("rsi"),
80
+ ta.mama("close").alias("mama"),
81
+ ta.supertrend("high", "low", "close", period=10, multiplier=3.0).alias("supertrend"),
82
+ )
83
+ ```
84
+
85
+ [More examples → Documentation](https://lavs9.github.io/quantwave/examples/batch-streaming/)
86
+
87
+ ## Get Started
88
+
89
+ **Primary paths**
90
+ - [Get Started with Python](https://lavs9.github.io/quantwave/getting-started/python/)
91
+ - [Get Started with Rust](https://lavs9.github.io/quantwave/getting-started/rust/)
92
+
93
+ **Explore further**
94
+ - [Browse All Indicators](https://lavs9.github.io/quantwave/guides/indicators/)
95
+ - [See Real Benchmarks](https://lavs9.github.io/quantwave/benchmarks/)
96
+ - [v0.4.0 Release Notes](https://github.com/lavs9/quantwave/releases/tag/v0.4.0)
97
+ - [Ask DeepWiki](https://deepwiki.com/lavs9/quantwave)
98
+
99
+ ---
100
+
101
+ **Made with ❤️ for the quant community.**
@@ -0,0 +1,7 @@
1
+ # Seeds for failure cases proptest has generated in the past. It is
2
+ # automatically read and these particular cases re-run before any
3
+ # novel cases are generated.
4
+ #
5
+ # It is recommended to check this file in to source control so that
6
+ # everyone who runs the test benefits from these saved cases.
7
+ cc 572d6eab56f4d50d39de44b76ecc8fd7a47740a359e835979a56784a3afd2818 # shrinks to data = [0.0, 0.0, 0.0, 0.0, 0.0]
@@ -0,0 +1,76 @@
1
+ //! Cyber Cycle feature extractor wrapper.
2
+ //!
3
+ //! Wraps the existing `CyberCycle` to expose both the cycle value and trigger line
4
+ //! plus a few derived features useful for ML (momentum, zero-cross signal, etc.).
5
+ //!
6
+ //! Primary source: quantwave-core/src/indicators/cyber_cycle.rs:35
7
+ //! (returns (CyberCycle, Trigger) per Ehlers "Cybernetic Analysis for Stocks and Futures")
8
+
9
+ use crate::indicators::cyber_cycle::CyberCycle;
10
+ use crate::traits::Next;
11
+
12
+ /// Rich multi-dimensional output for Cyber Cycle features.
13
+ #[derive(Debug, Clone, Copy, PartialEq)]
14
+ pub struct CyberCycleFeatures {
15
+ pub cycle: f64,
16
+ pub trigger: f64,
17
+ /// Simple momentum of the cycle (cycle - previous cycle)
18
+ pub cycle_momentum: f64,
19
+ /// Sign of (cycle - trigger) as a basic oscillator signal
20
+ pub trigger_signal: f64,
21
+ }
22
+
23
+ #[derive(Debug, Clone)]
24
+ pub struct CyberCycleFeatureExtractor {
25
+ inner: CyberCycle,
26
+ prev_cycle: f64,
27
+ }
28
+
29
+ impl CyberCycleFeatureExtractor {
30
+ pub fn new(length: usize) -> Self {
31
+ Self {
32
+ inner: CyberCycle::new(length),
33
+ prev_cycle: 0.0,
34
+ }
35
+ }
36
+ }
37
+
38
+ impl Next<f64> for CyberCycleFeatureExtractor {
39
+ type Output = CyberCycleFeatures;
40
+
41
+ fn next(&mut self, input: f64) -> Self::Output {
42
+ let (cycle, trigger) = self.inner.next(input);
43
+
44
+ let momentum = if self.prev_cycle == 0.0 { 0.0 } else { cycle - self.prev_cycle };
45
+ let trigger_signal = (cycle - trigger).signum();
46
+
47
+ self.prev_cycle = cycle;
48
+
49
+ CyberCycleFeatures {
50
+ cycle,
51
+ trigger,
52
+ cycle_momentum: momentum,
53
+ trigger_signal,
54
+ }
55
+ }
56
+ }
57
+
58
+ #[cfg(test)]
59
+ mod tests {
60
+ use super::*;
61
+ use approx::assert_relative_eq;
62
+
63
+ #[test]
64
+ fn test_cyber_cycle_features_basic() {
65
+ let mut extractor = CyberCycleFeatureExtractor::new(14);
66
+
67
+ // Feed some oscillatory data
68
+ for i in 0..50 {
69
+ let val = 100.0 + 5.0 * (i as f64 * 0.3).sin();
70
+ let f = extractor.next(val);
71
+ if !f.cycle.is_nan() {
72
+ assert!(f.cycle.abs() < 20.0); // sanity
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,63 @@
1
+ //! Ehlers Autocorrelation feature extractor wrapper.
2
+ //!
3
+ //! Wraps the lag correlation vector. For ML, we expose the full vector (or top lags)
4
+ //! plus a "dominant lag" summary – excellent cycle feature.
5
+ //!
6
+ //! Source: quantwave-core/src/indicators/ehlers_autocorrelation.rs (returns Vec<f64> correlations)
7
+
8
+ use crate::indicators::ehlers_autocorrelation::EhlersAutocorrelation;
9
+ use crate::traits::Next;
10
+
11
+ #[derive(Debug, Clone, PartialEq)]
12
+ pub struct EhlersAutocorrelationFeatures {
13
+ pub correlations: Vec<f64>,
14
+ pub dominant_lag: usize,
15
+ pub max_correlation: f64,
16
+ }
17
+
18
+ #[derive(Debug, Clone)]
19
+ pub struct EhlersAutocorrelationFeatureExtractor {
20
+ inner: EhlersAutocorrelation,
21
+ }
22
+
23
+ impl EhlersAutocorrelationFeatureExtractor {
24
+ pub fn new(length: usize, num_lags: usize) -> Self {
25
+ Self {
26
+ inner: EhlersAutocorrelation::new(length, num_lags),
27
+ }
28
+ }
29
+ }
30
+
31
+ impl Next<f64> for EhlersAutocorrelationFeatureExtractor {
32
+ type Output = EhlersAutocorrelationFeatures;
33
+
34
+ fn next(&mut self, input: f64) -> Self::Output {
35
+ let corrs = self.inner.next(input);
36
+ let (dominant_lag, &max_correlation) = corrs
37
+ .iter()
38
+ .enumerate()
39
+ .max_by(|a, b| a.1.partial_cmp(b.1).unwrap_or(std::cmp::Ordering::Equal))
40
+ .unwrap_or((0, &0.0));
41
+
42
+ EhlersAutocorrelationFeatures {
43
+ correlations: corrs,
44
+ dominant_lag,
45
+ max_correlation,
46
+ }
47
+ }
48
+ }
49
+
50
+ #[cfg(test)]
51
+ mod tests {
52
+ use super::*;
53
+
54
+ #[test]
55
+ fn test_autocorr_wrapper_basic() {
56
+ let mut ext = EhlersAutocorrelationFeatureExtractor::new(30, 10);
57
+ for i in 0..100 {
58
+ let val = 100.0 + 5.0 * (i as f64 * 0.2).sin();
59
+ let f = ext.next(val);
60
+ assert_eq!(f.correlations.len(), 10);
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,53 @@
1
+ //! Griffiths Dominant Cycle feature extractor wrapper.
2
+ //!
3
+ //! Wraps the Griffiths spectral estimation dominant cycle detector.
4
+ //! Returns the estimated dominant cycle length — a high-value stationary cycle feature for ML.
5
+ //!
6
+ //! Source: quantwave-core/src/indicators/griffiths_dominant_cycle.rs (returns f64 dominant cycle estimate)
7
+
8
+ use crate::indicators::griffiths_dominant_cycle::GriffithsDominantCycle;
9
+ use crate::traits::Next;
10
+
11
+ #[derive(Debug, Clone, Copy, PartialEq)]
12
+ pub struct GriffithsDominantCycleFeatures {
13
+ pub dominant_cycle: f64,
14
+ }
15
+
16
+ #[derive(Debug, Clone)]
17
+ pub struct GriffithsDominantCycleFeatureExtractor {
18
+ inner: GriffithsDominantCycle,
19
+ }
20
+
21
+ impl GriffithsDominantCycleFeatureExtractor {
22
+ pub fn new(lower_bound: usize, upper_bound: usize, length: usize) -> Self {
23
+ Self {
24
+ inner: GriffithsDominantCycle::new(lower_bound, upper_bound, length),
25
+ }
26
+ }
27
+ }
28
+
29
+ impl Next<f64> for GriffithsDominantCycleFeatureExtractor {
30
+ type Output = GriffithsDominantCycleFeatures;
31
+
32
+ fn next(&mut self, input: f64) -> Self::Output {
33
+ let dc = self.inner.next(input);
34
+ GriffithsDominantCycleFeatures { dominant_cycle: dc }
35
+ }
36
+ }
37
+
38
+ #[cfg(test)]
39
+ mod tests {
40
+ use super::*;
41
+
42
+ #[test]
43
+ fn test_griffiths_wrapper_basic() {
44
+ let mut ext = GriffithsDominantCycleFeatureExtractor::new(10, 40, 30);
45
+ for i in 0..100 {
46
+ let val = 100.0 + 5.0 * (i as f64 * 0.25).sin();
47
+ let f = ext.next(val);
48
+ if !f.dominant_cycle.is_nan() {
49
+ assert!(f.dominant_cycle > 5.0 && f.dominant_cycle < 50.0);
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,108 @@
1
+ //! Hurst Exponent feature extractor wrapper.
2
+ //!
3
+ //! Wraps the existing `HurstExponent` to provide a clean ML feature interface
4
+ //! (persistence value + optional regime classification).
5
+ //!
6
+ //! This is one of the highest-ROI single features for ML/regime work:
7
+ //! - H < 0.5 → mean-reverting (anti-persistent)
8
+ //! - H ≈ 0.5 → random walk
9
+ //! - H > 0.5 → trending (persistent)
10
+ //!
11
+ //! Source: quantwave-core/src/indicators/hurst.rs (Rescaled Range implementation)
12
+
13
+ use crate::indicators::hurst::HurstExponent;
14
+ use crate::traits::Next;
15
+
16
+ /// Rich output for Hurst-based features.
17
+ #[derive(Debug, Clone, Copy, PartialEq)]
18
+ pub struct HurstFeatures {
19
+ pub persistence: f64,
20
+ /// Optional discrete regime label for convenience in ML pipelines.
21
+ /// -1 = mean-reverting, 0 = random, +1 = trending (thresholds configurable later).
22
+ pub regime_label: Option<i8>,
23
+ }
24
+
25
+ impl HurstFeatures {
26
+ pub fn new(persistence: f64, regime_label: Option<i8>) -> Self {
27
+ Self { persistence, regime_label }
28
+ }
29
+ }
30
+
31
+ /// Wrapper that turns the existing HurstExponent into a feature-rich extractor.
32
+ #[derive(Debug, Clone)]
33
+ pub struct HurstFeatureExtractor {
34
+ inner: HurstExponent,
35
+ /// Thresholds for regime classification (can be made configurable later).
36
+ mean_reverting_threshold: f64,
37
+ trending_threshold: f64,
38
+ }
39
+
40
+ impl HurstFeatureExtractor {
41
+ pub fn new(period: usize) -> Self {
42
+ Self {
43
+ inner: HurstExponent::new(period),
44
+ mean_reverting_threshold: 0.45,
45
+ trending_threshold: 0.55,
46
+ }
47
+ }
48
+
49
+ pub fn with_thresholds(mut self, mean_rev: f64, trending: f64) -> Self {
50
+ self.mean_reverting_threshold = mean_rev;
51
+ self.trending_threshold = trending;
52
+ self
53
+ }
54
+ }
55
+
56
+ impl Next<f64> for HurstFeatureExtractor {
57
+ type Output = HurstFeatures;
58
+
59
+ fn next(&mut self, input: f64) -> Self::Output {
60
+ let persistence = self.inner.next(input);
61
+
62
+ let regime_label = if persistence.is_nan() {
63
+ None
64
+ } else if persistence < self.mean_reverting_threshold {
65
+ Some(-1)
66
+ } else if persistence > self.trending_threshold {
67
+ Some(1)
68
+ } else {
69
+ Some(0)
70
+ };
71
+
72
+ HurstFeatures::new(persistence, regime_label)
73
+ }
74
+ }
75
+
76
+ #[cfg(test)]
77
+ mod tests {
78
+ use super::*;
79
+ use approx::assert_relative_eq;
80
+
81
+ #[test]
82
+ fn test_hurst_feature_basic() {
83
+ let mut extractor = HurstFeatureExtractor::new(20);
84
+
85
+ // Feed trending data
86
+ for i in 0..30 {
87
+ let val = 100.0 + (i as f64) * 0.5;
88
+ let f = extractor.next(val);
89
+ if !f.persistence.is_nan() {
90
+ assert!(f.persistence > 0.5, "Expected trending persistence, got {}", f.persistence);
91
+ }
92
+ }
93
+ }
94
+
95
+ #[test]
96
+ fn test_hurst_feature_regime_labels() {
97
+ let mut extractor = HurstFeatureExtractor::new(10)
98
+ .with_thresholds(0.4, 0.6);
99
+
100
+ // Force a high persistence value via dummy (real impl will vary)
101
+ // This is a smoke test for the wrapper logic
102
+ let f = extractor.next(100.0);
103
+ // After warmup it should produce a label
104
+ if !f.persistence.is_nan() {
105
+ assert!(f.regime_label.is_some());
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,39 @@
1
+ //! Instantaneous Trendline feature extractor wrapper.
2
+ //!
3
+ //! Wraps the zero-lag trendline. For richer ML use we expose the trend value
4
+ //! + a simple derived "trend strength" (placeholder for phase/power in future).
5
+ //!
6
+ //! Source: quantwave-core/src/indicators/instantaneous_trendline.rs (returns f64 trend)
7
+
8
+ use crate::indicators::instantaneous_trendline::InstantaneousTrendline;
9
+ use crate::traits::Next;
10
+
11
+ #[derive(Debug, Clone, Copy, PartialEq)]
12
+ pub struct InstantaneousTrendlineFeatures {
13
+ pub trend: f64,
14
+ /// Placeholder for future phase/power derived features (0.0 for now)
15
+ pub strength: f64,
16
+ }
17
+
18
+ #[derive(Debug, Clone)]
19
+ pub struct InstantaneousTrendlineFeatureExtractor {
20
+ inner: InstantaneousTrendline,
21
+ }
22
+
23
+ impl InstantaneousTrendlineFeatureExtractor {
24
+ pub fn new() -> Self {
25
+ Self {
26
+ inner: InstantaneousTrendline::new(),
27
+ }
28
+ }
29
+ }
30
+
31
+ impl Next<f64> for InstantaneousTrendlineFeatureExtractor {
32
+ type Output = InstantaneousTrendlineFeatures;
33
+
34
+ fn next(&mut self, input: f64) -> Self::Output {
35
+ let trend = self.inner.next(input);
36
+ // For MVP, strength is 0.0. Real phase/power can be added later from the indicator internals if exposed.
37
+ InstantaneousTrendlineFeatures { trend, strength: 0.0 }
38
+ }
39
+ }