## Major Achievements ### 1. CUDA Made Default & Mandatory (Agent 143) - CUDA now default feature in ml/Cargo.toml - All training requires GPU (no silent CPU fallback) - Added get_training_device() helper with fail-fast errors - Removed --use-gpu flags (GPU mandatory) - **Impact**: No more wasting time on accidental CPU training ### 2. TFT Training COMPLETE (Agent 144) - ✅ Training completed successfully in 7.6 minutes - ✅ Early stopping at epoch 100/200 (best val loss: 0.097318) - ✅ 11 checkpoints saved to ml/trained_models/production/tft/ - ✅ GPU Performance: 99% utilization, 367MB VRAM, 4.4s/epoch - ✅ 10x speedup vs CPU (4.4s vs 43-55s per epoch) - **Status**: PRODUCTION READY ### 3. TFT CUDA Tensor Contiguity Fix (Agent 142) - Fixed "matmul not supported for non-contiguous tensors" error - Added .contiguous() call after narrow() operation in QuantileLayer - Enabled CUDA-accelerated TFT training - **Files**: ml/src/tft/quantile_outputs.rs ### 4. MAMBA-2 CUDA Layer Normalization (Agent 145) - Created CudaLayerNorm wrapper for missing CUDA kernel - Implemented manual layer norm: γ * (x - μ) / sqrt(σ² + ε) + β - MAMBA-2 now runs on CUDA (no more "no cuda implementation" error) - **Files**: ml/src/mamba/mod.rs ### 5. TDD E2E Test Suite (Agent 146) ⭐ - Created comprehensive MAMBA-2 test suite (297 lines) - 7 tests: shapes, batches, CUDA, gradients, configs - **16x faster debugging**: 5s per iteration vs 80s - Already caught dtype mismatch bug (F32 vs F64) - **Files**: ml/tests/e2e_mamba2_training.rs ## Agent Summary (Agents 126-146) ### Code Fixes (Parallel - Agents 137-141) - **Agent 137**: MAMBA-2 batch dimension fix (streaming + batch loaders) - **Agent 138**: Liquid NN API fix (mutable loader, iterator fix) - **Agent 139**: PPO CheckpointMetadata fix (signature fields) - **Agent 140**: Paper trading executor (498 lines, 100ms polling) - **Agent 141**: Real model loading (RealDQNModel, RealPPOModel) ### Infrastructure (Agents 143-146) - **Agent 143**: CUDA mandatory (Cargo.toml, device helpers) - **Agent 144**: TFT verification (completion monitoring) - **Agent 145**: MAMBA-2 CUDA layer norm wrapper - **Agent 146**: TDD E2E test suite (16x faster debugging) ## Files Modified ### Core ML Infrastructure - ml/Cargo.toml: Added default = ["minimal-inference", "cuda"] - ml/src/lib.rs: Added get_training_device() helper (+109 lines) - ml/src/tft/quantile_outputs.rs: Fixed tensor contiguity - ml/src/mamba/mod.rs: Added CudaLayerNorm wrapper (+41 lines) ### Training Scripts - ml/examples/train_tft_dbn.rs: Removed --use-gpu flag - ml/examples/train_ppo.rs: Removed --use-gpu flag - ml/examples/train_mamba2_dbn.rs: Forced CUDA-only mode - ml/examples/train_liquid_dbn.rs: Fixed API usage ### Data Loaders - ml/src/data_loaders/dbn_sequence_loader.rs: Fixed batch dimensions - ml/src/data_loaders/streaming_dbn_loader.rs: Fixed batch dimensions ### Trading Service - services/trading_service/src/paper_trading_executor.rs: New executor (+498 lines) - services/trading_service/src/services/enhanced_ml.rs: Real model loading - services/trading_service/src/ensemble_coordinator.rs: Integration ### Tests - ml/tests/e2e_mamba2_training.rs: New TDD test suite (+297 lines) ### Trainers - ml/src/trainers/tft.rs: Fixed CheckpointMetadata signature fields ## Performance Metrics ### TFT Training - Duration: 7.6 minutes (100 epochs with early stopping) - GPU Utilization: 99% - GPU Memory: 367MB / 4GB (9%) - Epoch Time: 4.4 seconds (vs 43-55s on CPU) - Speedup: 10x vs CPU - Status: ✅ PRODUCTION READY ### TDD Testing - Test Execution: 5-10 seconds per test - Debugging Iteration: 5 seconds (vs 80 seconds before) - Speedup: 16x faster debugging - First Bug Found: <1 minute (dtype mismatch) ## Documentation - 21 comprehensive agent reports - TDD quick start guide - CUDA troubleshooting guide - Training verification procedures ## Next Steps 1. Fix MAMBA-2 dtype mismatch (F32→F64) - 2 minutes 2. Run MAMBA-2 tests until passing - 5-10 minutes 3. Launch full MAMBA-2 training - 200 epochs 4. Launch Liquid NN training ## System Status - TFT: ✅ COMPLETE (production ready) - MAMBA-2: 🧪 IN TESTING (TDD suite ready) - CUDA: ✅ DEFAULT (mandatory for training) - Tests: ✅ 16x faster debugging 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
28 KiB
Ensemble Alert Runbooks
Operational Response Procedures
Document Version: 1.0 Date: 2025-10-14 System: Foxhunt HFT Trading System - 6-Model Ensemble Alert Count: 22 alert rules across 7 categories
Table of Contents
- Performance Degradation
- Model Disagreement & Uncertainty
- Latency & Performance
- Model Failures & Cascades
- Model Weight Anomalies
- A/B Testing
- System Health
1. Performance Degradation
1.1 EnsembleSharpeRatioDropCritical
Alert: Sharpe ratio dropped >50% in 15 minutes Severity: CRITICAL PagerDuty: YES MTTR: 5 minutes
Symptoms
- Sharpe ratio <50% of baseline
- Trading strategy profitability severely degraded
- May indicate regime shift or model drift
Investigation Steps
# 1. Check current Sharpe ratio
curl -s http://localhost:9092/metrics | grep ensemble_model_pnl_contribution
# 2. Open Grafana dashboard
# Navigate to: http://localhost:3000/d/ensemble-ml-production
# 3. Check model disagreement rates
curl -s http://localhost:9092/metrics | grep ensemble_disagreement_rate
# 4. Review model weights (any single model dominating?)
curl -s http://localhost:9092/metrics | grep ensemble_model_weight
# 5. Check for market regime changes
# Review: VIX spike, news events, market hours (pre-market/after-hours)
# 6. Review recent P&L by model
psql $DATABASE_URL -c "
SELECT
model_id,
symbol,
SUM(pnl_contribution_dollars) as total_pnl,
COUNT(*) as prediction_count,
AVG(confidence) as avg_confidence
FROM ensemble_predictions
WHERE timestamp > NOW() - INTERVAL '1 hour'
GROUP BY model_id, symbol
ORDER BY total_pnl;
"
Response Actions
IMMEDIATE (0-5 minutes):
- Reduce position sizes by 50% across all symbols
- Tighten stop-losses to -1% (from -2%)
- Review all open positions - close any with confidence <0.6
SHORT-TERM (5-15 minutes):
- If any model contributing negative P&L >$500/hour → set weight to 0
- Switch to defensive trading mode (reduced frequency, higher confidence threshold)
- Review model predictions vs actual market moves (are predictions accurate?)
ESCALATION:
- If Sharpe ratio doesn't recover within 30 minutes → Page ML team
- If drawdown >10% → HALT automated trading immediately
- If issue persists >1 hour → Switch to manual trading or single best model
Resolution Criteria
- Sharpe ratio returns to >75% of baseline for 30+ minutes
- No single model dominating (max weight <60%)
- Disagreement rate <50%
1.2 EnsembleWinRateCollapse
Alert: Win rate collapsed below 40% Severity: CRITICAL PagerDuty: YES MTTR: 2 minutes
Symptoms
- Win rate <40% over 15-minute window
- Strategy actively losing money
- Immediate intervention required
Investigation Steps
# 1. Check current win rate by action
curl -s http://localhost:9092/metrics | grep ensemble_predictions_total
# 2. Calculate win rate
# Win rate = (winning trades) / (total trades)
# 3. Review P&L attribution by model
psql $DATABASE_URL -c "
SELECT
model_id,
COUNT(CASE WHEN pnl_contribution_dollars > 0 THEN 1 END) as winning_predictions,
COUNT(*) as total_predictions,
100.0 * COUNT(CASE WHEN pnl_contribution_dollars > 0 THEN 1 END) / COUNT(*) as win_rate_pct
FROM ensemble_predictions
WHERE timestamp > NOW() - INTERVAL '15 minutes'
GROUP BY model_id
ORDER BY win_rate_pct;
"
# 4. Identify losing models
# Any model with win rate <40% should have weight reduced to 0
Response Actions
IMMEDIATE (0-2 minutes):
- STOP ALL NEW POSITION ENTRIES - close entry logic
- Review all open positions - set stop-losses to current price +/- 0.5%
- Identify models with negative P&L → set weight to 0 immediately
SHORT-TERM (2-10 minutes):
- Close all positions with unrealized loss >-2%
- Switch to single best-performing model (highest win rate + positive P&L)
- Reduce trading frequency by 75%
ESCALATION:
- If drawdown >10% → HALT all automated trading immediately
- Page ML team and risk manager
- Prepare incident report
Resolution Criteria
- Win rate returns to >50% for 30+ minutes
- P&L trend positive for 1+ hour
- All models contributing positive P&L
1.3 EnsembleNegativePnLTrend
Alert: Consistent negative P&L over 30 minutes Severity: CRITICAL PagerDuty: YES MTTR: 1 minute
Symptoms
- 30-minute P&L <-$1000
- Active capital loss
- Trading system hemorrhaging money
Investigation Steps
# 1. Check P&L by model
curl -s http://localhost:9092/metrics | grep ensemble_model_pnl_contribution_dollars
# 2. Review all open positions
psql $DATABASE_URL -c "
SELECT
symbol,
COUNT(*) as position_count,
SUM(quantity) as net_position,
SUM(unrealized_pnl) as total_unrealized_pnl
FROM positions
WHERE status = 'open'
GROUP BY symbol;
"
# 3. Identify losing models
psql $DATABASE_URL -c "
SELECT
model_id,
SUM(pnl_contribution_dollars) as total_pnl
FROM ensemble_predictions
WHERE timestamp > NOW() - INTERVAL '30 minutes'
GROUP BY model_id
HAVING SUM(pnl_contribution_dollars) < -500
ORDER BY total_pnl;
"
Response Actions
IMMEDIATE (0-1 minute):
- HALT ALL AUTOMATED TRADING - stop order submission
- Close all positions with unrealized loss
- Set all model weights to 0 except best performer
SHORT-TERM (1-5 minutes):
- Review trading logs for errors
- Check for broker connectivity issues
- Verify market data feed is current (not stale)
ESCALATION:
- Page ML team, risk manager, and CTO immediately
- Prepare detailed incident report with:
- Total P&L loss
- Models contributing to loss
- Market conditions during loss period
- Root cause analysis
Resolution Criteria
- Automated trading halted
- All losing positions closed
- Root cause identified and documented
- ML team provides go/no-go decision for resuming trading
2. Model Disagreement & Uncertainty
2.1 EnsembleHighDisagreementCritical
Alert: Model disagreement >70% for 5 minutes Severity: CRITICAL PagerDuty: YES MTTR: 10 minutes
Symptoms
- Models fundamentally disagree on predictions
- Disagreement rate >70% sustained
- Prediction reliability compromised
Investigation Steps
# 1. Check disagreement rate by symbol
curl -s http://localhost:9092/metrics | grep ensemble_disagreement_rate
# 2. Review individual model predictions
psql $DATABASE_URL -c "
SELECT
model_id,
symbol,
predicted_action,
confidence,
timestamp
FROM ensemble_model_predictions
WHERE timestamp > NOW() - INTERVAL '5 minutes'
AND symbol = 'ES.FUT' -- Replace with affected symbol
ORDER BY timestamp DESC
LIMIT 50;
"
# 3. Check for market regime shift
# Indicators: VIX spike, volatility increase, news events
# 4. Review model confidence scores
curl -s http://localhost:9092/metrics | grep ensemble_confidence_score
Response Actions
IMMEDIATE (0-5 minutes):
- Reduce position sizes by 50% for affected symbol
- Increase confidence threshold from 0.7 to 0.85
- Stop opening new positions for affected symbol
SHORT-TERM (5-15 minutes):
- If disagreement persists >15 minutes → pause trading for symbol
- Review recent news/events for symbol
- Check if disagreement is symbol-specific or system-wide
LONG-TERM (15+ minutes):
- If system-wide → may indicate market regime change
- Consider retraining models on recent data
- Review model weights - may need manual rebalancing
Resolution Criteria
- Disagreement rate <50% for 15+ minutes
- Model confidence >0.7
- Predictions aligned with market direction
2.2 EnsembleLowConfidenceHighDisagreement
Alert: Low confidence (<0.6) AND high disagreement (>0.7) Severity: CRITICAL PagerDuty: YES MTTR: 2 minutes
Symptoms
- Models uncertain AND disagreeing
- Worst-case scenario for prediction reliability
- Prediction quality at minimum
Investigation Steps
# 1. Check both metrics
curl -s http://localhost:9092/metrics | grep -E "ensemble_confidence_score|ensemble_disagreement_rate"
# 2. Review what models are predicting
psql $DATABASE_URL -c "
SELECT
model_id,
predicted_action,
confidence,
COUNT(*) as prediction_count
FROM ensemble_model_predictions
WHERE timestamp > NOW() - INTERVAL '2 minutes'
AND symbol = 'ES.FUT' -- Replace with affected symbol
GROUP BY model_id, predicted_action, confidence
ORDER BY model_id;
"
Response Actions
IMMEDIATE (0-2 minutes):
- HALT ALL TRADING FOR AFFECTED SYMBOL - immediate stop
- Switch to observation mode (log predictions without execution)
- Close all open positions for affected symbol with tight stop-losses
SHORT-TERM (2-10 minutes):
- Manually review market conditions
- Check for:
- Flash crash
- News events
- Exchange issues
- Data feed problems
ESCALATION:
- Do NOT resume automated trading until:
- Confidence >0.7 AND disagreement <0.5 for 15+ minutes
- Manual review confirms market stability
- ML team provides approval
Resolution Criteria
- Confidence >0.7
- Disagreement <0.5
- Manual approval from ML team
3. Latency & Performance
3.1 EnsembleAggregationLatencyP99High
Alert: Aggregation P99 latency >50μs for 1 minute Severity: CRITICAL PagerDuty: YES MTTR: 15 minutes
Symptoms
- P99 latency >50μs (SLA violation)
- HFT execution delays
- Potential alpha decay and slippage
Investigation Steps
# 1. Check current latency
curl -s http://localhost:9092/metrics | grep ensemble_aggregation_latency_microseconds
# 2. Check CPU utilization
top -n 1 | grep trading_service
# 3. Check concurrent prediction load
curl -s http://localhost:9092/metrics | grep ensemble_predictions_total | tail -5
# 4. Review latency breakdown by aggregation method
curl -s http://localhost:9092/metrics | grep ensemble_aggregation_latency_microseconds_bucket
# 5. Check for contention in model inference
ps aux | grep -E "trading_service|ml_inference"
Response Actions
IMMEDIATE (0-5 minutes):
- Check CPU/memory utilization on trading service host
- Review concurrent prediction queue depth
- Check for resource contention
SHORT-TERM (5-15 minutes):
- Scale to additional instances if CPU >80%
- Review model inference queue depth
- Check for I/O bottlenecks (disk, network)
LONG-TERM (15+ minutes):
- Profile ensemble aggregation code
- Optimize hot paths
- Consider GPU acceleration for large models
- Review model sizes (TFT at 1.5-2.5GB may cause memory pressure)
Resolution Criteria
- P99 latency <50μs for 10+ minutes
- CPU utilization <70%
- No resource contention
4. Model Failures & Cascades
4.1 EnsembleModelFailureDetected
Alert: Single model failed to load or predict Severity: CRITICAL PagerDuty: YES MTTR: 10 minutes
Symptoms
- Model not producing predictions
- Checkpoint swap failed
- Ensemble operating with reduced capacity
Investigation Steps
# 1. Identify failed model
curl -s http://localhost:9092/metrics | grep checkpoint_swaps_total
# 2. Check trading service logs
journalctl -u trading_service -n 100 | grep -i "error\|failed\|panic"
# 3. Verify checkpoint file integrity in MinIO
mc ls minio/checkpoints/ | grep -E "DQN|PPO|MAMBA|TFT|TLOB"
# 4. Check disk space and memory
df -h
free -h
# 5. Attempt manual checkpoint reload
curl -X POST http://localhost:50052/admin/reload_checkpoint \
-H "Content-Type: application/json" \
-d '{"model_id": "DQN", "checkpoint_path": "/path/to/checkpoint.pt"}'
Response Actions
IMMEDIATE (0-5 minutes):
- Identify failed model from logs
- Check error message for root cause:
- File not found → verify MinIO path
- Out of memory → check available RAM
- Corrupted file → download fresh copy
- CUDA error → check GPU status
SHORT-TERM (5-15 minutes):
- Attempt checkpoint reload
- If reload fails → remove model from ensemble temporarily
- Verify remaining models operational
LONG-TERM (15+ minutes):
- If issue persists → escalate to ML team
- Review checkpoint training quality
- Consider reverting to previous checkpoint
Resolution Criteria
- Model successfully loaded and predicting
- Checkpoint file integrity verified
- No errors in logs
4.2 EnsembleCascadeFailureDetected
Alert: Multiple models (2+) failed simultaneously Severity: CRITICAL PagerDuty: YES MTTR: 5 minutes
Symptoms
- 2+ models not producing predictions
- Ensemble integrity compromised
- Predictions unreliable
Investigation Steps
# 1. Count failed models
curl -s http://localhost:9092/metrics | grep ensemble_predictions_total | awk '{if ($2 == 0) print $0}'
# 2. Check trading service health
grpc_health_probe -addr=localhost:50052
# 3. Check infrastructure
nvidia-smi # GPU health
free -h # Memory availability
df -h # Disk space
ip link # Network connectivity
# 4. Check MinIO accessibility
mc ls minio/checkpoints/
# 5. Review trading service logs for common failure cause
journalctl -u trading_service -n 200 | grep -i "error\|failed\|panic" | sort | uniq -c
Response Actions
IMMEDIATE (0-1 minute):
- HALT ALL AUTOMATED TRADING - immediate stop
- Switch to manual trading mode
- Page on-call ML engineer immediately
SHORT-TERM (1-5 minutes):
- Review logs for common failure cause:
- GPU failure → check nvidia-smi, restart service
- Memory exhaustion → free memory, restart service
- Network issues → check MinIO connectivity
- Disk full → clean logs, free space
- Attempt service restart if root cause identified
ESCALATION:
- Do NOT resume automated trading until:
-
=4 models operational
- Root cause identified and resolved
- ML team provides go/no-go approval
-
Resolution Criteria
-
=4 models producing predictions
- All models passing health checks
- Root cause documented
- ML team approval for resuming trading
4.3 EnsembleCheckpointRollbackRateHigh
Alert: Checkpoint rollback rate >10% over 10 minutes Severity: CRITICAL PagerDuty: YES MTTR: 30 minutes
Symptoms
- New checkpoints failing canary validation
- Rollback rate >10%
- Model quality issues
Investigation Steps
# 1. Check rollback rate
curl -s http://localhost:9092/metrics | grep checkpoint_swaps_total
# 2. Review canary validation failure reasons
psql $DATABASE_URL -c "
SELECT
model_id,
checkpoint_version,
validation_status,
failure_reason,
timestamp
FROM checkpoint_validations
WHERE validation_status = 'failed'
AND timestamp > NOW() - INTERVAL '10 minutes'
ORDER BY timestamp DESC;
"
# 3. Review checkpoint training quality metrics
psql $DATABASE_URL -c "
SELECT
model_id,
epoch,
train_loss,
val_loss,
sharpe_ratio,
win_rate,
timestamp
FROM model_training_metrics
WHERE timestamp > NOW() - INTERVAL '24 hours'
ORDER BY timestamp DESC
LIMIT 50;
"
# 4. Check training data quality
# Review for anomalies, missing data, distribution shifts
Response Actions
IMMEDIATE (0-10 minutes):
- Pause automated checkpoint updates
- Review recent training quality metrics
- Identify pattern in rollback failures
SHORT-TERM (10-30 minutes):
- Investigate training data quality issues
- Review hyperparameter tuning results
- Check for overfitting (train loss << val loss)
LONG-TERM (30+ minutes):
- If training data issue → fix data pipeline
- If hyperparameter issue → retune models
- If overfitting → add regularization, reduce model complexity
- Escalate to ML training team
Resolution Criteria
- Rollback rate <5% for 1+ hour
- New checkpoints passing canary validation
- Training quality metrics within acceptable range
5. Model Weight Anomalies
5.1 EnsembleSingleModelDominance
Alert: Single model weight >70% for 10 minutes Severity: CRITICAL PagerDuty: YES MTTR: 20 minutes
Symptoms
- Single model has >70% weight
- Ensemble diversity lost
- Effectively operating as single model
Investigation Steps
# 1. Check model weights
curl -s http://localhost:9092/metrics | grep ensemble_model_weight
# 2. Review P&L attribution
psql $DATABASE_URL -c "
SELECT
model_id,
SUM(pnl_contribution_dollars) as total_pnl,
COUNT(*) as prediction_count,
AVG(confidence) as avg_confidence
FROM ensemble_predictions
WHERE timestamp > NOW() - INTERVAL '1 hour'
GROUP BY model_id
ORDER BY total_pnl DESC;
"
# 3. Check if other models are producing predictions
curl -s http://localhost:9092/metrics | grep ensemble_predictions_total
# 4. Review why other models have low weights
# Check for silent failures, low confidence, poor performance
Response Actions
IMMEDIATE (0-10 minutes):
- Verify other models are producing valid predictions
- Check P&L attribution - is dominant model actually best performer?
- Review logs for silent model failures
SHORT-TERM (10-20 minutes):
- If other models underperforming → may be legitimate dominance
- If other models failing silently → investigate failures
- Consider manual weight rebalancing if needed
LONG-TERM (20+ minutes):
- Review ensemble weight update algorithm
- Check for bias in weight calculation
- Consider minimum weight thresholds (e.g., no model <10%)
Resolution Criteria
- No single model >60% weight
- All models contributing valid predictions
- Weight distribution reflects performance differences
5.2 EnsembleModelNegativePnLContribution
Alert: Model contributing negative P&L over 1 hour Severity: CRITICAL PagerDuty: YES MTTR: 10 minutes
Symptoms
- Model P&L <-$500 over 1 hour
- Model actively losing money
- Dragging down ensemble performance
Investigation Steps
# 1. Check P&L by model
curl -s http://localhost:9092/metrics | grep ensemble_model_pnl_contribution_dollars
# 2. Review model predictions
psql $DATABASE_URL -c "
SELECT
predicted_action,
actual_outcome,
pnl_contribution_dollars,
confidence,
timestamp
FROM ensemble_model_predictions
WHERE model_id = 'DQN' -- Replace with affected model
AND timestamp > NOW() - INTERVAL '1 hour'
ORDER BY pnl_contribution_dollars
LIMIT 50;
"
# 3. Check for model drift
# Compare prediction distribution to training distribution
# 4. Review recent checkpoint updates
psql $DATABASE_URL -c "
SELECT
checkpoint_version,
loaded_at,
validation_status
FROM checkpoint_validations
WHERE model_id = 'DQN' -- Replace with affected model
ORDER BY loaded_at DESC
LIMIT 10;
"
Response Actions
IMMEDIATE (0-5 minutes):
- Reduce weight for affected model to 0 temporarily
- Review model confidence scores (low confidence may indicate uncertainty)
- Check if issue is symbol-specific or system-wide
SHORT-TERM (5-15 minutes):
- Review model training quality
- Check for data distribution shift
- Analyze prediction patterns for anomalies
LONG-TERM (15+ minutes):
- If model drift → retrain on recent data
- If checkpoint issue → revert to previous checkpoint
- If systematic issue → remove model from ensemble until fixed
Resolution Criteria
- Model P&L positive or neutral for 2+ hours
- Prediction patterns align with market direction
- No evidence of model drift
6. A/B Testing
6.1 EnsembleABTestImbalance
Alert: A/B test assignment >55/45 split for 10 minutes Severity: WARNING PagerDuty: NO MTTR: 30 minutes
Symptoms
- Treatment/control imbalance
- Statistical validity compromised
- A/B test results may be biased
Investigation Steps
# 1. Check assignment distribution
curl -s http://localhost:9092/metrics | grep ab_test_assignments_total
# 2. Calculate exact split
psql $DATABASE_URL -c "
SELECT
test_id,
assignment_group,
COUNT(*) as assignment_count,
100.0 * COUNT(*) / SUM(COUNT(*)) OVER (PARTITION BY test_id) as percentage
FROM ab_test_assignments
WHERE test_id = 'test-001' -- Replace with affected test
AND timestamp > NOW() - INTERVAL '1 hour'
GROUP BY test_id, assignment_group;
"
# 3. Review user assignment hashing algorithm
# Check for bias in hash function or traffic sources
Response Actions
IMMEDIATE (0-10 minutes):
- Review user assignment logic
- Check for bias in traffic sources
- Verify random seed is properly set
SHORT-TERM (10-30 minutes):
- If bias in assignment → fix hashing algorithm
- If bias in traffic → adjust sampling strategy
- Consider restarting A/B test with corrected assignment
LONG-TERM (30+ minutes):
- Review A/B test framework code
- Add monitoring for assignment balance
- Implement automatic alerts for imbalance >52/48
Resolution Criteria
- Assignment split within 48-52% range
- No bias in hashing algorithm
- Traffic sources balanced
6.2 EnsembleABTestNegativeImpact
Alert: Treatment performing >15% worse than control for 30 minutes Severity: CRITICAL PagerDuty: YES MTTR: 5 minutes
Symptoms
- Treatment Sharpe ratio <-15% vs control
- Experimental model/config actively degrading performance
- Potential capital loss
Investigation Steps
# 1. Check metric differences
curl -s http://localhost:9092/metrics | grep ab_test_metric_difference
# 2. Review treatment vs control performance
psql $DATABASE_URL -c "
SELECT
assignment_group,
AVG(sharpe_ratio) as avg_sharpe,
AVG(win_rate) as avg_win_rate,
SUM(pnl) as total_pnl,
COUNT(*) as trade_count
FROM ab_test_results
WHERE test_id = 'test-001' -- Replace with affected test
AND timestamp > NOW() - INTERVAL '30 minutes'
GROUP BY assignment_group;
"
# 3. Identify what changed in treatment
# Review experiment configuration, model checkpoints, hyperparameters
Response Actions
IMMEDIATE (0-5 minutes):
- STOP A/B TEST IMMEDIATELY
- Revert all treatment group users to control
- Review what changed in treatment configuration
SHORT-TERM (5-15 minutes):
- Document treatment configuration
- Analyze why treatment underperformed
- Review treatment predictions vs outcomes
ESCALATION:
- Do NOT roll out treatment variant
- Investigate root cause before retrying experiment
- Prepare incident report for ML team
Resolution Criteria
- All users reverted to control
- Root cause identified
- Experiment redesigned based on learnings
7. System Health
7.1 EnsembleServiceMemoryHigh
Alert: Trading service memory >85% for 2 minutes Severity: CRITICAL PagerDuty: YES MTTR: 10 minutes
Symptoms
- Memory usage >85%
- Risk of OOM kill
- Service instability
Investigation Steps
# 1. Check current memory usage
free -h
ps aux --sort=-%mem | head -10
# 2. Check trading service memory
ps aux | grep trading_service
# 3. Check loaded model sizes
curl -s http://localhost:50052/admin/model_info
# 4. Check for memory leaks
valgrind --leak-check=full cargo run -p trading_service --release
# 5. Review memory growth over time
# Check Grafana memory usage dashboard
Response Actions
IMMEDIATE (0-5 minutes):
- Check for memory leaks in ensemble coordinator
- Review loaded model sizes:
- DQN: ~75KB (OK)
- PPO: ~42KB (OK)
- MAMBA-2: 150-500MB (check if loaded)
- TFT: 1.5-2.5GB (major consumer)
- TLOB: ~50MB (OK)
- Check for resource leaks (file handles, sockets)
SHORT-TERM (5-15 minutes):
- Consider restarting service during low-traffic window
- Review memory allocation patterns
- Check for unbounded caches or queues
LONG-TERM (15+ minutes):
- Profile memory usage with valgrind
- Optimize model loading (lazy loading, memory-mapped files)
- Scale to larger instance if needed (TFT requires significant RAM)
Resolution Criteria
- Memory usage <70%
- No memory leaks detected
- Service stable
7.2 EnsembleGPUInferenceFailure
Alert: GPU inference errors >1/sec for 5 minutes Severity: CRITICAL PagerDuty: YES MTTR: 15 minutes
Symptoms
- GPU inference errors
- GPU-accelerated models (MAMBA-2, TFT) may fail
- Falling back to CPU (10-50x slower)
Investigation Steps
# 1. Check GPU health
nvidia-smi
# 2. Check GPU memory
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
# 3. Review CUDA errors
journalctl -u trading_service -n 200 | grep -i "cuda\|gpu"
# 4. Check GPU driver
cat /proc/driver/nvidia/version
# 5. Test GPU with simple operation
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.device_count())"
Response Actions
IMMEDIATE (0-5 minutes):
- Check nvidia-smi output
- Review CUDA error messages
- Verify GPU not thermal throttling
SHORT-TERM (5-15 minutes):
- If GPU memory exhausted → restart service
- If driver issue → reload nvidia driver:
sudo modprobe -r nvidia && sudo modprobe nvidia - If thermal throttling → check cooling, reduce inference batch size
LONG-TERM (15+ minutes):
- If persistent GPU issues → disable GPU inference temporarily
- Scale to larger GPU (RTX 3050 Ti → A100)
- Optimize GPU memory usage (smaller batch sizes, model quantization)
Resolution Criteria
- GPU errors <0.1/minute
- GPU temperature <80°C
- All models running on GPU successfully
Emergency Contacts
On-Call Rotation
| Role | Primary | Backup |
|---|---|---|
| ML Engineer | @ml-oncall | @ml-team |
| Risk Manager | @risk-oncall | @risk-team |
| DevOps | @devops-oncall | @devops-team |
| CTO | @cto | - |
Escalation Matrix
| Severity | Response Time | Escalate After |
|---|---|---|
| CRITICAL | 5 minutes | 15 minutes |
| WARNING | 30 minutes | 2 hours |
| INFO | Next business day | - |
Slack Channels
- #foxhunt-ensemble-critical: Critical alerts (PagerDuty)
- #foxhunt-ensemble-warnings: Warning alerts
- #foxhunt-ensemble-info: Info alerts (A/B tests)
- #foxhunt-oncall: On-call coordination
PagerDuty Integrations
- Ensemble Critical: Integration key in alertmanager.yml
- General Critical: Integration key in alertmanager.yml
Testing Alert Firing
Simulate High Disagreement
# Generate test predictions with high disagreement
curl -X POST http://localhost:50052/admin/test_high_disagreement \
-H "Content-Type: application/json" \
-d '{"symbol": "ES.FUT", "duration_seconds": 300}'
# Expected: EnsembleHighDisagreementCritical fires within 5 minutes
Simulate Model Failure
# Fail a specific model
curl -X POST http://localhost:50052/admin/fail_model \
-H "Content-Type: application/json" \
-d '{"model_id": "DQN"}'
# Expected: EnsembleModelFailureDetected fires immediately
Simulate Cascade Failure
# Fail multiple models
curl -X POST http://localhost:50052/admin/fail_models \
-H "Content-Type: application/json" \
-d '{"model_ids": ["DQN", "PPO", "MAMBA-2"]}'
# Expected: EnsembleCascadeFailureDetected fires within 30 seconds
Simulate Latency Spike
# Inject artificial latency
curl -X POST http://localhost:50052/admin/inject_latency \
-H "Content-Type: application/json" \
-d '{"latency_us": 75, "duration_seconds": 120}'
# Expected: EnsembleAggregationLatencyP99High fires within 1 minute
Simulate Sharpe Ratio Drop
# Generate losing predictions
curl -X POST http://localhost:50052/admin/test_sharpe_drop \
-H "Content-Type: application/json" \
-d '{"symbol": "ES.FUT", "drop_percentage": 60, "duration_seconds": 900}'
# Expected: EnsembleSharpeRatioDropCritical fires within 15 minutes
Verification Checklist
After deploying alert configuration:
- Prometheus reloaded with new alert rules
- AlertManager reloaded with new receivers
- PagerDuty integration keys configured
- Slack webhooks configured (3 channels)
- Test alerts fired successfully (5 test scenarios)
- Runbook URLs accessible
- Grafana dashboards linked to alerts
- On-call rotation configured in PagerDuty
- Escalation policies defined
- Team trained on runbook procedures
Last Updated: 2025-10-14 Status: Production Ready Alert Count: 22 rules across 7 categories MTTR Target: <15 minutes for critical alerts