TT Lab
Blog Get started
Learn Learning paths Courses

Insurance Domain Deep Dive

Reserves, IFRS 17, and the Solvency Pipeline

Continue in TT Lab

Goal

You calculate the policy reserves of in-force contracts with the assumptions at the time of enrollment, revalue the same contracts at the current discount rate to pull out IFRS 17's best estimate liability, risk adjustment, and contractual service margin, and then build even a simplified solvency ratio from company figures in a single pipeline.

Why it matters

An insurer keeps promises of decades from now with the premiums it receives today. So the core question of accounting is "how much to set aside now for money to be paid in the future," and the answer is the policy reserve. The reserve of a term insurance is the present value of benefits to be paid in the future minus the present value of net premiums to be received in the future. It is small early in the contract and grows later as the risk increases.

IFRS 17 demands a different answer to the same question. It evaluates liabilities not with the assumptions at enrollment but with current assumptions (the best estimate liability, BEL), adds compensation for uncertainty (risk adjustment, RA), and books the unrealized profit that still remains as a liability called the contractual service margin (CSM), then recognizes it as profit in portions over the contract period. It is a device that prevents profit from being recognized early, and a contract expected to lose money is booked immediately as a loss.

The solvency regime (K-ICS) looks at the company as a whole. Insurance, market, and credit risks are each converted to capital requirements and combined, and it looks at what % of that requirement the available capital is. These three layers — cost-basis reserves, current-value liabilities, and solvency — are the backbone of an insurer's closing system, and the same contract shows up with different numbers in the three layers.

Rules of this lab

Steps

  1. Save the generator in the example on the right as /root/ins/make_reserve.py and run it with python3 make_reserve.py. lifetable.csv, inforce.csv (5 contracts), params.csv, and capital.csv are created. Also save the actuarial function file /root/ins/act.py, which later steps use, as in the example on the right — it contains term_insurance(qx, lx, x, n, i) and annuity_due(qx, lx, x, n, i).
  2. Write the current-point reserve of P001 in /root/ins/reserve_P001.txt in three lines: A=, annuity=, and reserve=.
  3. Write all 5 contracts in /root/ins/reserves.csv with the header policy_no,age_now,remaining,A,annuity,reserve, and write one line, total_reserve= (the sum of the reserve column), in /root/ins/reserves.txt.
  4. Write the recursion check in /root/ins/recursion_check.csv with the header policy_no,v_next,lhs,rhs,diff. v_next is the reserve one year later, V_(t+1) (0 at maturity); v_next, lhs, and rhs are rounded to integers, and diff is lhs − rhs.
  5. Write /root/ins/bel.csv, applying the current discount rate at the enrollment point, with the header policy_no,pv_claims,pv_premiums,bel.
  6. Write /root/ins/csm.csv with the header policy_no,bel,ra,fcf,csm,loss_component, and write two lines (the sum of each column) in /root/ins/csm.txt: total_csm= and total_loss_component=.
  7. Write four lines in /root/ins/kics.txt: required_capital=, available_capital=, ratio_pct=, and meets_100=. ratio_pct has one decimal place, and meets_100 is YES or NO.
  8. In /root/ins/valuation_report.md, write a closing memo in four sections: ## Policy Reserves, ## IFRS17 Summary, ## Solvency, and ## Data and Regulatory Notes. The section titles can be the English ones or titles with the same meaning in Korean, Japanese, or Chinese, and you can also write both, one in parentheses.

Notes

Create the in-force contracts and assumptions

Save the generator in the example on the right as /root/ins/make_reserve.py and run it with python3 make_reserve.py. lifetable.csv, inforce.csv (5 contracts), params.csv, and capital.csv are created. Also save the actuarial function file /root/ins/act.py, which later steps use, as in the example on the right — it contains term_insurance(qx, lx, x, n, i) and annuity_due(qx, lx, x, n, i).

Save the generator in the lab instructions as /root/ins/make_reserve.py and run it with python3. Also save the actuarial functions in the example on the right as /root/ins/act.py — the grader imports the two functions term_insurance(qx, lx, x, n, i) and annuity_due(qx, lx, x, n, i) to check their values (this lab starts a new Pod, so the file from Module 1 is no longer there).

Calculate the reserve of one contract

Write the current-point reserve of P001 in /root/ins/reserve_P001.txt in three lines: A=, annuity=, and reserve=.

Age = 35 + 5 = 40, remaining term = 20 − 5 = 15. Find A(40, 15, 2.5%) and ä(40, 15, 2.5%), then reserve = int(S × A − P × ä + 0.5). P is 198386 in inforce.csv.

Pull out the reserves for all in-force contracts

Write all 5 contracts in /root/ins/reserves.csv with the header policy_no,age_now,remaining,A,annuity,reserve, and write one line, total_reserve= (the sum of the reserve column), in /root/ins/reserves.txt.

Repeat step 2 over the five lines of inforce.csv and sum the reserve. age_now = issue_age + elapsed, remaining = term − elapsed.

Verify the reserves with the recursion formula

Write the recursion check in /root/ins/recursion_check.csv with the header policy_no,v_next,lhs,rhs,diff. v_next is the reserve one year later, V_(t+1) (0 at maturity); v_next, lhs, and rhs are rounded to integers, and diff is lhs − rhs.

V(t+1) is calculated with the same formula after moving the age forward by one and reducing the remaining term by one (0 at maturity). lhs = (V_t + P) × 1.025, rhs = q(x+t) × S + (1 − q(x+t)) × V_(t+1). lhs and rhs must each be within ±2 won of the true value, and diff ends up near 0. In the v_next column, write the V_(t+1) you put into rhs, rounded to the nearest won.

Find the best estimate liability at the current discount rate

Write /root/ins/bel.csv, applying the current discount rate at the enrollment point, with the header policy_no,pv_claims,pv_premiums,bel.

It is the enrollment point, so use issue_age and term as they are (without subtracting the elapsed time), and the rate is current_rate (0.030) in params.csv. pv_claims = int(S × A + 0.5), pv_premiums = int(P × ä + 0.5), and bel is the difference between the two. Use P as it is.

Split into risk adjustment and contractual service margin

Write /root/ins/csm.csv with the header policy_no,bel,ra,fcf,csm,loss_component, and write two lines (the sum of each column) in /root/ins/csm.txt: total_csm= and total_loss_component=.

ra = int(pv_claims × 0.005 + 0.5), fcf = bel + ra. If fcf < 0, csm = −fcf and loss_component = 0; otherwise, csm = 0 and loss_component = fcf. Read the step 5 file and calculate.

Calculate the solvency ratio

Write four lines in /root/ins/kics.txt: required_capital=, available_capital=, ratio_pct=, and meets_100=. ratio_pct has one decimal place, and meets_100 is YES or NO.

required = round(√(I² + M² + C² + 2 × 0.25 × (IM + IC + MC)) + O), and ratio = available ÷ required × 100 as %.1f. The result must be smaller than the simple sum (6600).

Write the closing memo

In /root/ins/valuation_report.md, write a closing memo in four sections: ## Policy Reserves, ## IFRS17 Summary, ## Solvency, and ## Data and Regulatory Notes. The section titles can be the English ones or titles with the same meaning in Korean, Japanese, or Chinese, and you can also write both, one in parentheses.

Use the four section titles exactly as given, either the English titles or titles with the same meaning in Korean, Japanese, or Chinese. In the policy reserves section, write the total; in the IFRS17 section, the CSM (contractual service margin) total on the same line as the word "CSM" and the current discount rate of 3.0% on the same line as the word "discount"; in the solvency section, the ratio; and in the cautions section, the matter of sensitive data.