TT Lab
Get started
Learn Learning paths Courses

Insurance Domain Deep Dive

Pinning Down Where 349 Won Split, Rule by Rule

Continue in TT Lab

Goal

You recalculate the unearned premium of mid-term canceled contracts, point to the differences made by the day count basis, rounding mode, and segment splitting at the contract level, and produce the correction list as well.

Why it matters

A refund looks like one line, "annual premium times unexpired days divided by total days," but hidden in that one line are three values that must be decided as policy. How you count days, where you cut, and whether you reflect mid-term changes. Two systems that chose the three values differently each calculate correctly and yet give different answers. What is needed then is not "there is a difference" but an explanation like "this contract's difference is due to the day count basis and that one's is due to segments." The grader does not compare the numbers you wrote against each other. It recomputes the reference values from the step 1 data and checks against them, so you must follow the rules in the instructions exactly.

Steps

  1. Create and run /root/prem/gen_prem.py to create /root/prem/policies.csv (60 rows) and /root/prem/changes.csv (15 rows).
  2. For each contract, write the total days, elapsed days, and unexpired days on the two bases, actual days and 30/360, to /root/prem/daycount.json.
  3. Calculate the unearned premium on the actual-days basis and write it to /root/prem/refund_actual.json.
  4. Calculate the same contracts on the 30/360 basis, write them to /root/prem/refund_30360.json, and leave the difference from step 3 too.
  5. Cut the contracts with coverage changes before and after the change date and write the per-segment refund to /root/prem/segments.json.
  6. Write the difference between the sum cut per segment and the value cut once at the end, and the monthly 12-way split, to /root/prem/rounding.json.
  7. Run the claims system and accounting system calculations side by side and write each contract's difference and cause to /root/prem/diff.json.
  8. Bundle the correction list and the conclusion into /root/prem/report.json and write the sha256 of policies.csv along with it.

Notes

Generate the contract and coverage change data

Create and run /root/prem/gen_prem.py to create /root/prem/policies.csv (60 rows) and /root/prem/changes.csv (15 rows).

The expiry date is tricky. When the same date one year after the start date does not exist (2024-02-29), you must pull it back to the last day of that month, and calendar.monthrange tells you the last day of that month. Write all dates as YYYY-MM-DD.

Separate the two day count bases

For each contract, write term_days, used_days, unused_days and the three 30/360 versions to /root/prem/daycount.json, and also leave the list of contracts whose insurance period contains February 29 and the number of contracts whose unexpired days differ between the two bases.

Actual days come directly from date subtraction. For 30/360, first apply the two rules that pull 31 down, and then add the year, month, and day differences. You must decide whether to include both ends the same way for the two bases for the comparison to hold.

Calculate the unearned premium on actual days

Write basis, rounding, each contract's unused_days and refund_krw, and total_krw to /root/prem/refund_actual.json. This step ignores coverage changes and calculates the whole period with the original annual premium.

Multiply and divide with Decimal and then cut at the 1-won place with quantize. If you calculate in floating point, 0.5 is not exactly 0.5, so choosing a rounding mode itself becomes meaningless.

Try changing the denominator to 30/360

Write the 30/360 refund, the diff_krw from step 3, and diff_rows and total_diff_krw to /root/prem/refund_30360.json.

You must change both the denominator and the numerator to 30/360. If you change only one side, the refund rate of a contract with a one-year period can exceed 1. diff_krw is the 30/360 value minus the actual-days value.

Split mid-term coverage changes into segments

Pick only the 15 contracts with coverage changes and write to /root/prem/segments.json the two segments (from, to, annual_krw, unused_days, refund_krw), the segment-summed refund_krw, the whole_period_refund_krw that ignores the change, and their difference gap_krw.

The earlier segment runs up to the day before the change date. Unexpired days count only the days on which the segment overlaps the stretch from the cancellation date to the expiry date, so if the change date is before the cancellation date, the earlier segment's unexpired days are 0. The denominator for both segments is the whole contract's total days.

Where to put the cutting place

Write segment_rounding (policies_with_gap, total_gap_krw) and monthly_split (policies, count, all_exact) to /root/prem/rounding.json. The 12-month split of a monthly-payment contract must sum exactly to the annual premium.

Compare the sum cut per segment with the value obtained by adding up all the exact per-segment values and then cutting just once. For the monthly split, give the quotient rounded down and then attach the remaining won as 1 won extra from the earlier months, and the sum matches.

Point to the difference between the two systems by rule

Write the rules of the two systems, each contract's claims_krw, acct_krw, diff_krw, causes, and diff_rows, total_diff_krw, and by_cause to /root/prem/diff.json.

Do not attach causes by guessing. Switch just one rule in the accounting calculation to the claims side and recompute, and only the rules for which the value changes are causes. You can just toggle each of the three rules once.

The correction list and the conclusion on one page

Write 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, and verdict to /root/prem/report.json. verdict is claims-system-is-authoritative.

In corrections put only the contracts that differ, in ascending policy_id order, with only the four keys policy_id, from_krw, to_krw, and delta_krw. from is the value to be fixed (accounting), and to is the value taken as the reference (claims). Recompute the hash now from policies.csv.