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>
111 lines
4.0 KiB
Rust
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))
|
|
},
|
|
}
|
|
}
|
|
}
|