0f9548e5fb
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>
301 lines
7.6 KiB
Markdown
301 lines
7.6 KiB
Markdown
# 🚨 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`):
|
|
|
|
```python
|
|
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:**
|
|
1. **Threshold terlalu sempit!** Difference antara Low dan High cuma **0.00058** (0.058%)
|
|
2. **Gold lebih volatile** dari thresholds ini → selalu fall into "Low" bucket
|
|
3. 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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```bash
|
|
python train_models.py --retrain-hmm --data-period 90 # Last 90 days
|
|
```
|
|
|
|
**Steps:**
|
|
1. Fetch 90 days of M15 Gold data (include volatile + quiet periods)
|
|
2. Calculate 8 features (log returns, vol 20, vol 100, ATR, etc.)
|
|
3. Train HMM with 3-4 states
|
|
4. Map states based on actual volatility distribution
|
|
|
|
**Expected new thresholds:**
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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):**
|
|
1. Use Option 3 (ATR-based) as temporary replacement
|
|
2. Modify `src/regime_detector.py` to add fallback logic
|
|
3. Restart bot
|
|
|
|
**Permanent Fix (30 minutes):**
|
|
1. Retrain HMM with 90 days data
|
|
2. Verify new thresholds make sense
|
|
3. Backtest to ensure regime changes appropriately
|
|
4. 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 data
|
|
- `models/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
|