Phase C/dry-run·미사용 모듈·재생성 HTML을 제거하고, 운영 체결을 sim_causal_hybrid와 동일한 hybrid 로직으로 통합한다. Co-authored-by: Cursor <cursoragent@cursor.com>
421 lines
18 KiB
Python
421 lines
18 KiB
Python
"""
|
|
전역 설정 (WLD). 값은 PROJECT_ROOT/.env → OS 환경 변수 순으로 읽습니다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from deepcoin.env_loader import load_project_env
|
|
|
|
load_project_env(override=True)
|
|
|
|
|
|
def _getenv(key: str, default: str = "") -> str:
|
|
return os.getenv(key, default)
|
|
|
|
|
|
def _getenv_int(key: str, default: str) -> int:
|
|
return int(_getenv(key, default))
|
|
|
|
|
|
def _getenv_float(key: str, default: str) -> float:
|
|
return float(_getenv(key, default))
|
|
|
|
|
|
def _parse_int_tuple(env_key: str, default: str) -> tuple[int, ...]:
|
|
raw = _getenv(env_key, default)
|
|
return tuple(int(x.strip()) for x in raw.split(",") if x.strip())
|
|
|
|
|
|
def _parse_int_set(env_key: str, default: str) -> frozenset[int]:
|
|
return frozenset(_parse_int_tuple(env_key, default))
|
|
|
|
|
|
def _parse_interval_map(env_key: str, default: str) -> dict[int, int]:
|
|
"""
|
|
'3:120,5:100' → {3: 120, 5: 100}.
|
|
"""
|
|
raw = _getenv(env_key, default)
|
|
out: dict[int, int] = {}
|
|
for part in raw.split(","):
|
|
part = part.strip()
|
|
if ":" not in part:
|
|
continue
|
|
k, v = part.split(":", 1)
|
|
out[int(k.strip())] = int(v.strip())
|
|
return out
|
|
|
|
|
|
def _parse_str_map(env_key: str, default: str) -> dict[int, str]:
|
|
"""'3:m3,1440:d1' → {3: 'm3', 1440: 'd1'}."""
|
|
raw = _getenv(env_key, default)
|
|
out: dict[int, str] = {}
|
|
for part in raw.split(","):
|
|
part = part.strip()
|
|
if ":" not in part:
|
|
continue
|
|
k, v = part.split(":", 1)
|
|
out[int(k.strip())] = v.strip()
|
|
return out
|
|
|
|
|
|
# --- API / 알림 ---
|
|
BITHUMB_ACCESS_KEY = _getenv("BITHUMB_ACCESS_KEY")
|
|
BITHUMB_SECRET_KEY = _getenv("BITHUMB_SECRET_KEY")
|
|
BITHUMB_API_URL = _getenv("BITHUMB_API_URL", "https://api.bithumb.com")
|
|
BITHUMB_API_CANDLE_COUNT = _getenv_int("BITHUMB_API_CANDLE_COUNT", "200")
|
|
BITHUMB_MINUTE_INTERVALS = _parse_int_set(
|
|
"BITHUMB_MINUTE_INTERVALS", "3,5,10,15,30,60,240"
|
|
)
|
|
HTS_API_RETRY_SLEEP_SEC = _getenv_float("HTS_API_RETRY_SLEEP_SEC", "0.5")
|
|
|
|
COIN_TELEGRAM_BOT_TOKEN = _getenv("COIN_TELEGRAM_BOT_TOKEN")
|
|
COIN_TELEGRAM_CHAT_ID = _getenv("COIN_TELEGRAM_CHAT_ID")
|
|
|
|
# --- 거래 대상 ---
|
|
SYMBOL = _getenv("SYMBOL", "WLD")
|
|
COIN_NAME = _getenv("COIN_NAME", "월드코인")
|
|
KR_COINS: dict[str, str] = {SYMBOL: COIN_NAME}
|
|
|
|
# --- 타임프레임 (분) ---
|
|
DAILY_INTERVAL_MIN = _getenv_int("DAILY_INTERVAL_MIN", "1440")
|
|
ENTRY_INTERVAL = _getenv_int("ENTRY_INTERVAL", "3")
|
|
TREND_INTERVAL_1H = _getenv_int("TREND_INTERVAL_1H", "60")
|
|
TREND_INTERVAL_1D = _getenv_int("TREND_INTERVAL_1D", "1440")
|
|
|
|
ALL_INTERVALS: tuple[int, ...] = _parse_int_tuple(
|
|
"ALL_INTERVALS", "3,5,10,15,30,60,240,1440"
|
|
)
|
|
# 1분봉은 01_download·ops_sync 미적재 (DOWNLOAD_EXCLUDED_INTERVALS).
|
|
DOWNLOAD_INTERVALS: tuple[int, ...] = _parse_int_tuple(
|
|
"DOWNLOAD_INTERVALS",
|
|
"3,5,10,15,30,60,240,1440",
|
|
)
|
|
# 주봉(10080)·월봉(43200) — 01_download 별도 적재, 기본 2년(DOWNLOAD_MONTHS_WM)
|
|
WEEK_INTERVAL_MIN = _getenv_int("WEEK_INTERVAL_MIN", "10080")
|
|
MONTH_INTERVAL_MIN = _getenv_int("MONTH_INTERVAL_MIN", "43200")
|
|
DOWNLOAD_INTERVALS_WM: tuple[int, ...] = _parse_int_tuple(
|
|
"DOWNLOAD_INTERVALS_WM",
|
|
"10080,43200",
|
|
)
|
|
DOWNLOAD_MONTHS_WM = _getenv_int("DOWNLOAD_MONTHS_WM", "24")
|
|
GENERAL_ANALYSIS_INTERVALS: tuple[int, ...] = _parse_int_tuple(
|
|
"GENERAL_ANALYSIS_INTERVALS", "3,5,10,15,30,60,240,1440"
|
|
)
|
|
TIMING_INTERVALS: tuple[int, ...] = _parse_int_tuple(
|
|
"TIMING_INTERVALS", "3,5,10,15"
|
|
)
|
|
TREND_INTERVALS: tuple[int, ...] = _parse_int_tuple(
|
|
"TREND_INTERVALS", "60,240,1440"
|
|
)
|
|
|
|
INTERVAL_PREFIX: dict[int, str] = _parse_str_map(
|
|
"INTERVAL_PREFIX",
|
|
"3:m3,5:m5,10:m10,15:m15,30:m30,60:m60,240:m240,1440:d1,10080:w1,43200:mo1",
|
|
)
|
|
|
|
# --- 볼린저 / RSI ---
|
|
BB_PERIOD = _getenv_int("BB_PERIOD", "20")
|
|
BB_STD = _getenv_float("BB_STD", "2")
|
|
BB_MIN_WIDTH_PCT = _getenv_float("BB_MIN_WIDTH_PCT", "0.8")
|
|
RSI_PERIOD = _getenv_int("RSI_PERIOD", "14")
|
|
|
|
# --- 이격도 ---
|
|
DISPARITY_PERIODS: tuple[int, ...] = _parse_int_tuple("DISPARITY_PERIODS", "5,20,60")
|
|
DISPARITY_OVERBOUGHT = _getenv_float("DISPARITY_OVERBOUGHT", "105")
|
|
DISPARITY_OVERSOLD = _getenv_float("DISPARITY_OVERSOLD", "95")
|
|
|
|
# --- MACD / Stochastic ---
|
|
MACD_FAST = _getenv_int("MACD_FAST", "12")
|
|
MACD_SLOW = _getenv_int("MACD_SLOW", "26")
|
|
MACD_SIGNAL = _getenv_int("MACD_SIGNAL", "9")
|
|
STOCH_K_PERIOD = _getenv_int("STOCH_K_PERIOD", "14")
|
|
STOCH_D_PERIOD = _getenv_int("STOCH_D_PERIOD", "3")
|
|
STOCH_SMOOTH_K = _getenv_int("STOCH_SMOOTH_K", "3")
|
|
STOCH_OVERSOLD = _getenv_float("STOCH_OVERSOLD", "20")
|
|
STOCH_OVERBOUGHT = _getenv_float("STOCH_OVERBOUGHT", "80")
|
|
|
|
# --- 추세 ---
|
|
TREND_RANGE_MA_GAP_PCT = _getenv_float("TREND_RANGE_MA_GAP_PCT", "0.5")
|
|
|
|
# --- MTF 합성·정렬 ---
|
|
ALIGN_RSI_OVERSOLD = _getenv_float("ALIGN_RSI_OVERSOLD", "35")
|
|
ALIGN_RSI_OVERBOUGHT = _getenv_float("ALIGN_RSI_OVERBOUGHT", "65")
|
|
ALIGN_RSI_CONFLICT_TIMING_LOW = _getenv_float("ALIGN_RSI_CONFLICT_TIMING_LOW", "40")
|
|
ALIGN_RSI_CONFLICT_TIMING_HIGH = _getenv_float("ALIGN_RSI_CONFLICT_TIMING_HIGH", "65")
|
|
ALIGN_RSI_CONFLICT_TREND_LOW = _getenv_float("ALIGN_RSI_CONFLICT_TREND_LOW", "40")
|
|
ALIGN_RSI_CONFLICT_TREND_HIGH = _getenv_float("ALIGN_RSI_CONFLICT_TREND_HIGH", "65")
|
|
ALIGN_BB_POS_LOW = _getenv_float("ALIGN_BB_POS_LOW", "0.2")
|
|
ALIGN_BB_POS_HIGH = _getenv_float("ALIGN_BB_POS_HIGH", "0.8")
|
|
|
|
# --- 다운로드 / DB ---
|
|
DOWNLOAD_MONTHS = _getenv_int("DOWNLOAD_MONTHS", "12")
|
|
INCREMENTAL_OVERLAP_BARS = _getenv_int("INCREMENTAL_OVERLAP_BARS", "3")
|
|
DOWNLOAD_BACKFILL_EXTRA_BARS = _getenv_int("DOWNLOAD_BACKFILL_EXTRA_BARS", "200")
|
|
DOWNLOAD_MIN_INCREMENTAL_BARS = _getenv_int("DOWNLOAD_MIN_INCREMENTAL_BARS", "50")
|
|
DOWNLOAD_DAILY_EXTRA_DAYS = _getenv_int("DOWNLOAD_DAILY_EXTRA_DAYS", "20")
|
|
# 05/06 시작 시 누락·지연 봉 자동 증분 (01_download와 동일 저장)
|
|
OPS_SYNC_ON_START = _getenv("OPS_SYNC_ON_START", "1").strip().lower() in (
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
)
|
|
OPS_SYNC_MAX_LAG_BARS = _getenv_int("OPS_SYNC_MAX_LAG_BARS", "2")
|
|
DB_READ_LIMIT_DEFAULT = _getenv_int("DB_READ_LIMIT_DEFAULT", "7000")
|
|
DB_ROW_WARMUP_BARS = _getenv_int("DB_ROW_WARMUP_BARS", "200")
|
|
DB_ROW_MIN_DAILY_BARS = _getenv_int("DB_ROW_MIN_DAILY_BARS", "100")
|
|
DB_ROW_DAILY_PADDING_DAYS = _getenv_int("DB_ROW_DAILY_PADDING_DAYS", "30")
|
|
|
|
|
|
def _paths():
|
|
from deepcoin.paths import (
|
|
ANALYSIS_CAPABILITY_HTML,
|
|
ANALYSIS_LATEST_DIR,
|
|
ANALYSIS_REPORT_HTML,
|
|
ANALYSIS_TRADES_CSV,
|
|
resolve_db_path,
|
|
resolve_ground_truth_file,
|
|
)
|
|
|
|
return (
|
|
resolve_db_path(),
|
|
resolve_ground_truth_file(),
|
|
ANALYSIS_TRADES_CSV,
|
|
ANALYSIS_REPORT_HTML,
|
|
ANALYSIS_CAPABILITY_HTML,
|
|
ANALYSIS_LATEST_DIR,
|
|
)
|
|
|
|
|
|
_db, _gt, _a_csv, _a_html, _a_cap, _a_latest = _paths()
|
|
DB_PATH = _getenv("DB_PATH", str(_db))
|
|
GROUND_TRUTH_PATH = _gt
|
|
REPORTS_ANALYSIS_TRADES_CSV = _a_csv
|
|
REPORTS_ANALYSIS_REPORT_HTML = _a_html
|
|
REPORTS_ANALYSIS_CAPABILITY_HTML = _a_cap
|
|
REPORTS_ANALYSIS_LATEST_DIR = _a_latest
|
|
GROUND_TRUTH_FILE = _getenv("GROUND_TRUTH_FILE", str(_gt))
|
|
|
|
# --- 차트 ---
|
|
CHART_LOOKBACK_DAYS = _getenv_int("CHART_LOOKBACK_DAYS", "365")
|
|
GT_UNLIMITED_CHRONOLOGICAL_DAYS = _getenv_int("GT_UNLIMITED_CHRONOLOGICAL_DAYS", "300")
|
|
|
|
# --- Ground Truth ---
|
|
GT_MIN_SWING_PCT = _getenv_float("GT_MIN_SWING_PCT", "4.0")
|
|
GT_PIVOT_ORDER = _getenv_int("GT_PIVOT_ORDER", "20")
|
|
GT_MIN_BARS_BETWEEN = _getenv_int("GT_MIN_BARS_BETWEEN", "30")
|
|
GT_MAX_ROUND_TRIPS = _getenv_int("GT_MAX_ROUND_TRIPS", "24")
|
|
GT_SELECTION_MODE = _getenv("GT_SELECTION_MODE", "split_buy_peak_sell")
|
|
GT_MIN_LEG_PCT = _getenv_float("GT_MIN_LEG_PCT", "8.0")
|
|
GT_BUY_MIN_SWING_PCT = _getenv_float("GT_BUY_MIN_SWING_PCT", "3.0")
|
|
GT_BUY_BB_MAX = _getenv_float("GT_BUY_BB_MAX", "0.45")
|
|
GT_BUY_MIN_BARS = _getenv_int("GT_BUY_MIN_BARS", "24")
|
|
GT_MAX_BUYS_PER_LEG = _getenv_int("GT_MAX_BUYS_PER_LEG", "12")
|
|
GT_MAX_SELLS_PER_LEG = _getenv_int("GT_MAX_SELLS_PER_LEG", "2")
|
|
GT_SELL_SPLIT_GAP_PCT = _getenv_float("GT_SELL_SPLIT_GAP_PCT", "2.5")
|
|
GT_SELL_SPLIT_WEIGHTS: tuple[float, ...] = tuple(
|
|
float(x.strip())
|
|
for x in _getenv("GT_SELL_SPLIT_WEIGHTS", "0.65,0.35").split(",")
|
|
if x.strip()
|
|
) or (0.65, 0.35)
|
|
GT_BUY_WEIGHT_RULE = _getenv("GT_BUY_WEIGHT_RULE", "inverse_price_normalized")
|
|
GT_MARKER_SIZE_MIN = _getenv_int("GT_MARKER_SIZE_MIN", "10")
|
|
GT_MARKER_SIZE_MAX = _getenv_int("GT_MARKER_SIZE_MAX", "32")
|
|
GT_INITIAL_CASH_KRW = _getenv_int("GT_INITIAL_CASH_KRW", "400000")
|
|
GT_MIN_ORDER_KRW = _getenv_int("GT_MIN_ORDER_KRW", "5000")
|
|
GT_BUY_PCT_LARGE_LEG = _getenv_float("GT_BUY_PCT_LARGE_LEG", "1.0")
|
|
GT_BUY_PCT_SMALL_LEG = _getenv_float("GT_BUY_PCT_SMALL_LEG", "0.05")
|
|
GT_LARGE_LEG_TOP_PCT = _getenv_float("GT_LARGE_LEG_TOP_PCT", "0.2")
|
|
# 시뮬·스캔: 1=인과적 신호·tier (미래 데이터 미사용, 운영 정합)
|
|
GT_SIGNAL_CAUSAL = _getenv("GT_SIGNAL_CAUSAL", "1").strip().lower() in (
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
)
|
|
SIM_CAUSAL_TIER = _getenv("SIM_CAUSAL_TIER", "1").strip().lower() in (
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
)
|
|
# 인과 GT leg 엔진 (Option C +300% 경로)
|
|
CAUSAL_GT_PEAK_MODE = _getenv("CAUSAL_GT_PEAK_MODE", "local").strip().lower()
|
|
if CAUSAL_GT_PEAK_MODE not in ("local", "zigzag"):
|
|
CAUSAL_GT_PEAK_MODE = "local"
|
|
CAUSAL_GT_MIN_LEG_PCT = _getenv_float("CAUSAL_GT_MIN_LEG_PCT", "5.0")
|
|
CAUSAL_GT_MIN_BARS_BETWEEN_LEGS = _getenv_int("CAUSAL_GT_MIN_BARS_BETWEEN_LEGS", "60")
|
|
CAUSAL_GT_USE_LOCAL_TROUGH = _getenv("CAUSAL_GT_USE_LOCAL_TROUGH", "1").strip().lower() in (
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
)
|
|
CAUSAL_GT_DD_LARGE_PCT = _getenv_float("CAUSAL_GT_DD_LARGE_PCT", "8.0")
|
|
CAUSAL_GT_DD_MEDIUM_PCT = _getenv_float("CAUSAL_GT_DD_MEDIUM_PCT", "4.0")
|
|
GT_BUY_PCT_MEDIUM_LEG = _getenv_float("GT_BUY_PCT_MEDIUM_LEG", "0.25")
|
|
SIM_TIER_CONVICTION_DD_PCT = _getenv_float("SIM_TIER_CONVICTION_DD_PCT", "10.0")
|
|
TRADING_FEE_RATE = _getenv_float("TRADING_FEE_RATE", "0.0005")
|
|
|
|
# --- 모니터 / API 수집 ---
|
|
MONITOR_LOOP_SLEEP_SEC = _getenv_int("MONITOR_LOOP_SLEEP_SEC", "180")
|
|
MONITOR_POOL_WORKERS = _getenv_int("MONITOR_POOL_WORKERS", "12")
|
|
MONITOR_DEFAULT_INTERVAL = _getenv_int("MONITOR_DEFAULT_INTERVAL", "60")
|
|
MONITOR_API_RETRIES = _getenv_int("MONITOR_API_RETRIES", "3")
|
|
MONITOR_API_BONG_COUNT = _getenv_int("MONITOR_API_BONG_COUNT", "3000")
|
|
MONITOR_SLEEP_AFTER_REQUEST_SEC = _getenv_float("MONITOR_SLEEP_AFTER_REQUEST_SEC", "0.5")
|
|
MONITOR_SLEEP_RATE_LIMIT_SEC = _getenv_float("MONITOR_SLEEP_RATE_LIMIT_SEC", "5")
|
|
MONITOR_SLEEP_BETWEEN_CHUNKS_SEC = _getenv_float("MONITOR_SLEEP_BETWEEN_CHUNKS_SEC", "0.3")
|
|
MONITOR_API_CHUNK_BARS = _getenv_int("MONITOR_API_CHUNK_BARS", "200")
|
|
MONITOR_MA_WINDOWS: tuple[int, ...] = _parse_int_tuple(
|
|
"MONITOR_MA_WINDOWS", "5,20,40,120,200,240,720,1440"
|
|
)
|
|
MONITOR_NORM_WINDOW = _getenv_int("MONITOR_NORM_WINDOW", "20")
|
|
MONITOR_TELEGRAM_BATCH_SIZE = _getenv_int("MONITOR_TELEGRAM_BATCH_SIZE", "20")
|
|
# 규칙 알림 참고 금액(매수 시 수량=금액/가격). 매도 시에는 보유 수량 우선.
|
|
MONITOR_ALERT_KRW_AMOUNT = _getenv_int("MONITOR_ALERT_KRW_AMOUNT", "40000")
|
|
# 05/06·live_eval API 수집 시 coins.db 증분 INSERT (01_download와 동일 append_data)
|
|
MONITOR_PERSIST_CANDLES = _getenv("MONITOR_PERSIST_CANDLES", "1").strip().lower() in (
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
)
|
|
|
|
# --- general_analysis ---
|
|
GA_COL_PREFIX = _getenv("GA_COL_PREFIX", "ga_")
|
|
LOOKBACK_BARS: dict[int, int] = _parse_interval_map(
|
|
"LOOKBACK_BARS",
|
|
"3:120,5:100,10:80,15:60,30:50,60:40,240:30,1440:60",
|
|
)
|
|
CONTEXT_TAIL_ROWS: dict[int, int] = _parse_interval_map(
|
|
"CONTEXT_TAIL_ROWS",
|
|
"3:6000,5:5000,10:4000,15:3000,30:2000,60:1500,240:800,1440:500",
|
|
)
|
|
GA_DEFAULT_TAIL_EXPORT = _getenv_int("GA_DEFAULT_TAIL_EXPORT", "200")
|
|
GA_PATTERN_TOLERANCE_PCT = _getenv_float("GA_PATTERN_TOLERANCE_PCT", "2.5")
|
|
GA_VP_BINS = _getenv_int("GA_VP_BINS", "30")
|
|
GA_VP_VALUE_AREA_PCT = _getenv_float("GA_VP_VALUE_AREA_PCT", "0.70")
|
|
GA_HV_ROLLING_BARS = _getenv_int("GA_HV_ROLLING_BARS", "20")
|
|
GA_HV_PERCENTILE_WINDOW = _getenv_int("GA_HV_PERCENTILE_WINDOW", "120")
|
|
GA_HV_ANNUALIZE_SQRT = _getenv_float("GA_HV_ANNUALIZE_SQRT", "339.41148133")
|
|
GA_DIVERGENCE_LOOKBACK = _getenv_int("GA_DIVERGENCE_LOOKBACK", "10")
|
|
GA_SMA_PERIODS: tuple[int, ...] = _parse_int_tuple("GA_SMA_PERIODS", "5,20,60,120")
|
|
GA_EMA_SPANS: tuple[int, ...] = _parse_int_tuple("GA_EMA_SPANS", "12,26")
|
|
GA_ATR_PERIOD = _getenv_int("GA_ATR_PERIOD", "14")
|
|
GA_KELTNER_ATR_MULT = _getenv_float("GA_KELTNER_ATR_MULT", "2")
|
|
GA_AO_FAST = _getenv_int("GA_AO_FAST", "5")
|
|
GA_AO_SLOW = _getenv_int("GA_AO_SLOW", "34")
|
|
GA_LINREG_WINDOW = _getenv_int("GA_LINREG_WINDOW", "20")
|
|
GA_ADX_PERIOD = _getenv_int("GA_ADX_PERIOD", "14")
|
|
GA_ADX_TREND_THRESHOLD = _getenv_float("GA_ADX_TREND_THRESHOLD", "25")
|
|
GA_SUPERTREND_ATR_MULT = _getenv_float("GA_SUPERTREND_ATR_MULT", "3")
|
|
GA_VOL_SPIKE_MULT = _getenv_float("GA_VOL_SPIKE_MULT", "1.8")
|
|
GA_VOL_MA_WINDOW = _getenv_int("GA_VOL_MA_WINDOW", "20")
|
|
GA_CCI_PERIOD = _getenv_int("GA_CCI_PERIOD", "20")
|
|
GA_WILLIAMS_PERIOD = _getenv_int("GA_WILLIAMS_PERIOD", "14")
|
|
GA_ROC_PERIOD = _getenv_int("GA_ROC_PERIOD", "10")
|
|
GA_MFI_PERIOD = _getenv_int("GA_MFI_PERIOD", "14")
|
|
GA_CMF_PERIOD = _getenv_int("GA_CMF_PERIOD", "20")
|
|
GA_DONCHIAN_PERIOD = _getenv_int("GA_DONCHIAN_PERIOD", "20")
|
|
GA_BB_SQUEEZE_WINDOW = _getenv_int("GA_BB_SQUEEZE_WINDOW", "50")
|
|
GA_BB_SQUEEZE_QUANTILE = _getenv_float("GA_BB_SQUEEZE_QUANTILE", "0.2")
|
|
GA_PIVOT_ORDER = _getenv_int("GA_PIVOT_ORDER", "3")
|
|
GA_PSAR_AF_START = _getenv_float("GA_PSAR_AF_START", "0.02")
|
|
GA_PSAR_AF_STEP = _getenv_float("GA_PSAR_AF_STEP", "0.02")
|
|
GA_PSAR_AF_MAX = _getenv_float("GA_PSAR_AF_MAX", "0.2")
|
|
|
|
# --- 04 매칭 (GT 프로필 + 전구간 EV) ---
|
|
MATCH_PRIMARY_INTERVAL = _getenv_int("MATCH_PRIMARY_INTERVAL", "3")
|
|
MATCH_GT_TOLERANCE_MIN = _getenv_int("MATCH_GT_TOLERANCE_MIN", "15")
|
|
MATCH_FORWARD_BARS = _getenv_int("MATCH_FORWARD_BARS", "60")
|
|
MATCH_FEE_RATE = _getenv_float("MATCH_FEE_RATE", "0.0005")
|
|
MATCH_MIN_FIRES = _getenv_int("MATCH_MIN_FIRES", "10")
|
|
MATCH_TRAIN_RATIO = _getenv_float("MATCH_TRAIN_RATIO", "0.7")
|
|
MATCH_MAX_RULES_PER_SIDE = _getenv_int("MATCH_MAX_RULES_PER_SIDE", "5")
|
|
MATCH_PROFILE_QUANTILE_LO = _getenv_float("MATCH_PROFILE_QUANTILE_LO", "0.25")
|
|
MATCH_PROFILE_QUANTILE_HI = _getenv_float("MATCH_PROFILE_QUANTILE_HI", "0.75")
|
|
MATCH_MIN_EV_VALID = _getenv_float("MATCH_MIN_EV_VALID", "0.0")
|
|
MATCH_MIN_PROFIT_FACTOR = _getenv_float("MATCH_MIN_PROFIT_FACTOR", "1.0")
|
|
MATCH_MAX_VALID_FIRE_RATE = _getenv_float("MATCH_MAX_VALID_FIRE_RATE", "0.35")
|
|
MATCH_BEST_EFFORT_PER_SIDE = _getenv_int("MATCH_BEST_EFFORT_PER_SIDE", "3")
|
|
MATCH_INCLUDE_WIDE_RULES = _getenv("MATCH_INCLUDE_WIDE_RULES", "0").strip() in (
|
|
"1",
|
|
"true",
|
|
"True",
|
|
"yes",
|
|
)
|
|
MATCH_PROFILE_TIGHT_LO = _getenv_float("MATCH_PROFILE_TIGHT_LO", "0.35")
|
|
MATCH_PROFILE_TIGHT_HI = _getenv_float("MATCH_PROFILE_TIGHT_HI", "0.65")
|
|
MATCH_PROFILE_TOP_PER_TF = _getenv_int("MATCH_PROFILE_TOP_PER_TF", "6")
|
|
MATCH_PROFILE_TOP_GLOBAL = _getenv_int("MATCH_PROFILE_TOP_GLOBAL", "30")
|
|
MATCH_PROFILE_MIN_SEPARATION = _getenv_float("MATCH_PROFILE_MIN_SEPARATION", "0.25")
|
|
MATCH_PROFILE_MIN_SAMPLES = _getenv_int("MATCH_PROFILE_MIN_SAMPLES", "10")
|
|
MATCH_INCLUDE_MTF_CROSS = _getenv("MATCH_INCLUDE_MTF_CROSS", "1").strip() in (
|
|
"1",
|
|
"true",
|
|
"True",
|
|
"yes",
|
|
)
|
|
MATCH_LIVE_LOOKBACK_DAYS = _getenv_int("MATCH_LIVE_LOOKBACK_DAYS", "14")
|
|
MATCH_LIVE_CACHE_SEC = _getenv_int("MATCH_LIVE_CACHE_SEC", "180")
|
|
MATCH_LABEL_MODE = _getenv("MATCH_LABEL_MODE", "leg_gt")
|
|
MATCH_MAX_HOLD_DAYS = _getenv_int("MATCH_MAX_HOLD_DAYS", "45")
|
|
MATCH_INCLUDE_ATOMIC = _getenv("MATCH_INCLUDE_ATOMIC", "0").strip() in (
|
|
"1",
|
|
"true",
|
|
"True",
|
|
"yes",
|
|
)
|
|
MATCH_HOLDOUT_RATIO = _getenv_float("MATCH_HOLDOUT_RATIO", "0.15")
|
|
MATCH_MIN_FIRES_HOLDOUT = _getenv_int("MATCH_MIN_FIRES_HOLDOUT", "5")
|
|
MATCH_MONITOR_MAX_PER_SIDE = _getenv_int("MATCH_MONITOR_MAX_PER_SIDE", "1")
|
|
MONITOR_ALERT_COOLDOWN_MIN = _getenv_int("MONITOR_ALERT_COOLDOWN_MIN", "3")
|
|
MATCH_KIND_PRIORITY: tuple[str, ...] = tuple(
|
|
x.strip()
|
|
for x in _getenv(
|
|
"MATCH_KIND_PRIORITY",
|
|
"mtf_cross,compound_tight,contrast,compound,atomic,wide",
|
|
).split(",")
|
|
if x.strip()
|
|
)
|
|
|
|
# --- Simulation: 시뮬레이션 리포트 ---
|
|
SIM_WALK_FORWARD_MIN_MONTHS = _getenv_int("SIM_WALK_FORWARD_MIN_MONTHS", "3")
|
|
SIM_FEE_STRESS_MULT = _getenv_float("SIM_FEE_STRESS_MULT", "2.0")
|
|
SIM_GO_MIN_HOLDOUT_EV = _getenv_float("SIM_GO_MIN_HOLDOUT_EV", "0.0")
|
|
SIM_GO_MIN_HOLDOUT_PF = _getenv_float("SIM_GO_MIN_HOLDOUT_PF", "1.0")
|
|
SIM_GO_WF_POSITIVE_RATIO = _getenv_float("SIM_GO_WF_POSITIVE_RATIO", "0.5")
|
|
# hybrid DD tier 승격·검증 (Option C +300%)
|
|
SIM_HYBRID_MIN_HOLDOUT_PNL_PCT = _getenv_float("SIM_HYBRID_MIN_HOLDOUT_PNL_PCT", "0.0")
|
|
SIM_HYBRID_MAX_MDD_PCT = _getenv_float("SIM_HYBRID_MAX_MDD_PCT", "30.0")
|
|
SIM_OPTION_C_TARGET_PNL_PCT = _getenv_float("SIM_OPTION_C_TARGET_PNL_PCT", "300.0")
|
|
SIM_OPTION_C_PHASE2_TARGET_PNL_PCT = _getenv_float("SIM_OPTION_C_PHASE2_TARGET_PNL_PCT", "1000.0")
|
|
SIM_OPTION_C_PHASE2_FEE_STRESS_RATIO = _getenv_float("SIM_OPTION_C_PHASE2_FEE_STRESS_RATIO", "0.85")
|
|
SIM_OPTION_C_MIN_GT_CAPTURE = _getenv_float("SIM_OPTION_C_MIN_GT_CAPTURE", "0.23")
|
|
SIM_HYBRID_PORTFOLIO_WF_MIN_RATIO = _getenv_float("SIM_HYBRID_PORTFOLIO_WF_MIN_RATIO", "0.5")
|
|
SIM_PRIMARY_SIZING = _getenv("SIM_PRIMARY_SIZING", "auto").strip().lower()
|
|
if SIM_PRIMARY_SIZING not in ("auto", "hybrid", "causal_tier"):
|
|
SIM_PRIMARY_SIZING = "auto"
|
|
|
|
# --- Operations: 실거래 (LIVE=1, 시뮬 Go·monitor_rules 선행) ---
|
|
LIVE_TRADING_ENABLED = _getenv("LIVE_TRADING_ENABLED", "1").strip() in (
|
|
"1",
|
|
"true",
|
|
"True",
|
|
"yes",
|
|
)
|
|
LIVE_ORDER_KRW = _getenv_int("LIVE_ORDER_KRW", "40000")
|
|
LIVE_BUY_PCT_LARGE = _getenv_float("LIVE_BUY_PCT_LARGE", "1.0")
|
|
LIVE_BUY_PCT_SMALL = _getenv_float("LIVE_BUY_PCT_SMALL", "0.05")
|
|
# 운영 기본: 일한도=초기자금 1배 (GT_INITIAL_CASH_KRW).
|
|
LIVE_DAILY_KRW_MAX = _getenv_int("LIVE_DAILY_KRW_MAX", "400000")
|
|
LIVE_COOLDOWN_MIN = _getenv_int("LIVE_COOLDOWN_MIN", "3")
|
|
LIVE_MAX_TRADES_PER_DAY = _getenv_int("LIVE_MAX_TRADES_PER_DAY", "15")
|
|
LIVE_DAILY_LOSS_LIMIT_KRW = _getenv_int("LIVE_DAILY_LOSS_LIMIT_KRW", "40000")
|
|
LIVE_SLIPPAGE_PCT = _getenv_float("LIVE_SLIPPAGE_PCT", "0.05")
|
|
# 06: fire_outcomes monitor 발화로 hybrid 이력 부트스트랩 (시뮬 sim_causal_hybrid 정합)
|
|
LIVE_HYBRID_BOOTSTRAP_FIRES = _getenv("LIVE_HYBRID_BOOTSTRAP_FIRES", "1").strip() in (
|
|
"1",
|
|
"true",
|
|
"True",
|
|
"yes",
|
|
)
|