114 lines
4.6 KiB
Python
114 lines
4.6 KiB
Python
"""
|
|
config.py — Global configuration for ChanMacro.
|
|
|
|
All weights, thresholds, and paths are configurable.
|
|
V1 weights are deliberately simple; they will be tuned via Phase 0 validation.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
"""Global configuration. Override via config.json or env vars."""
|
|
|
|
# ── Paths ──────────────────────────────────────────────
|
|
db_path: str = "data/macro.db"
|
|
data_dir: str = "data"
|
|
|
|
# ── Data Provider ──────────────────────────────────────
|
|
provider_url: str = "https://provider.jackyu66.com"
|
|
btc_symbol: str = "BTC/USDT:USDT"
|
|
top50_symbols: list[str] = field(default_factory=lambda: [
|
|
"BTC/USDT:USDT", "ETH/USDT:USDT", "SOL/USDT:USDT",
|
|
"BNB/USDT:USDT", "XRP/USDT:USDT", "DOGE/USDT:USDT",
|
|
"SUI/USDT:USDT", "TON/USDT:USDT", "ZEC/USDT:USDT",
|
|
"1000PEPE/USDT:USDT", "SAGA/USDT:USDT",
|
|
"XAU/USDT:USDT", "XAG/USDT:USDT",
|
|
"CL/USDT:USDT", "BILL/USDT:USDT", "BZ/USDT:USDT",
|
|
"LAB/USDT:USDT", "CRCL/USDT:USDT", "SNDK/USDT:USDT",
|
|
"CHIP/USDT:USDT",
|
|
])
|
|
|
|
# ── Breadth ────────────────────────────────────────────
|
|
breadth_top_n: list[int] = field(default_factory=lambda: [20, 30, 50])
|
|
breadth_ema_period: int = 20
|
|
breadth_new_high_window: int = 20
|
|
|
|
# ── Regime (factor-locked: Price + Breadth + Vol) ─────
|
|
regime_version: str = "v1_price_breadth_vol"
|
|
# Weights for trend_score within regime detection
|
|
regime_w_price: float = 0.35
|
|
regime_w_breadth: float = 0.50
|
|
regime_w_vol: float = 0.15
|
|
# Weights for panic_score
|
|
regime_panic_w_anti_trend: float = 0.60
|
|
regime_panic_w_vol_extreme: float = 0.40
|
|
|
|
# ── Price Structure ────────────────────────────────────
|
|
ps_ema_fast: int = 20
|
|
ps_ema_mid: int = 60
|
|
ps_ema_slow: int = 120
|
|
ps_adx_period: int = 14
|
|
ps_adx_threshold: int = 25
|
|
ps_atr_period: int = 14
|
|
ps_bb_period: int = 20
|
|
ps_roc_periods: list[int] = field(default_factory=lambda: [5, 10, 20])
|
|
|
|
# ── OI Matrix ──────────────────────────────────────────
|
|
oi_price_threshold_pct: float = 0.5 # min price change% to classify
|
|
oi_oi_threshold_pct: float = 0.5 # min OI change% to classify
|
|
|
|
# ── Volatility Regime ──────────────────────────────────
|
|
vol_atr_period: int = 14
|
|
vol_hv_short: int = 20
|
|
vol_hv_long: int = 60
|
|
# Thresholds (ATR/Close %)
|
|
vol_low_threshold: float = 2.0
|
|
vol_high_threshold: float = 5.0
|
|
vol_explosive_threshold: float = 10.0
|
|
|
|
# ── Trend (L2 aggregation) ─────────────────────────────
|
|
trend_w_price: float = 0.30
|
|
trend_w_breadth: float = 0.70
|
|
|
|
# ── Maturity Score ─────────────────────────────────────
|
|
maturity_w_trend: float = 0.50
|
|
maturity_w_breadth: float = 0.30
|
|
maturity_w_vol: float = 0.20
|
|
|
|
# ── Expectancy ─────────────────────────────────────────
|
|
half_life_days: int = 180
|
|
sufficiency_min_effective: int = 30
|
|
sufficiency_low: int = 50
|
|
sufficiency_medium: int = 100
|
|
level_min_samples: int = 50
|
|
knn_max_distance: float = 0.35
|
|
knn_k: int = 200
|
|
|
|
# ── Validation ─────────────────────────────────────────
|
|
min_history_days: int = 365
|
|
regime_min_avg_duration: int = 5
|
|
regime_max_flip_rate: float = 0.15
|
|
|
|
@classmethod
|
|
def from_json(cls, path: str = "config.json") -> "Config":
|
|
"""Load config from JSON file, overriding defaults."""
|
|
import json
|
|
config = cls()
|
|
try:
|
|
with open(path) as f:
|
|
data = json.load(f)
|
|
for key, value in data.items():
|
|
if hasattr(config, key):
|
|
setattr(config, key, value)
|
|
except FileNotFoundError:
|
|
pass
|
|
return config
|
|
|
|
|
|
# Global singleton
|
|
config = Config()
|