Files
foxhunt/docs/monitoring/ENSEMBLE_ALERT_RUNBOOKS.md
jgrusewski 35feadf55e 🚀 Wave 160 Phase 6: CUDA Mandatory + TDD Testing + TFT Complete (21 Agents)
## 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>
2025-10-14 23:13:34 +02:00

1104 lines
28 KiB
Markdown

# 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
1. [Performance Degradation](#1-performance-degradation)
2. [Model Disagreement & Uncertainty](#2-model-disagreement--uncertainty)
3. [Latency & Performance](#3-latency--performance)
4. [Model Failures & Cascades](#4-model-failures--cascades)
5. [Model Weight Anomalies](#5-model-weight-anomalies)
6. [A/B Testing](#6-ab-testing)
7. [System Health](#7-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
```bash
# 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)**:
1. Reduce position sizes by 50% across all symbols
2. Tighten stop-losses to -1% (from -2%)
3. Review all open positions - close any with confidence <0.6
**SHORT-TERM (5-15 minutes)**:
1. If any model contributing negative P&L >$500/hour → set weight to 0
2. Switch to defensive trading mode (reduced frequency, higher confidence threshold)
3. 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
```bash
# 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)**:
1. **STOP ALL NEW POSITION ENTRIES** - close entry logic
2. Review all open positions - set stop-losses to current price +/- 0.5%
3. Identify models with negative P&L → set weight to 0 immediately
**SHORT-TERM (2-10 minutes)**:
1. Close all positions with unrealized loss >-2%
2. Switch to single best-performing model (highest win rate + positive P&L)
3. 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
```bash
# 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)**:
1. **HALT ALL AUTOMATED TRADING** - stop order submission
2. Close all positions with unrealized loss
3. Set all model weights to 0 except best performer
**SHORT-TERM (1-5 minutes)**:
1. Review trading logs for errors
2. Check for broker connectivity issues
3. 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
```bash
# 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)**:
1. Reduce position sizes by 50% for affected symbol
2. Increase confidence threshold from 0.7 to 0.85
3. Stop opening new positions for affected symbol
**SHORT-TERM (5-15 minutes)**:
1. If disagreement persists >15 minutes → pause trading for symbol
2. Review recent news/events for symbol
3. Check if disagreement is symbol-specific or system-wide
**LONG-TERM (15+ minutes)**:
1. If system-wide → may indicate market regime change
2. Consider retraining models on recent data
3. 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
```bash
# 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)**:
1. **HALT ALL TRADING FOR AFFECTED SYMBOL** - immediate stop
2. Switch to observation mode (log predictions without execution)
3. Close all open positions for affected symbol with tight stop-losses
**SHORT-TERM (2-10 minutes)**:
1. Manually review market conditions
2. 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
```bash
# 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)**:
1. Check CPU/memory utilization on trading service host
2. Review concurrent prediction queue depth
3. Check for resource contention
**SHORT-TERM (5-15 minutes)**:
1. Scale to additional instances if CPU >80%
2. Review model inference queue depth
3. Check for I/O bottlenecks (disk, network)
**LONG-TERM (15+ minutes)**:
1. Profile ensemble aggregation code
2. Optimize hot paths
3. Consider GPU acceleration for large models
4. 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
```bash
# 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)**:
1. Identify failed model from logs
2. 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)**:
1. Attempt checkpoint reload
2. If reload fails → remove model from ensemble temporarily
3. Verify remaining models operational
**LONG-TERM (15+ minutes)**:
1. If issue persists → escalate to ML team
2. Review checkpoint training quality
3. 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
```bash
# 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)**:
1. **HALT ALL AUTOMATED TRADING** - immediate stop
2. Switch to manual trading mode
3. Page on-call ML engineer immediately
**SHORT-TERM (1-5 minutes)**:
1. 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
2. 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
```bash
# 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)**:
1. Pause automated checkpoint updates
2. Review recent training quality metrics
3. Identify pattern in rollback failures
**SHORT-TERM (10-30 minutes)**:
1. Investigate training data quality issues
2. Review hyperparameter tuning results
3. Check for overfitting (train loss << val loss)
**LONG-TERM (30+ minutes)**:
1. If training data issue → fix data pipeline
2. If hyperparameter issue → retune models
3. If overfitting → add regularization, reduce model complexity
4. 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
```bash
# 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)**:
1. Verify other models are producing valid predictions
2. Check P&L attribution - is dominant model actually best performer?
3. Review logs for silent model failures
**SHORT-TERM (10-20 minutes)**:
1. If other models underperforming → may be legitimate dominance
2. If other models failing silently → investigate failures
3. Consider manual weight rebalancing if needed
**LONG-TERM (20+ minutes)**:
1. Review ensemble weight update algorithm
2. Check for bias in weight calculation
3. 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
```bash
# 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)**:
1. Reduce weight for affected model to 0 temporarily
2. Review model confidence scores (low confidence may indicate uncertainty)
3. Check if issue is symbol-specific or system-wide
**SHORT-TERM (5-15 minutes)**:
1. Review model training quality
2. Check for data distribution shift
3. Analyze prediction patterns for anomalies
**LONG-TERM (15+ minutes)**:
1. If model drift → retrain on recent data
2. If checkpoint issue → revert to previous checkpoint
3. 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
```bash
# 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)**:
1. Review user assignment logic
2. Check for bias in traffic sources
3. Verify random seed is properly set
**SHORT-TERM (10-30 minutes)**:
1. If bias in assignment → fix hashing algorithm
2. If bias in traffic → adjust sampling strategy
3. Consider restarting A/B test with corrected assignment
**LONG-TERM (30+ minutes)**:
1. Review A/B test framework code
2. Add monitoring for assignment balance
3. 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
```bash
# 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)**:
1. **STOP A/B TEST IMMEDIATELY**
2. Revert all treatment group users to control
3. Review what changed in treatment configuration
**SHORT-TERM (5-15 minutes)**:
1. Document treatment configuration
2. Analyze why treatment underperformed
3. 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
```bash
# 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)**:
1. Check for memory leaks in ensemble coordinator
2. 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)
3. Check for resource leaks (file handles, sockets)
**SHORT-TERM (5-15 minutes)**:
1. Consider restarting service during low-traffic window
2. Review memory allocation patterns
3. Check for unbounded caches or queues
**LONG-TERM (15+ minutes)**:
1. Profile memory usage with valgrind
2. Optimize model loading (lazy loading, memory-mapped files)
3. 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
```bash
# 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)**:
1. Check nvidia-smi output
2. Review CUDA error messages
3. Verify GPU not thermal throttling
**SHORT-TERM (5-15 minutes)**:
1. If GPU memory exhausted → restart service
2. If driver issue → reload nvidia driver: `sudo modprobe -r nvidia && sudo modprobe nvidia`
3. If thermal throttling → check cooling, reduce inference batch size
**LONG-TERM (15+ minutes)**:
1. If persistent GPU issues → disable GPU inference temporarily
2. Scale to larger GPU (RTX 3050 Ti → A100)
3. 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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