Pinning Down Where 349 Won Split, Rule by Rule
한국어 원문으로 표시합니다.
목표
중도 해지 계약의 미경과보험료를 다시 계산하고, 일수 기준과 반올림 방식과 구간 분리가 만드는 차이를 계약 단위로 지목해 정정 목록까지 낸다.
왜 중요한가
환급액은 "연보험료 곱하기 미경과일수 나누기 총일수" 한 줄처럼 보이지만, 그 한 줄 안에 정책으로 정해야 하는 값이 세 개 숨어 있다. 일수를 어떻게 세는가, 어디서 끊는가, 기중 변경을 반영하는가. 세 값을 다르게 잡은 두 시스템은 각자 맞는 계산을 하면서도 다른 답을 낸다. 그때 필요한 것은 "차이가 납니다" 가 아니라 "이 계약의 차이는 일수 기준 때문이고 저 계약은 구간 때문" 이라는 설명이다. 채점기는 여러분이 적은 숫자끼리 견주지 않는다. 1단계 자료에서 기준값을 다시 계산해 대조하니, 안내의 규칙을 그대로 따라야 한다.
단계
- /root/prem/gen_prem.py 를 만들어 실행해 /root/prem/policies.csv(60건)와 /root/prem/changes.csv(15건)를 만든다.
- 계약마다 실제 일수와 30/360 두 기준의 총일수·경과일수·미경과일수를 /root/prem/daycount.json 에 적는다.
- 실제 일수 기준으로 미경과보험료를 계산해 /root/prem/refund_actual.json 에 적는다.
- 같은 계약을 30/360 기준으로 계산해 /root/prem/refund_30360.json 에 적고 3단계와의 차이를 함께 남긴다.
- 보장 변경이 있는 계약을 변경일 앞뒤로 쪼개 /root/prem/segments.json 에 구간별 환급액을 적는다.
- 구간마다 끊은 합과 끝에서 한 번만 끊은 값의 차이, 그리고 월납 12분할을 /root/prem/rounding.json 에 적는다.
- 청구 시스템과 회계 시스템의 계산을 나란히 돌려 /root/prem/diff.json 에 계약별 차이와 원인을 적는다.
- 정정 목록과 결론을 /root/prem/report.json 하나로 묶고 policies.csv 의 sha256 을 함께 적는다.
참고
- 1단계 계약 규칙(i 는 0 부터 59): policy_id 는
P0001부터 네 자리, 시작일은 2024-01-01 에(i * 59) % 730일을 더한 날, 만기일은 시작일의 1년 뒤 같은 날에서 하루 전(그 날이 없으면 그 달 말일로 당긴 뒤 하루 전), pay_mode 는 i 가 홀수면 monthly 짝수면 annual, 연보험료는120000 + (i * 7777) % 880001, 해지일은 시작일에37 + (i * 29) % 300일을 더한 날이다. - 1단계 변경 규칙: i 를 4로 나눈 나머지가 2 인 계약만 변경이 있다. 변경일은 시작일에
30 + (i * 47) % 260일을 더한 날, 새 연보험료는연보험료 + 60000 + (i * 3331) % 200000이다. - 일수 정의: 총일수는 시작일과 만기일을 모두 포함해 세고, 경과일수는 해지일에서 시작일을 뺀 날수(해지일 당일은 보장하지 않는다), 미경과일수는 총일수에서 경과일수를 뺀 값이다.
- 30/360(US) 규칙: 앞 날짜의 일이 31 이면 30 으로 당기고, 뒤 날짜의 일이 31 이면서 앞이 30 이상이면 30 으로 당긴 뒤
360 * 연차 + 30 * 월차 + 일차로 센다. 총일수와 미경과일수는 여기에 실제 일수와 같은 방식으로 1 을 더해 양끝을 포함시킨다. - 환급액:
연보험료 * 미경과일수 / 총일수를 1원 단위로 끊는다. 3 · 4 · 5단계의 정책은 ROUND_HALF_UP 이다. - 구간 미경과일수: 구간이 해지일부터 만기일까지와 겹치는 날만 센다. 겹치지 않으면 0 이다.
- 7단계 두 경로: 청구 시스템은 실제 일수 · ROUND_HALF_UP · 구간 반영이고, 회계 시스템은 30/360 · 원 미만 절사(ROUND_DOWN) · 구간 무시(원래 연보험료로 전체 기간)다. 원인은 회계 계산에서 규칙 하나만 청구 쪽으로 바꿨을 때 값이 달라지는 것만
daycount,rounding,segment순서로 적는다. - 흔한 실수: 미경과일수에 해지일 당일을 넣기, 30/360 에서 양끝 포함을 빼먹기, 구간이 미경과 구간과 겹치지 않는데 1일로 세기, 월납 분할에서 나머지 버리기.
- 확인:
python3 -c "import json;print(json.load(open('/root/prem/diff.json'))['by_cause'])"
계약과 보장 변경 자료 만들기
/root/prem/gen_prem.py 를 만들어 실행해 /root/prem/policies.csv(60건)와 /root/prem/changes.csv(15건)를 만드세요.
만기일이 까다롭습니다. 시작일의 1년 뒤 같은 날이 없는 경우(2024-02-29)를 그 달 말일로 당겨야 하는데, calendar.monthrange 가 그 달의 마지막 날을 알려 줍니다. 날짜는 전부 YYYY-MM-DD 로 적습니다.
일수 기준 두 가지를 갈라 놓기
계약마다 term_days, used_days, unused_days 와 30/360 판 세 값을 /root/prem/daycount.json 에 적고, 보험기간에 2월 29일이 들어 있는 계약 목록과 두 기준의 미경과일수가 다른 계약 수도 함께 남기세요.
실제 일수는 date 뺄셈으로 바로 나옵니다. 30/360 은 31일을 당기는 두 규칙을 먼저 적용한 뒤 연·월·일 차이를 더합니다. 양끝을 포함할지 말지를 두 기준에서 똑같이 정해야 비교가 성립합니다.
실제 일수로 미경과보험료 계산하기
/root/prem/refund_actual.json 에 basis, rounding, 계약별 unused_days 와 refund_krw, 그리고 total_krw 를 적으세요. 이 단계는 보장 변경을 무시하고 원래 연보험료로 전체 기간을 계산합니다.
Decimal 로 곱하고 나눈 뒤 quantize 로 1원 자리에서 끊습니다. 실수로 계산하면 0.5 가 정확히 0.5 가 아니라서 반올림 모드를 고르는 일 자체가 무의미해집니다.
분모를 30/360 으로 바꿔 보기
/root/prem/refund_30360.json 에 30/360 기준 환급액과 3단계와의 diff_krw, 그리고 diff_rows 와 total_diff_krw 를 적으세요.
분모와 분자를 모두 30/360 으로 바꿔야 합니다. 한쪽만 바꾸면 기간이 1년인 계약의 환급률이 1 을 넘는 일이 생깁니다. diff_krw 는 30/360 값에서 실제 일수 값을 뺀 것입니다.
기중 보장 변경을 구간으로 쪼개기
보장 변경이 있는 계약 15건만 골라 /root/prem/segments.json 에 구간 2개(from, to, annual_krw, unused_days, refund_krw)와 구간 합산 refund_krw, 변경을 무시한 whole_period_refund_krw, 그 차이 gap_krw 를 적으세요.
앞 구간은 변경일 하루 전까지입니다. 미경과일수는 구간이 해지일부터 만기일까지와 겹치는 날만 세니, 변경일이 해지일보다 앞이면 앞 구간의 미경과일수는 0 입니다. 분모는 두 구간 모두 계약 전체의 총일수입니다.
끊는 자리를 어디에 둘 것인가
/root/prem/rounding.json 에 segment_rounding(policies_with_gap, total_gap_krw)과 monthly_split(policies, count, all_exact)을 적으세요. 월납 계약의 12개월 분할은 합이 연보험료와 정확히 같아야 합니다.
구간마다 끊은 합과, 구간별 정확한 값을 다 더한 뒤 한 번만 끊은 값을 견줍니다. 월납 분할은 몫을 내림으로 준 뒤 남은 원을 앞 달부터 1원씩 더 붙이면 합이 맞습니다.
두 시스템의 차이를 규칙 단위로 지목하기
/root/prem/diff.json 에 두 시스템의 규칙, 계약별 claims_krw, acct_krw, diff_krw, causes, 그리고 diff_rows, total_diff_krw, by_cause 를 적으세요.
원인은 짐작으로 붙이지 않습니다. 회계 계산에서 규칙을 하나만 청구 쪽으로 바꿔 다시 계산해 보고, 값이 달라지는 규칙만 원인입니다. 세 규칙을 각각 한 번씩 토글하면 됩니다.
정정 목록과 결론을 한 장으로
/root/prem/report.json 에 policies_sha256, policies, changed_policies, refund_actual_total_krw, refund_30360_total_krw, basis_gap_krw, segment_gap_policies, diff_rows, total_diff_krw, by_cause, corrections, policy_basis, policy_rounding, verdict 를 적으세요. verdict 는 claims-system-is-authoritative 입니다.
corrections 에는 차이가 난 계약만 policy_id 오름차순으로, policy_id·from_krw·to_krw·delta_krw 네 키만 담습니다. from 은 고칠 값(회계), to 는 기준으로 삼기로 한 값(청구)입니다. 해시는 지금 policies.csv 에서 다시 계산합니다.