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>
286 lines
10 KiB
Rust
286 lines
10 KiB
Rust
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
|
#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
|
|
#![allow(dead_code)]
|
|
#![allow(missing_docs)]
|
|
#![allow(missing_debug_implementations)]
|
|
#![allow(unused_crate_dependencies)]
|
|
#![allow(clippy::float_arithmetic)]
|
|
#![allow(clippy::non_ascii_literal)]
|
|
#![allow(clippy::str_to_string)]
|
|
#![allow(clippy::partial_pub_fields)]
|
|
#![allow(clippy::multiple_inherent_impl)]
|
|
#![allow(clippy::same_name_method)]
|
|
#![allow(clippy::shadow_reuse)]
|
|
#![allow(clippy::shadow_unrelated)]
|
|
#![allow(clippy::shadow_same)]
|
|
#![allow(clippy::doc_markdown)]
|
|
#![allow(clippy::indexing_slicing)]
|
|
#![allow(clippy::missing_const_for_fn)]
|
|
#![allow(clippy::module_name_repetitions)]
|
|
#![allow(clippy::integer_division)]
|
|
#![allow(clippy::cognitive_complexity)]
|
|
#![allow(clippy::similar_names)]
|
|
#![allow(clippy::clone_on_ref_ptr)]
|
|
#![allow(clippy::too_many_lines)]
|
|
#![allow(clippy::as_conversions)]
|
|
#![allow(clippy::cast_precision_loss)]
|
|
#![allow(clippy::cast_possible_truncation)]
|
|
#![allow(clippy::default_numeric_fallback)]
|
|
#![allow(clippy::arithmetic_side_effects)]
|
|
#![allow(clippy::needless_range_loop)]
|
|
#![allow(clippy::into_iter_on_ref)]
|
|
#![allow(clippy::new_without_default)]
|
|
#![allow(clippy::manual_let_else)]
|
|
#![allow(clippy::unnecessary_wraps)]
|
|
#![allow(clippy::too_many_arguments)]
|
|
#![allow(clippy::must_use_candidate)]
|
|
#![allow(clippy::missing_errors_doc)]
|
|
#![allow(clippy::cast_sign_loss)]
|
|
#![allow(clippy::cast_possible_wrap)]
|
|
#![allow(clippy::cast_lossless)]
|
|
#![allow(clippy::unused_async)]
|
|
#![allow(clippy::match_same_arms)]
|
|
#![allow(clippy::unused_self)]
|
|
#![allow(clippy::map_err_ignore)]
|
|
#![allow(clippy::single_match_else)]
|
|
#![allow(clippy::wildcard_imports)]
|
|
#![allow(clippy::unnecessary_cast)]
|
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
|
#![allow(clippy::redundant_clone)]
|
|
#![allow(clippy::redundant_closure)]
|
|
#![allow(clippy::type_complexity)]
|
|
#![allow(clippy::manual_clamp)]
|
|
#![allow(clippy::clone_on_copy)]
|
|
#![allow(clippy::should_implement_trait)]
|
|
#![allow(clippy::derivable_impls)]
|
|
#![allow(clippy::useless_conversion)]
|
|
#![allow(clippy::get_first)]
|
|
#![allow(clippy::len_zero)]
|
|
#![allow(clippy::assign_op_pattern)]
|
|
#![allow(clippy::if_same_then_else)]
|
|
#![allow(clippy::unused_enumerate_index)]
|
|
#![allow(clippy::doc_lazy_continuation)]
|
|
#![allow(clippy::doc_overindented_list_items)]
|
|
#![allow(clippy::single_char_add_str)]
|
|
#![allow(clippy::let_and_return)]
|
|
#![allow(clippy::useless_format)]
|
|
#![allow(clippy::manual_div_ceil)]
|
|
#![allow(clippy::io_other_error)]
|
|
#![allow(clippy::manual_range_contains)]
|
|
#![allow(clippy::unwrap_or_default)]
|
|
#![allow(clippy::used_underscore_binding)]
|
|
#![allow(clippy::trivially_copy_pass_by_ref)]
|
|
#![allow(clippy::needless_borrows_for_generic_args)]
|
|
#![allow(clippy::needless_borrow)]
|
|
#![allow(clippy::missing_safety_doc)]
|
|
#![allow(clippy::module_inception)]
|
|
#![allow(clippy::if_not_else)]
|
|
|
|
//! # Neural Risk Management System
|
|
//!
|
|
//! Advanced ML-driven risk management with neural VaR models, Kelly criterion optimization,
|
|
//! and real-time regime detection for production HFT systems using canonical types.
|
|
|
|
pub mod circuit_breakers;
|
|
pub mod graph_risk_model;
|
|
pub mod kelly_optimizer;
|
|
pub mod kelly_position_sizing_service;
|
|
pub mod position_sizing;
|
|
pub mod slippage;
|
|
pub mod var_models;
|
|
|
|
// Re-export key types from submodules
|
|
pub use circuit_breakers::MLCircuitBreaker;
|
|
pub use kelly_optimizer::{
|
|
KellyCriterionOptimizer, KellyOptimizerConfig, KellyPositionRecommendation,
|
|
};
|
|
pub use position_sizing::PositionSizingNetwork;
|
|
pub use slippage::{FixedCostModel, LinearImpactConfig, LinearImpactModel, MarketImpactModel};
|
|
pub use var_models::{NeuralVarConfig, NeuralVarModel};
|
|
|
|
// Re-export core ML types used throughout risk modules
|
|
pub use ml_core::{MLError, MLResult, MarketDataSnapshot};
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use ndarray::Array2;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use common::{Price, Volume};
|
|
|
|
// AssetId type for risk management
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
|
|
pub struct AssetId(String);
|
|
|
|
/// Risk assessment levels
|
|
/// RiskLevel component.
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd)]
|
|
pub enum RiskLevel {
|
|
VeryLow,
|
|
Low,
|
|
Medium,
|
|
High,
|
|
VeryHigh,
|
|
Critical,
|
|
}
|
|
|
|
/// Portfolio risk profile
|
|
/// RiskProfile component.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RiskProfile {
|
|
pub total_var_95: f64, // 1-day 95% VaR
|
|
pub total_var_99: f64, // 1-day 99% VaR
|
|
pub expected_shortfall: f64, // Expected tail loss
|
|
pub maximum_drawdown: f64, // Historical maximum drawdown
|
|
pub current_drawdown: f64, // Current drawdown from peak
|
|
pub sharpe_ratio: f64, // Risk-adjusted return
|
|
pub sortino_ratio: f64, // Downside risk-adjusted return
|
|
pub calmar_ratio: f64, // Return over maximum drawdown
|
|
pub beta: f64, // Market beta
|
|
pub tracking_error: f64, // Volatility vs benchmark
|
|
pub concentration_risk: f64, // Single position concentration
|
|
pub correlation_risk: f64, // Average correlation risk
|
|
pub liquidity_risk: f64, // Liquidity-adjusted risk
|
|
pub regime_risk: f64, // Market regime risk factor
|
|
pub overall_risk_score: f64, // Combined ML risk score (0-1)
|
|
pub risk_level: RiskLevel, // Categorical risk assessment
|
|
pub timestamp: DateTime<Utc>,
|
|
}
|
|
|
|
/// Position-level risk metrics
|
|
/// PositionRisk component.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PositionRisk {
|
|
pub asset_id: AssetId,
|
|
pub position_size: f64, // Current position size
|
|
pub market_value: f64, // Current market value
|
|
pub var_contribution: f64, // Contribution to portfolio VaR
|
|
pub marginal_var: f64, // Marginal VaR (change in portfolio VaR)
|
|
pub component_var: f64, // Component VaR (allocation of portfolio VaR)
|
|
pub standalone_var: f64, // Position VaR in isolation
|
|
pub beta_to_portfolio: f64, // Beta relative to portfolio
|
|
pub correlation_risk: f64, // Correlation with other positions
|
|
pub liquidity_horizon: f64, // Days to liquidate position
|
|
pub concentration_weight: f64, // Weight in portfolio
|
|
pub stress_loss: f64, // Loss under stress scenarios
|
|
pub kelly_optimal_size: f64, // Kelly optimal position size
|
|
pub recommended_size: f64, // ML recommended position size
|
|
pub risk_score: f64, // Individual risk score (0-1)
|
|
pub timestamp: DateTime<Utc>,
|
|
}
|
|
|
|
/// `Market` data for risk calculations
|
|
/// MarketData component.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct MarketData {
|
|
pub timestamp: DateTime<Utc>,
|
|
pub prices: HashMap<AssetId, Price>,
|
|
pub volumes: HashMap<AssetId, Volume>,
|
|
pub volatilities: HashMap<AssetId, f64>,
|
|
pub correlations: Array2<f64>,
|
|
pub market_cap_weights: HashMap<AssetId, f64>,
|
|
pub sector_exposures: HashMap<String, f64>,
|
|
}
|
|
|
|
/// Risk limits and constraints
|
|
/// RiskLimits component.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RiskLimits {
|
|
pub max_portfolio_var: f64, // Maximum portfolio VaR
|
|
pub max_position_size: f64, // Maximum single position size
|
|
pub max_sector_exposure: f64, // Maximum sector exposure
|
|
pub max_correlation: f64, // Maximum position correlation
|
|
pub max_drawdown: f64, // Maximum allowed drawdown
|
|
pub min_liquidity_days: f64, // Minimum liquidity (days to exit)
|
|
pub max_leverage: f64, // Maximum portfolio leverage
|
|
pub var_limit_buffer: f64, // VaR limit buffer (e.g., 0.8 of limit)
|
|
}
|
|
|
|
impl Default for RiskLimits {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_portfolio_var: 0.02, // 2% daily VaR limit
|
|
max_position_size: 0.05, // 5% maximum position size
|
|
max_sector_exposure: 0.20, // 20% maximum sector exposure
|
|
max_correlation: 0.70, // 70% maximum correlation
|
|
max_drawdown: 0.10, // 10% maximum drawdown
|
|
min_liquidity_days: 2.0, // 2 days maximum liquidation time
|
|
max_leverage: 3.0, // 3x maximum leverage
|
|
var_limit_buffer: 0.80, // Use 80% of VaR limit
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Comprehensive risk configuration
|
|
/// RiskConfig component.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RiskConfig {
|
|
pub var_confidence_levels: Vec<f64>,
|
|
pub lookback_days: usize,
|
|
pub monte_carlo_simulations: usize,
|
|
pub stress_scenarios: usize,
|
|
pub regime_detection_window: usize,
|
|
pub update_frequency_seconds: u32,
|
|
pub enable_neural_var: bool,
|
|
pub enable_regime_detection: bool,
|
|
pub enable_ml_position_sizing: bool,
|
|
pub enable_dynamic_hedging: bool,
|
|
pub risk_limits: RiskLimits,
|
|
}
|
|
|
|
impl Default for RiskConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
var_confidence_levels: vec![0.95, 0.99],
|
|
lookback_days: 252,
|
|
monte_carlo_simulations: 10_000,
|
|
stress_scenarios: 1_000,
|
|
regime_detection_window: 60,
|
|
update_frequency_seconds: 60,
|
|
enable_neural_var: true,
|
|
enable_regime_detection: true,
|
|
enable_ml_position_sizing: true,
|
|
enable_dynamic_hedging: true,
|
|
risk_limits: RiskLimits::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Main neural risk management system
|
|
#[derive(Debug)]
|
|
pub struct NeuralRiskManager {
|
|
config: RiskConfig,
|
|
var_model: NeuralVarModel,
|
|
kelly_optimizer: KellyCriterionOptimizer,
|
|
position_sizer: PositionSizingNetwork,
|
|
circuit_breaker: MLCircuitBreaker,
|
|
}
|
|
|
|
impl NeuralRiskManager {
|
|
/// Create new neural risk management system
|
|
pub fn new(config: RiskConfig) -> MLResult<Self> {
|
|
let var_config = NeuralVarConfig {
|
|
confidence_levels: config.var_confidence_levels.clone(),
|
|
lookback_days: config.lookback_days,
|
|
lookback_period: config.lookback_days,
|
|
monte_carlo_simulations: config.monte_carlo_simulations,
|
|
enable_stress_testing: true,
|
|
hidden_layers: vec![128, 64, 32],
|
|
};
|
|
|
|
let var_model = NeuralVarModel::new(var_config)?;
|
|
let kelly_optimizer = KellyCriterionOptimizer::new(Default::default())?;
|
|
let position_sizer = PositionSizingNetwork::new(Default::default())?;
|
|
let circuit_breaker = MLCircuitBreaker::new(Default::default())?;
|
|
|
|
Ok(Self {
|
|
config,
|
|
var_model,
|
|
kelly_optimizer,
|
|
position_sizer,
|
|
circuit_breaker,
|
|
})
|
|
}
|
|
}
|