Files
edf/docs/technical_methodology.md

27 KiB
Raw Permalink Blame History

주식 변동성 기반 등급별 부도율 산출 — 기술 문서

프로젝트: KRX 상장 한국 기업 대상 Equity Volatility → Default Rate by Rating
작성일: 2026-03-11
버전: v0.1 (초안)


목차

  1. 이론적 기초
  2. 핵심 수학적 프레임워크
  3. 한국 시장 등급 관측 문제 및 대안
  4. 글로벌 접근 방법론 비교
  5. 구현 아키텍처
  6. 데이터 명세
  7. 알고리즘 상세
  8. 검증 방법론
  9. 한국 시장 특수 고려사항
  10. 기술 스택 및 의존성
  11. 참고 문헌

1. 이론적 기초

1.1 구조적 모형(Structural Model) 계보

Black-Scholes (1973)
    └─ Merton (1974) ─── 기업부도를 옵션으로 해석
         ├─ Black-Cox (1976) ─── First Passage Time (배리어 부도)
         ├─ Geske (1977) ─── 복합옵션 (쿠폰부 부채)
         ├─ Longstaff-Schwartz (1995) ─── 확률적 이자율
         └─ KMV (Kealhofer-McQuown-Vasicek)
              └─ Moody's Analytics EDF™ ─── 상용화

1.2 Merton 모형 (1974)

핵심 가정:

  • 기업의 자산가치 V(t)는 기하 브라운 운동(GBM)을 따름
  • 부채는 만기 T에 원금 D가 일시 상환되는 제로쿠폰 채권
  • 자기자본 E는 자산 V에 대한 유럽형 콜옵션

자산 역학:

dV = μ·V·dt + σ_V·V·dW
  • μ: 자산 기대수익률 (drift)
  • σ_V: 자산 변동성
  • W: 위너 과정

부도 조건:

Default ⟺ V(T) < D    (만기 시점에 자산가치 < 부채)

자기자본의 옵션 해석:

E = Call(V, D, T) = V·N(d₁) - D·e^{-rT}·N(d₂)

1.3 KMV-Moody's EDF 모형

Merton 모형의 실무 확장:

구분 Merton 원형 KMV 수정
부도점 D (총부채) STD + 0.5×LTD
부도 시점 만기 T 시점만 임의 시점 (First Passage)
EDF 산출 N(-DD) 이론값 경험적 부도 빈도 매핑
데이터 단일 시점 시계열 반복 추정

1.4 축약형 모형(Reduced-Form Model)

CreditRisk+ (Credit Suisse)

  • 부도를 포아송 과정으로 모형화
  • 부도율의 변동성을 명시적 반영 (부도율 자체가 확률변수)
  • 섹터별 체계적 요인으로 부도 상관관계 간접 포착
  • 장점: 구현 용이, 대규모 포트폴리오 적합
  • 한계: 시장 데이터 반영 제한, 등급전이 미반영

Jarrow-Turnbull / Duffie-Singleton

  • 부도 강도(hazard rate)가 시장 변수에 의존
  • CDS/채권 스프레드에서 내재 부도확률 추출
  • 한국 적용 한계: CDS 시장 유동성 부족

1.5 CreditMetrics 접근법

  • 등급전이행렬(Rating Transition Matrix) 기반
  • 잠재 변수 Zt를 통해 체계적 리스크 반영
  • 전이확률 × 등급별 스프레드 → 포트폴리오 가치 분포
  • 한국 시장: 신평사 발표 전이행렬과 연동 가능

2. 핵심 수학적 프레임워크

2.1 Merton 연립방정식

관측 가능한 (E, σ_E)로부터 비관측 (V, σ_V)를 추정:

방정식 1 — 자기자본 가치:

E = V·N(d₁) - D·e^{-rT}·N(d₂)

방정식 2 — 변동성 관계 (Itô's Lemma):

σ_E = (V/E)·N(d₁)·σ_V

여기서:

d₁ = [ln(V/D) + (r + σ²_V/2)·T] / (σ_V·√T)
d₂ = d₁ - σ_V·√T

2.2 Distance-to-Default (DD)

DD = [ln(V/DP) + (μ - σ²_V/2)·T] / (σ_V·√T)
  • DP = STD + 0.5 × LTD (KMV 부도점)
  • μ: 자산 기대수익률 (실무에서는 r 또는 과거 추정값 사용)

해석: DD는 자산가치가 부도점까지 하락하는 데 필요한 표준편차 수

2.3 EDF 산출

이론적 EDF (정규분포 가정):

EDF_theoretical = N(-DD) = Φ(-DD)

경험적 EDF (KMV 방식):

EDF_empirical = (DD 구간별 실제 부도 기업 수) / (DD 구간별 전체 기업 수)

한국 시장 보정 EDF:

EDF_KR = EDF_theoretical × Calibration_Factor(rating_grade)

2.4 주가 변동성 추정 방법

(a) 역사적 변동성 (Historical Volatility)

σ_E = √(252) × std(ln(P_t / P_{t-1}))
  • 일별 로그수익률의 표준편차 × √252 (연환산)
  • 추정 윈도우: 1년 (약 250 거래일)

(b) EWMA (Exponentially Weighted Moving Average)

σ²_t = λ·σ²_{t-1} + (1-λ)·r²_{t-1}
  • λ = 0.94 (RiskMetrics 표준)
  • 최근 변동에 더 높은 가중치

(c) GARCH(1,1)

σ²_t = ω + α·ε²_{t-1} + β·σ²_{t-1}
  • ω, α, β: 최대우도추정(MLE)으로 산출
  • α + β < 1 (정상성 조건)
  • 변동성 클러스터링 반영 가능

3. 한국 시장 등급 관측 문제 및 대안

3.1 문제 진단

KRX 상장사 약 2,500개
├── 신용등급 보유: 약 500~600개 (주로 회사채/CP 발행사)
│   ├── 관측 가능 등급: BBB ~ A 중심 (약 70%)
│   ├── 고등급 (AAA~AA): 소수 (우량사, 등급 불필요)
│   └── 저등급 (B 이하): 극소수 (상장 유지 자체가 어려움)
└── 신용등급 미보유: 약 1,900개 (소형주, 미발행사)

등급별 관측 분포 추정:

등급군 KRX 상장사 중 비율 부도 관측 가능성 주요 이슈
AAA~AA ~5% 극히 낮음 부도 사례 거의 0
A ~20% 낮음 부도 희소하나 관측 가능
BBB ~40% 보통 가장 관측 풍부
BB ~20% 높음 투기등급 진입, 데이터 확보
B 이하 ~5% 높으나 표본 부족 상장폐지와 혼재
무등급 ~10% (등급보유 대비) Shadow 필요 대부분 소형주

3.2 대안 전략 상세

대안 1: Shadow Rating (내재등급) 모형

목적: DD 및 재무비율을 기반으로 무등급 기업에 내재등급 부여

방법론 — Ordered Probit 모형:

y* = β'X + ε,   ε ~ N(0, 1)

y = k  if  τ_{k-1} < y* ≤ τ_k

여기서:
- y: 관측등급 (AAA=1, AA+=2, ..., D=n)
- X: [DD, log(총자산), 부채비율, 이자보상비율, EBITDA마진, ROA, 유동비율, 산업더미]
- τ_k: 등급 경계 절단점(cutoff)

학습 과정:

  1. 등급 보유 기업의 (X, y) 쌍으로 β, τ를 MLE 추정
  2. 등급 미보유 기업에 추정된 β'X를 적용하여 각 등급 확률 계산
  3. 최대 확률 등급을 Shadow Rating으로 부여

설명변수 후보:

변수 정의 기대 부호
DD Distance-to-Default + (높을수록 고등급)
log_assets ln(총자산) + 규모 효과
leverage 총부채/총자산 -
int_coverage EBITDA/이자비용 +
ebitda_margin EBITDA/매출 +
roa 순이익/총자산 +
current_ratio 유동자산/유동부채 +
cash_ratio 현금/유동부채 +
industry 산업 더미 산업별 상이

대안 2: DD-Rating 직접 매핑

글로벌 벤치마크를 기반으로 DD 구간 → 등급 매핑:

DD 범위 Moody's 등급 한국 등급 (추정) 이론적 EDF
> 6.0 Aaa ~ Aa1 AAA ~ AA+ < 0.02%
5.0 ~ 6.0 Aa2 ~ Aa3 AA ~ AA- 0.02% ~ 0.05%
4.0 ~ 5.0 A1 ~ A3 A+ ~ A- 0.05% ~ 0.20%
3.0 ~ 4.0 Baa1 ~ Baa2 BBB+ ~ BBB 0.20% ~ 0.70%
2.5 ~ 3.0 Baa3 BBB- 0.70% ~ 1.50%
2.0 ~ 2.5 Ba1 BB+ 1.50% ~ 3.00%
1.5 ~ 2.0 Ba2 ~ Ba3 BB ~ BB- 3.00% ~ 5.00%
1.0 ~ 1.5 B1 ~ B2 B+ ~ B 5.00% ~ 10.00%
0.5 ~ 1.0 B3 ~ Caa1 B- ~ CCC+ 10.00% ~ 20.00%
< 0.5 Caa2 이하 CCC 이하 > 20.00%

주의: 글로벌 매핑은 한국 시장에 직접 적용 시 보정(calibration) 필수

대안 3: 등급군 병합(Grade Pooling)

표본 부족 등급을 인접 등급과 통합:

Pool 1: AAA + AA+ + AA + AA- → "최우량군"    (Super-Prime)
Pool 2: A+ + A + A-           → "우량군"      (Prime)
Pool 3: BBB+ + BBB + BBB-     → "투자적격군"  (Investment)
Pool 4: BB+ + BB + BB-        → "투기등급군"  (Speculative)
Pool 5: B+ 이하               → "고위험군"    (High-Risk)

병합 기준:

  • 각 풀 내 최소 관측수: 30개 이상 (통계적 유의성)
  • Hosmer-Lemeshow 검정 등으로 풀 내 균질성 확인

대안 4: 글로벌 데이터 블렌딩

한국 데이터와 글로벌 벤치마크를 표본수 기반 가중 혼합:

DR_blended(g) = w(g) × DR_KR(g) + [1 - w(g)] × DR_Global(g)

w(g) = min(1, N_KR(g) / N_threshold)
  • DR_KR(g): 한국 등급 g의 관측 부도율
  • DR_Global(g): Moody's/S&P 등급 g의 글로벌 부도율
  • N_KR(g): 한국 등급 g의 관측 표본수
  • N_threshold: 신뢰도 임계치 (예: 50)

대안 5: 베이지안 보정

사전분포(Prior):     π(θ_g) ~ Beta(α_0, β_0)    ← 글로벌 부도율에서 유도
우도(Likelihood):    L(data|θ_g) = θ_g^d × (1-θ_g)^{n-d}
사후분포(Posterior): π(θ_g|data) ~ Beta(α_0 + d, β_0 + n - d)

여기서:
- θ_g: 등급 g의 실제 부도율 (추정 대상)
- d: 한국 등급 g에서 관측된 부도 건수
- n: 한국 등급 g에서 관측된 전체 기업수
- α_0, β_0: 글로벌 데이터에서 유도된 사전 파라미터

장점: 표본 부족 등급에서 글로벌 Prior에 자연스럽게 의존, 표본 충분 등급에서는 한국 데이터 위주로 수렴


4. 글로벌 접근 방법론 비교

방법론 모형 유형 핵심 입력 장점 한계 한국 적용성
Merton-KMV 구조적 주가, 부채 시장기반, 전향적 상장사 한정, 분포가정 ★★★★★
CreditMetrics 전이행렬 등급전이, 스프레드 포트폴리오 리스크 등급 의존적 ★★★☆☆
CreditRisk+ 축약형 부도율, 변동성 구현 용이 시장 미반영 ★★☆☆☆
Jarrow-Turnbull 축약형 CDS스프레드 시장가격 반영 CDS시장 미발달 ★★☆☆☆
Altman Z-Score 판별분석 재무비율 간단, 검증됨 시장변동 미반영 ★★★☆☆
ML (XGBoost) 비모수 다양한 데이터 유연, 비선형 해석부족, 과적합 ★★★☆☆
Bharath-Shumway 구조적(간편) 주가, 부채 단순 구현 정밀도 한계 ★★★★☆

Bharath-Shumway 간편 DD (Naïve DD)

반복 추정 없이 직접 DD 계산 (실무 빠른 적용용):

V_naive = E + D
σ_V_naive = (E/(E+D)) × σ_E + (D/(E+D)) × (0.05 + 0.25×σ_E)
DD_naive = [ln(V_naive/D) + (μ - σ²_V_naive/2)×T] / (σ_V_naive × √T)
  • Bharath & Shumway (2008) 연구에서 반복추정 DD와 유사한 부도예측력 보고
  • 대규모 데이터 처리 시 1차 필터로 유용

5. 구현 아키텍처

5.1 시스템 구조

EDF/
├── config/
│   ├── settings.yaml          # 전역 설정 (기간, 파라미터)
│   └── rating_mapping.yaml    # DD-등급 매핑 테이블
├── data/
│   ├── raw/                   # 원본 데이터
│   ├── processed/             # 전처리된 데이터
│   └── external/              # 글로벌 부도율 통계
├── src/
│   ├── data/
│   │   ├── krx_fetcher.py     # KRX 주가 수집
│   │   ├── dart_fetcher.py    # DART 재무제표 수집
│   │   ├── rating_fetcher.py  # 신용등급 수집
│   │   └── preprocessor.py    # 데이터 전처리
│   ├── models/
│   │   ├── merton.py          # Merton 연립방정식 풀이
│   │   ├── dd_calculator.py   # DD/EDF 산출
│   │   ├── shadow_rating.py   # Shadow Rating 모형
│   │   └── volatility.py      # 변동성 추정 (Historical/EWMA/GARCH)
│   ├── calibration/
│   │   ├── global_benchmark.py  # 글로벌 벤치마크 로딩
│   │   ├── blending.py          # 블렌딩/베이지안 보정
│   │   └── grade_pooling.py     # 등급군 병합
│   ├── validation/
│   │   ├── backtesting.py     # 백테스팅
│   │   ├── discriminatory.py  # 변별력 검증 (ROC, KS, CAP)
│   │   └── calibration_test.py # 보정력 검증 (Hosmer-Lemeshow)
│   └── utils/
│       ├── financial.py       # 재무비율 계산
│       └── statistics.py      # 통계 유틸리티
├── notebooks/
│   ├── 01_data_exploration.ipynb
│   ├── 02_merton_analysis.ipynb
│   ├── 03_shadow_rating.ipynb
│   └── 04_default_rate_output.ipynb
├── outputs/
│   ├── dd_results/            # DD/EDF 산출 결과
│   ├── rating_results/        # 등급별 부도율 결과
│   └── reports/               # 검증 보고서
├── docs/
│   └── technical_methodology.md  # 이 문서
├── requirements.txt
└── README.md

5.2 처리 파이프라인

[Phase 1: 데이터 수집]
    KRX 주가 → 전처리 → 주가변동성 산출
    DART 재무제표 → 부채 구조(STD/LTD) 추출
    신평사 등급 → 연도별 등급 스냅샷

[Phase 2: Merton-KMV 모형]
    (E, σ_E, D, r, T) → 반복 추정 → (V, σ_V) → DP → DD → EDF

[Phase 3: Shadow Rating]
    등급 보유 기업: (DD, 재무비율) ↔ 등급 매핑 학습
    등급 미보유 기업: 학습 모형 → Shadow Rating 부여

[Phase 4: 등급별 부도율 집계]
    실제등급 + Shadow Rating → 등급별 연간 부도율 집계
    표본 부족 등급 → 글로벌 블렌딩 / 등급군 병합

[Phase 5: 검증]
    백테스팅, 변별력/보정력 검증, CRA 발표 데이터 비교

6. 데이터 명세

6.1 필수 데이터

데이터 항목 소스 수집 주기 필수/선택
일별 종가 KRX / pykrx 일별 필수
시가총액 KRX / pykrx 일별 필수
발행주식수 KRX / DART 분기 필수
유동부채 (STD) DART 재무제표 분기/연간 필수
비유동부채 (LTD) DART 재무제표 분기/연간 필수
총자산 DART 재무제표 분기/연간 필수
신용등급 한기평/한신평/나이스 연간 스냅샷 필수
무위험이자율 한국은행(ECOS) 일별 필수
부도/워크아웃 이력 KRX 상장폐지, 뉴스 사건 기반 필수

6.2 보조 데이터 (Shadow Rating 강화용)

데이터 항목 소스 용도
EBITDA DART 이자보상비율, 마진
이자비용 DART 이자보상비율
매출액 DART EBITDA 마진
현금 및 현금성 자산 DART 유동성 비율
산업분류코드 (KSIC) KRX / DART 산업 더미 변수
거래량 KRX 유동성 필터링

6.3 글로벌 벤치마크 데이터

데이터 소스 내용
등급별 연간 부도율 Moody's Annual Default Study Aaa~C 20년+ 평균
등급별 누적 부도율 S&P Global Default Study AAAD 120년
한국 등급별 부도율 한기평/한신평/나이스 연간 발표 국내 기준

6.4 부도(Default) 정의

다음 이벤트 중 하나 이상 발생 시 "부도"로 정의:

1. 법정관리(회생절차) 개시 결정
2. 워크아웃(채권단 자율협약) 개시
3. 상장폐지 (재무 사유: 자본잠식, 감사의견 거절 등)
4. 부도어음/부도수표 발생
5. 기업회생절차 신청
6. 파산 선고

※ 제외: 합병·분할·자진 상장폐지 등 비재무적 사유

7. 알고리즘 상세

7.1 Merton 연립방정식 풀이

import numpy as np
from scipy.optimize import fsolve
from scipy.stats import norm

def solve_merton(E: float, sigma_E: float, D: float, 
                  r: float, T: float = 1.0) -> tuple[float, float]:
    """
    Merton 연립방정식을 풀어 자산가치(V)와 자산변동성(σ_V)을 추정.
    
    Parameters
    ----------
    E : float
        자기자본 시장가치 (시가총액, 억원)
    sigma_E : float
        주가수익률 변동성 (연환산, 예: 0.30 = 30%)
    D : float
        부도점 = STD + 0.5 × LTD (억원)
    r : float
        무위험이자율 (연, 예: 0.035 = 3.5%)
    T : float
        시간 수평선 (년, 기본 1.0)
    
    Returns
    -------
    V : float
        추정 자산가치 (억원)
    sigma_V : float
        추정 자산변동성 (연환산)
    """
    def equations(params):
        V, sigma_V = params
        d1 = (np.log(V / D) + (r + 0.5 * sigma_V**2) * T) / (sigma_V * np.sqrt(T))
        d2 = d1 - sigma_V * np.sqrt(T)
        
        eq1 = V * norm.cdf(d1) - D * np.exp(-r * T) * norm.cdf(d2) - E
        eq2 = (V / E) * norm.cdf(d1) * sigma_V - sigma_E
        return [eq1, eq2]
    
    # 초기값: V0 = E + D, sigma_V0 = sigma_E * E / (E + D)
    V0 = E + D
    sigma_V0 = sigma_E * E / (E + D)
    
    solution = fsolve(equations, [V0, sigma_V0], full_output=True)
    V, sigma_V = solution[0]
    
    return max(V, E), max(sigma_V, 0.01)  # 하한 설정


def calculate_dd(V: float, sigma_V: float, D: float,
                  mu: float, T: float = 1.0) -> float:
    """Distance-to-Default 산출"""
    if D <= 0 or V <= 0 or sigma_V <= 0:
        return np.nan
    DD = (np.log(V / D) + (mu - 0.5 * sigma_V**2) * T) / (sigma_V * np.sqrt(T))
    return DD


def calculate_edf(DD: float) -> float:
    """이론적 EDF 산출 (정규분포 가정)"""
    if np.isnan(DD):
        return np.nan
    return norm.cdf(-DD)

7.2 변동성 추정

def historical_volatility(prices: np.ndarray, window: int = 252) -> float:
    """역사적 변동성 (연환산)"""
    log_returns = np.diff(np.log(prices))
    if len(log_returns) < window:
        window = len(log_returns)
    return np.std(log_returns[-window:]) * np.sqrt(252)


def ewma_volatility(prices: np.ndarray, lmbda: float = 0.94) -> float:
    """EWMA 변동성 (연환산)"""
    log_returns = np.diff(np.log(prices))
    variance = log_returns[0]**2
    for ret in log_returns[1:]:
        variance = lmbda * variance + (1 - lmbda) * ret**2
    return np.sqrt(variance * 252)


def garch_volatility(prices: np.ndarray) -> float:
    """GARCH(1,1) 변동성 (arch 패키지 사용)"""
    from arch import arch_model
    log_returns = np.diff(np.log(prices)) * 100  # 백분율
    model = arch_model(log_returns, vol='Garch', p=1, q=1, dist='normal')
    result = model.fit(disp='off')
    # 최신 조건부 변동성을 연환산
    cond_vol = result.conditional_volatility[-1] / 100
    return cond_vol * np.sqrt(252)

7.3 Shadow Rating (Ordered Probit)

import statsmodels.api as sm
import pandas as pd

def fit_shadow_rating_model(df_rated: pd.DataFrame, 
                              feature_cols: list,
                              rating_col: str = 'rating_numeric') -> object:
    """
    등급 보유 기업 데이터로 Ordered Probit 모형 적합.
    
    Parameters
    ----------
    df_rated : pd.DataFrame
        등급 보유 기업 데이터 (DD, 재무비율, 등급 포함)
    feature_cols : list
        설명변수 컬럼명 리스트
    rating_col : str
        등급 숫자 컬럼 (1=AAA, 2=AA+, ...)
    """
    X = df_rated[feature_cols]
    y = df_rated[rating_col]
    
    model = sm.OrderedModel(y, X, distr='probit')
    result = model.fit(method='bfgs', disp=False)
    
    return result


def predict_shadow_rating(model_result, df_unrated: pd.DataFrame,
                            feature_cols: list) -> pd.DataFrame:
    """등급 미보유 기업에 Shadow Rating 부여"""
    X = df_unrated[feature_cols]
    pred_probs = model_result.predict(X)
    
    # 각 기업의 최대 확률 등급
    df_unrated = df_unrated.copy()
    df_unrated['shadow_rating_numeric'] = pred_probs.values.argmax(axis=1) + 1
    
    return df_unrated

7.4 등급별 부도율 산출 (블렌딩)

def compute_blended_default_rates(df: pd.DataFrame,
                                    rating_col: str,
                                    default_col: str,
                                    global_dr: dict,
                                    threshold: int = 50) -> pd.DataFrame:
    """
    등급별 부도율을 한국 관측 + 글로벌 벤치마크 블렌딩으로 산출.
    
    Parameters
    ----------
    df : pd.DataFrame
        전체 기업 데이터 (등급 + 부도여부 포함)
    rating_col : str
        등급 컬럼명
    default_col : str
        부도 여부 컬럼명 (0/1)
    global_dr : dict
        {등급: 글로벌 부도율} 매핑
    threshold : int
        블렌딩 전환 표본수 임계치
    """
    results = []
    for grade in sorted(df[rating_col].unique()):
        subset = df[df[rating_col] == grade]
        n = len(subset)
        d = subset[default_col].sum()
        kr_dr = d / n if n > 0 else 0
        
        g_dr = global_dr.get(grade, kr_dr)
        w = min(1.0, n / threshold)
        blended = w * kr_dr + (1 - w) * g_dr
        
        results.append({
            'grade': grade,
            'n_firms': n,
            'n_defaults': d,
            'korean_dr': kr_dr,
            'global_dr': g_dr,
            'weight_kr': w,
            'blended_dr': blended
        })
    
    return pd.DataFrame(results)

7.5 베이지안 부도율 추정

from scipy.stats import beta as beta_dist

def bayesian_default_rate(n: int, d: int,
                           prior_mean: float,
                           prior_strength: float = 50) -> dict:
    """
    베이지안 방식 등급별 부도율 추정.
    
    Parameters
    ----------
    n : int
        관측 기업수
    d : int
        부도 건수
    prior_mean : float
        사전 부도율 (글로벌 벤치마크)
    prior_strength : float
        사전 강도 (글로벌 표본수에 비례)
    """
    # Beta prior 파라미터
    alpha_0 = prior_mean * prior_strength
    beta_0 = (1 - prior_mean) * prior_strength
    
    # 사후 분포 (Beta-Binomial conjugacy)
    alpha_post = alpha_0 + d
    beta_post = beta_0 + (n - d)
    
    # 사후 통계량
    posterior_mean = alpha_post / (alpha_post + beta_post)
    posterior_mode = (alpha_post - 1) / (alpha_post + beta_post - 2) \
                     if (alpha_post > 1 and beta_post > 1) else posterior_mean
    ci_lower, ci_upper = beta_dist.ppf([0.025, 0.975], alpha_post, beta_post)
    
    return {
        'posterior_mean': posterior_mean,
        'posterior_mode': posterior_mode,
        'ci_95_lower': ci_lower,
        'ci_95_upper': ci_upper,
        'prior_mean': prior_mean,
        'n_obs': n,
        'n_defaults': d
    }

8. 검증 방법론

8.1 변별력(Discriminatory Power) 검증

지표 설명 기준
AUROC ROC 곡선 하 면적 > 0.70 (수용), > 0.80 (양호)
KS 통계량 부도/비부도 분포 최대 이격 > 0.30 (수용)
CAP/AR 정확도 비율 > 0.50 (수용)
정보값(IV) 변수별 변별 기여도 > 0.10 (유의미)

8.2 보정력(Calibration) 검증

지표 설명
Hosmer-Lemeshow 예측 부도율 vs 실제 부도율 적합도
Binomial Test 등급별 실제 부도율이 예측 구간 내 존재 여부
Traffic Light Basel II 권장 — 녹색/황색/적색 신호

8.3 백테스팅 프로세스

for year in [T-5, T-4, T-3, T-2, T-1]:
    1. year 말 기준 DD/EDF 산출
    2. year+1 동안의 실제 부도 여부 관측
    3. 예측 EDF vs 실현 부도율 비교
    4. 변별력/보정력 지표 산출

8.4 CRA 발표 데이터와 비교

  • 한기평·한신평·나이스 연간 발표 등급별 부도율과 본 모형 산출치 비교
  • 등급별 편차(bias) 및 상관관계 분석
  • 부도 시점 대비 DD 하락 시점의 선행성 분석

9. 한국 시장 특수 고려사항

9.1 데이터 관련

항목 고려사항 대응
KOSPI vs KOSDAQ KOSDAQ 소형·고변동성 기업 다수 시장별 분리 분석 또는 통합+더미
금융업 부채 구조 상이 (예금 = 부채) 분석 제외 또는 별도 모형
등급 불일치 한기평·한신평·나이스 등급 차이 중위값 또는 최빈값 사용
분기 vs 연간 재무제표 시차 분기 데이터 우선, 없으면 연간 보간
상장폐지 부도 vs 비부도 폐지 구분 폐지 사유 코드로 필터링

9.2 구조적 특성

특성 영향 모형 반영 방법
재벌 계열 그룹 지원으로 개별 DD 대비 부도율 하락 계열사 더미 / 그룹 DD 산출
정부 지원 공기업 부도율 ≈ 0 정부지원 등급에서 제외 또는 별도 처리
채권단 자율협약 형식적 부도 회피 워크아웃 개시를 부도 사건에 포함
유상증자/CB 부도 직전 자본 확충으로 DD 왜곡 이벤트 전 DD 사용 또는 플래그

9.3 변동성 추정 주의사항

상황 문제 대응
장기 거래정지 변동성 과소추정 정지 기간 제외, 30일 이상 정지 시 분석 제외
저거래량 비유동성 프리미엄 혼재 거래량 하위 10% 제외 또는 유동성 보정
극단 이벤트 일시적 급등락으로 변동성 왜곡 Winsorization (상하 1%) 또는 트리밍
공매도 제한 하락 변동성 억제 변동성 하향 편의 인지, 글로벌 대비 보정

10. 기술 스택 및 의존성

10.1 Python 패키지

# 핵심 (requirements.txt)
numpy>=1.24
pandas>=2.0
scipy>=1.10
statsmodels>=0.14

# 데이터 수집
pykrx>=1.0          # KRX 주가 데이터
OpenDartReader>=0.3  # DART 전자공시 API

# 변동성 모형
arch>=6.0           # GARCH/EWMA 모형

# 시각화
matplotlib>=3.7
plotly>=5.15
seaborn>=0.12

# 머신러닝 (선택)
scikit-learn>=1.3
xgboost>=2.0

# 유틸리티
tqdm>=4.65
pyyaml>=6.0

10.2 무위험이자율

  • 한국은행 ECOS의 국고채 1년물 금리 사용
  • 또는 통화안정증권(MSB) 1년물

10.3 데이터베이스

  • 개발 단계: SQLite (로컬 파일)
  • 운영 단계: PostgreSQL (필요시)

11. 참고 문헌

핵심 논문

  1. Merton, R.C. (1974). "On the Pricing of Corporate Debt: The Risk Structure of Interest Rates." Journal of Finance, 29(2), 449-470.
  2. Black, F. & Cox, J.C. (1976). "Valuing Corporate Securities: Some Effects of Bond Indenture Provisions." Journal of Finance, 31(2), 351-367.
  3. Bharath, S.T. & Shumway, T. (2008). "Forecasting Default with the Merton Distance to Default Model." Review of Financial Studies, 21(3), 1339-1369.
  4. Crosbie, P. & Bohn, J. (2003). "Modeling Default Risk." Moody's KMV Working Paper.

한국 시장 연구

  1. 한국은행. "IRB 접근법 하에서의 장기 부도확률 추정."
  2. 한국기업평가. "연간 부도율 통계" (korearatings.com)
  3. 한국신용평가. "신용등급별 부도율 및 전이행렬" (kisrating.com)

기술 참고

  1. Credit Suisse Financial Products. (1997). "CreditRisk+: A Credit Risk Management Framework."
  2. JP Morgan. (1997). "CreditMetrics — Technical Document."
  3. Basel Committee on Banking Supervision. "Studies on the Validation of Internal Rating Systems."