Add #![deny(clippy::unwrap_used, clippy::expect_used)] to database, ml-data,
trading-data, and broker_gateway_service crates, fixing all violations:
- database/src/transaction.rs: replace 7x .expect("Transaction already consumed")
with .ok_or_else(|| DatabaseError::Transaction) and 2x .unwrap() on take()
in commit/rollback with safe .ok_or_else() variants
- ml-data/src/performance.rs: replace .last().unwrap() and .first().unwrap()
with if-let destructuring pattern
- trading-data/src/positions.rs: replace 3x write!().unwrap() with let _ = write!()
and Decimal::from_str_exact("0.02").unwrap() with Decimal::new(2, 2)
- trading-data/src/executions.rs: replace 3x write!().unwrap() with let _ = write!(),
and 3x .expect() on and_hms_opt(0,0,0) with .unwrap_or_default()
- broker_gateway_service/src/main.rs: replace encode().unwrap() with if-let,
and from_utf8().unwrap() with .unwrap_or_else()
- Add #[allow(clippy::unwrap_used)] to test modules in all affected crates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
217 lines
6.0 KiB
Rust
217 lines
6.0 KiB
Rust
#![allow(missing_docs)] // Internal implementation details don't require documentation
|
|
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
|
//! ML Data Repository
|
|
//!
|
|
//! Production-ready ML data management for HFT trading systems.
|
|
//! Provides repositories for training data, model artifacts, performance tracking,
|
|
//! and feature engineering with PostgreSQL integration.
|
|
|
|
use database::Database;
|
|
use std::sync::Arc;
|
|
|
|
pub mod features;
|
|
pub mod models;
|
|
pub mod performance;
|
|
pub mod training;
|
|
|
|
/// Common error types for ML data operations
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum MlDataError {
|
|
#[error("Database error: {0}")]
|
|
Database(#[from] database::DatabaseError),
|
|
|
|
#[error("SQL error: {0}")]
|
|
Sql(#[from] sqlx::Error),
|
|
|
|
#[error("Serialization error: {0}")]
|
|
Serialization(#[from] serde_json::Error),
|
|
|
|
#[error("IO error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("Validation error: {message}")]
|
|
Validation { message: String },
|
|
|
|
#[error("Version conflict: {message}")]
|
|
VersionConflict { message: String },
|
|
|
|
#[error("Not found: {resource_type} with id {id}")]
|
|
NotFound { resource_type: String, id: String },
|
|
|
|
#[error("Configuration error: {0}")]
|
|
Configuration(#[from] config::ConfigError),
|
|
}
|
|
|
|
pub type Result<T> = std::result::Result<T, MlDataError>;
|
|
|
|
/// Configuration for ML data repositories
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct MlDataConfig {
|
|
/// Database connection configuration
|
|
pub database: config::DatabaseConfig,
|
|
|
|
/// Model artifact storage path
|
|
pub model_storage_path: String,
|
|
|
|
/// Feature store configuration
|
|
pub feature_store: FeatureStoreConfig,
|
|
|
|
/// Performance tracking settings
|
|
pub performance: PerformanceConfig,
|
|
|
|
/// Training data management
|
|
pub training: TrainingConfig,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct FeatureStoreConfig {
|
|
/// Maximum number of features to cache in memory
|
|
pub cache_size: usize,
|
|
|
|
/// Feature TTL in seconds
|
|
pub ttl_seconds: u64,
|
|
|
|
/// Batch size for feature computation
|
|
pub batch_size: usize,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct PerformanceConfig {
|
|
/// Metrics retention period in days
|
|
pub retention_days: u32,
|
|
|
|
/// Performance degradation threshold
|
|
pub degradation_threshold: f64,
|
|
|
|
/// A/B test confidence level
|
|
pub confidence_level: f64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct TrainingConfig {
|
|
/// Maximum dataset size in bytes
|
|
pub max_dataset_size: u64,
|
|
|
|
/// Data validation rules
|
|
pub validation_rules: ValidationRules,
|
|
|
|
/// Default train/validation/test split ratios
|
|
pub default_splits: SplitRatios,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct ValidationRules {
|
|
/// Minimum number of samples required
|
|
pub min_samples: usize,
|
|
|
|
/// Maximum missing value ratio allowed
|
|
pub max_missing_ratio: f64,
|
|
|
|
/// Required features list
|
|
pub required_features: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
pub struct SplitRatios {
|
|
pub train: f64,
|
|
pub validation: f64,
|
|
pub test: f64,
|
|
}
|
|
|
|
impl Default for SplitRatios {
|
|
fn default() -> Self {
|
|
Self {
|
|
train: 0.7,
|
|
validation: 0.2,
|
|
test: 0.1,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// ML Data Repository Manager
|
|
///
|
|
/// Central coordinator for all ML data operations
|
|
#[derive(Clone)]
|
|
pub struct MlDataManager {
|
|
pub training: Arc<training::TrainingDataRepository>,
|
|
pub models: Arc<models::ModelRepository>,
|
|
pub performance: Arc<performance::PerformanceRepository>,
|
|
pub features: Arc<features::FeatureRepository>,
|
|
config: MlDataConfig,
|
|
}
|
|
|
|
impl MlDataManager {
|
|
/// Create a new ML data manager with the provided configuration
|
|
pub async fn new(config: MlDataConfig) -> Result<Self> {
|
|
let db = Database::new(config.database.clone()).await?;
|
|
|
|
let training = Arc::new(
|
|
training::TrainingDataRepository::new(db.clone(), config.training.clone()).await?,
|
|
);
|
|
|
|
let models = Arc::new(
|
|
models::ModelRepository::new(db.clone(), config.model_storage_path.clone()).await?,
|
|
);
|
|
|
|
let performance = Arc::new(
|
|
performance::PerformanceRepository::new(db.clone(), config.performance.clone()).await?,
|
|
);
|
|
|
|
let features = Arc::new(
|
|
features::FeatureRepository::new(db.clone(), config.feature_store.clone()).await?,
|
|
);
|
|
|
|
Ok(Self {
|
|
training,
|
|
models,
|
|
performance,
|
|
features,
|
|
config,
|
|
})
|
|
}
|
|
|
|
/// Get the configuration
|
|
pub fn config(&self) -> &MlDataConfig {
|
|
&self.config
|
|
}
|
|
|
|
/// Initialize database schema for all repositories
|
|
pub async fn initialize_schema(&self) -> Result<()> {
|
|
tracing::info!("Initializing ML data repository schemas");
|
|
|
|
self.training.initialize_schema().await?;
|
|
self.models.initialize_schema().await?;
|
|
self.performance.initialize_schema().await?;
|
|
self.features.initialize_schema().await?;
|
|
|
|
tracing::info!("ML data repository schemas initialized successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Health check for all repositories
|
|
pub async fn health_check(&self) -> Result<HealthStatus> {
|
|
let training_health = self.training.health_check().await?;
|
|
let models_health = self.models.health_check().await?;
|
|
let performance_health = self.performance.health_check().await?;
|
|
let features_health = self.features.health_check().await?;
|
|
|
|
Ok(HealthStatus {
|
|
training: training_health,
|
|
models: models_health,
|
|
performance: performance_health,
|
|
features: features_health,
|
|
overall: training_health && models_health && performance_health && features_health,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Health status for all ML data repositories
|
|
#[derive(Debug, serde::Serialize)]
|
|
pub struct HealthStatus {
|
|
pub training: bool,
|
|
pub models: bool,
|
|
pub performance: bool,
|
|
pub features: bool,
|
|
pub overall: bool,
|
|
}
|