feat: Wave 1 - Update HIGH RISK files (225→54 features)
WAVE 21: Core type definitions and trainer configs updated Files Modified (13 files): - ml/src/features/extraction.rs: FeatureVector = [f64; 54] - common/src/features/types.rs: Added FeatureVector54 - ml/src/trainers/dqn.rs: state_dim 225→54 - ml/src/trainers/ppo.rs: state_dim 225→54 - ml/src/dqn/dqn.rs, config.rs, replay_buffer.rs: Updated configs - ml/src/hyperopt/adapters/: All adapters updated to 54-dim - ml/src/features/unified.rs: Struct fields updated - ml/src/trainers/tft_parquet.rs: Return types updated Agents Deployed: 5 parallel agents Test Results: cargo check --package ml --lib PASSING Next: Wave 2 (examples), Wave 3 (tests), Wave 4 (OFI integration) Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -445,7 +445,7 @@ impl HyperparameterOptimizable for ContinuousPPOTrainer {
|
||||
|
||||
// Create continuous PPO config
|
||||
let policy_config = ContinuousPolicyConfig {
|
||||
state_dim: 225,
|
||||
state_dim: 54,
|
||||
hidden_dims: vec![128, 64],
|
||||
action_min: params.action_min as f32,
|
||||
action_max: params.action_max as f32,
|
||||
@@ -454,7 +454,7 @@ impl HyperparameterOptimizable for ContinuousPPOTrainer {
|
||||
};
|
||||
|
||||
let ppo_config = ContinuousPPOConfig {
|
||||
state_dim: 225,
|
||||
state_dim: 54,
|
||||
policy_config,
|
||||
value_hidden_dims: vec![128, 64],
|
||||
policy_learning_rate: params.policy_lr,
|
||||
|
||||
@@ -526,7 +526,7 @@ pub struct DQNMetrics {
|
||||
/// - **DBN data dir**: Market data source (OHLCV bars from Databento)
|
||||
/// - **Epochs**: Number of training epochs per trial
|
||||
/// - **Device**: CUDA GPU (falls back to CPU if unavailable)
|
||||
/// - **Features**: 125 features (Wave 16D: Reduced from 225 by Agent 37)
|
||||
/// - **Features**: 54 features (Wave 1 Agent 5: Reduced from 225→54)
|
||||
///
|
||||
/// ## Fixed Architecture
|
||||
///
|
||||
@@ -784,7 +784,7 @@ impl DQNTrainer {
|
||||
/// - No Parquet or DBN files found
|
||||
/// - File format is invalid
|
||||
/// - Feature extraction fails
|
||||
fn load_training_data(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
fn load_training_data(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use std::path::Path;
|
||||
|
||||
let dir_path = Path::new(&self.dbn_data_dir);
|
||||
@@ -803,10 +803,10 @@ impl DQNTrainer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Load training data from Parquet file
|
||||
/// Load training data from Parquet file (54-feature vectors)
|
||||
///
|
||||
/// Reads OHLCV bars from Parquet file, extracts 225-feature vectors,
|
||||
/// and creates (state, reward) tuples for DQN training.
|
||||
/// Reads OHLCV bars from Parquet file, extracts 54-feature vectors,
|
||||
/// and creates (state, reward) tuples for DQN training
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@@ -818,7 +818,7 @@ impl DQNTrainer {
|
||||
/// - No Parquet file found in directory
|
||||
/// - Parquet file is malformed
|
||||
/// - Feature extraction fails
|
||||
fn load_from_parquet(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
fn load_from_parquet(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use crate::features::extraction::OHLCVBar;
|
||||
use arrow::array::{Array, Float64Array, PrimitiveArray, UInt64Array};
|
||||
use arrow::datatypes::TimestampNanosecondType;
|
||||
@@ -925,16 +925,16 @@ impl DQNTrainer {
|
||||
/// # Returns
|
||||
///
|
||||
/// Error indicating DBN loading not yet implemented
|
||||
fn load_from_dbn(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
fn load_from_dbn(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
Err(anyhow::anyhow!(
|
||||
"DBN file loading not yet implemented for DQN. Please use Parquet files instead."
|
||||
))
|
||||
}
|
||||
|
||||
/// Extract 225-feature vectors from OHLCV bars and create training data
|
||||
/// Extract 54-feature vectors from OHLCV bars and create training data
|
||||
///
|
||||
/// Uses the production feature extraction API (extract_ml_features) to
|
||||
/// generate 225-feature vectors from OHLCV bars. Creates dummy rewards
|
||||
/// generate 54-feature vectors from OHLCV bars. Creates dummy rewards
|
||||
/// for DQN training (actual rewards are computed during training).
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -943,8 +943,8 @@ impl DQNTrainer {
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Vector of (state, reward) tuples where:
|
||||
/// - state: [f32; 225] feature vector
|
||||
/// Vector of (state, reward) tuples where
|
||||
/// - state: [f32; 54] feature vector
|
||||
/// - reward: f64 dummy reward (0.0)
|
||||
///
|
||||
/// # Errors
|
||||
@@ -955,11 +955,11 @@ impl DQNTrainer {
|
||||
fn extract_features_and_targets(
|
||||
&self,
|
||||
ohlcv_bars: &[crate::features::extraction::OHLCVBar],
|
||||
) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use crate::features::extraction::extract_ml_features;
|
||||
|
||||
info!(
|
||||
"Extracting 225-feature vectors from {} OHLCV bars...",
|
||||
"Extracting 54-feature vectors from {} OHLCV bars...",
|
||||
ohlcv_bars.len()
|
||||
);
|
||||
|
||||
@@ -971,18 +971,18 @@ impl DQNTrainer {
|
||||
));
|
||||
}
|
||||
|
||||
// Extract features using production API (returns Vec<[f64; 225]>)
|
||||
// Extract features using production API (returns Vec<[f64; 54]>)
|
||||
let feature_vectors = extract_ml_features(ohlcv_bars)
|
||||
.map_err(|e| anyhow::anyhow!("Feature extraction failed: {}", e))?;
|
||||
|
||||
info!("Extracted {} feature vectors", feature_vectors.len());
|
||||
|
||||
// Convert to [f32; 225] and create dummy rewards (actual rewards computed during training)
|
||||
let training_data: Vec<([f32; 225], f64)> = feature_vectors
|
||||
// Convert to [f32; 54] and create dummy rewards (actual rewards computed during training)
|
||||
let training_data: Vec<([f32; 54], f64)> = feature_vectors
|
||||
.into_iter()
|
||||
.map(|vec_f64| {
|
||||
// Convert [f64; 225] to [f32; 225]
|
||||
let mut vec_f32 = [0.0_f32; 225];
|
||||
// Convert [f64; 54] to [f32; 54]
|
||||
let mut vec_f32 = [0.0_f32; 54];
|
||||
for (i, &val) in vec_f64.iter().enumerate() {
|
||||
vec_f32[i] = val as f32;
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ impl HyperparameterOptimizable for PPOTrainer {
|
||||
|
||||
// Create PPO config with trial hyperparameters
|
||||
let ppo_config = PPOConfig {
|
||||
state_dim: 225, // Wave D features
|
||||
state_dim: 54, // Wave D features
|
||||
num_actions: 45, // 5×3×3 factored action space (size × order type × duration)
|
||||
policy_hidden_dims: vec![128, 64],
|
||||
value_hidden_dims: vec![256, 128, 64],
|
||||
@@ -585,8 +585,8 @@ impl HyperparameterOptimizable for PPOTrainer {
|
||||
impl PPOTrainer {
|
||||
/// Load training data from Parquet/DBN files
|
||||
///
|
||||
/// Returns feature vectors (225 dims) with target close prices for trajectory generation
|
||||
fn load_training_data(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
/// Returns feature vectors (54 dims) with target close prices for trajectory generation
|
||||
fn load_training_data(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use std::path::Path;
|
||||
|
||||
let dir_path = Path::new(&self.dbn_data_dir);
|
||||
@@ -606,7 +606,7 @@ impl PPOTrainer {
|
||||
}
|
||||
|
||||
/// Load training data from Parquet file (optimized path)
|
||||
fn load_from_parquet(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
fn load_from_parquet(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use crate::features::extraction::OHLCVBar;
|
||||
use arrow::array::{Array, Float64Array, PrimitiveArray, UInt64Array};
|
||||
use arrow::datatypes::TimestampNanosecondType;
|
||||
@@ -704,7 +704,7 @@ impl PPOTrainer {
|
||||
}
|
||||
|
||||
/// Load training data from DBN files
|
||||
fn load_from_dbn(&self) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
fn load_from_dbn(&self) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
let dbn_files: Vec<_> = std::fs::read_dir(&self.dbn_data_dir)?
|
||||
.filter_map(|entry| entry.ok())
|
||||
.filter(|entry| entry.path().extension().and_then(|s| s.to_str()) == Some("dbn"))
|
||||
@@ -724,15 +724,15 @@ impl PPOTrainer {
|
||||
));
|
||||
}
|
||||
|
||||
/// Extract 225-feature vectors and targets from OHLCV bars
|
||||
/// Extract 54-feature vectors and targets from OHLCV bars
|
||||
fn extract_features_and_targets(
|
||||
&self,
|
||||
ohlcv_bars: &[crate::features::extraction::OHLCVBar],
|
||||
) -> anyhow::Result<Vec<([f32; 225], f64)>> {
|
||||
) -> anyhow::Result<Vec<([f32; 54], f64)>> {
|
||||
use crate::features::extraction::extract_ml_features;
|
||||
|
||||
info!(
|
||||
"Extracting 225-feature vectors from {} OHLCV bars...",
|
||||
"Extracting 54-feature vectors from {} OHLCV bars...",
|
||||
ohlcv_bars.len()
|
||||
);
|
||||
|
||||
@@ -744,12 +744,12 @@ impl PPOTrainer {
|
||||
));
|
||||
}
|
||||
|
||||
// Extract features using production API (returns Vec<[f64; 225]>)
|
||||
// Extract features using production API (returns Vec<[f64; 54]>)
|
||||
let feature_vectors = extract_ml_features(ohlcv_bars)
|
||||
.map_err(|e| anyhow::anyhow!("Feature extraction failed: {}", e))?;
|
||||
|
||||
info!(
|
||||
"Extracted {} feature vectors (225 dimensions each)",
|
||||
"Extracted {} feature vectors (54 dimensions each)",
|
||||
feature_vectors.len()
|
||||
);
|
||||
|
||||
@@ -767,13 +767,13 @@ impl PPOTrainer {
|
||||
let features_f32: Vec<f32> = feature_vectors[i].iter().map(|&f| f as f32).collect();
|
||||
|
||||
// Convert Vec to fixed-size array
|
||||
if features_f32.len() == 225 {
|
||||
let mut feature_array = [0.0f32; 225];
|
||||
if features_f32.len() == 54 {
|
||||
let mut feature_array = [0.0f32; 54];
|
||||
feature_array.copy_from_slice(&features_f32);
|
||||
training_data.push((feature_array, next_close));
|
||||
} else {
|
||||
warn!(
|
||||
"Feature vector has wrong size: {} != 225",
|
||||
"Feature vector has wrong size: {} != 54",
|
||||
features_f32.len()
|
||||
);
|
||||
}
|
||||
@@ -787,15 +787,15 @@ impl PPOTrainer {
|
||||
.iter()
|
||||
.map(|&f| f as f32)
|
||||
.collect();
|
||||
if features_f32.len() == 225 {
|
||||
let mut feature_array = [0.0f32; 225];
|
||||
if features_f32.len() == 54 {
|
||||
let mut feature_array = [0.0f32; 54];
|
||||
feature_array.copy_from_slice(&features_f32);
|
||||
training_data.push((feature_array, last_close));
|
||||
}
|
||||
}
|
||||
|
||||
info!(
|
||||
"Created {} training samples with 225-dim features",
|
||||
"Created {} training samples with 54-dim features",
|
||||
training_data.len()
|
||||
);
|
||||
|
||||
@@ -808,7 +808,7 @@ impl PPOTrainer {
|
||||
/// to select actions and computing rewards based on price movements.
|
||||
fn generate_trajectories_from_data(
|
||||
&self,
|
||||
data: &[([f32; 225], f64)],
|
||||
data: &[([f32; 54], f64)],
|
||||
num_episodes: usize,
|
||||
) -> anyhow::Result<TrajectoryBatch> {
|
||||
use crate::ppo::trajectories::{Trajectory, TrajectoryStep};
|
||||
|
||||
Reference in New Issue
Block a user