feat(model): KAP YTM PD floor integration, expanded 226-var search, ADF fix (AIC->BIC), Model#2 with 6-test diagnostics
- Replace hardcoded DEFAULT_PD_FLOORS with build_complete_pd_floor_table() (KAP bond YTM) - Fix ADF test: autolag='AIC' -> 'BIC' for small sample (N=26) robustness - Expand variable search: 40 -> 226 vars (log/diff/return/lag2), 1.9M combos - Select Model #2: HOUSING_PRICE + CREDIT_SPREAD_LAG1 + CURRENT_ACCOUNT_R - Add 6-test diagnostics table to AR1 sheet (ADF/LB/DW/BP/ARCH/Shapiro) - Add Korean variable names for transformed variables - Generate report v7 with full diagnostics
This commit is contained in:
35
main.py
35
main.py
@@ -103,18 +103,38 @@ def main():
|
||||
tm_source = data_config.get("transition_source", "builtin")
|
||||
tm_dir = data_config.get("transition_dir", None)
|
||||
logger.info(f"전이행렬 로딩 중 (source={tm_source})...")
|
||||
transition_matrices = load_transition_matrices(tm_source, data_dir=tm_dir)
|
||||
transition_matrices_all = load_transition_matrices(tm_source, data_dir=tm_dir)
|
||||
# 2000-2025 필터
|
||||
transition_matrices_raw = {y:m for y,m in transition_matrices_all.items() if 2000 <= y <= 2025}
|
||||
|
||||
# PD 플로어 적용: KAP 채권 YTM 기반 시장내재 PD
|
||||
from data.pd_floor import apply_pd_floor_to_matrices, build_complete_pd_floor_table
|
||||
pd_floors_broad, _, pd_floors_full = build_complete_pd_floor_table()
|
||||
transition_matrices = apply_pd_floor_to_matrices(transition_matrices_raw, pd_floors_broad)
|
||||
|
||||
ttc_matrix = compute_ttc_matrix(transition_matrices)
|
||||
default_rates = get_default_rates(transition_matrices)
|
||||
|
||||
print(f"\n 전이행렬: {len(transition_matrices)}개 연도 ({min(transition_matrices.keys())}~{max(transition_matrices.keys())})"
|
||||
f" [source={tm_source}]")
|
||||
print(display_matrix(ttc_matrix, "TTC 전이행렬 (장기 평균)"))
|
||||
print(f" PD 플로어 (KAP 채권 YTM 기반): AAA={pd_floors_broad['AAA']*10000:.0f}bp, AA={pd_floors_broad['AA']*10000:.0f}bp, "
|
||||
f"A={pd_floors_broad['A']*10000:.0f}bp, BBB={pd_floors_broad['BBB']*10000:.0f}bp")
|
||||
print(display_matrix(ttc_matrix, "TTC 전이행렬 (KAP PD Floor 적용 후 장기 평균)"))
|
||||
|
||||
# 거시경제변수
|
||||
if args.no_api:
|
||||
logger.info("Fallback 거시경제 데이터 사용")
|
||||
macro_data = _fallback_macro_data()
|
||||
# ECOS fallback 데이터도 병합 (37개 변수)
|
||||
try:
|
||||
from data.ecos_fetcher import load_macro_data as load_ecos_macro
|
||||
ecos_data = load_ecos_macro()
|
||||
if ecos_data is not None and not ecos_data.empty:
|
||||
macro_data = pd.concat([macro_data, ecos_data], axis=1)
|
||||
macro_data = macro_data.loc[:, ~macro_data.columns.duplicated()]
|
||||
logger.info(f"ECOS fallback 병합 완료: {len(macro_data.columns)}개 변수")
|
||||
except Exception as e:
|
||||
logger.warning(f"ECOS fallback 병합 실패: {e}")
|
||||
else:
|
||||
macro_data = load_macro_data(args.config)
|
||||
|
||||
@@ -167,10 +187,19 @@ def main():
|
||||
model_input = macro_data
|
||||
|
||||
forced_vars = config.get("model", {}).get("macro_vars", None)
|
||||
macro_model = build_macro_zt_model(zt_dict, model_input, method="stepwise_aic",
|
||||
macro_method = config.get("model", {}).get("macro_method", "ar1_macro")
|
||||
macro_model = build_macro_zt_model(zt_dict, model_input, method=macro_method,
|
||||
forced_vars=forced_vars)
|
||||
|
||||
print(f"\n 선택된 변수: {macro_model.selected_vars}")
|
||||
if macro_model.is_ar1:
|
||||
import math
|
||||
phi = macro_model.ar1_phi
|
||||
half_life = math.log(2) / abs(math.log(abs(phi))) if 0 < abs(phi) < 1 else float('inf')
|
||||
print(f" [AR(1)+Macro] φ = {phi:.4f} (반감기 = {half_life:.1f}년)")
|
||||
print(f" c = {macro_model.ar1_const:.4f}")
|
||||
for var, beta in macro_model.ar1_beta.items():
|
||||
print(f" β({var}) = {beta:+.6f}")
|
||||
print(macro_model.summary())
|
||||
|
||||
diag = macro_model.diagnostics()
|
||||
|
||||
Reference in New Issue
Block a user