Files
foxhunt/ml/src/ensemble/mod.rs
jgrusewski 1b7f72a0d2 feat(ml,trading): add gate optimizer, model registry, and P&L attribution
Gate optimizer adjusts conviction gate thresholds based on win-rate per
confidence bucket with cooldown and kill switch safety rails. Model
registry provides lifecycle management (Candidate → Staging → Production
→ Archived) with InMemoryModelRegistry for testing. P&L attribution
decomposes realized trade P&L into per-model contributions using signal
alignment.

24 new tests across 3 modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:39:22 +01:00

111 lines
4.0 KiB
Rust

//! Ensemble signal aggregation for trading models
use std;
use thiserror::Error;
pub mod ab_testing;
pub mod adaptive_ml_integration; // Adaptive ML ensemble with regime detection
pub mod aggregator;
pub mod confidence;
pub mod coordinator;
pub mod coordinator_extended; // Extended 6-model coordinator
pub mod decision;
pub mod hot_swap;
pub mod metrics;
pub mod model;
pub mod training_integration; // Training integration for ML service
pub mod voting;
pub mod weights;
pub mod inference_adapter;
pub mod inference_ensemble;
pub mod signal;
pub mod adapters;
pub mod conviction_gates;
pub mod weight_optimizer;
pub mod gate_optimizer;
// Re-export key types that are used across ensemble modules
pub use ab_testing::{
ABGroup, ABMetricsTracker, ABTestConfig, ABTestResults, ABTestRouter, GroupMetrics,
Recommendation, StatisticalTestResult,
};
pub use adaptive_ml_integration::{
AdaptiveMLEnsemble, AdaptiveMetrics, MarketRegime, PricePoint, RegimeConfig,
};
pub use aggregator::{ModelSignal, SignalMetadata, SignalStatistics};
pub use coordinator::{EnsembleCoordinator, ModelRegistry, SignalAggregator};
pub use coordinator_extended::{
DiversityAnalyzer, DiversityMetrics, EnsembleConfig as ExtendedEnsembleConfig,
ExtendedEnsembleCoordinator, ModelPerformance, PerformanceAttribution, PerformanceTracker,
SupportedModel, WeightSnapshot,
};
pub use decision::{EnsembleDecision, ModelVote, ModelWeight, PerformanceMetrics, TradingAction};
pub use hot_swap::{
CanaryMetrics, CanaryResult, CheckpointModel, CheckpointValidator, HotSwapManager,
ModelBufferPair, RollbackPolicy, ValidationResult,
};
pub use metrics::{
EnsembleMetrics, CANARY_MONITORING_TOTAL, CHECKPOINT_SWAPS_TOTAL,
CHECKPOINT_SWAP_LATENCY_MICROSECONDS, CHECKPOINT_VALIDATION_TOTAL,
};
pub use training_integration::EnsembleTrainingIntegration;
pub use inference_adapter::{EnsemblePrediction, FeatureVector, ModelInferenceAdapter, PredictionMeta};
pub use conviction_gates::{
ConvictionGateConfig, ConvictionGateEvaluator, ConvictionGateOutcome, GateEvaluation,
GateInput, GatePassResult, GateRejection, TradingSession,
};
pub use weight_optimizer::{
ModelRollingMetrics, OptimizationResult, WeightAdjustment, WeightOptimizer,
WeightOptimizerConfig,
};
pub use gate_optimizer::{
GateBucketMetrics, GateOptimizationResult, GateOptimizer, GateOptimizerConfig,
ThresholdAdjustment,
};
/// Errors that can occur in ensemble operations
#[derive(Error, Debug)]
/// `EnsembleError` component.
pub enum EnsembleError {
#[error("Failed to acquire lock: {0}")]
LockAcquisitionFailed(String),
#[error("Invalid ensemble configuration: {0}")]
InvalidConfiguration(String),
#[error("Model not found: {0}")]
ModelNotFound(String),
#[error("Insufficient models for ensemble: expected {expected}, got {actual}")]
InsufficientModels { expected: usize, actual: usize },
#[error("Weight calculation failed: {0}")]
WeightCalculationFailed(String),
#[error("Aggregation failed: {0}")]
AggregationFailed(String),
}
// Implement From trait for EnsembleError to MLError conversion
impl From<EnsembleError> for crate::MLError {
fn from(err: EnsembleError) -> Self {
match err {
EnsembleError::InvalidConfiguration(msg) => crate::MLError::ConfigurationError(msg),
EnsembleError::ModelNotFound(msg) => crate::MLError::ModelNotFound(msg),
EnsembleError::InsufficientModels { expected, actual } => {
crate::MLError::ValidationError {
message: format!("Insufficient models: expected {}, got {}", expected, actual),
}
},
EnsembleError::LockAcquisitionFailed(msg) => crate::MLError::LockError(msg),
EnsembleError::WeightCalculationFailed(msg) => {
crate::MLError::ModelError(format!("Weight calculation failed: {}", msg))
},
EnsembleError::AggregationFailed(msg) => {
crate::MLError::InferenceError(format!("Aggregation failed: {}", msg))
},
}
}
}