- 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>
9.8 KiB
Feature Engineering
File:
src/feature_eng.pyClass:FeatureEngineerFramework: Pure Polars (vectorized, tanpa loop, tanpa TA-Lib — bukan Pandas)
Pipeline Feature Engineering
flowchart LR
A["OHLCV Data\n(open, high, low,\nclose, volume, time)"] --> B["calculate_all()"]
subgraph B["calculate_all()"]
direction TB
B1["calculate_rsi()"]
B2["calculate_atr()"]
B3["calculate_macd()"]
B4["calculate_bollinger_bands()"]
B5["calculate_ema_crossover()"]
B6["calculate_volume_features()"]
B7["calculate_ml_features()\n(returns, volatility,\nlags, trend, time)"]
B1 --> B2 --> B3 --> B4 --> B5 --> B6 --> B7
end
B --> C["40+ Fitur Numerik"]
C --> D["ML Ready\n(XGBoost Input)"]
style A fill:#2d3748,stroke:#63b3ed,color:#fff
style C fill:#2d3748,stroke:#48bb78,color:#fff
style D fill:#2d3748,stroke:#f6ad55,color:#fff
Performa: Seluruh pipeline dijalankan dalam < 100ms untuk 5000 bar menggunakan Pure Polars (vectorized, 10-100x lebih cepat dari Pandas loop). Menghasilkan 40+ fitur yang siap digunakan model ML.
Apa Itu Feature Engineering?
Feature Engineering adalah proses mengubah data harga mentah (OHLCV) menjadi 40+ fitur numerik yang bisa dibaca oleh model machine learning. Ini adalah "mata" dari AI -- tanpa fitur yang baik, model tidak bisa belajar apapun.
Analogi: Feature Engineering adalah alat ukur -- thermometer, barometer, kompas -- yang mengubah data mentah menjadi informasi bermakna.
Flow Utama: calculate_all()
Input: DataFrame OHLCV (open, high, low, close, volume)
|
|-- calculate_rsi() -> rsi
|-- calculate_atr() -> atr, atr_percent
|-- calculate_macd() -> macd, macd_signal, macd_histogram
|-- calculate_bollinger_bands() -> bb_upper, bb_lower, bb_width, bb_percent_b
|-- calculate_ema_crossover() -> ema_9, ema_21, ema_cross_bull/bear
|-- calculate_volume_features() -> volume_ratio, high_volume
|
|-- [jika include_ml_features=True]
| calculate_ml_features() -> returns, volatility, lags, trends, time
|
v
Output: DataFrame dengan 40+ kolom fitur
Data minimum: 26 bar (kebutuhan MACD slow EMA) agar semua fitur stabil.
Kategori 1: Indikator Teknikal
RSI (Relative Strength Index) -- Period 14
Formula: RSI = 100 - (100 / (1 + RS))
RS = Average Gain / Average Loss
Smoothing: Wilder's EMA (alpha = 1/14)
| Nilai | Interpretasi |
|---|---|
| RSI > 70 | Overbought (potensi turun) |
| RSI < 30 | Oversold (potensi naik) |
| RSI ~ 50 | Netral |
Output: rsi
ATR (Average True Range) -- Period 14
True Range = max(High-Low, |High-PrevClose|, |Low-PrevClose|)
ATR = Wilder's EMA dari True Range
ATR% = (ATR / Close) * 100
| Kondisi | Interpretasi |
|---|---|
| ATR tinggi | Pasar volatile (pergerakan besar) |
| ATR rendah | Pasar tenang (pergerakan kecil) |
Output: atr, atr_percent
MACD (Moving Average Convergence Divergence) -- 12/26/9
MACD Line = EMA(12) - EMA(26)
Signal = EMA(MACD Line, 9)
Histogram = MACD Line - Signal
| Kondisi | Interpretasi |
|---|---|
| Histogram > 0 & naik | Bullish momentum menguat |
| Histogram < 0 & turun | Bearish momentum menguat |
| MACD cross Signal ke atas | Potensi reversal naik |
| MACD cross Signal ke bawah | Potensi reversal turun |
Output: macd, macd_signal, macd_histogram
Bollinger Bands -- Period 20, StdDev 2.0
Middle = SMA(20)
Upper = Middle + 2 * StdDev
Lower = Middle - 2 * StdDev
Width = (Upper - Lower) / Middle
%B = (Close - Lower) / (Upper - Lower)
| Kondisi | Interpretasi |
|---|---|
| %B > 1 | Harga di atas upper band (extreme bullish) |
| %B < 0 | Harga di bawah lower band (extreme bearish) |
| %B ~ 0.5 | Harga di tengah |
| Width melebar | Volatility meningkat |
| Width menyempit | Volatility menurun (squeeze) |
Output: bb_middle, bb_upper, bb_lower, bb_width, bb_percent_b
EMA Crossover -- 9/21
EMA9 = Exponential Moving Average (cepat)
EMA21 = Exponential Moving Average (lambat)
EMA (Exponential Moving Average) memberikan bobot lebih besar pada data terbaru, sehingga lebih responsif terhadap perubahan harga dibanding SMA.
| Kondisi | Interpretasi |
|---|---|
| EMA9 > EMA21 | Trend naik |
| EMA9 < EMA21 | Trend turun |
| EMA9 cross atas EMA21 | Sinyal beli (bullish crossover) |
| EMA9 cross bawah EMA21 | Sinyal jual (bearish crossover) |
Output: ema_9, ema_21, ema_cross_bull, ema_cross_bear
Kategori 2: Volume Features -- Period 20
volume_sma = Rolling Mean(volume, 20)
volume_ratio = volume / volume_sma
volume_increasing = 1 jika volume > volume sebelumnya
high_volume = 1 jika volume_ratio > 1.5
Fungsi: Konfirmasi breakout -- pergerakan besar harus didukung volume tinggi.
Catatan: Jika kolom volume tidak ada di data, fitur ini di-skip (graceful degradation).
Kategori 3: ML-Specific Features
Returns & Momentum
returns_1 = (Close[t] / Close[t-1]) - 1 # Return 1 bar
returns_5 = (Close[t] / Close[t-5]) - 1 # Return 5 bar
returns_20 = (Close[t] / Close[t-20]) - 1 # Return 20 bar
log_returns = ln(Close[t] / Close[t-1]) # Log return
Fungsi: Mengukur kecepatan dan arah pergerakan harga (momentum) dalam berbagai timeframe.
Price Position
price_position = (Close - Low) / (High - Low) # Posisi 0-1 dalam range candle
dist_from_sma_20 = (Close / SMA20) - 1 # Jarak (%) dari rata-rata
Fungsi: Mengukur dimana harga relatif terhadap range dan rata-rata.
Volatility
volatility_20 = StdDev(log_returns, 20) # Realized volatility
normalized_range = (High - Low) / Close # Range sebagai % harga
avg_normalized_range = SMA(normalized_range, 14) # Rata-rata range 14 bar
Fungsi: Input penting untuk HMM regime detection dan risk sizing. Volatility yang tinggi menandakan pasar bergejolak dan mempengaruhi ukuran posisi.
Lag Features
close_lag_1 = Close[t-1]
close_lag_2 = Close[t-2]
close_lag_3 = Close[t-3]
close_lag_5 = Close[t-5]
Fungsi: Auto-regressive features -- menangkap pola harga berulang. Lag features memberikan konteks historis langsung kepada model.
Trend Features
higher_high = 1 jika High[t] > High[t-1], else 0
lower_low = 1 jika Low[t] < Low[t-1], else 0
hh_count_5 = Sum(higher_high, 5 bar) # Berapa kali HH dalam 5 bar
ll_count_5 = Sum(lower_low, 5 bar) # Berapa kali LL dalam 5 bar
Fungsi: Mengukur konsistensi trend -- banyak HH = strong uptrend.
Time Features
hour = Jam (0-23)
weekday = Hari (0=Senin, 6=Minggu)
london_session = 1 jika jam 08:00-16:00 UTC
ny_session = 1 jika jam 13:00-21:00 UTC
Fungsi: Pasar berperilaku berbeda tiap sesi -- London volatile, Asian tenang. Time features membantu model mengenali pola berbasis waktu.
Catatan: Hanya dihitung jika kolom time bertipe Datetime.
Kategori 4: SMC sebagai Fitur Numerik
Dari SMC Analyzer, dikonversi jadi angka untuk XGBoost:
swing_high = 1 / 0
swing_low = -1 / 0
fvg_signal = 1 (bull) / -1 (bear) / 0
ob = 1 (bull) / -1 (bear) / 0
bos = 1 (bull) / -1 (bear) / 0
choch = 1 (bull) / -1 (bear) / 0
market_structure = 1 (bull) / -1 (bear) / 0
regime = 0 / 1 / 2 (dari HMM)
Target Variable (Label Training)
create_target(df, lookahead=1, threshold=0.0):
target = 1 jika close[t+1] > close[t] # Harga naik
target = 0 jika close[t+1] <= close[t] # Harga turun/tetap
target_return = close[t+1] / close[t] - 1 # Return kontinu
Catatan: Target dibuat saat training saja, tidak saat live trading.
Preprocessing untuk ML
Penanganan Null
# Bar awal memiliki NaN karena lookback period
# Saat training: baris dengan NaN di-drop
df_clean = df.select(features + [target]).drop_nulls()
Penanganan Infinity
# Saat prediksi: NaN & infinity diganti 0
X = np.nan_to_num(X, nan=0.0, posinf=0.0, neginf=0.0)
Normalisasi
Tidak dilakukan -- XGBoost berbasis tree, scale-invariant (tidak perlu scaling).
Cleanup Kolom Temporary
Setiap method membersihkan kolom sementara yang diawali _ (misal _delta, _avg_gain, dll).
Fitur yang Digunakan vs Tidak
Digunakan oleh XGBoost (24+ fitur)
Semua indikator teknikal, returns, volatility, trend, time features, SMC numerik, regime.
Tidak Digunakan (Excluded)
- Kolom OHLCV asli:
time,open,high,low,close,volume - Kolom meta:
spread,real_volume,target,target_return - Kolom SMC level:
fvg_top,fvg_bottom,ob_top,ob_bottom, dll - Kolom temporary: apapun yang diawali
_
Parameter Konfigurasi
| Indikator | Parameter | Default | Configurable |
|---|---|---|---|
| RSI (Relative Strength Index) | period | 14 | Ya |
| ATR (Average True Range) | period | 14 | Ya |
| MACD (Moving Average Convergence Divergence) | fast/slow/signal | 12/26/9 | Ya |
| Bollinger Bands | period, std_dev | 20, 2.0 | Ya |
| EMA Crossover | fast/slow | 9/21 | Ya |
| Volume | period | 20 | Ya |
| Returns | lookback | [1, 5, 20] | Hardcoded |
| Volatility | window | 20 | Hardcoded |
| Session | London hours | 08-16 UTC | Hardcoded |
| Session | NY hours | 13-21 UTC | Hardcoded |
Performa
- 5000 bar features: < 100ms (sangat cepat)
- Framework: Pure Polars vectorized (10-100x lebih cepat dari Pandas loop) -- bukan Pandas
- Memory: ~1.6MB untuk 40+ fitur x 5000 bar
- Total fitur: 40+ kolom numerik siap ML