1.3 탈퇴와 발생#

이 챕터에서 배우는 것

  • 보험 계약은 매달 서로 다른 두 가지를 따로 본다 — ① 계약에서 빠졌는가 (탈퇴: 사망·해지), ② 보험금 줄 사유가 생겼는가(발생: 사망·진단·입원)

  • 이 둘은 원래 한 몸인데 엔진이 쪼갠 게 아니라 처음부터 다른 개념이라는 것

  • 일반사망보험에서만 두 일이 같은 사망 사건이라 숫자가 겹치고, 같은 숫자라고 같은 개념은 아니라는 것

  • 엔진에서 탈퇴는 mortality_annual·lapse_annual, 발생은 담보 rate가 맡고, 사망은 그 둘이 갈라지는 가장 헷갈리는 자리라는 것

  • 이 구분이 1.4의 “한 번 vs 반복” 청구 메커니즘으로 이어지는 길

보험 계약에서 매달 일어나는 일은 두 종류입니다. 하나는 계약에서 빠지는 일 — 사람이 죽거나 해지하면 그 계약은 보유계약(in-force)에서 사라집니다. 다른 하나는 보험금 줄 사유가 생기는 일 — 사망·암 진단·입원 같은 사건이 보험금 지급을 일으킵니다. 같은 사건이 두 일을 동시에 일으킬 때도, 한쪽만 일으킬 때도 있습니다.

사건

계약에서 빠지는가 (탈퇴)

보험금을 지급하는가 (발생)

해지

상품에 따라 (해지환급금)

보장하는 원인의 사망

보장하지 않는 원인의 사망

아니요

암 진단

아니요

입원

아니요

왼쪽 열이 탈퇴, 오른쪽 열이 발생입니다. 두 열은 독립이라 같은 행에서 ‘예/아니요’가 자유롭게 갈립니다 — 진단·입원은 계약에서 안 빠지고 보험금만 나가고, 보장하지 않는 원인의 사망은 빠지지만 보험금은 안 나갑니다. 보장하는 원인의 사망만 두 열이 모두 ‘예’라, 한 번의 사망 사건이 탈퇴와 지급을 동시에 일으킵니다. 그래서 숫자가 같아질 수 있을 뿐, 두 열은 여전히 다른 개념 입니다.

엔진도 이 두 열을 다른 입력으로 받습니다:

코드 입력

역할

용어

무엇을 하는가

mortality_annual

탈퇴

보유계약 사망률

계약 전체 in-force를 줄임

lapse_annual

탈퇴

해지율

계약 전체 in-force를 줄임

DEATH 담보의 rate

발생

사망보험금 발생률

사망보험금 지급액 계산

DIAGNOSIS 담보의 rate

발생

진단 발생률

진단보험금 + 그 담보의 미진단 풀에서 탈퇴

MORBIDITY 담보의 rate

발생

반복급부 발생률

반복 보험금 (어느 풀도 안 줄임)

핵심 한 줄: 탈퇴율은 누가 계약에 남는가 를, 발생률은 어떤 보험금을 지급하는가 를 계산합니다. 사망은 둘이 겹치는 한 사례일 뿐, 출발점이 같은 양은 아닙니다. 이 챕터는 그 가장 헷갈리는 자리 — 사망의 탈퇴(보유계약 사망률)와 발생(사망보험금 발생률) — 을 갈라 둡니다.

표준 용어로는 — 탈퇴(decrement) vs 발생(incidence)

위 두 열은 다중탈퇴모형(multiple-decrement model)의 교과서 구분 그대로입니다.

  • 탈퇴(decrement) = 계약 전체 in-force에서 빼는 입력. mortality_annual은 표준 용어로 사망탈퇴율(mortality decrement, q_x^(d)) — 연단위 확률이라 이지 (force, μ)이 아니고, 엔진은 inforce x (1 - q)로 축소합니다. lapse_annual은 해지탈퇴율.

  • 발생(incidence) = 보험금 줄 사유의 빈도. 담보의 rate가 그것. 발생은 계약 전체 in-force는 건드리지 않습니다. 다만 담보에 따라 자기 하위 풀은 줄일 수 있어 — DIAGNOSIS는 자기 미진단 풀을 (1 - 발생률)로 축소하고, DEATH·MORBIDITY는 어느 풀도 줄이지 않습니다 (위 표 마지막 열).

엔진 코드도 같은 어휘입니다 — mortality_annual의 docstring은 “in-force decrement”, 전이율은 waiver_incidence_annual / ci_incidence_annual처럼 _incidence 접미사.

1.3.1 탈퇴 — 보유계약 사망률#

엔진의 모든 cash flow는 한 가지 양에 비례합니다 — 그 시점의 보유계약 수 inforce. 그리고 inforce를 매월 줄이는 사망 입력이 보유계약 사망률 (mortality_annual, 곧 사망탈퇴율)입니다.

inforce[t+1] = inforce[t] × (1 - 보유계약사망률_월) × (1 - 해지율_월)

contract당 한 값. 어느 원인으로든 사람이 in-force에서 빠지는 전체 (all-cause) 율입니다. 사람이 죽으면 보험료 납입도 멈추고, 사업비도 멈추고, 만기금도 사라지고, 청구도 더 못 받습니다. 그래서 보유계약 사망률은 엔진 어디서도 비켜갈 수 없는 보편적 감쇠 — 보험료·사업비·만기금, 그리고 모든 보장의 청구가 같은 inforce에 묶여 함께 줄어듭니다.

basis = fcf.Basis(
    mortality_annual = 0.012,  # 보유계약 사망률 (all-cause). 스칼라 / 배열 / 표 / 콜러블 다 가능
    ...
)

워크북에서는 segments 시트의 mortality_table 컬럼이 가리키는 mortality_tables 시트가 이 입력의 출처입니다. 회사별·성별·연령별 all-cause 사망률 테이블 한 장.

이 한 슬롯이 가장 큰 가정입니다 — 보유계약 사망률을 +10% shock하면 거의 모든 cash flow가 함께 흔들립니다.

1.3.2 발생 — 사망보험금 발생률#

보유계약 사망률이 누가 남아 있는가 를 정했다면, 사망보험금의 지급액 을 계산하는 자리는 완전히 따로 있습니다 — 사망보험금 발생률.

생각해보면 그래야 합니다. 사람이 죽는 사건은 보유계약 사망률로 이미 inforce에서 빠지는 효과를 냈습니다. 그 사람에게 얼마의 사망보험금이 지급되느냐 는 별개의 질문 — 보장 약관, 면책·감액, 보험금액의 함수입니다. 그래서 엔진은 사망 보장의 청구를 그 보장에 묶인 별도 rate(사망보험금 발생률) 로 계산합니다.

사망보험금[t] = inforce[t] × 사망보험금발생률 × DEATH.benefit

이 발생률은 보유계약 사망률과 이름만 둘 다 “사망”일 뿐, 서로 다른 입력 슬롯입니다:

basis = fcf.Basis(
    mortality_annual = ...,                                   # 보유계약 사망률 (in-force 감쇠)
    coverages        = (fcf.CoverageRate("DEATH", rate_fn),)  # 사망보험금 발생률 (청구)
)

워크북에서도 schema path가 다릅니다 — coverages 시트의 rate_table 컬럼이 가리키는 mortality_tables 또는 incidence_rate_tables 시트. 같은 워크북 안에서도 별개의 슬롯입니다.

중요한 비대칭: 사망보험금 발생률은 어떤 풀도 줄이지 않습니다. in-force를 줄이는 건 어디까지나 보유계약 사망률이고, 발생률은 그 위에서 지급액만 계산합니다. 이 “발생률은 풀을 안 줄인다”가 1.4의 반복급부(MORBIDITY)와 직접 이어집니다.

1.3.3 둘이 같은 숫자일 때#

가장 단순한 정기보험을 봅시다. 사망 보장이 일반사망(all-cause) 하나만 붙은 경우. 어느 원인으로든 사람이 죽으면 두 일이 동시에 일어납니다 — 보유계약 에서 한 명 빠지고(보유계약 사망률의 일), 그 사람에게 사망보험금이 지급됨 (사망보험금 발생률의 일). 같은 사건의 같은 빈도라 두 율이 자연히 같은 숫자가 됩니다.

같은 숫자이지만 여전히 두 개의 입력입니다. cookbook의 손계산 예제 (1.4 / 2.1)가 이 경우라, 두 슬롯에 같은 callable을 넘깁니다:

import fastcashflow as fcf

# 사망률 -- 월 사망률 1% 의 연 환산
death_rate = 1 - (1 - 0.01) ** 12

# 해지율 -- 해지 없음
lapse_rate = 0.0

basis = fcf.Basis(
    mortality_annual = death_rate,                               # 보유계약 사망률 (all-cause)
    lapse_annual     = lapse_rate,                               # 해지율 (없음)
    discount_annual  = 0.03,                                     # 할인율
    ra_confidence    = 0.75,                                     # 위험조정 신뢰수준
    mortality_cv     = 0.10,                                     # 사망률 변동계수
    coverages        = (fcf.CoverageRate("DEATH", death_rate),)  # 사망보험금 발생률 (일반사망)
)

한 변수 death_rate을 두 슬롯에 공유합니다. “두 율이 같다” 는 사실을 코드에 명시하는 동시에, 한 쪽만 바꾸다 생기는 silent 어긋남이 구조적으로 차단됩니다.

1.3.4 둘이 다른 숫자일 때#

두 율이 명시적으로 달라지는 경우는 흔합니다. 핵심은 all-cause vs cause-specific 의 구분.

경우 1 — cause-specific 사망 보장 하나만 있을 때

사망 보장이 질병사망 / 재해사망 같은 cause-specific이면, 보장이 하나뿐이어도 두 율이 다릅니다.

mortality_annual = rate_all_cause                # 보유계약 사망률 (all-cause)

coverages = (
    fcf.CoverageRate("ADB", rate_accident),  # 사망보험금 발생률: 재해사망만 (예: 연 0.3%)
)

보유계약은 어느 원인으로든 사람이 죽으면 빠지니까 보유계약 사망률은 all-cause(예: 연 1.2%). 하지만 사망보험금 발생률은 재해 사고로 죽은 경우만 — 발생률(0.3%)이 보유계약 사망률보다 훨씬 낮습니다. 두 율이 다른 숫자.

경우 2 — 다종 사망 보장이 함께 붙을 때

한 계약에 일반사망 + 질병사망 + 재해사망 세 보장이 함께 붙으면:

mortality_annual = rate_all_cause                         # 보유계약 사망률: all-cause (예: 연 1.2%)

coverages = (
    fcf.CoverageRate("DEATH",         rate_all_cause),  # 사망보험금 발생률: 일반사망 (1.2%)
    fcf.CoverageRate("DISEASE_DEATH", rate_disease),    # 사망보험금 발생률: 질병사망 (0.9%)
    fcf.CoverageRate("ADB",           rate_accident),   # 사망보험금 발생률: 재해사망 (0.3%)
)

사람은 한 번만 죽으므로 inforce는 보유계약 사망률(all-cause)로 한 번 감쇠. 그 한 번의 사망 사건이 여러 보장의 청구를 동시 트리거(재해로 죽으면 일반사망금 + 재해사망금 둘 다 지급). 두 cause-specific의 합(0.9 + 0.3 = 1.2)이 all-cause와 일치 — 같은 사망 사건의 원인별 분해라서.

보유계약 사망률을 보장 청구 식 안에 묶었다면 세 사망 보장 중 어느 하나의 율로만 in-force를 감쇠해야 했을 겁니다. 분리되어 있으니 감쇠는 contract 전체에 한 번, 청구는 보장마다 자기 발생률.

경우 3 — calibration 출처가 다를 때

같은 일반사망 보장이어도 두 율의 source가 다른 경우. 보유계약 사망률은 경험률표(실측 자료)로 calibrate, 사망보험금 발생률은 공시 표준 mortality table(규제 의무)로. 두 표가 다른 숫자라 두 슬롯도 다른 숫자.

1.3.5 손계산 입력 연결의 안전 패턴#

위 사례들이 fastcashflow가 두 입력을 분리한 이유입니다. 단순 정기보험 손계산은 두 값이 같지만, 두 슬롯에 별개의 값을 실수로 넘기면 결과가 silent로 어긋납니다.

잘못된 연결

결과

보유계약 사망률 = 0%, 사망보험금 발생률 = 1%

in-force가 안 줄어 매월 사망보험금 청구 — MORBIDITY와 똑같은 메커니즘. 보험기간 내내 반복 청구되어 BEL 과대평가.

보유계약 사망률 = 1%, 사망보험금 발생률 = 0%

in-force는 줄고 사망보험금 없음. BEL 과소평가.

두 패턴 모두 에러 없이 통과 — 조용히 어긋나는 함정. 한 변수 공유 패턴 (death_rate을 두 슬롯에)이 구조적 방어입니다. (위 첫 행이 곧 1.3.6의 “풀이 안 줄면 반복”임을 보여줍니다.)

워크북에서도 두 셀은 따로

fcf.read_basis("basis.xlsx")로 읽을 때도 두 슬롯은 다른 셀에서 옵니다 — mortality_annualsegments 시트의 mortality_table 컬럼, DEATH 담보의 발생률은 coverages 시트의 rate_table 컬럼. 로더는 둘을 독립적으로 조회하며 자동으로 잇지 않습니다. 두 율을 같게 하려면 두 셀에 같은 table_id를 적으면 됩니다 (둘 다 mortality_tables 네임스페이스를 공유하므로 같은 테이블로 해석됨). 손계산에서 death_rate을 두 슬롯에 공유한 것과 같은 선택을, 워크북에서는 셀로 하는 셈입니다.

1.3.6 풀로 보면#

이 “어떤 풀을 줄이는가” 관점이 다음 챕터(1.4)의 핵심을 미리 정리해 줍니다. 세 담보 모두 청구식은 inforce × 발생률 × benefit똑같고, “한 번이냐 반복이냐”는 그 발생률로 어떤 풀이 줄어드느냐 만의 문제입니다:

  • DEATH — “한 번”. 별도의 보유계약 사망률이 공유 in-force를 같은 율로 줄여, 죽은 사람이 다시 청구하지 못함. (사망보험금 발생률 자체는 풀을 안 줄임 — in-force를 줄이는 건 보유계약 사망률.)

  • DIAGNOSIS — “한 번”. 진단 발생률그 담보의 미진단 풀(1 - 진단발생률)로 직접 축소. 한 번 진단받으면 그 풀에서 빠짐. (계약은 안 끝남 — 사람은 in-force에 남아 보험료 내고 다른 담보도 작동.)

  • MORBIDITY — “반복”. 반복급부 발생률어떤 풀도 줄이지 않음. 공유 in-force만 보유계약 사망률·해지율로 줄 뿐이라, 살아있는 한 매월 새로 청구.

즉 셋의 차이는 청구 식이 아니라 발생률이 어떤 풀을 (또는 어떤 풀도 안) 줄이는가 입니다. 1.4 담보별 산출방법이 이 셋을 toy 예제로 한 페이지에 보여줍니다.