返戻金が1ウォン違うのに、どちらのシステムも正しいと言う
一言でいうと
中途解約の払戻額は「年間保険料×未経過日数÷総日数」の1行のように見えますが、日数の数え方の基準、端数を処理する位置、区間の分け方が、それぞれ別の答えを作ります。この3つをポリシーとして固定し、計算経路を1つにまとめることが、この問題のすべてです。
なぜ必要なのか
顧客が5月に契約を解約しました。請求システムは払戻額412,331ウォンを案内し、数日後に会計システムが作った精算ファイルには411,982ウォンと書かれています。349ウォンの差です。2つのチームを呼んで計算を突き合わせてみると、どちらにも間違いはありません。一方は実際のカレンダーの日数で割り、もう一方は1か月を30日と数える古い慣行に従いました。一方はウォン単位で丸め、もう一方は切り捨てました。一方は3月にあった保障変更を反映して期間を2つに分け、もう一方は契約時点の保険料で全期間を一度に計算しました。
こうした差は、1件では数百ウォンです。ところが毎月数千件が通ると突合項目になり、突合項目は、誰かが毎月手で説明しなければならない仕事になります。そして顧客に聞かれたとき、「システムごとに違います」と答えるわけにはいきません。
どう動くのか
1つ目は、日数を数える基準(day count convention)です。実日数(actual/actual)は、カレンダーそのままに数えます。2月は28日か29日で、1年は365日か366日です。30/360は、すべての月を30日、1年を360日とみなす方式で、債券の利息計算で長く使われ、手計算の時代の単純さがそのまま残ったものです。2つの方式は、同じ期間に別の日数を出します。Pythonのdateオブジェクトは、引き算で実日数をそのまま出し、30/360は、日付の数字を手で調整して作る必要があります。
期間の終わりを決めることにも落とし穴があります。2024年2月29日に始まった1年契約の満期日はいつでしょうか。2025年には2月29日がありません。calendarモジュールのmonthrange()でその月の末日を求めて引き寄せるのが一般的な処理ですが、どちらに寄せるかを約款が決めていなければ、2つのシステムが分かれる最初の地点になります。日付はRFC 3339のYYYY-MM-DDでやり取りして、桁の順序でもめることをなくします。
2つ目は、端数を切る位置と丸め方式です。ウォン単位で切るところまでは簡単に合意できますが、0.5ウォンを切り上げるか切り捨てるかは違います。保守的に切り捨てる会計の慣行と、顧客に不利にならないように丸める請求の慣行が、1つの会社の中で共存していることがよくあります。Pythonのdecimalモジュールのquantize()は、ROUND_HALF_UPやROUND_DOWNのようなモードを明示的に選ばせます。実数(float)で計算すると、この選択そのものが無意味になります。0.5がそもそも正確に0.5ではないからです。
3つ目は、区間の分割です。保障を期中に変えると、保険料もその日から変わります。払戻額は、変更前後に分けて計算して足してはじめて合います。ところが分けると丸めを2回行うことになり、区間ごとに端数処理した合計は、全体を一度に処理した値と1ウォンずつずれます。これはエラーではなく選択です。区間ごとに切るのか、最後に1回だけ切るのかを決め、その規則を書いておかなければなりません。
계약기간 |-----------------------------------------|
변경일 ^ 해지일 ^
구간1 |-------| (옛 보험료)
구간2 |-------------------------|(새 보험료)
미경과분 |----| ← 이 겹침만 환급
現場での姿
差に直面したとき、最も役に立たない報告は「349ウォンの差が出ます」です。役に立つ報告は「349ウォンのうち300ウォンは日数基準、49ウォンは丸め、残りは区間の反映の有無」です。原因をルール単位に分ける方法は単純です。一方のシステムの計算で、ルールを1つだけ相手側に変えてみて、結果が変わるかどうかを見ます。3つのルールを1つずつ切り替えると、どのルールがこの契約に実際に影響しているかがわかります。
もう1つよく見るのは、月払契約の分割です。年間保険料を12で割ると、たいてい余りが出ますが、それを捨てると1年分の請求合計が年間保険料に届かず、すべての月で切り上げると超えてしまいます。どの月に1ウォンを上乗せするかまで決めておいてはじめて、請求システムと収納元帳が年末に合います。前の月から上乗せする会社もあれば、最後の月にまとめて上乗せする会社もありますが、どちらにせよ規則が必要です。
そして訂正は、数字を変えるだけの仕事ではありません。どの計算を基準にすると決めたのか、その決定でいくら動くのか、対象契約が何件なのかが1枚にあってはじめて、決裁が下ります。差額だけが書かれたリストは、2回目の訂正のときに役に立たなくなります。出発点がどこだったのか、誰もわからないからです。
実務で本当に大切なこと
- 日数基準・丸め方式・区間の分割は、約款と社内規程が定める値です。コードが先に決めてしまうと、あとで変えられません。
- 計算経路は1つにまとめます。2つのチームがそれぞれ組むと、差が必ず生じます。
- 差は合計ではなく、ルール単位で説明します。
- 訂正リストには、訂正前の金額と訂正後の金額を一緒に書きます。差額だけを書くと、追跡が途切れます。
- 報告書は、根拠となった資料をハッシュで指し示します。資料が変われば、数字も出し直す必要があります。
次のラボですること
契約60件と期中の保障変更15件を自分で作り、同じ解約案件を実日数と30/360でそれぞれ計算して、どれだけ分かれるかを見ます。次に変更のある契約を区間に分割し、区間ごとに端数処理した合計と一度だけ端数処理した値の差を数え、月払12分割が年間保険料とぴったり合うようにします。最後に請求と会計の2つの経路を並べて実行し、契約ごとの差の原因をルール単位で指し示して、訂正リストを出します。