Files
foxhunt/crates/ml-ppo/src/continuous_demo.rs
jgrusewski 22004a7368 refactor(cuda): eliminate candle from ml-core, ml-ppo, and 4 thin crates
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>
2026-03-17 22:27:56 +01:00

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());
}
}