Hard refactor — no shims, no compat layers. Candle removed from Cargo.toml and all source files in 6 crates: - ml-core: MlDevice enum, checkpoint.rs (safetensors direct), cudarc imports fixed from candle re-export to direct, AdamWConfig lr_decay, cuda_compat gutted. Net -7,341 lines. - ml-ppo: All 16 files rewritten. LSTM→CudaLSTM, VarMap→GpuVarStore, PPOAgent 2306→700 lines, checkpoint→binary format. - ml-ensemble: GPU-resident sigmoid via custom CUDA kernel. - ml-explainability: Integrated gradients via GPU finite-difference kernels. - ml-labeling: Device→MlDevice. - ml-hyperopt: Cargo.toml only. Remaining: ml-dqn (24 files), ml-supervised (4 files), ml crate (104 files). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
131 lines
4.1 KiB
Rust
131 lines
4.1 KiB
Rust
//! Simple Continuous Policy Demo
|
|
//!
|
|
//! Demonstrates the core functionality of the Gaussian continuous policy
|
|
//! for position sizing without the complex PPO training infrastructure.
|
|
|
|
use super::continuous_policy::{ContinuousAction, ContinuousPolicyConfig, ContinuousPolicyNetwork};
|
|
use ml_core::MLError;
|
|
use tracing::info;
|
|
|
|
/// Simple demo showing Gaussian policy for continuous position sizing
|
|
#[allow(clippy::cognitive_complexity)]
|
|
pub fn demo_continuous_position_sizing() -> Result<(), MLError> {
|
|
info!("Continuous Position Sizing Demo");
|
|
|
|
let config = ContinuousPolicyConfig {
|
|
state_dim: 8,
|
|
hidden_dims: vec![16, 8],
|
|
min_log_std: -2.0,
|
|
max_log_std: 0.5,
|
|
init_log_std: -1.0,
|
|
learnable_std: true,
|
|
action_bounds: (0.0, 1.0),
|
|
};
|
|
|
|
let policy = ContinuousPolicyNetwork::new(config)?;
|
|
|
|
info!("Created continuous policy network");
|
|
|
|
let market_scenarios = vec![
|
|
("Bullish Market", vec![1.0_f32, 0.1, 0.8, 0.02, 0.7, 0.1, 0.05, 0.3]),
|
|
("Bearish Market", vec![0.2, 0.3, 0.3, 0.08, 0.2, -0.2, 0.03, 0.1]),
|
|
("Volatile Market", vec![0.5, 0.8, 0.6, 0.15, 0.4, 0.0, 0.1, 0.5]),
|
|
("Stable Market", vec![0.6, 0.1, 0.9, 0.01, 0.5, 0.05, 0.02, 0.2]),
|
|
];
|
|
|
|
info!("Position Sizing Recommendations:");
|
|
|
|
for (scenario_name, state_vec) in market_scenarios {
|
|
let mut position_sizes = Vec::new();
|
|
for _ in 0..5 {
|
|
let (action_value, log_prob) = policy.sample_action_host(&state_vec)?;
|
|
let action = ContinuousAction::new(action_value);
|
|
position_sizes.push((action.position_size(), log_prob));
|
|
}
|
|
|
|
let mean_position: f32 =
|
|
position_sizes.iter().map(|(pos, _)| *pos).sum::<f32>() / position_sizes.len() as f32;
|
|
let samples: Vec<_> = position_sizes
|
|
.iter()
|
|
.map(|(pos, _)| format!("{:.1}%", pos * 100.0))
|
|
.collect();
|
|
info!(
|
|
scenario = scenario_name,
|
|
avg_position_pct = %(mean_position * 100.0),
|
|
samples = %samples.join(", "),
|
|
"Position sizing recommendation"
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Demonstrate the difference between discrete and continuous actions
|
|
#[allow(clippy::cognitive_complexity)]
|
|
pub fn compare_discrete_vs_continuous() -> Result<(), MLError> {
|
|
info!("Discrete vs Continuous Action Comparison");
|
|
info!("Discrete Actions Available: Hold, Small, Medium, Large, Max");
|
|
info!("Continuous Actions Available: any position size from 0.0% to 100.0%");
|
|
Ok(())
|
|
}
|
|
|
|
/// Example of how continuous policy integrates with trading system
|
|
pub fn trading_integration_example() -> Result<(), MLError> {
|
|
info!("Trading System Integration Example");
|
|
|
|
let config = ContinuousPolicyConfig {
|
|
state_dim: 16,
|
|
hidden_dims: vec![32, 16],
|
|
action_bounds: (0.0, 0.8),
|
|
..ContinuousPolicyConfig::default()
|
|
};
|
|
|
|
let policy = ContinuousPolicyNetwork::new(config)?;
|
|
|
|
let trading_state = vec![
|
|
0.95_f32, 0.02, 0.15, 0.7,
|
|
0.6, 0.1, 0.8, 0.3,
|
|
0.12, 0.05, 0.25, 0.9,
|
|
0.6, 0.4, 0.15, 0.3,
|
|
];
|
|
|
|
let (action_value, log_prob) = policy.sample_action_host(&trading_state)?;
|
|
let recommended_position = ContinuousAction::new(action_value);
|
|
|
|
let portfolio_value = 100_000.0_f64;
|
|
let position_value = portfolio_value * recommended_position.position_size() as f64;
|
|
|
|
info!(
|
|
position_size_pct = %(recommended_position.position_size() * 100.0),
|
|
log_prob = %log_prob,
|
|
position_value = %position_value,
|
|
"AI Recommendation"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[allow(clippy::use_debug, clippy::assertions_on_result_states)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_continuous_demo() {
|
|
let result = demo_continuous_position_sizing();
|
|
assert!(result.is_ok(), "Demo failed: {:?}", result.err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_comparison_demo() {
|
|
let result = compare_discrete_vs_continuous();
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_integration_example() {
|
|
let result = trading_integration_example();
|
|
assert!(result.is_ok());
|
|
}
|
|
}
|