2026-02-06 09:01:35 +07:00
# 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
```
2026-02-06 10:06:43 +07:00
**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
```
2026-02-06 09:01:35 +07:00
**Untuk signal BUY, block jika:**
2026-02-06 10:06:43 +07:00
- Harga turun > bounce_threshold (15% ATR) dalam 3 candle terakhir
2026-02-06 09:01:35 +07:00
- MACD bearish + harga turun
- Harga jauh di bawah EMA9 + terus turun
**Untuk signal SELL, block jika:**
2026-02-06 10:06:43 +07:00
- Harga naik > bounce_threshold (15% ATR) dalam 3 candle terakhir
2026-02-06 09:01:35 +07:00
- 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
2026-02-06 10:06:43 +07:00
-> Block jika bounce > 15% ATR (v5: dinamis)
2026-02-06 09:01:35 +07:00
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)
2026-02-06 10:06:43 +07:00
5. Consolidation Check
-> Jika movement < 10% ATR = consolidation → ALLOW
-> v5: dinamis, bukan fixed $1.5
2026-02-06 09:01:35 +07:00
```
---
### 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
2026-02-06 10:06:43 +07:00
# Step E: Slippage Validation (v5 BARU)
2026-02-06 09:01:35 +07:00
if result . success :
2026-02-06 10:06:43 +07:00
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)
2026-02-06 09:01:35 +07:00
smart_risk . register_position (
ticket = result . order_id ,
2026-02-06 10:06:43 +07:00
entry_price = actual_price , # v5: harga aktual (bukan expected)
lot_size = filled_volume , # v5: volume aktual (bukan requested)
2026-02-06 09:01:35 +07:00
direction = signal . signal_type ,
)
```
2026-02-06 10:06:43 +07:00
### 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)
```
2026-02-06 09:01:35 +07:00
---
## Post-Entry
```python
2026-02-06 10:06:43 +07:00
# Step H: Log trade detail
2026-02-06 09:01:35 +07:00
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).