Files
foxhunt/crates/ml-risk/src/position_sizing.rs
jgrusewski d313486dc2 refactor(ml): split monolith into 9 sub-crates + delete dead code
Extract 9 new sub-crates from the ml monolith to enable parallel
compilation across the workspace:

New crates (this commit):
- ml-features (282 tests): feature engineering, 21 modules
- ml-labeling (45 tests): triple barrier, meta-labeling, fractional diff
- ml-ensemble (116 tests): ensemble coordination, voting, confidence
- ml-hyperopt (47 tests): core PSO/TPE optimizer, parameter space
- ml-checkpoint (41 tests): checkpoint persistence, compression, signing
- ml-regime (68 tests): CUSUM, Bayesian changepoint, regime classification
- ml-data-validation (67 tests): FDR correction, CPCV, data quality
- ml-risk (33 tests): neural VaR, Kelly criterion, circuit breakers
- ml-validation (43 tests): statistical validation, walk-forward, DSR

Extended existing crates:
- ml-dqn: added evaluation/ (backtesting engine, metrics, reports)
  and checkpoint implementation
- ml-supervised: added checkpoint implementations
- ml-core: added shared types needed by new sub-crates

Pattern: each module in ml/ becomes a thin facade (pub use subcrate::*)
with bridge modules staying in ml for cross-model adapter code.

Dead code deleted (~7K lines):
- 13 undeclared files in microstructure/ (never compiled)
- 7 undeclared files + tests/ in risk/ (never compiled)
- parquet_io, cache_service, cache_storage, minio_integration (unused)
- extraction_wave_d_impl.rs (bare fn outside impl block)

All 2,746 sub-crate tests + 951 ml tests pass.
Full workspace builds clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:17:22 +01:00

111 lines
3.7 KiB
Rust

//! Position Sizing Neural Networks for HFT Risk Management
//!
//! Implements advanced neural networks for position sizing that enhance
//! Kelly criterion optimization with market microstructure insights.
use ndarray::Array1;
use crate::MLResult as Result;
// Using placeholder type for PositionSizingRecommendation
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PositionSizingRecommendation {
pub recommended_size: f64,
pub max_size: f64,
pub confidence: f64,
}
// CIRCULAR DEPENDENCY FIX: Use MarketRegime from core types
use common::trading::MarketRegime;
#[derive(Debug, Clone)]
pub struct PositionSizingConfig {
pub max_position_size: f64,
pub min_position_size: f64,
pub regime_scaling: bool,
}
impl Default for PositionSizingConfig {
fn default() -> Self {
Self {
max_position_size: 1.0,
min_position_size: 0.01,
regime_scaling: true,
}
}
}
#[derive(Debug)]
pub struct PositionSizingNetwork {
config: PositionSizingConfig,
}
impl PositionSizingNetwork {
pub fn new(config: PositionSizingConfig) -> Result<Self> {
Ok(Self { config })
}
pub fn calculate_regime_scaling(&self, regime: MarketRegime) -> Result<f64> {
match regime {
MarketRegime::Normal => Ok(1.0),
MarketRegime::Crisis => Ok(0.5),
MarketRegime::Trending => Ok(1.2),
MarketRegime::Sideways => Ok(0.8),
MarketRegime::Bull => Ok(1.3),
MarketRegime::Bear => Ok(0.6),
}
}
pub fn softmax_activation(&self, input: &Array1<f64>) -> Result<Array1<f64>> {
let max_val = input.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
let exp_values: Vec<f64> = input.iter().map(|&x| (x - max_val).exp()).collect();
let sum: f64 = exp_values.iter().sum();
let result: Vec<f64> = exp_values.iter().map(|&x| x / sum).collect();
Ok(Array1::from_vec(result))
}
}
// DISABLED: Tests
// // #[cfg(test)]
// mod tests {
// use super::*;
// // use crate::safe_operations; // DISABLED - module not found
//
// #[test]
// fn test_regime_scaling() {
// let config = PositionSizingConfig::default();
// let network = PositionSizingNetwork::new(config)?;
//
// let crisis_scaling = network.calculate_regime_scaling(MarketRegime::Crisis)?;
// let bull_scaling = network.calculate_regime_scaling(MarketRegime::Bull)?;
// let normal_scaling = network.calculate_regime_scaling(MarketRegime::Normal)?;
//
// assert!(crisis_scaling < normal_scaling); // Crisis should reduce positions
// assert!(bull_scaling > normal_scaling); // Bull should increase positions
// assert_eq!(normal_scaling, 1.0); // Normal should be baseline
// assert_eq!(crisis_scaling, 0.5); // Crisis should be 50% of normal
// }
//
// #[test]
// fn test_softmax_activation() {
// let config = PositionSizingConfig::default();
// let network = PositionSizingNetwork::new(config)?;
//
// let input = Array1::from_vec(vec![1.0, 2.0, 0.5]);
// let output = network.softmax_activation(&input)?;
//
// // Check that outputs sum to approximately 1
// let sum: f64 = output.iter().sum();
// assert!((sum - 1.0).abs() < 0.01); // Within 1% tolerance
//
// // Check that all outputs are positive
// for &val in &output {
// assert!(val > 0.0);
// }
//
// // Check that the softmax ordering is preserved (higher input -> higher output)
// assert!(output[1] > output[0]); // input[1]=2.0 > input[0]=1.0
// assert!(output[0] > output[2]); // input[0]=1.0 > input[2]=0.5
// }
// }