Files
XauBot/docs/arsitektur-ai/05-Risk-Management.md
T
GifariKemal 757b499033 docs: sync architecture docs with v5 major issues fix
5 major issues reflected in documentation:

1. Confidence calibration (03-SMC, 00-ARSITEKTUR):
   - Base 55% + 10% each → base 40% + weighted scoring
   - Structure +15%, BOS/CHoCH +12%, FVG +8%, OB +10%, Trend +10%

2. ATR-based pullback filter (09-Entry, 00-ARSITEKTUR):
   - Hardcoded $2/$1.5 → bounce 15% ATR, consolidation 10% ATR

3. Smarter time-based exit (10-Exit, 05-Risk, 00-ARSITEKTUR):
   - 4h: check profit growth, not just profit<$5
   - 6h: extend to 8h if profit>$10 and growing + ML agrees

4. Slippage validation (09-Entry, 23-Main, 00-ARSITEKTUR):
   - Check actual vs expected price, log if >0.15%

5. Partial fill handling (09-Entry, 23-Main, 00-ARSITEKTUR):
   - Check filled volume, use actual values for tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 10:06:43 +07:00

14 KiB

Risk Management

File utama: src/smart_risk_manager.py File pendukung: src/risk_engine.py, src/position_manager.py Konfigurasi: src/config.py


Apa Itu Risk Management?

Risk Management adalah sistem pelindung modal yang menentukan seberapa besar boleh trading, kapan harus berhenti, dan bagaimana mengelola posisi terbuka. Ini adalah komponen paling kritis — tanpa risk management yang baik, bahkan strategi terbaik pun bisa bangkrut.

Analogi: Risk Management adalah sabuk pengaman + airbag + rem ABS — melindungi dari kerugian fatal.


3 Modul Risk Management

Modul File Fungsi
SmartRiskManager smart_risk_manager.py Ultra-safe position sizing & daily limits
RiskEngine risk_engine.py Kelly Criterion & circuit breaker
SmartPositionManager position_manager.py Trailing stop & profit protection

Trading Mode (4 State)

Bot beroperasi dalam salah satu dari 4 mode:

NORMAL -> RECOVERY -> PROTECTED -> STOPPED
  |         |            |            |
  |    3 loss berturut   |    80% limit tercapai
  |                      |            |
  |                      |    100% limit -> STOP total
  v                      v
Trading penuh      Lot minimum saja
Mode Bisa Trade? Lot Size Kondisi
NORMAL Ya 0.01 - 0.02 Operasi standar
RECOVERY Ya 0.01 saja Setelah 3 loss berturut
PROTECTED Ya 0.01 saja Daily loss 80% dari limit
STOPPED Tidak 0.00 Daily/total limit tercapai

Transisi Mode (Prioritas tinggi ke rendah)

1. Cek total_loss >= $500 (10%)      -> STOPPED
2. Cek daily_loss >= $250 (5%)       -> STOPPED
3. Cek total_loss >= $400 (80%)      -> PROTECTED
4. Cek daily_loss >= $200 (80%)      -> PROTECTED
5. Cek consecutive_losses >= 3       -> RECOVERY
6. Sisanya                           -> NORMAL

Kalkulasi Lot Size

Formula

calculate_lot_size(entry_price, confidence, regime, ml_confidence):

1. Base lot = 0.01

2. Cek trading mode:
   NORMAL    -> lot 0.01 - 0.02
   RECOVERY  -> lot 0.01 (fixed)
   PROTECTED -> lot 0.01 (fixed)
   STOPPED   -> lot 0.00 (tidak trade)

3. Cek ML confidence:
   effective = min(confidence, ml_confidence)

   >= 0.65 -> lot 0.02 (HIGH)
   >= 0.55 -> lot 0.01 (MEDIUM)
   <  0.55 -> lot 0.01 (LOW)

4. Cek regime:
   high_volatility / crisis -> paksa lot 0.01

5. Apply session multiplier:
   Sydney session -> lot * 0.5
   London-NY overlap -> lot * 1.2

6. Cap ke max_allowed_lot berdasarkan state
7. Round ke increment 0.01

Contoh Perhitungan

Input:
  confidence = 0.78 (SMC)
  ml_confidence = 0.72 (XGBoost)
  regime = "medium_volatility"
  session = "London"

Langkah:
  1. Mode = NORMAL
  2. effective = min(0.78, 0.72) = 0.72 >= 0.65 -> lot = 0.02
  3. Regime = medium -> tidak override
  4. Session = London (1.0x) -> lot tetap 0.02
  5. Final lot = 0.02
Input:
  confidence = 0.65
  ml_confidence = 0.60
  regime = "high_volatility"
  session = "Sydney"

Langkah:
  1. Mode = NORMAL
  2. effective = min(0.65, 0.60) = 0.60 >= 0.55 -> lot = 0.01
  3. Regime = high_volatility -> paksa lot 0.01
  4. Session = Sydney (0.5x) -> lot = max(0.01, 0.01*0.5) = 0.01
  5. Final lot = 0.01

Limit Proteksi (untuk modal $5,000)

Per Trade

Proteksi Persentase Nilai Mekanisme
Software S/L 1.0% $50 Bot tutup posisi otomatis
Emergency Broker S/L 2.0% $100 SL broker sebagai safety net

Per Hari

Proteksi Persentase Nilai Aksi
Warning 4.0% (80%) $200 Mode -> PROTECTED (lot minimum)
Daily Loss Limit 5.0% $250 Mode -> STOPPED (berhenti total)

Total (Kumulatif)

Proteksi Persentase Nilai Aksi
Warning 8.0% (80%) $400 Mode -> PROTECTED
Total Loss Limit 10.0% $500 Mode -> STOPPED permanen

Position Limit

Max concurrent positions: 2

Cek sebelum buka posisi baru:
  can_open_position():
    jika active_positions >= 2:
      return False, "Max positions reached (2/2)"
    else:
      return True, "OK"

Manajemen Posisi Terbuka

Evaluasi Posisi (evaluate_position())

Setiap posisi terbuka dievaluasi setiap loop:

1. TAKE PROFIT CHECK
   Jika profit >= $40:
     -> TUTUP (exit_reason: TAKE_PROFIT)

2. ML REVERSAL CHECK (v3: threshold diturunkan)
   Jika ML confidence > 65% berlawanan arah:       <- sebelumnya 70%
     DAN loss >= 40% dari max ($20):
       -> TUTUP (exit_reason: TREND_REVERSAL)

3. EARLY CUT (v4 — Smart Hold DIHAPUS)
   Jika loss >= 30% max ($15) DAN momentum < -30:
     -> TUTUP CEPAT (early cut, jangan tunggu recovery)

   v4: "Smart Hold" dihapus — tidak ada lagi hold losers
       menunggu golden time atau sesi London.

   MAX LOSS CHECK (50% threshold):
   Jika loss >= $25 (50% dari $50 max):
     -> TUTUP (exit_reason: POSITION_LIMIT)

4. STALL DETECTION
   Jika harga stall 10+ candle DAN loss >= $15:
     stall_count++
     Jika stall_count >= 5:
       -> TUTUP (exit_reason: STALL)

5. PROFIT PROTECTION (Peak Tracking)
   Jika peak_profit > $30 DAN current < 60% dari peak:
     -> TUTUP (lindungi profit)

6. SMART TIME-BASED EXIT (v5: Don't Cut Winners)
   Jika posisi terbuka >= 4 jam:
     - profit < $5 DAN tidak growing -> TUTUP
     - profit >= $5 DAN growing + ML agrees -> HOLD (extend)
   Jika posisi terbuka >= 6 jam:
     - profit < $10 ATAU tidak growing -> TUTUP
     - profit >= $10 DAN growing -> extend ke 8 jam
   Jika posisi terbuka >= 8 jam:
     -> TUTUP (take profit atau max time)

Smart Time-Based Exit Detail (v5 Update)

Jam 0        Jam 4              Jam 6              Jam 8
|------------|------------------|------------------|-----> waktu
             |                  |                  |
             | stuck?           | profitable?      | FINAL EXIT
             | (no growth)      | (growing?)       |
             |   -> TUTUP       |   -> extend!     |
             |                  | not growing?     |
             | growing?         |   -> TUTUP       |
             |   -> HOLD        |                  |

v5 Perubahan dari v3:
  - 4h: Cek profit GROWTH (momentum), bukan hanya profit < $5
  - 6h: Bukan force close lagi — extend ke 8h jika profit > $10 + growing
  - ML agreement diperhitungkan sebelum timeout
  - Prinsip: jangan potong pemenang yang masih berjalan

Broker Stop Loss (v3: ATR-Based Protection)

Perubahan utama v3: Bot sekarang mengirim SL ke broker (bukan SL=0 seperti sebelumnya).

# v2 (lama): Tidak ada proteksi broker
result = mt5.send_order(sl=0, ...)  # Bergantung 100% pada software

# v3 (baru): ATR-based broker protection
broker_sl = signal.stop_loss  # SL dari SMC (ATR-based, min 1.5 ATR)

# Validasi jarak minimum (10 pips untuk XAUUSD)
min_sl_distance = 1.0  # $1 = 10 pips
if direction == "BUY" and current_price - broker_sl < min_sl_distance:
    broker_sl = current_price - (min_sl_distance * 2)  # Paksa lebih lebar
if direction == "SELL" and broker_sl - current_price < min_sl_distance:
    broker_sl = current_price + (min_sl_distance * 2)  # Paksa lebih lebar

result = mt5.send_order(sl=broker_sl, ...)  # SL AKTIF di broker

Fallback jika broker reject SL:

# Error code 10016 = SL/TP rejected
if not result.success and result.retcode == 10016:
    # Fallback ke software SL (tanpa broker protection)
    result = mt5.send_order(sl=0, ...)  # Software tetap mengelola

Emergency Stop Loss (Safety Net Terakhir)

calculate_emergency_sl(entry_price, lot_size, direction):
    pip_value = lot_size * 10  # XAUUSD
    emergency_pips = emergency_sl_usd / pip_value  # $100 / pip_value
    price_distance = emergency_pips * 0.01

    if direction == "BUY":
        sl = entry_price - price_distance
    else:
        sl = entry_price + price_distance

Perbandingan Proteksi Lama vs Baru

┌─────────────────┬───────────────────────┬──────────────────────────┐
│ Skenario        │ Sebelum (v2)          │ Sesudah (v3)             │
├─────────────────┼───────────────────────┼──────────────────────────┤
│ Weekend Gap     │ Loss unlimited        │ Broker SL aktif          │
├─────────────────┼───────────────────────┼──────────────────────────┤
│ Flash Crash     │ Bergantung software   │ Broker SL aktif          │
├─────────────────┼───────────────────────┼──────────────────────────┤
│ Connection Lost │ Loss unlimited        │ Broker SL aktif          │
├─────────────────┼───────────────────────┼──────────────────────────┤
│ Trade Stuck     │ Ditahan selamanya     │ Exit max 6 jam           │
├─────────────────┼───────────────────────┼──────────────────────────┤
│ Reversal Lambat │ Tunggu 70% confidence │ Exit di 65% (lebih cepat)│
└─────────────────┴───────────────────────┴──────────────────────────┘

Circuit Breaker (RiskEngine)

# Automatic halt jika kondisi darurat
if daily_pnl_percent <= -max_daily_loss:
    activate_circuit_breaker("Daily loss limit breached")
    can_trade = False

# Flash crash protection
if price_move > flash_crash_threshold (2.5%):
    activate_circuit_breaker("Flash crash detected")
    can_trade = False

Drawdown Tracking

Daily Drawdown

# Saat loss:
daily_loss += abs(profit)
total_loss += abs(profit)
consecutive_losses += 1

# Saat profit:
total_loss = max(0, total_loss - profit)  # Recovery
consecutive_losses = 0  # Reset

Peak Equity Drawdown

# Track peak equity
if equity > peak_equity:
    peak_equity = equity

# Hitung drawdown
drawdown = ((peak_equity - equity) / peak_equity) * 100

Per-Position Peak Tracking

# Track peak profit per posisi
peak_profits[ticket] = max(peak_profits[ticket], current_profit)

# Profit protection: tutup jika profit turun 40% dari peak
if current_profit < peak_profit * 0.6:
    close_position()  # Lindungi profit

Daily Reset

check_new_day():
    if date.today() != current_date:
        # Reset semua counter harian
        daily_loss = 0
        daily_trades = 0
        consecutive_losses = 0
        mode = NORMAL (jika total_loss OK)
        current_date = today

Integrasi dalam Main Loop

Main Trading Loop (candle-based + position check setiap ~10 detik)
    |
    v
1. check_new_day()         <- Reset harian
    |
    v
2. get_trading_recommendation()
    |-- can_trade? -> Jika False, skip
    |-- mode? -> Tentukan lot limit
    |
    v
3. calculate_lot_size()    <- Hitung lot aman
    |-- Input: confidence, regime, ml_confidence
    |-- Output: lot 0.01-0.02
    |
    v
4. Apply session_multiplier <- Sydney 0.5x, Golden 1.2x
    |
    v
5. can_open_position()     <- Cek limit posisi (max 2)
    |
    v
6. execute_trade()         <- Kirim order ke MT5 (v3: DENGAN broker SL)
    |-- broker_sl = signal.stop_loss (ATR-based)
    |-- Fallback sl=0 jika broker reject
    |-- register_position() <- Track posisi baru + entry_time
    |
    v
7. evaluate_position()     <- Monitor posisi terbuka
    |-- Cek TP, ML reversal (65%), max loss, stall
    |-- Cek time-based exit (4 jam / 6 jam)   <- v3 BARU
    |
    v
8. record_trade_result()   <- Catat profit/loss
    |-- Update daily_loss, total_loss
    |-- Cek apakah limit tercapai

Semua Parameter Konfigurasi

Parameter Nilai Fungsi
capital $5,000 Modal awal
max_daily_loss_percent 5.0% Limit harian ($250)
max_total_loss_percent 10.0% Limit kumulatif ($500)
max_loss_per_trade_percent 1.0% Software SL ($50)
emergency_sl_percent 2.0% Broker SL ($100)
base_lot_size 0.01 Lot minimum
max_lot_size 0.02 Lot maximum
recovery_lot_size 0.01 Lot saat recovery
trend_reversal_threshold 0.65 ML confidence untuk tutup (v3: diturunkan dari 0.70)
max_concurrent_positions 2 Posisi terbuka max
flash_crash_threshold 2.5% Deteksi crash
breakeven_pips 15.0 Pindah SL ke breakeven
trail_start_pips 25.0 Mulai trailing stop
trail_step_pips 10.0 Jarak trailing

Sinkronisasi Backtest (backtest_live_sync.py)

Backtest menggunakan logika exit yang identik dengan live trading:

Exit reversal:   0.65 (65% ML confidence)    <- synced dengan live
Smart time-based exit (v5):
  16 bars (4 jam M15) + no growth   -> exit (stuck)
  16 bars + growing + ML agrees     -> hold (extend)
  24 bars (6 jam M15) + profit<$10  -> exit
  24 bars + profit>$10 + growing    -> extend ke 32 bars (8 jam)
  32 bars (8 jam M15)               -> final exit

Perhitungan bar:
  bars_since_entry = current_bar_index - entry_bar_index
  16 bars * 15 menit = 4 jam
  24 bars * 15 menit = 6 jam
  32 bars * 15 menit = 8 jam (v5: max extended time)

Kenapa penting disinkronkan? Agar hasil backtest akurat mewakili performa live trading.


Filosofi Kunci

  1. Dual-Layer SL — ATR-based broker SL + software-managed exit (v3 update)
  2. Ultra-Conservative — Lot 0.01-0.02 saja, tidak pernah agresif
  3. Multi-Layer Protection — Per-trade, per-day, total limit, circuit breaker
  4. Recovery First — Setelah loss, otomatis masuk mode defensif
  5. Profit Protection — Jika profit sudah besar, lindungi dari drawback
  6. Smart Time-Bounded — Tidak ada posisi "zombie", max 6-8 jam, tapi jangan potong pemenang (v5 update)
  7. Faster Reversal — Exit lebih cepat di 65% ML confidence (v3 update)