|
1 | 1 | """ |
2 | 2 | IHSG Quantitative Trading Model Configuration |
| 3 | +Refactored for LSTM + Triple Barrier Labeling (Paper Implementation) |
3 | 4 | """ |
4 | 5 | from dataclasses import dataclass, field |
5 | 6 | from typing import List |
|
10 | 11 | @dataclass |
11 | 12 | class DataConfig: |
12 | 13 | """Data fetching configuration""" |
13 | | - # Stock universe - Comprehensive Liquid IHSG Universe (IDX80 + Kompas100 + Liquid Growth) |
| 14 | + # Stock universe |
14 | 15 | stock_universe: List[str] = field(default_factory=lambda: IDX_UNIVERSE) |
15 | 16 |
|
16 | 17 | # Data storage |
17 | 18 | db_path: str = "data/ihsg_trading.db" |
18 | 19 |
|
19 | 20 | # Historical data settings |
20 | | - lookback_days: int = 365 * 5 # 5 years of history |
21 | | - min_data_points: int = 252 # Minimum data points for calculation |
22 | | - |
23 | | - |
24 | | -@dataclass |
25 | | -class SignalConfig: |
26 | | - """Signal generation parameters""" |
27 | | - # Technical indicators |
28 | | - rsi_period: int = 14 |
29 | | - macd_fast: int = 12 |
30 | | - macd_slow: int = 26 |
31 | | - macd_signal: int = 9 |
32 | | - bb_period: int = 20 |
33 | | - bb_std: float = 2.0 |
34 | | - atr_period: int = 14 |
35 | | - |
36 | | - # Mean reversion |
37 | | - zscore_period: int = 20 |
38 | | - zscore_entry_threshold: float = 2.0 |
| 21 | + lookback_days: int = 365 * 5 # 5 years |
| 22 | + min_data_points: int = 252 |
39 | 23 |
|
40 | | - # Momentum |
41 | | - momentum_periods: List[int] = field(default_factory=lambda: [5, 10, 20]) |
| 24 | + # Sequence generation |
| 25 | + window_size: int = 100 # From Paper: Optimal Window Size |
42 | 26 |
|
43 | 27 |
|
44 | 28 | @dataclass |
45 | 29 | class MLConfig: |
46 | | - """Machine learning model configuration""" |
47 | | - # Training windows (5 years total - using more of your 5-year historical data) |
48 | | - training_window: int = 1008 # 4 years of trading days for training |
49 | | - validation_window: int = 252 # 1 year of trading days for validation |
50 | | - validation_split: float = 0.2 # Deprecated, use validation_window instead |
51 | | - |
52 | | - # Prediction target (aligned with max_holding_days for day trading) |
53 | | - target_horizon: int = 5 # Predict 5-day forward return (matches max hold) |
54 | | - |
55 | | - # XGBoost parameters (Conservative Defaults with Strong Regularization) |
56 | | - # Note: Based on training results, 50 trees is the sweet spot before overfitting |
57 | | - # Regularization allows using more trees without overfitting |
58 | | - n_estimators: int = 500 |
59 | | - max_depth: int = 4 |
60 | | - learning_rate: float = 0.05 |
61 | | - min_child_weight: int = 5 |
62 | | - |
63 | | - # Regularization parameters (prevent overfitting) |
64 | | - subsample: float = 0.7 # Use 70% of data per tree (randomness prevents overfitting) |
65 | | - colsample_bytree: float = 0.7 # Use 70% of features per tree |
66 | | - gamma: float = 0.2 # Minimum loss reduction required to split (conservative) |
67 | | - reg_alpha: float = 1.0 # Stronger L1 regularization (feature selection) |
68 | | - reg_lambda: float = 2.0 # Stronger L2 regularization |
69 | | - |
70 | | - use_gpu: bool = False |
| 30 | + """Machine learning model configuration (LSTM)""" |
| 31 | + # Model Architecture (Paper: Hidden Size 8 was optimal) |
| 32 | + input_size: int = 5 # Open, High, Low, Close, Volume |
| 33 | + hidden_size: int = 8 |
| 34 | + num_layers: int = 2 # Starting with 2 stacked LSTMs |
| 35 | + dropout: float = 0.0 |
| 36 | + |
| 37 | + # Training |
| 38 | + batch_size: int = 64 |
| 39 | + learning_rate: float = 0.001 |
| 40 | + epochs: int = 50 |
| 41 | + patience: int = 10 # Early stopping |
| 42 | + |
| 43 | + # Triple Barrier Labeling (Optimized for IHSG) |
| 44 | + # Found via optimization: Horizon=5, Barrier=3.0% |
| 45 | + tbl_horizon: int = 5 |
| 46 | + tbl_barrier: float = 0.03 |
| 47 | + num_classes: int = 3 # 0: Loss, 1: Hold, 2: Profit |
71 | 48 |
|
72 | | - # Feature settings |
73 | | - feature_lags: List[int] = field(default_factory=lambda: [1, 2, 3, 5, 10, 15, 20]) |
74 | 49 |
|
75 | 50 | @dataclass |
76 | 51 | class ExitConfig: |
77 | 52 | """Exit strategy configuration""" |
78 | | - stop_loss_atr_mult: float = 2.0 # Tighter stop (2.0x is standard for swing) |
79 | | - take_profit_atr_mult: float = 5.0 # Reduced from 10.0. (4-6x is a "Home Run" in 5 days) |
80 | | - trailing_stop_atr_mult: float = 2.5 # Trail loosely to let winners run |
81 | | - |
82 | | - # Time-based exit (hold longer for bigger moves) |
83 | | - max_holding_days: int = 5 |
| 53 | + # Legacy ATR-based exits (kept for PositionManager compatibility) |
| 54 | + # TBL barrier is 3%, so we map roughly to that. |
| 55 | + # If ATR is ~2%, then 1.5x ATR = 3%. |
| 56 | + stop_loss_atr_mult: float = 1.5 |
| 57 | + take_profit_atr_mult: float = 1.5 |
| 58 | + signal_threshold: float = 0.5 |
84 | 59 |
|
85 | | - # Fixed stops (fallback for extreme cases) |
86 | | - max_loss_pct: float = 0.08 # Tighten max loss to 8% (preservation is key) |
87 | | - min_profit_pct: float = 0.15 # Realistic 15% upside target for 1 week |
88 | | - |
89 | | - signal_threshold: float = 0.55 # Minimum ML signal to enter/hold position |
90 | 60 |
|
91 | 61 | @dataclass |
92 | 62 | class PortfolioConfig: |
93 | | - """Portfolio management configuration""" |
94 | | - # Total portfolio value for sizing calculations |
95 | | - total_value: float = 100_000_000 # Default 100M IDR |
96 | | - |
97 | | - # Position sizing |
98 | | - max_positions: int = 8 # Reduced: Focus capital on best ideas |
99 | | - base_position_pct: float = 0.125 # 12.5% per trade |
100 | | - max_sector_exposure: float = 0.25 # 25% max per sector |
101 | | - |
102 | | - # Liquidity filter |
103 | | - min_avg_volume: int = 2_000_000 # 2M shares minimum |
104 | | - min_market_cap: float = 2e12 # 2 Trillion IDR minimum |
105 | | - |
106 | | - # Risk management |
107 | | - max_portfolio_volatility: float = 0.20 # 20% annual vol target |
108 | | - max_correlation: float = 0.6 # Avoid highly correlated positions |
| 63 | + """Portfolio simulation settings""" |
| 64 | + total_value: float = 100_000_000.0 # Default 100M IDR |
| 65 | + max_positions: int = 10 |
| 66 | + risk_per_trade: float = 0.02 # 2% Risk per trade (Optional usage) |
109 | 67 |
|
110 | 68 |
|
111 | 69 | @dataclass |
112 | 70 | class Config: |
113 | 71 | """Master configuration""" |
114 | 72 | data: DataConfig = field(default_factory=DataConfig) |
115 | | - signal: SignalConfig = field(default_factory=SignalConfig) |
116 | 73 | ml: MLConfig = field(default_factory=MLConfig) |
117 | 74 | exit: ExitConfig = field(default_factory=ExitConfig) |
118 | 75 | portfolio: PortfolioConfig = field(default_factory=PortfolioConfig) |
|
0 commit comments