Move 17 library crates into crates/, CLI binary into bin/fxt, consolidate 10 test crates into testing/, split config crate from deployment config files. Root directory reduced from 38+ to ~17 directories. All Cargo.toml paths and build.rs proto refs updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
75 lines
2.7 KiB
Rust
75 lines
2.7 KiB
Rust
/// WAVE 8 AGENT 37: Extract Wave D regime detection features (24 total)
|
|
///
|
|
/// ## Feature Breakdown (Indices 201-224)
|
|
/// - 201-210: CUSUM features (10)
|
|
/// - 211-215: ADX & directional indicators (5)
|
|
/// - 216-220: Transition probabilities (5)
|
|
/// - 221-224: Adaptive position/stop-loss (4)
|
|
fn extract_wave_d_features(&mut self, out: &mut [f64]) -> Result<()> {
|
|
let bar = self.bars.back().context("No current bar")?;
|
|
let mut idx = 0;
|
|
|
|
// Features 201-210: CUSUM regime detection (10 features)
|
|
let return_value = if self.bars.len() > 1 {
|
|
let prev = &self.bars[self.bars.len() - 2];
|
|
safe_log_return(bar.close, prev.close)
|
|
} else {
|
|
0.0
|
|
};
|
|
let cusum_features = self.regime_cusum.update(return_value);
|
|
out[idx..idx + 10].copy_from_slice(&cusum_features);
|
|
idx += 10;
|
|
|
|
// Features 211-215: ADX & directional indicators (5 features)
|
|
// Convert OHLCVBar to regime_adx OHLCVBar format
|
|
let adx_bar = crate::features::regime_adx::OHLCVBar {
|
|
timestamp: bar.timestamp.timestamp(),
|
|
open: bar.open,
|
|
high: bar.high,
|
|
low: bar.low,
|
|
close: bar.close,
|
|
volume: bar.volume,
|
|
};
|
|
let adx_features = self.regime_adx.update(&adx_bar);
|
|
out[idx..idx + 5].copy_from_slice(&adx_features);
|
|
idx += 5;
|
|
|
|
// Features 216-220: Transition probabilities (5 features)
|
|
// Determine current regime based on ADX and CUSUM
|
|
let adx_value = adx_features[0]; // ADX strength
|
|
let cusum_direction = cusum_features[3]; // Direction feature
|
|
let current_regime = if adx_value > 25.0 {
|
|
if cusum_direction > 0.5 {
|
|
MarketRegime::Bull
|
|
} else if cusum_direction < -0.5 {
|
|
MarketRegime::Bear
|
|
} else {
|
|
MarketRegime::Trending
|
|
}
|
|
} else if adx_value < 20.0 {
|
|
MarketRegime::Sideways
|
|
} else {
|
|
MarketRegime::Normal
|
|
};
|
|
let transition_features = self.regime_transition.update(current_regime);
|
|
out[idx..idx + 5].copy_from_slice(&transition_features);
|
|
idx += 5;
|
|
|
|
// Features 221-224: Adaptive position sizing & stop-loss (4 features)
|
|
// Convert bars to regime_adaptive format
|
|
let adaptive_bars: Vec<crate::features::regime_adaptive::OHLCVBar> = self.bars.iter().map(|b| {
|
|
crate::features::regime_adaptive::OHLCVBar {
|
|
timestamp: b.timestamp,
|
|
open: b.open,
|
|
high: b.high,
|
|
low: b.low,
|
|
close: b.close,
|
|
volume: b.volume,
|
|
}
|
|
}).collect();
|
|
let adaptive_features = self.regime_adaptive.update(current_regime, return_value, 0.0, &adaptive_bars);
|
|
out[idx..idx + 4].copy_from_slice(&adaptive_features);
|
|
|
|
Ok(())
|
|
}
|