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>
412 lines
10 KiB
Markdown
412 lines
10 KiB
Markdown
# Entry Trade — Proses Masuk Posisi
|
||
|
||
> **File utama:** `main_live.py`
|
||
> **File pendukung:** `src/smc_polars.py`, `src/ml_model.py`, `src/smart_risk_manager.py`, `src/session_filter.py`
|
||
|
||
---
|
||
|
||
## Apa Itu Entry Trade?
|
||
|
||
Entry Trade adalah keseluruhan proses dari **mendeteksi peluang** hingga **mengirim order ke broker**. Bot menggunakan **10+ filter** yang harus SEMUA lolos sebelum satu trade dieksekusi.
|
||
|
||
**Analogi:** Entry Trade seperti **proses boarding pesawat** — harus punya tiket (signal), passport valid (confirmation), lulus security check (risk), tepat waktu (session), dan gate terbuka (position limit).
|
||
|
||
---
|
||
|
||
## Checklist Entry (Semua Harus PASS)
|
||
|
||
```
|
||
1. [SESSION] Session filter izinkan trading?
|
||
2. [RISK MODE] Trading mode bukan STOPPED?
|
||
3. [SMC SIGNAL] Ada signal dari SMC Analyzer?
|
||
4. [ML CONFIRM] XGBoost confidence >= 50%?
|
||
5. [ML AGREE] ML tidak strongly disagree (>65% berlawanan)?
|
||
6. [QUALITY] Market quality bukan AVOID/CRISIS?
|
||
7. [CONFIRM] Signal konsisten 2 bar berturut?
|
||
8. [PULLBACK] Bukan sedang pullback/retrace?
|
||
9. [COOLDOWN] Sudah 5 menit sejak trade terakhir?
|
||
10. [POS LIMIT] Posisi terbuka < 2?
|
||
11. [LOT SIZE] Lot > 0 setelah semua adjustment?
|
||
|
||
SEMUA PASS -> Execute Trade
|
||
SATU GAGAL -> Skip, tunggu loop berikutnya
|
||
```
|
||
|
||
---
|
||
|
||
## Step-by-Step Flow
|
||
|
||
### Step 1: Session Filter
|
||
|
||
```python
|
||
# main_live.py Lines 472-483
|
||
session_ok, session_reason, session_multiplier = self.session_filter.can_trade()
|
||
|
||
if not session_ok:
|
||
return # Skip — bukan waktu trading
|
||
|
||
# Simpan multiplier untuk lot sizing nanti
|
||
self._current_session_multiplier = session_multiplier
|
||
```
|
||
|
||
**Bisa block:** Weekend, Friday >23:00, danger zone (00:00-06:00), low volatility session.
|
||
|
||
---
|
||
|
||
### Step 2: Risk Mode Check
|
||
|
||
```python
|
||
# main_live.py Lines 537-542
|
||
risk_rec = self.smart_risk.get_trading_recommendation()
|
||
|
||
if not risk_rec["can_trade"]:
|
||
return # STOPPED mode — daily/total limit tercapai
|
||
```
|
||
|
||
**Bisa block:** Mode STOPPED (daily loss >= $250, total loss >= $500).
|
||
|
||
---
|
||
|
||
### Step 3: SMC Signal Generation
|
||
|
||
```python
|
||
# main_live.py Lines 498-499
|
||
smc_signal = self.smc.generate_signal(df)
|
||
|
||
if smc_signal is None:
|
||
return # Tidak ada setup SMC yang valid
|
||
```
|
||
|
||
**SMC membutuhkan:**
|
||
- Market structure (bullish/bearish) ATAU BOS/CHoCH
|
||
- DAN (FVG ATAU Order Block)
|
||
- Minimum 2:1 risk/reward
|
||
|
||
**Output:** Entry price, SL, TP, confidence (55-85%), reason.
|
||
|
||
---
|
||
|
||
### Step 4: ML Confidence Check
|
||
|
||
```python
|
||
# main_live.py Lines 419-425
|
||
ml_prediction = self.ml_model.predict(df, feature_cols)
|
||
|
||
# Lines 664-669
|
||
if ml_prediction.confidence < 0.50:
|
||
return # ML terlalu tidak yakin
|
||
```
|
||
|
||
---
|
||
|
||
### Step 5: ML Agreement Check
|
||
|
||
```python
|
||
# main_live.py Lines 676-684
|
||
# Jika SMC bilang BUY tapi ML bilang SELL dengan confidence > 65%:
|
||
if smc_signal.signal_type == "BUY":
|
||
if ml_prediction.signal == "SELL" and ml_prediction.confidence > 0.65:
|
||
return # ML strongly disagrees — VETO
|
||
|
||
if smc_signal.signal_type == "SELL":
|
||
if ml_prediction.signal == "BUY" and ml_prediction.confidence > 0.65:
|
||
return # ML strongly disagrees — VETO
|
||
```
|
||
|
||
---
|
||
|
||
### Step 6: Dynamic Market Quality
|
||
|
||
```python
|
||
# main_live.py Lines 618-657
|
||
# Analisis kualitas pasar berdasarkan:
|
||
# - Session (London/NY = tinggi, Sydney = rendah)
|
||
# - Regime (low vol = bagus, crisis = block)
|
||
# - Volatility (medium = ideal)
|
||
# - Trend strength
|
||
# - SMC confluence
|
||
# - ML signal alignment
|
||
|
||
quality_score = analyze_market_quality(...)
|
||
# EXCELLENT (80+), GOOD (60+), MODERATE (40+), POOR (20+), AVOID (<20), CRISIS
|
||
|
||
if quality == "AVOID" or quality == "CRISIS":
|
||
return # Pasar tidak layak untuk trading
|
||
```
|
||
|
||
---
|
||
|
||
### Step 7: Signal Confirmation (2 Bar Berturut)
|
||
|
||
```python
|
||
# main_live.py Lines 686-709
|
||
signal_key = f"{smc_signal.signal_type}_{smc_signal.entry_price:.0f}"
|
||
|
||
if signal_key in self._signal_persistence:
|
||
self._signal_persistence[signal_key] += 1
|
||
else:
|
||
self._signal_persistence[signal_key] = 1
|
||
|
||
if self._signal_persistence[signal_key] < 2:
|
||
return # Belum dikonfirmasi — tunggu 1 loop lagi
|
||
|
||
# Signal sudah muncul 2x berturut -> CONFIRMED
|
||
```
|
||
|
||
**Tujuan:** Mencegah whipsaw — signal yang hanya muncul 1 detik kemungkinan noise.
|
||
|
||
---
|
||
|
||
### Step 8: Pullback Filter
|
||
|
||
```python
|
||
# main_live.py Lines 742-871
|
||
can_enter, pullback_reason = self._check_pullback_filter(df, signal.signal_type)
|
||
|
||
if not can_enter:
|
||
return # Sedang pullback, tunggu momentum selaras
|
||
```
|
||
|
||
**v5: Threshold sekarang ATR-based (bukan hardcoded)**
|
||
|
||
```
|
||
ATR diambil dari data (default $12 untuk XAUUSD)
|
||
bounce_threshold = ATR × 0.15 # ~$1.80 (sebelumnya: $2.00 fixed)
|
||
consolidation_threshold = ATR × 0.10 # ~$1.20 (sebelumnya: $1.50 fixed)
|
||
|
||
Kenapa ATR-based?
|
||
- Threshold menyesuaikan volatilitas pasar saat ini
|
||
- Saat volatilitas tinggi (ATR=$20): bounce=$3, consolidation=$2
|
||
- Saat volatilitas rendah (ATR=$8): bounce=$1.2, consolidation=$0.8
|
||
- Lebih akurat daripada threshold tetap
|
||
```
|
||
|
||
**Untuk signal BUY, block jika:**
|
||
- Harga turun > bounce_threshold (15% ATR) dalam 3 candle terakhir
|
||
- MACD bearish + harga turun
|
||
- Harga jauh di bawah EMA9 + terus turun
|
||
|
||
**Untuk signal SELL, block jika:**
|
||
- Harga naik > bounce_threshold (15% ATR) dalam 3 candle terakhir
|
||
- MACD bullish + harga naik
|
||
- Harga jauh di atas EMA9 + terus naik
|
||
|
||
**Komponen yang dicek:**
|
||
|
||
```
|
||
1. Short-term Momentum (3 candle terakhir)
|
||
-> Arah pergerakan harga terkini
|
||
-> Block jika bounce > 15% ATR (v5: dinamis)
|
||
|
||
2. MACD Histogram
|
||
-> Rising = bullish momentum
|
||
-> Falling = bearish momentum
|
||
|
||
3. Harga vs EMA9
|
||
-> Di atas = bullish bias
|
||
-> Di bawah = bearish bias
|
||
|
||
4. RSI Extreme
|
||
-> RSI > 80 = overbought (block BUY)
|
||
-> RSI < 20 = oversold (block SELL)
|
||
|
||
5. Consolidation Check
|
||
-> Jika movement < 10% ATR = consolidation → ALLOW
|
||
-> v5: dinamis, bukan fixed $1.5
|
||
```
|
||
|
||
---
|
||
|
||
### Step 9: Trade Cooldown
|
||
|
||
```python
|
||
# main_live.py Lines 520-524
|
||
trade_cooldown = 300 # 5 menit
|
||
|
||
if last_trade_time:
|
||
elapsed = (now - last_trade_time).total_seconds()
|
||
if elapsed < trade_cooldown:
|
||
return # Tunggu cooldown selesai
|
||
```
|
||
|
||
**Tujuan:** Mencegah overtrading — minimal 5 menit antar trade.
|
||
|
||
---
|
||
|
||
### Step 10: Position Limit
|
||
|
||
```python
|
||
# main_live.py Lines 588-592
|
||
can_open, limit_reason = self.smart_risk.can_open_position()
|
||
|
||
if not can_open:
|
||
return # Sudah 2 posisi terbuka (max)
|
||
```
|
||
|
||
---
|
||
|
||
### Step 11: Lot Size Calculation
|
||
|
||
```python
|
||
# main_live.py Lines 544-560
|
||
safe_lot = self.smart_risk.calculate_lot_size(
|
||
entry_price=signal.entry_price,
|
||
confidence=signal.confidence, # SMC confidence
|
||
regime=regime_name, # HMM regime
|
||
ml_confidence=ml_prediction.confidence, # ML confidence
|
||
)
|
||
|
||
# Apply session multiplier
|
||
safe_lot = max(0.01, safe_lot * session_multiplier)
|
||
|
||
if safe_lot <= 0:
|
||
return # Lot 0 = tidak boleh trade
|
||
```
|
||
|
||
---
|
||
|
||
## Eksekusi Order
|
||
|
||
Setelah semua 11 filter lolos:
|
||
|
||
```python
|
||
# main_live.py Lines 985-1008
|
||
# Step A: Ambil harga real-time
|
||
tick = mt5.get_tick(symbol)
|
||
current_price = tick.ask if BUY else tick.bid
|
||
|
||
# Step B: Validasi broker SL (min 10 pips)
|
||
broker_sl = signal.stop_loss
|
||
if jarak_terlalu_dekat:
|
||
broker_sl = paksa_lebih_lebar
|
||
|
||
# Step C: Kirim order
|
||
result = mt5.send_order(
|
||
symbol="XAUUSD",
|
||
order_type="BUY" / "SELL",
|
||
volume=0.01 - 0.02, # Lot dari risk calculation
|
||
sl=broker_sl, # ATR-based SL (v3)
|
||
tp=signal.take_profit, # SMC TP (ATR-capped)
|
||
magic=123456, # ID bot
|
||
comment="AI Safe v3",
|
||
)
|
||
|
||
# Step D: Fallback jika broker reject SL
|
||
if gagal dan error 10016:
|
||
result = mt5.send_order(sl=0, ...) # Tanpa broker SL
|
||
|
||
# Step E: Slippage Validation (v5 BARU)
|
||
if result.success:
|
||
actual_price = result.price
|
||
slippage = abs(actual_price - signal.entry_price)
|
||
max_slippage = signal.entry_price * 0.0015 # 0.15% dari harga
|
||
|
||
if slippage > max_slippage:
|
||
log WARNING "HIGH SLIPPAGE" # Catat slippage tinggi
|
||
# Gunakan harga AKTUAL untuk tracking, bukan harga expected
|
||
|
||
# Step F: Partial Fill Check (v5 BARU)
|
||
filled_volume = result.volume
|
||
if filled_volume < requested_volume:
|
||
log WARNING "PARTIAL FILL"
|
||
# Update lot_size ke volume yang sebenarnya terisi
|
||
position.lot_size = filled_volume
|
||
|
||
# Step G: Register posisi (gunakan nilai AKTUAL)
|
||
smart_risk.register_position(
|
||
ticket=result.order_id,
|
||
entry_price=actual_price, # v5: harga aktual (bukan expected)
|
||
lot_size=filled_volume, # v5: volume aktual (bukan requested)
|
||
direction=signal.signal_type,
|
||
)
|
||
```
|
||
|
||
### Slippage & Partial Fill (v5 Detail)
|
||
|
||
```
|
||
SLIPPAGE VALIDATION:
|
||
expected_price = signal.entry_price
|
||
actual_price = result.price (dari broker)
|
||
slippage = |actual - expected|
|
||
max_acceptable = 0.15% dari harga (~$4 untuk XAUUSD @$2650)
|
||
|
||
Jika slippage > max_acceptable:
|
||
-> LOG WARNING (untuk monitoring & analisis)
|
||
-> Tetap pakai harga aktual untuk position tracking
|
||
|
||
PARTIAL FILL HANDLING:
|
||
requested_volume = lot dari risk calculation
|
||
filled_volume = result.volume (dari broker)
|
||
|
||
Jika filled < requested:
|
||
-> LOG WARNING dengan fill ratio (%)
|
||
-> Update position.lot_size ke filled_volume
|
||
-> Risk calculation tetap akurat (berdasarkan volume sebenarnya)
|
||
```
|
||
|
||
---
|
||
|
||
## Post-Entry
|
||
|
||
```python
|
||
# Step H: Log trade detail
|
||
trade_logger.log_trade_open(
|
||
signal, ml_prediction, regime, market_quality, ...
|
||
)
|
||
|
||
# Step G: Kirim notifikasi Telegram
|
||
await telegram.send_trade_open(trade_info)
|
||
|
||
# Step H: Update cooldown timer
|
||
last_trade_time = now
|
||
```
|
||
|
||
---
|
||
|
||
## Diagram Flow Lengkap
|
||
|
||
```
|
||
Loop setiap 1 detik
|
||
|
|
||
v
|
||
Fetch 200 bar M15 -> Feature Eng -> SMC -> HMM -> XGBoost
|
||
|
|
||
v
|
||
[1] Session OK? ----NO----> Skip
|
||
|YES
|
||
[2] Risk OK? -------NO----> Skip (STOPPED)
|
||
|YES
|
||
[3] SMC Signal? ----NO----> Skip (tidak ada setup)
|
||
|YES
|
||
[4] ML >= 50%? -----NO----> Skip (terlalu uncertain)
|
||
|YES
|
||
[5] ML Agree? ------NO----> Skip (ML veto)
|
||
|YES
|
||
[6] Quality OK? ----NO----> Skip (AVOID/CRISIS)
|
||
|YES
|
||
[7] Confirmed 2x? --NO----> Skip (tunggu konfirmasi)
|
||
|YES
|
||
[8] No Pullback? ---NO----> Skip (retrace)
|
||
|YES
|
||
[9] Cooldown OK? ---NO----> Skip (< 5 menit)
|
||
|YES
|
||
[10] Pos < 2? ------NO----> Skip (full)
|
||
|YES
|
||
[11] Lot > 0? ------NO----> Skip
|
||
|YES
|
||
v
|
||
EXECUTE TRADE -> Register -> Log -> Telegram
|
||
```
|
||
|
||
---
|
||
|
||
## Statistik Filter
|
||
|
||
Dalam kondisi normal, dari ratusan loop per jam:
|
||
- **~95%** diblokir oleh "tidak ada SMC signal" (pasar sideways)
|
||
- **~3%** diblokir oleh ML disagreement atau low confidence
|
||
- **~1%** diblokir oleh pullback filter atau session
|
||
- **<1%** lolos semua filter dan menghasilkan trade
|
||
|
||
**Rata-rata:** 3-8 trade per hari (sangat selektif).
|