🔧 Wave 33: Partial TimeDelta Migration - ML Crate Complete

## Progress Update
-  ml/src/features.rs: Complete TimeDelta migration (6 fixes)
-  ml/src/training_pipeline.rs: Complete TimeDelta migration (3 fixes)
- ⚠️  backtesting crate: Needs TimeDelta migration
- ⚠️  trading_service: Needs TimeDelta migration
- ⚠️  ml_training_service: Needs TimeDelta migration

## Fixes Applied
- Added TimeDelta to imports across ml crate
- Converted Duration::hours/days/minutes → TimeDelta::hours/days/minutes
- Added TimeDelta::from_std() conversions for std::time::Duration
- Fixed method calls: as_secs_f64() → num_milliseconds() / 1000.0

## Next Steps
Deploy parallel agents to complete migration workspace-wide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2025-10-01 20:36:58 +02:00
parent 3cc57a068b
commit bb1042b848
2 changed files with 17 additions and 14 deletions

View File

@@ -16,7 +16,7 @@ use common::types::{Price, Quantity, Volume, Symbol};
use std::collections::HashMap;
use std::sync::Arc;
use chrono::{DateTime, Utc};
use chrono::{DateTime, TimeDelta, Utc};
use rand::prelude::*;
use rust_decimal::prelude::ToPrimitive;
use serde::{Deserialize, Serialize};
@@ -985,15 +985,15 @@ impl UnifiedFeatureExtractor {
let news_sentiment_1h = alt_data
.news_data
.as_ref()
.and_then(|news| self.calculate_news_sentiment_score(news, Duration::hours(1)));
.and_then(|news| self.calculate_news_sentiment_score(news, TimeDelta::hours(1)));
let news_sentiment_1d = alt_data
.news_data
.as_ref()
.and_then(|news| self.calculate_news_sentiment_score(news, Duration::days(1)));
.and_then(|news| self.calculate_news_sentiment_score(news, TimeDelta::days(1)));
let news_volume_1h = alt_data
.news_data
.as_ref()
.map(|news| self.calculate_news_volume(news, Duration::hours(1)));
.map(|news| self.calculate_news_volume(news, TimeDelta::hours(1)));
// Social media sentiment
let social_sentiment = alt_data
@@ -1332,13 +1332,13 @@ impl UnifiedFeatureExtractor {
news_data: Some(NewsData {
articles: vec![
NewsArticle {
timestamp: Utc::now() - Duration::minutes(30),
timestamp: Utc::now() - TimeDelta::minutes(30),
sentiment_score: 0.65,
relevance_score: 0.8,
title: "Sample positive news".to_string(),
},
NewsArticle {
timestamp: Utc::now() - Duration::hours(2),
timestamp: Utc::now() - TimeDelta::hours(2),
sentiment_score: -0.3,
relevance_score: 0.6,
title: "Sample negative news".to_string(),
@@ -1358,7 +1358,7 @@ impl UnifiedFeatureExtractor {
}),
earnings_data: Some(EarningsData {
latest_surprise: Some(0.12), // 12% earnings surprise
next_earnings_date: Utc::now() + Duration::days(45),
next_earnings_date: Utc::now() + TimeDelta::days(45),
}),
options_data: Some(OptionsData {
put_call_ratio: 0.85,

View File

@@ -8,7 +8,7 @@
use common::types::Price;
use std;
use chrono::{DateTime, Utc};
use chrono::{DateTime, TimeDelta, Utc};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Instant;
@@ -201,7 +201,7 @@ pub struct ProductionTrainingMetrics {
pub nan_detections: usize,
/// Training performance
pub epoch_duration: Duration,
pub epoch_duration: TimeDelta,
pub memory_usage_bytes: usize,
pub gpu_utilization: Option<f64>,
@@ -339,8 +339,10 @@ impl ProductionMLTrainingSystem {
};
// Collect comprehensive metrics
let elapsed = epoch_start.elapsed();
let epoch_duration = TimeDelta::from_std(elapsed).unwrap_or(TimeDelta::zero());
let epoch_metrics = self
.collect_epoch_metrics(epoch, train_loss, val_loss, epoch_start.elapsed())
.collect_epoch_metrics(epoch, train_loss, val_loss, epoch_duration)
.await?;
training_metrics.push(epoch_metrics.clone());
@@ -353,7 +355,7 @@ impl ProductionMLTrainingSystem {
train_loss,
val_loss,
epoch_metrics.learning_rate,
epoch_metrics.epoch_duration.as_secs_f64()
epoch_metrics.epoch_duration.num_milliseconds() as f64 / 1000.0
);
// Early stopping logic
@@ -401,6 +403,7 @@ impl ProductionMLTrainingSystem {
history.extend(training_metrics.clone());
let training_duration = training_start.elapsed();
let training_duration_td = TimeDelta::from_std(training_duration).unwrap_or(TimeDelta::zero());
info!(
"Training completed in {:.2}s. Best validation loss: {:.6}",
training_duration.as_secs_f64(),
@@ -414,7 +417,7 @@ impl ProductionMLTrainingSystem {
.map(|m| m.train_loss)
.unwrap_or(f64::NAN),
final_val_loss: best_val_loss,
training_duration,
training_duration: training_duration_td,
epochs_trained: training_metrics.len(),
metrics_history: training_metrics,
convergence_achieved: best_val_loss < f64::INFINITY,
@@ -692,7 +695,7 @@ impl ProductionMLTrainingSystem {
epoch: usize,
train_loss: f64,
val_loss: f64,
duration: Duration,
duration: TimeDelta,
) -> SafetyResult<ProductionTrainingMetrics> {
let grad_manager = self.gradient_manager.lock().await;
let gradient_stats = grad_manager.get_statistics().await;
@@ -737,7 +740,7 @@ pub struct TrainingResult {
pub model_id: Uuid,
pub final_train_loss: f64,
pub final_val_loss: f64,
pub training_duration: Duration,
pub training_duration: TimeDelta,
pub epochs_trained: usize,
pub metrics_history: Vec<ProductionTrainingMetrics>,
pub convergence_achieved: bool,