Exit Strategy v6.6 "Professor AI Validated" - All recommendations implemented FIX #1: Remove Misleading Debug Code - Removed manual trajectory calculation (line 1262-1269) - Trajectory predictor was CORRECT, debug comparison was WRONG - Cleaned up false "bug found" warnings FIX #2: Peak Detection Logic (CHECK 0A.4) - Detects approaching peak (vel > 0, accel < 0) - Holds position if peak within 30s and 15%+ profit ahead - Suppresses fuzzy exits during peak approach - Target: Peak capture 38% -> 70%+ - Added peak_hold_active field to PositionGuard FIX #3: London False Breakout Filter - London session + ATR ratio < 1.2 = whipsaw risk - Requires ML confidence 70% (instead of 60%) - Prevents false breakouts during low volatility - Implemented in main_live.py before signal logic FIX #4: Enhanced Kelly Partial Exit Strategy - Active for all profits >= tp_min * 0.5 (not just >$8) - Recommends partial exits for better peak capture - Full exit when Kelly suggests >70% close - Note: Actual partial close needs MT5 volume parameter (TODO) FIX #5: Unicode Encoding Fixes - Added UTF-8 encoding to file logger - Replaced all emoji (⚠️ -> [WARNING]) and arrows (-> -> ->) - No more UnicodeEncodeError on Windows console - Fixed in 11 src/*.py files Expected Performance: - Peak Capture: 38% -> 70%+ (+84%) - Avg Profit: $2.00 -> $4.50 (+125%) - Risk/Reward: 0.49 -> 1.2+ (+145%) - Win Rate: Maintain 76% Files Modified: - src/smart_risk_manager.py (peak detection, Kelly, unicode) - src/trajectory_predictor.py (unicode arrows) - main_live.py (London filter, UTF-8 encoding) - src/*.py (unicode cleanup: 11 files) - VERSION (0.2.1 -> 0.2.2) - CHANGELOG.md (comprehensive v0.2.2 docs) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
7.6 KiB
🚨 Regime Detection Stuck on "Low Volatility"
Date: 2026-02-09 19:20 WIB Issue: HMM Regime Detector always shows "Low Volatility" Status: 🔴 MODEL CALIBRATION ISSUE
📊 THE PROBLEM
Dashboard always shows:
Regime: Low Volatility
Volatility: 0.27
Confidence: 100%
Observation: Regime NEVER changes from "Low Volatility" despite market conditions changing.
🔍 ROOT CAUSE ANALYSIS
HMM Model Thresholds (dari models/hmm_regime.pkl):
State 0 (Low Vol): 0.001039 # Volatility 20-period std
State 1 (Medium Vol): 0.001350 # +0.000311 difference
State 2 (High Vol): 0.001621 # +0.000271 difference
Masalah:
- Threshold terlalu sempit! Difference antara Low dan High cuma 0.00058 (0.058%)
- Gold lebih volatile dari thresholds ini → selalu fall into "Low" bucket
- Model di-train dengan data yang terlalu low volatility atau old data
Perbandingan dengan Real Market:
Gold (XAUUSD) Typical Volatility:
- Quiet market: 0.0005 - 0.0015 (0.05% - 0.15%)
- Normal market: 0.0015 - 0.0030 (0.15% - 0.30%)
- Volatile market: 0.0030 - 0.0060+ (0.30% - 0.60%+)
Current HMM bands:
- Low: < 0.001350 (< 0.135%)
- Medium: 0.001350 - 0.001621 (0.135% - 0.162%)
- High: > 0.001621 (> 0.162%)
Problem:
- Band "Medium" dan "High" terlalu sempit (only 0.027% range!)
- Most Gold trading happens in 0.15% - 0.40% range
- Current thresholds: 0.104% - 0.162% (MISALIGNED!)
📈 EVIDENCE
From Bot Logs:
19:14:08 | Session: London (high volatility) ← Session filter
19:15:03 | Regime: low_volatility ← HMM detector
Contradiction:
- Session filter (based on session time) says "high volatility"
- HMM detector (based on price action) says "low volatility"
Both can be correct IF:
- London session = typically high volatility hours
- BUT actual price action RIGHT NOW = low volatility movement
However, the issue is HMM NEVER changes. Meaning thresholds are miscalibrated.
From HMM Model Analysis:
Regime Mapping: {
0: LOW_VOLATILITY (mean: 0.001039),
1: MEDIUM_VOLATILITY (mean: 0.001350),
2: HIGH_VOLATILITY (mean: 0.001621)
}
Samples: 1888 (training data)
Log Likelihood: 33039.09
Training Data Issue:
- Model trained on 1888 samples (probably old M15 data)
- If data was from low volatility period → thresholds too low
- If data included mix → thresholds compressed
🎯 WHY THIS IS A PROBLEM
1. H1 Bias Weights Misaligned
Dynamic H1 Bias menggunakan regime untuk adjust weights:
if regime == "Low Volatility": # RANGING
weights = {
"rsi": 0.30, # RSI prioritas tinggi
"macd": 0.25,
"ema_trend": 0.15 # EMA trend kurang penting
}
elif regime == "High Volatility": # TRENDING
weights = {
"ema_trend": 0.30, # EMA trend prioritas
"ema_cross": 0.25,
"rsi": 0.10 # RSI kurang reliable
}
Problem:
- Jika regime stuck on "Low Vol" → weights selalu set untuk ranging
- Padahal market bisa trending → weights jadi suboptimal
2. Risk Management Suboptimal
Risk manager bisa adjust based on regime:
- Low vol → bisa increase position size (safe)
- High vol → reduce position size (dangerous)
Stuck on Low Vol:
- Risk manager thinks market always safe
- Might be taking too much risk saat actually volatile
3. Filter Decisions Wrong
Entry filters might check regime:
- "Don't trade in extreme volatility"
- "Increase confidence threshold in choppy low vol"
If regime wrong:
- Filters make wrong decisions
- Miss good trades or take bad trades
🔧 SOLUTIONS
Option 1: Retrain HMM Model (RECOMMENDED)
Retrain dengan data yang include diverse market conditions:
python train_models.py --retrain-hmm --data-period 90 # Last 90 days
Steps:
- Fetch 90 days of M15 Gold data (include volatile + quiet periods)
- Calculate 8 features (log returns, vol 20, vol 100, ATR, etc.)
- Train HMM with 3-4 states
- Map states based on actual volatility distribution
Expected new thresholds:
Low Vol: < 0.002 (< 0.20%) # Quiet market
Medium Vol: 0.002 - 0.004 (0.20% - 0.40%) # Normal trading
High Vol: > 0.004 (> 0.40%) # Volatile/news events
Option 2: Manual Threshold Adjustment
Edit src/regime_detector.py to use rule-based regime:
def get_current_state_simple(self, df: pl.DataFrame) -> RegimeState:
"""Simple rule-based regime (fallback if HMM stuck)."""
# Calculate 20-period volatility
log_returns = (df["close"] / df["close"].shift(1)).log()
vol_20 = log_returns.rolling_std(window_size=20).tail(1).item()
# Adjusted thresholds for Gold
if vol_20 < 0.0020:
regime = MarketRegime.LOW_VOLATILITY
recommendation = "TRADE"
elif vol_20 < 0.0040:
regime = MarketRegime.MEDIUM_VOLATILITY
recommendation = "TRADE"
else:
regime = MarketRegime.HIGH_VOLATILITY
recommendation = "REDUCE"
# Calculate confidence based on distance from thresholds
if regime == MarketRegime.LOW_VOLATILITY:
confidence = 1.0 - (vol_20 / 0.0020)
elif regime == MarketRegime.MEDIUM_VOLATILITY:
confidence = min(
1.0 - abs(vol_20 - 0.0030) / 0.0010,
0.9
)
else:
confidence = min((vol_20 - 0.0040) / 0.0020, 1.0)
return RegimeState(
regime=regime,
confidence=max(0.5, min(confidence, 1.0)),
probabilities={r.value: 0.33 for r in MarketRegime},
volatility=vol_20 * 100, # Convert to percentage
recommendation=recommendation
)
Option 3: Use ATR % Instead
Replace HMM with simple ATR-based regime:
def get_regime_from_atr(df: pl.DataFrame) -> str:
"""Simple ATR-based regime detection."""
atr_pct = df["atr_percent"].tail(1).item()
if atr_pct < 0.25:
return "low_volatility"
elif atr_pct < 0.50:
return "medium_volatility"
else:
return "high_volatility"
Thresholds based on ATR %:
- Low: < 0.25% ATR (quiet)
- Medium: 0.25% - 0.50% (normal)
- High: > 0.50% (volatile)
📊 EXPECTED IMPACT AFTER FIX
Before (Current - Stuck):
Regime Distribution (Last 100 candles):
Low: 100 (100%) ❌ STUCK
Medium: 0 (0%)
High: 0 (0%)
H1 Bias Weights: ALWAYS "ranging mode"
Risk Management: ALWAYS "safe mode"
After (Fixed):
Regime Distribution (Last 100 candles):
Low: 45 (45%) ✓ Quiet periods
Medium: 40 (40%) ✓ Normal trading
High: 15 (15%) ✓ Volatile spikes
H1 Bias Weights: ADAPTIVE (changes with market)
Risk Management: DYNAMIC (responds to volatility)
🚀 RECOMMENDED ACTION
PRIORITY: HIGH (affects all adaptive systems)
Quick Fix (5 minutes):
- Use Option 3 (ATR-based) as temporary replacement
- Modify
src/regime_detector.pyto add fallback logic - Restart bot
Permanent Fix (30 minutes):
- Retrain HMM with 90 days data
- Verify new thresholds make sense
- Backtest to ensure regime changes appropriately
- Deploy new model
Verification: After fix, regime should change 10-20 times per day (not stuck on one!)
📝 FILES TO MODIFY
Quick Fix:
src/regime_detector.py- Add fallback ATR-based regime
Permanent Fix:
train_models.py- Add HMM retraining with better datamodels/hmm_regime.pkl- Replace with new model
Next Step: User decides which solution to implement.
Expected improvement:
- More accurate regime detection
- Better H1 bias weight selection
- Improved risk management decisions
- Higher overall profitability