feat: add 5 dashboard features — dark mode, trade history, backtests, model insights, alerts
- Dark mode: class-based theme toggle with localStorage persistence and flash prevention - Trade History (/trades): paginated table, stats cards, equity curve chart with DB API endpoints - Backtest Viewer (/backtests): log parser for 35 backtest results, sidebar + detail + comparison tabs - Model Insights: dashboard card + dialog showing feature importance, regime distribution, training history - Alert/Signal Log (/alerts): signal stats, filterable table with execution tracking - API: 8 new endpoints with psycopg2 DB connection pool - Dark mode sweep across books page, about dialog, and all dashboard components - Architecture docs rewritten with Mermaid diagrams (23 docs) - README and FEATURES.md rewritten bilingual (Indonesian + English) - main_live.py: write model_metrics.json on startup and retrain Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b2dc2dacd7
commit
e8355b3f62
@@ -1,4 +1,4 @@
|
||||
# Risk Management
|
||||
# Manajemen Risiko — *Smart Risk Manager*
|
||||
|
||||
> **File utama:** `src/smart_risk_manager.py`
|
||||
> **File pendukung:** `src/risk_engine.py`, `src/position_manager.py`
|
||||
@@ -6,454 +6,157 @@
|
||||
|
||||
---
|
||||
|
||||
## Apa Itu Risk Management?
|
||||
## Gambaran Umum
|
||||
|
||||
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.
|
||||
Manajemen risiko adalah **fondasi terpenting** dari sistem *trading*. Bot menggunakan pendekatan berlapis — dari kalkulasi ukuran posisi hingga perlindungan otomatis saat kondisi pasar memburuk.
|
||||
|
||||
---
|
||||
|
||||
## 3 Modul Risk Management
|
||||
## 4 Mode *Trading*
|
||||
|
||||
| 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 |
|
||||
```mermaid
|
||||
graph LR
|
||||
A["NORMAL<br/>🟢 Trading normal"] -->|"Kerugian > 50% batas harian"| B["PROTECTED<br/>🟡 Lot dikurangi 50%"]
|
||||
B -->|"Kerugian > 80% batas harian"| C["RECOVERY<br/>🟠 Lot minimal, sangat ketat"]
|
||||
C -->|"Kerugian = batas harian"| D["COOLDOWN/STOPPED<br/>🔴 Berhenti total"]
|
||||
D -->|"Hari baru (reset)"| A
|
||||
B -->|"Profit pulih"| A
|
||||
```
|
||||
|
||||
| Mode | Kondisi | Efek |
|
||||
|------|---------|------|
|
||||
| **NORMAL** | Kerugian < 50% batas harian | *Lot* normal, semua filter standar |
|
||||
| **PROTECTED** | Kerugian 50-80% batas harian | *Lot* dikurangi 50%, *entry* lebih ketat |
|
||||
| **RECOVERY** | Kerugian 80-100% batas harian | *Lot* minimal, hanya sinyal sangat kuat |
|
||||
| **COOLDOWN / STOPPED** | Kerugian = batas harian | **Berhenti total** — tidak boleh *trading* |
|
||||
|
||||
---
|
||||
|
||||
## Trading Mode (4 State)
|
||||
## Batas Risiko (Akun *Small* $5.000)
|
||||
|
||||
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
|
||||
```
|
||||
| Batas | Nilai | Kalkulasi |
|
||||
|-------|-------|-----------|
|
||||
| **Risiko per *trade*** | 1.0% | $50 |
|
||||
| **Kerugian harian** | 3.0% | $150 |
|
||||
| **Posisi bersamaan** | Max 3 | Terbatas oleh risiko |
|
||||
| **Max *lot*** | 0.05 | Batas keras |
|
||||
| **Min *lot*** | 0.01 | *Lot* paling kecil |
|
||||
| ***Cooldown*** | 5 menit | Antar *trade* |
|
||||
|
||||
---
|
||||
|
||||
## Kalkulasi Lot Size
|
||||
## Kalkulasi Ukuran Posisi
|
||||
|
||||
### 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).
|
||||
Bot menggunakan **metode *Half-Kelly Criterion***:
|
||||
|
||||
```python
|
||||
# v2 (lama): Tidak ada proteksi broker
|
||||
result = mt5.send_order(sl=0, ...) # Bergantung 100% pada software
|
||||
# 1. Hitung jumlah risiko
|
||||
risk_amount = balance * risk_per_trade / 100
|
||||
# $5.000 * 1% = $50
|
||||
|
||||
# v3 (baru): ATR-based broker protection
|
||||
broker_sl = signal.stop_loss # SL dari SMC (ATR-based, min 1.5 ATR)
|
||||
# 2. Hitung jarak SL
|
||||
sl_distance = abs(entry - stop_loss)
|
||||
sl_pips = sl_distance / 0.1 # XAUUSD
|
||||
|
||||
# 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
|
||||
# 3. Hitung lot
|
||||
lot = risk_amount / (sl_pips * pip_value)
|
||||
|
||||
result = mt5.send_order(sl=broker_sl, ...) # SL AKTIF di broker
|
||||
```
|
||||
# 4. Half-Kelly (keamanan)
|
||||
lot *= 0.5
|
||||
|
||||
**Fallback jika broker reject SL:**
|
||||
```python
|
||||
# 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
|
||||
```
|
||||
# 5. Apply multiplier
|
||||
lot *= session_multiplier # 0.5x - 1.2x
|
||||
lot *= regime_multiplier # Dikurangi saat volatile
|
||||
|
||||
### Emergency Stop Loss (Safety Net Terakhir)
|
||||
|
||||
```python
|
||||
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)│
|
||||
└─────────────────┴───────────────────────┴──────────────────────────┘
|
||||
# 6. Batasi
|
||||
lot = max(0.01, min(lot, 0.05))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Circuit Breaker (RiskEngine)
|
||||
## Proteksi Berlapis
|
||||
|
||||
### Lapis 1: *Entry Filter* (Sebelum *Trade*)
|
||||
|
||||
14 filter *entry* harus lolos — termasuk *session filter*, *regime check*, dan *smart risk gate*.
|
||||
|
||||
### Lapis 2: *Position Monitoring* (Saat *Trade* Aktif)
|
||||
|
||||
12 kondisi *exit* diperiksa setiap ~10 detik:
|
||||
- *Smart Take Profit* (4 sub-kondisi)
|
||||
- *Early Cut* (momentum negatif)
|
||||
- *Trend Reversal* (ML sinyal balik)
|
||||
- *Max Loss* per *trade*
|
||||
- *Stall Detection*
|
||||
- Batas harian
|
||||
- *Weekend close*
|
||||
- *Time-based exit* (4-8 jam)
|
||||
- *Trailing SL* + *Breakeven*
|
||||
|
||||
### Lapis 3: *Broker-Level SL*
|
||||
|
||||
```python
|
||||
# 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
|
||||
# SL dikirim ke broker sebagai proteksi darurat
|
||||
result = mt5.send_order(
|
||||
sl=emergency_sl, # Berbasis ATR — proteksi server-side
|
||||
tp=signal.take_profit,
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
Jika koneksi internet terputus, **SL di *broker* tetap aktif**.
|
||||
|
||||
## Drawdown Tracking
|
||||
|
||||
### Daily Drawdown
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# Track peak equity
|
||||
if equity > peak_equity:
|
||||
peak_equity = equity
|
||||
|
||||
# Hitung drawdown
|
||||
drawdown = ((peak_equity - equity) / peak_equity) * 100
|
||||
```
|
||||
|
||||
### Per-Position Peak Tracking
|
||||
```python
|
||||
# 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
|
||||
### Lapis 4: *Circuit Breaker*
|
||||
|
||||
```python
|
||||
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
|
||||
# Flash crash detection — hentikan semua trading
|
||||
flash_crash_threshold = 2.5 # Pergerakan 2.5% dalam 1 menit
|
||||
if move_percent > threshold:
|
||||
HALT_ALL_TRADING
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integrasi dalam Main Loop
|
||||
## 7 Alasan *Exit* (*ExitReason*)
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
| Kode | Deskripsi |
|
||||
|------|-----------|
|
||||
| `TAKE_PROFIT` | Target profit tercapai atau profit diamankan |
|
||||
| `TREND_REVERSAL` | ML mendeteksi pembalikan *trend* |
|
||||
| `DAILY_LIMIT` | Batas kerugian harian tercapai |
|
||||
| `POSITION_LIMIT` | Batas kerugian per posisi (S/L) |
|
||||
| `TOTAL_LIMIT` | Batas kerugian total tercapai |
|
||||
| `WEEKEND_CLOSE` | Mendekati penutupan *weekend* |
|
||||
| `MANUAL` | Penutupan manual oleh pengguna |
|
||||
|
||||
---
|
||||
|
||||
## Semua Parameter Konfigurasi
|
||||
## *State* Risiko Harian
|
||||
|
||||
| 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 |
|
||||
```python
|
||||
@dataclass
|
||||
class RiskState:
|
||||
mode: TradingMode # NORMAL/PROTECTED/RECOVERY/COOLDOWN
|
||||
daily_profit: float # Total profit hari ini ($)
|
||||
daily_loss: float # Total kerugian hari ini ($)
|
||||
daily_trades: int # Jumlah trade hari ini
|
||||
consecutive_losses: int # Kerugian berturut-turut
|
||||
last_loss_amount: float # Kerugian terakhir ($)
|
||||
can_trade: bool # Boleh trading atau tidak
|
||||
```
|
||||
|
||||
*State* **di-reset setiap hari baru** (00:00 WIB) — hari baru, kesempatan baru.
|
||||
|
||||
---
|
||||
|
||||
## Sinkronisasi Backtest (backtest_live_sync.py)
|
||||
## *Position Guard* (Per Posisi)
|
||||
|
||||
Backtest menggunakan **logika exit yang identik** dengan live trading:
|
||||
Setiap posisi yang terbuka memiliki *guard* sendiri yang melacak:
|
||||
|
||||
```
|
||||
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)
|
||||
| Properti | Keterangan |
|
||||
|----------|------------|
|
||||
| `entry_price` | Harga masuk |
|
||||
| `peak_profit` | Profit tertinggi yang pernah dicapai |
|
||||
| `profit_history` | Riwayat profit (untuk *stall detection*) |
|
||||
| `reversal_warnings` | Jumlah peringatan *reversal* dari ML |
|
||||
| `stall_count` | Berapa kali harga *stuck* |
|
||||
| `entry_time` | Waktu masuk (untuk *time-based exit*) |
|
||||
|
||||
Reference in New Issue
Block a user