Technical Notes#
Status: Draft, 2026-08-29; citations re-verified against the primary documents 2026-08-30.
Scope note. These notes specify a reference liability cash-flow projection model — model name
KLV_DE_S, annual grid — for the standardized composite German kapitalbildende
Lebensversicherung defined in product-spec.md (same directory). This is not any single insurer’s
product. [S#] / [R#] tags refer to the source list in sources.md (numbering carried from
_research/kapitallebensversicherung.md; frozen); [REG-R#] tags refer to the cross-product library
references/regulatory-and-actuarial-references.md (its own frozen R1–R56 numbering). std marks
a standardization introduced for the reference implementation; unverified marks a claim no search
result corroborated. Parameter values are identical to those in product-spec.md. delib was
drafted with all HTTP egress blocked and no document retrieved; the citations have since been
re-verified against the primary documents, and forty-five of the forty-seven entries in
sources.md now record a document that was opened and read, the two exceptions being [S8] (404)
and R24 (429). Treat a claim as sound where its entry says Retrieved: yes, and as a pointer
rather than a certificate — an instrument named, not one anybody checked — where it does not.
Cells names, model-point columns and CSV headers are English lower_snake_case; German terms of art
keep their German form in prose.
Model scope and conventions#
Purpose. Project gross best-estimate liability cash flows, undiscounted — Beiträge in; Todesfallleistungen, Erlebensfallleistungen and Rückkaufswerte out; insurer expenses and commission — for a single-policy model point on an expected basis, with the three state variables that make the product what it is: the guaranteed Deckungskapital, the accumulated Überschussguthaben and the accrued Schlussüberschussanteil.
Out of scope, and said so. No discounting. No Deckungsrückstellung: the model projects the contract’s Deckungskapital — the amount that should be held — not the balance-sheet quantity of § 341f HGB REG-R54. No Zinszusatzreserve REG-R17, no RfB stock REG-R10 REG-R19, no MindZV allocation R6 REG-R18, no P&L, no Solvency II technical provision, risk margin, SCR or MCR REG-R1 REG-R2 REG-R6. No Beteiligung an den Bewertungsreserven in the base run — the parameter exists and is zero R1 R8. No tax: delib publishes gross benefits and the tax rules enter only as design constraints. No premium-default path, §§ 37 and 38 VVG never having been researched (gap 20); no § 222 or § 314 VAG write-down REG-R12; no Zusatzversicherungen, Kapitalwahlrecht, Dynamik or Beleihung.
Projection frequency. Monthly grid, over an annual product. Every contractual mechanic on this contract is annual and stays annual: the surplus is declared once a year and allocated at the Bilanzstichtag [S9], the Rückkaufswert is struck at the end of the current Versicherungsperiode R2, the beitragsfreie Versicherungssumme is tabulated für jedes Versicherungsjahr R3, the Deckungskapital rolls forward by Fackler from one anniversary to the next at an annual Rechnungszins, and the Ablauf falls on an anniversary [S7]. What the finer grid resolves is everything that is not contractually annual — the Beitrag the contract bills in instalments, the insurer’s running expense, and the decrements, which now fall in the month they happen.
Two clocks, and which quantity runs on which. Cells that state an annual account take a 0-based policy year
k: the whole pricing block, all three reserves, the § 169 value, the paid-up purchase, every part of the Überschussbeteiligung, the Stornoabzug band and the expense inflation. Cells that state a month taket: the in force, the claims, the premium instalments and everyresult_cf()column. The decrement rates taketand return the year’s annual rate;mort_rate_mth(t)andlapse_rate_mth(t)are what the recursion applies, each1 − (1 − r)^(1/12)std, so twelve of each compound back to the year’s rate exactly.What
tcounts, and it is 0-based.tis the policy month index, measured from issue: monthtruns from timetto timet + 1.duration(t) = t // 12is the completed policy years at the start of montht— the bridge between the two clocks — and is what every duration-keyed schedule is indexed on: the Stornoabzug, the lapse table, the § 169 Abs. 3 five-year spreading, the beitragsfreie Versicherungssumme.age(t) = issue_age + duration(t)steps on the anniversary and not monthly, andis_anniv(t) = (t % 12 == 11)marks the month the annual machinery acts in. The contractual policy year is the 1-based labelpolicy_year(t) = duration(t) + 1, and it is derived, never indexed by: it is the key into the tables whose own column is calledpolicy_year.Where the frame starts, and
proj_len().proj_len_y() = policy_termis the number of policy years and what every annual construction is written against;proj_len() = 12 · proj_len_y()is the frame’s exclusive end. The frame runst = t_start() … proj_len() − 1contiguously witht_start() = 12 · duration_init—duration_initbeing an elapsed count of policy years, so the conversion is a multiplication — andk_start() = duration_initis its annual counterpart. Henceresult_cf().index[-1] == proj_len() − 1,len(result_cf()) == proj_len() − t_start(),result_cf().index[0] == t_start()andpols_if(t_start()) == pols_if_init()on every model point. This is lifelib’s ownfor t in range(proj_len()). The Ablauf falls at the end of the last month; there is not = proj_len()row.result_cf_annual()sums the frame into policy years and is the view the worked example below is stated on.Timing conventions std. A Beitrag instalment on the Zahlweise’s own cycle at the beginning of the month — one month in twelve for an annual payer, every month for a monthly one; acquisition expense and initial commission in month
t_start()at issue, as single amounts and not twelfths; one twelfth of the maintenance expense and the renewal commission on the instalment, at the beginning of the month on the in-force; the guaranteed Deckungskapital rolling forward over the policy year at the Rechnungszins; the surplus declared and credited at the anniversary on that year’s closing reserve; death and maturity claims at the end of the month; surrender at the end of the month, after the mortality decrement.What a mid-year exit is paid std. A death or surrender in a non-anniversary month is paid the balances standing at the end of that month — which are the ones struck at the last anniversary, the year’s declaration not having happened yet. So
av_sur_close_pp,bonus_si_close_pp,term_bonus_close_ppandres_guar_close_ppreturn the year’s own closing figure in an anniversary month and the previous one otherwise. On a gezillmert contract the guaranteed leg of a surrender is therefore exactly zero through the whole first policy year, which is the consumer fact this product is best known for and one the annual grid could not express: it had to pay a month-0 surrender the value the coming anniversary would close at, a forward-looking payment at a date it is not yet due. The documented alternative — a pro rata temporis accrual of the year’s declared surplus — is a variant and not the base: no retrieved German wording describes one, and it would put an unsourced accrual rule inside the benefit. It reconciles at the anniversary just as exactly, so only the sources decide between them.What the § 169 value does not resolve. § 169 Abs. 3 VVG strikes the Rückkaufswert “zum Schluss der laufenden Versicherungsperiode” and § 12 VVG makes that period follow the Zahlweise, so on a monthly-paying contract the statute would strike it monthly. The model does not, and says so rather than interpolating: a monthly § 169 value needs a monthly Deckungskapital, and the tariff defines the Rechnungsgrundlagen der Prämienkalkulation on an annual Rechnungszins and an annual first-order table. The value standing between two anniversaries is the one struck at the last.
The Bilanzstichtag becomes the policy anniversary std. The sources put the allocation at the Bilanzstichtag, 31 December [S9]; on a policy-year grid that falls inside a policy year for every contract not written on 1 January, so the model allocates at the policy-year end. The effect is a timing shift of up to one year in the surplus credit, stated rather than hidden. The monthly grid does not narrow it: it is a mismatch between two annual clocks, not a resolution limit.
Age basis. Age last birthday at issue, stepping at the policy anniversary std — no located German endowment wording states one (
product-spec.md, footnote 6). The age steps att = 12, 24, …, and the monthly grid does not make it finer.Unisex pricing is a hard constraint.
sexis carried and drives the decrement lookup but must not enter the premium: § 20 Abs. 2 Satz 1 AGG was repealed and new business has been unisex since 21 December 2012 REG-R34. The pricing basis is a fixed portfolio blend; lettingsexleak intoprem_gross_ppreproduces a tariff unlawful in Germany since 2012 (pitfall 17).No account value in the unit-linked sense. The house vocabulary’s
prem_to_av_pphas no counterpart here and is not published: a Beitrag funds the Deckungskapital through the tariff, not a policyholder account, and the only true account is the Überschussguthaben, which receives surplus and never premium.withdrawalsis likewise absent — a classic German endowment has no partial-withdrawal right in any located wording.Currency, sign and rounding. EUR throughout.
net_cf(t)is income-positive (premiums +, claims, expenses and commission −), with the outgo-positive orientation published asliability_cf(t) = −net_cf(t). Intermediate values at full precision; displayed cash flows to euro cents andpols_ifto six decimals std.
Model point attributes#
Every column of model_point_table.csv is published as a cells of the same name.
Attribute |
Type |
Meaning |
Exercised by |
|---|---|---|---|
|
int |
Row key; |
all |
|
str |
Human-readable identifier |
all |
|
enum {M, F} |
Decrement lookup only; never a pricing input REG-R34 |
7 (F) |
|
enum {N, S} |
Feeds |
14 (S) |
|
int |
Cohort identity: fixes the DeckRV ceilings REG-R15 and the tax cohort R10 |
10 (2012) |
|
int |
Age last birthday at issue |
all |
|
int |
Completed policy years at the valuation date; 0 = new business. An elapsed count, so already 0-based: it is |
10 (14) |
|
float |
Policies represented at |
all |
|
int |
Versicherungsdauer, in years; equals |
all |
|
int |
Beitragszahlungsdauer ≤ |
2 (1), 3 (15) |
|
EUR |
Guaranteed Erlebensfallleistung (Versicherungssumme) |
all |
|
float |
Todesfallleistung ÷ Erlebensfallleistung; 1.00 = the endowment proper |
14 (0.60) |
|
enum {annual, half_yearly, quarterly, monthly} |
Payment frequency |
4–7 |
|
enum {echt, unecht} |
Whether the sub-annual premium is a genuine sub-annual Versicherungsperiode (no loading) or an instalment of an annual one (loaded) R28 |
4 / 5 |
|
rate |
The contract’s own guaranteed technical rate, fixed at conclusion REG-R14 |
10 (1.75%) |
|
0/1 |
Whether the Deckungskapital is gezillmert. std — § 4 DeckRV sets a ceiling, not a mandate R7, and no retrieved carrier wording is un-zillmered |
13 (0) |
|
str |
Key into |
all |
|
enum {ansammlung, bonus, beitragsverrechnung} |
Überschussverwendung R28 |
8, 9 |
|
str |
Key into |
3 (low), 14 (nil) |
|
float |
Risikozuschlag multiplier on the risk premium; 1.00 at standard rates R5 |
14 (1.50) |
|
EUR |
Überschussguthaben carried at the valuation date |
10 |
|
EUR |
Bonus sum insured already bought (Bonussystem, in force) |
— |
|
int |
Contractual, 1-based policy year at whose end Beitragsfreistellung is elected; 0 = never; ≤ |
11 (10), 12 (3) |
sum_assured and death_ratio are the two halves of the gemischte Versicherung, and the
Mindesttodesfallschutz R12 REG-R45 requires the death sum to be at least 50 % of the
Beitragssumme — a model-point design constraint, checked when the table is built, not a model
formula. rechnungszins is a contract term, not a market rate: fixed at conclusion and carried for the
whole term REG-R14, which is why the in-force point carries 1,75 % and new business 1,00 %.
The fourteen model points. Point 1 is the worked example’s anchor; the other thirteen each exercise
something it does not. Every one satisfies the Mindesttodesfallschutz R12 REG-R45 and carries a
rechnungszins at or below its cohort’s ceiling REG-R15.
# |
What it adds |
Key columns |
|---|---|---|
1 |
Anchor. New-business gemischte Versicherung, level annual premium over the full term |
M 37, term 25, |
2 |
Einmalbeitrag — the other premium form; the 25 ‰ Zillmersatz then buys almost nothing |
as 1 with |
3 |
Abgekürzte Beitragszahlungsdauer: premiums stop at 15, cover runs to 25; on the |
as 1 with |
4 |
Monthly, unecht — the 5 % Ratenzahlungszuschlag applies |
|
5 |
Monthly, echt — a genuine monthly Versicherungsperiode, so no loading R28 |
|
6 |
Half-yearly (2 % loading) |
|
7 |
Quarterly (3 % loading), female — the unisex-pricing pair with 1 |
|
8 |
Bonussystem — pairs with 1 for the R28 maturity/death asymmetry |
|
9 |
Beitragsverrechnung — the surplus reduces the Zahlbeitrag instead of a benefit |
|
10 |
In force, a 2012 cohort on a 1,75 % guarantee, opening at |
issue 2012, M 40, term 30, |
11 |
Beitragsfreistellung succeeding: premiums cease at the end of policy year 10 ( |
as 1 with |
12 |
Boundary. Beitragsfreistellung failing the Mindestversicherungsleistung, so the election becomes a surrender at the end of policy year 3 — |
M 45, term 20, SI 6,000, |
13 |
Non-gezillmert — the § 169 floor is then slack and the three reserves coincide. std: all four retrieved wordings that state a method apply § 4 DeckRV Zillmerung [S7] [S9] [S18], so this point exercises the ceiling being a maximum rather than a market option anyone was observed taking |
as 1 with |
14 |
Boundary. Unequal sums, old entry, a Risikozuschlag, and zero declared surplus |
M 55 smoker, term 12, SI 30,000, ratio 0.60, |
State variables#
Variable |
Description |
Updated |
|---|---|---|
|
Policies in force at the start of month |
monthly decrements |
|
Guaranteed Deckungskapital per policy at the start of policy year |
annual, prospective, with a roll-forward check |
|
Überschussguthaben per policy at the start of policy year |
annual recursion |
|
Accrued Schlussüberschussanteil at the start of policy year |
annual accrual |
|
The four balances above — and the § 169 value — standing at the end of month |
derived, monthly |
|
Whether the contract is beitragsfrei at the start of policy year |
set once, at the |
|
Beitragsfreie Versicherungssumme bought at the Beitragsfreistellung, or 0 where the Mindestversicherungsleistung test fails and the election became a surrender |
once per model point |
There is no unit fund, no policyholder account fed by premium and no partial-withdrawal ledger. The Überschussguthaben is a genuine account fed by declared surplus alone, and § 341f HGB confirms the separation from the other direction: the Deckungsrückstellung is formed excluding verzinslich angesammelte Überschussanteile REG-R54.
Assumption inputs#
The external CSVs. Every input is a plain UTF-8 CSV in the model folder’s parent, read once per
model by a reader cells in Data — the annuallife/TradLife_A layout, not basiclife/BasicTerm_S’s
embedded IOSpec. Every file but model_point_table.csv carries a final provenance column, one tag
per row: delib’s second ruling, machine-checked.
File |
Index columns |
Value columns |
|---|---|---|
|
|
the 22 further attributes of the table above (exempt from |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cost_table.csv deliberately carries the first-order tariff loadings and the second-order expense
assumptions on the same row, because the difference between them is the Kostenüberschuss, and
deckrv_table.csv carries both DeckRV ceilings — § 2’s Höchstrechnungszins and § 4’s
Höchstzillmersatz — keyed by issue_year, both being cohort facts that travel with the contract
REG-R14 REG-R15 REG-R16. The scalars that are not tables — mort_be_factor, suicide_share,
bfz_min_si, term_surr_share, bwr_rate and the two behaviour-module switches — are Projection
References, and their values and tags are in this section.
Three classes. Class (a) is contractual or statutory and is cited; class (b) is the insurer’s current discretionary declaration, revisable annually and capable of being zero [S3] [S9]; class (c) is the modeller’s view of experience. The split is the German Rechnungsgrundlagen erster und zweiter Ordnung distinction wearing different clothes REG-R47: (a) is the first-order basis, which fixes the Bruttobeitrag and the guaranteed benefits — the numbers the contract states — while (c) is the second-order basis, which drives the projection, and (b) is the output of the insurer’s policy for distributing the wedge between them.
(a) Contractual / guaranteed elements (cited)#
Input |
Value |
Basis |
|---|---|---|
Rechnungszins |
Model-point column; 1.00% for new business from 1 January 2025, the cohort’s rate otherwise |
|
Höchstrechnungszins ceiling by cohort |
3.50% to 06/1994; 4.00% to 06/2000; 3.25% to 2003; 2.75% to 2006; 2.25% to 2011; 1.75% to 2014; 1.25% to 2016; 0.90% to 2021; 0.25% to 2024; 1.00% from 2025 |
|
Höchstzillmersatz ceiling by cohort |
40 ‰ of the Beitragssumme to 2014, 25 ‰ from 1 January 2015; the rate used at conclusion applies for the whole term |
|
Zillmersatz |
25 ‰ of the Beitragssumme, at the ceiling |
|
Premium form and frequency |
Level Bruttobeitrag over the Beitragszahlungsdauer, in advance, ceasing on death [S7], on Beitragsfreistellung R3 and at the end of the Beitragszahlungsdauer; Ratenzahlungszuschlag 2% half-yearly, 3% quarterly, 5% monthly, applied only to |
|
The two benefits |
Erlebensfallleistung |
[S7] [S11] R1 [R18-family] |
Rückkaufswert |
The Deckungskapital on the Rechnungsgrundlagen der Prämienkalkulation, at the end of the current Versicherungsperiode, floored on Kündigung by the five-year-spread Mindestrückkaufswert, less a vereinbart, beziffert and angemessen Stornoabzug, plus the Überschussguthaben |
|
Beitragsfreistellung |
At the end of the current Versicherungsperiode, if the Mindestversicherungsleistung is reached; otherwise the insurer pays the § 169 value and the election becomes a surrender. The paid-up sum is computed on the § 169 value |
|
Selbsttötung |
Within three years of conclusion the insurer is leistungsfrei but must pay the Rückkaufswert including Überschussanteile — a benefit substitution, not a forfeiture |
|
Surplus allocation base and timing |
A percentage of the Deckungskapital — “in Prozent des maßgeblichen Deckungskapitals” [S7], the reserve “um ein Jahr mit dem Rechnungszins abgezinst” [S18], booked into the Deckungskapital at each Bilanztermin, 31 December [S9]. Entitlement timing varies across carriers: none at [S9], a one-year Wartezeit at [S18], three years at [S7] tariff group A and [S3]; the model takes the shortest, which is std |
[S7] [S18] [S9] [S3] R1 |
Beteiligung an den Bewertungsreserven |
Half of the amount determined on termination, but only to the extent it exceeds the Sicherungsbedarf. Zero in the base run |
The published history splits 1994 and 2000 mid-year REG-R15 and a year-keyed table cannot, so both split years take the higher of the two rates — 4,00 % — making
check_rechnungszins_cap()permissive rather than strict in exactly the two years where the model cannot know which half of the year a contract was written in. Years after 2026 carry 1,00 %, held flat std R15.§ 169 Abs. 3 VVG’s “gleichmäßige Verteilung … auf die ersten fünf Vertragsjahre” R2 is implemented as a straight-line amortisation of
alpha_costin five equal instalments; the alternative reading — a five-year Zillmerung — gives a slightly lower floor at durations 1 to 4 and the same value from duration 5, and is pitfall 5.
(b) Insurer-discretionary current elements (snapshot; revisable annually, and may be zero)#
Input |
Base value |
Basis |
|---|---|---|
Declared laufende Verzinsung |
2.70% p.a., level, whence the derived |
Allianz’s 2025 declaration for “die klassischen Lebens- und Rentenversicherungen”, i.e. a combined book, reported by the trade press R26 — the three Allianz pages state no declared rate at all [S11], and no carrier in this corpus publishes one for an endowment book; the retrieved named-carrier band is 2.25%–2.80% R26; level-forever std (3); derivation REG-R53 |
Schlussüberschussanteilsatz |
0.40% p.a. of the Deckungskapital, accrued and paid at the Ablauf and on death |
std (4) — no rate of any kind was established (gap 1) |
Ansammlungszinssatz |
2.70% p.a., equal to the declared rate |
mechanism R28; the § 28 RechVersV disclosure names the rate as a published quantity REG-R54; the level std (5) |
Scenarios |
|
|
Stornoabzug |
10% of the guaranteed value in years 1–5, 7.5% in 6–10, 5% in 11–15, 2.5% from 16 |
three carrier schedules on three bases: 0–20% of the Deckungskapital, decaying to nil over the last ten years, sub judice [S3] R22 R30; 50 € + 0,15% of premiums × years remaining [S9]; 100 € + 0,2% of (sum insured − reserve) [S18]; schedule std |
Bewertungsreserven rate |
0.00% |
Level for the whole projection is a modelling choice, not a forecast: the corpus supports a direction — about one in three insurers raised the rate for 2026, Allianz did not, the caution attributed to remaining stille Lasten R25 R26 — and no path, so two alternative paths ship as scenarios and the sensitivity is exercisable rather than argued.
Nothing in the corpus fixes a terminal-bonus level, for any insurer, in any year (gap 1). 0.40 % p.a. on the Deckungskapital makes the terminal share a visible but clearly secondary part of the maturity benefit; paying it at the Ablauf and on death and not on surrender is the choice that does not invent an entitlement the sources do not describe (
product-spec.md, footnote 12).Setting
ans_rate = decl_rateis a market convention rather than a sourced fact, and it matters for one reason: becauseans_rate > rechnungszins, the verzinsliche Ansammlung out-accumulates the Bonussystem at maturity while the Bonussystem pays more on an early death — exactly the asymmetry R28 records (pitfall 15). Settingans_rate = rechnungszinswould destroy it.
(c) Behavioural / experience assumptions (the modeller’s view)#
Every input in this class is std. No German insurer publishes a mortality basis, an expense loading, a commission scale or a lapse rate for this product, and the DAV tables are not public.
Mortality — two bases, one table. The first-order basis is mort_table.csv, a std Makeham-form
proxy, sex-specific, ages 0 to 120:
mort_rate_1st(M, x) = 0.00022 + B · 1.10^x with B fixed by the anchor below
mort_rate_1st(F, x) = 0.00016 + B · 1.10^(x − 3) a three-year setback on the same curve
The anchor is mort_rate_1st(M, 37) = 0.001200 exactly, which fixes B and makes the worked
example reproduce; the Data docstring states it.
The table is read twice, for two different purposes, and they must not be confused. The
tariff rate mort_rate_at_age(x) — what prices and what reserves — is a fixed unisex blend
of the two rows, ½ · q₁(M, x) + ½ · q₁(F, x) std, because German new business has been
unisex since 21 December 2012 REG-R34 and a tariff that priced on sex would be unlawful; the
blend itself is a portfolio mix no insurer publishes. The decrement is the policy’s own
sex-specific row, mort_rate_base(t), and the best-estimate basis is that scaled:
mort_rate(t) = mort_rate_base(t) × mort_be_factor with mort_be_factor = 0.75 std, so the
first-order table carries a 33 % safety loading. That wedge is the Sicherheitszuschlag and its
systematic release is the Risikoüberschuss REG-R47 — the model does not compute the surplus
from it, but the two must not be confused, and using one basis where the other belongs is pitfall 14.
The table this proxy stands in for is DAV 2008 T, the market-standard first-order basis for German death-benefit business, derived from insurers’ own policy data over the observation years 2001 to 2004 — the derivation paper was read for this pass and says so; 2006–2008, recorded here before, is when the DAV working group did the work — pooled from Gen Re, Münchener Rück, Swiss Re and the Verband öffentlicher Versicherer across 47 undertakings and more than 100 million Bestandsjahre, the cleansed insured data covering 60 % of the German market in the Kapitallebensversicherung segment R14. It is a single Schlusstafel built from data from the sixth policy year onwards to strip out selection, and there is no separate endowment table: about 91 % of the observations behind it are endowment data, and endowment mortality from the sixth year is 101 % of the all-tariff level R14. It is the property of the Deutsche Aktuarvereinigung, is not public and is not redistributed here R14 REG-R47 REG-R48. A replacement must preserve four things: an insured-lives, not population, level, materially lighter than Destatis at the working ages REG-R52; sex-specific base tables, the raw material even though a tariff may not price on sex REG-R34; no projected improvement, because for a death cover improvement favours the insurer REG-R48; and an explicit Sicherheitszuschlag directed upward for the death leg. The proxy carries no selection factors, which DAV 2008 T is understood to have REG-R48, so a book of newly underwritten lives shows more early deaths here than a real one — stated rather than corrected by a second unsourced factor. And the Richtlinie states the suitability limit in terms — “Die Sterbetafel DAV 2008 T ist grundsätzlich auch für die Beitragskalkulation von Lebensversicherungen mit Todesfallcharakter, ausgenommen Tarife ohne Gesundheitsprüfung, geeignet” R14 — so the whole basis presupposes the underwriting the composite specifies.
One table for two legs — a compromise. The death leg wants a prudent basis with mortality higher than expected and the survival leg one lower, so the direction of prudence forks and a single first-order table cannot be prudent for both REG-R47 REG-R48. German practice resolves this in the tariff rather than the table and the model follows: one first-order table for both legs, the compromise named here and asserted as pitfall 13 rather than papered over.
Lapse std. The decrement is surrender only. lapse_table.csv:
Policy year ( |
1–2 |
3–8 |
9–11 |
12 |
13+ |
final year |
|---|---|---|---|---|---|---|
|
5.0% |
3.5% |
2.0% |
6.0% |
2.5% |
0 |
The file’s key column is the contractual, 1-based policy_year, so the row for policy year 12 is
read at t = 11.
The shape is the one thing the evidence supports: the half-income tax rule needs twelve years and
age 60 or 62 R10 REG-R45, so surrenders are suppressed approaching duration 12 and spike at it,
exactly as the eight-year threshold drives French assurance vie REG-R45. The levels are not
sourced. The only German lapse datum is a market aggregate: “Die Stornoquote (Anzahl) stieg im Jahr
2023 leicht auf 2,56 % (Vorjahr: 2,51 %)” R20 — one count measure over all life business,
neither endowment-specific nor split by duration, so it cannot be a surrender decrement (pitfall 10).
The 2,72 % for 2024 and the second 1,2 % measure recorded here before this pass are not in the
retrieved GDV publication and are withdrawn. What the supervisor adds is directional rather than
numerical: some products show “sehr hohen Stornoquoten … speziell in den ersten Jahren nach
Vertragsabschluss”, which is the shape of the first two rows above R18. In the final
policy year the rate is zero: the end of year t = n − 1 is the Ablauf, so the survivors leave as
a maturity. Unlike frlib’s term product this is not a bookkeeping split — a final-year surrender would pay
the § 169 value while a maturity pays the sum insured plus surplus — so it decides a real payment, and
is stated as an assumption and asserted as pitfall 18.
Expenses, commission and the tariff loadings, side by side. cost_table.csv carries both, on one
row per cost_id, because the difference between them is the Kostenüberschuss:
Input |
Basis |
Class |
Tag |
|---|---|---|---|
|
25 ‰ of the Beitragssumme, zillmered |
first order |
|
|
3.0% of the Bruttobeitrag, over the Beitragszahlungsdauer |
first order |
|
|
1.5 ‰ of the Versicherungssumme p.a., over the Versicherungsdauer |
first order |
form not established, gap 17; std |
|
300 EUR per policy at issue |
second order |
|
|
2.5% of the Beitragssumme at conclusion |
second order |
set at the 25 ‰ zillmering ceiling R7, which is not a commission cap — “Eine Deckelung der Provisionen ist gesetzlich nicht vorgesehen” R29; no carrier commission rate is established, so std with no observation behind it |
|
1.5% of the Bruttobeitrag from year 2 (Bestandsprovision) |
second order |
|
|
45 EUR per in-force policy p.a. |
second order |
|
|
1.8% p.a. |
second order |
|
|
120 EUR per death, maturity or surrender claim |
second order |
No charge level of any kind was established for any German carrier (gap 7). The levels are placeholders sized so the first-year acquisition outgo — 300 EUR plus 2,5 % of the Beitragssumme — modestly exceeds what the Zillmerung recovers, so the anchor carries the new-business strain a real German endowment carries. The Effektivkosten they produce is a validation target, not an input: reproducing one needs the PRIIPs Annex VI algorithm and a holding period, neither of which delib implements R9 R19 REG-R31 REG-R32.
Suicide share suicide_share = 0.02 std. § 161 VVG substitutes the Rückkaufswert for the sum
insured on the suicide sub-cause of death in the first three policy years R4 REG-R26. No source
gives a suicide share of deaths at any age, so 2 % is a placeholder standing for “about one death in
fifty in the window is an excluded suicide”. Setting it to zero is a defensible variant; paying nil
instead of the Rückkaufswert is not (pitfall 7). The Bewertungsreserven share is zero for the
reason in product-spec.md, footnote 13, and there is no dynamic lapse formula in the base run — the
optional modules are under Policyholder behaviour modelling.
Cash flow components and recursions#
Notation (defined once, used throughout)#
Symbol |
Cells |
Meaning |
|---|---|---|
|
— |
month index, 0-based from issue, |
|
|
completed policy years at the start of month |
|
|
contractual, 1-based policy year label, |
(anniv) |
|
whether month |
|
|
Versicherungsdauer; Beitragszahlungsdauer. |
|
|
attained age at the start of policy year |
|
|
guaranteed survival sum; guaranteed death sum |
|
|
first-order interest rate; |
|
|
first-order tariff mortality at attained age |
|
|
best-estimate annual mortality of month |
|
|
the monthly rate applied, |
(table) |
|
this policy’s own sex-specific first-order annual rate |
|
|
annual surrender rate of the policy year; Stornoabzug rate at duration |
|
|
the monthly rate applied, |
|
|
policies in force at the start of month |
|
|
Zillmersatz; premium loading; sum-insured loading; Ratenzahlungszuschlag, 1.000 where |
|
|
annual Bruttobeitrag before |
|
|
net level premium; Zillmer premium |
|
|
Deckungskapital at the start of policy year |
|
|
the § 169 guaranteed value at the end of policy year |
(closing) |
|
the same value standing at the end of month |
|
|
Rückkaufswert actually payable on a surrender at the end of month |
|
|
Überschussguthaben; bonus sum insured; accrued Schlussüberschussanteil |
(closing) |
|
the same three standing at the end of month |
|
|
declared rate; interest-surplus rate; Ansammlungszinssatz; terminal rate |
|
|
surplus allocated to the contract for policy year |
|
|
premium instalments a policy year: 1 / 2 / 4 / 12, with |
q₁, q, w, σ, d, z, a, s are dimensionless annual rates; SE, SD, B, V, U,
Z, S are EUR per policy; every cash-flow component is EUR per policy year.
The first-order basis and the pricing equivalence#
First-order survival from issue and the two annuities-due, computed by summation on the model point’s
own sex and rechnungszins:
tpx_1st(k) = Π_{j=0}^{k-1} ( 1 − q₁(x_0 + j) ), tpx_1st(0) = 1
pv_death_1st = SD · Σ_{k=0}^{n-1} v₁^(k+1) · tpx_1st(k) · q₁(x_0 + k)
pv_maturity_1st = SE · v₁^n · tpx_1st(n)
pv_benefit_1st = pv_death_1st + pv_maturity_1st
ann_due_prem_1st = Σ_{k=0}^{m-1} v₁^k · tpx_1st(k)
ann_due_term_1st = Σ_{k=0}^{n-1} v₁^k · tpx_1st(k)
The Bruttobeitrag is struck by equivalence, which is linear in B because BS = B · m:
B · ann_due_prem_1st = pv_benefit_1st + α · B · m
+ β · B · ann_due_prem_1st + γ · SE · ann_due_term_1st
⇒ prem_gross_pp = ( pv_benefit_1st + γ · SE · ann_due_term_1st ) / ( (1 − β) · ann_due_prem_1st − α · m )
check_equivalence() asserts that identity closes. Note that the acquisition cost α · BS is in
the premium whether or not the contract is zillmered: Zillmerung decides where the cost sits in the
reserve, not whether it is charged (zillmer_on enters alpha_cost, not the pricing equation).
That is why zillmer_on moves the reserve profile and the surrender values without moving
prem_gross_pp at all. The risk element carries the Risikozuschlag: rating_factor multiplies q₁ in the
death leg of pv_death_1st only, never the survival leg, never the benefit, and never a
best-estimate rate (pitfall 12).
Then the two reserving premiums, and the zillmered cost:
beitragssumme = prem_gross_pp · m
alpha_cost = zillmer_on · alpha_rate · beitragssumme
prem_net_level_pp = pv_benefit_1st / ann_due_prem_1st
prem_zill_pp = prem_net_level_pp + alpha_cost / ann_due_prem_1st
Single premium. prem_term = 1 gives ann_due_prem_1st = 1 and BS = B, so the 25 ‰
Zillmersatz buys almost nothing and the § 169 floor is slack from the first anniversary. That is
the correct answer, not a degenerate case.
The Deckungskapital#
Prospectively, at the start of year t (duration k = t), on the first-order basis, over the
remaining term and the remaining premium period:
pv_benefit_fut(t) = SD · Σ_{j=0}^{n-k-1} v₁^(j+1) · jp(x(t)) · q₁(x(t)+j) + SE · v₁^(n-k) · (n-k)p(x(t))
ann_due_prem_fut(t) = Σ_{j=0}^{max(0, m-k)-1} v₁^j · jp(x(t))
res_net_pp(t) = pv_benefit_fut(t) − prem_net_level_pp · ann_due_prem_fut(t)
res_zill_pp(t) = res_net_pp(t) − alpha_cost · ann_due_prem_fut(t) / ann_due_prem_1st
res_min_pp(t) = res_net_pp(t) − alpha_cost · max(0, 1 − t / 5)
res_pp(t) = res_zill_pp(t) while premium-paying
= bfz_si_pp · pu_single_prem(t) once paid-up
Three facts about those three lines. res_zill_pp(0) = −alpha_cost exactly: the gezillmerte
Deckungskapital is negative at issue, which is the arithmetic of R28 and the reason § 169
Abs. 3 needs a floor at all. How long it stays negative is a parameter question, not a structural
one, and on the shipped basis the answer is under a year: 25 ‰ of a twenty-five-year
Beitragssumme is 0,625 of one annual premium, so the first Zillmer premium more than repays it and
the reserve is positive from the first anniversary (−1 252,53 € opening, +570,75 € closing, on the
anchor cell). Under the pre-2015 40 ‰ ceiling R7 REG-R16, or on a long term with a short
Beitragszahlungsdauer, it is negative for longer. res_min_pp is that floor, on the
straight-line reading of the five-year spreading. And the floor normally binds:
ann_due_prem_fut(t)/ann_due_prem_1st falls roughly linearly over m years while max(0, 1 − k/5)
reaches zero after five, so res_min_pp(t) ≥ res_zill_pp(t) at every duration on a long gezillmert
contract, with equality only at durations 0 and m. A model publishing only the Zillmer reserve as
the surrender value understates it at essentially every duration; one publishing only the floor loses
the quantity the Deckungsrückstellung and the paid-up sum are built on (pitfall 4). With
zillmer_on = 0 all three coincide and the floor is slack — a useful invariance test.
Rückkaufswert, Beitragsfreistellung and the paid-up sum#
G(t) is struck at the end of policy year t — on the reserve at the start of year t + 1 —
because that is what “zum Schluss der laufenden Versicherungsperiode” requires R2:
res_guar_pp(t) = max( res_zill_pp(t+1), res_min_pp(t+1), 0 )
surr_value_pp(t) = res_guar_pp(t) · (1 − storno_rate(t)) + av_sur_pp_at(t, "AFT_CREDIT")
+ term_surr_share · term_bonus_pp(t+1)
pu_single_prem(t) = SD/SE · Σ_{j} v₁^(j+1) · jp(x(t)) · q₁(x(t)+j) + v₁^(n-k) · (n-k)p(x(t))
bfz_si_pp = res_guar_pp(e) / pu_single_prem(e + 1), e = bfz_year − 1
e = bfz_year − 1 is the 0-based index of the election year: bfz_year is the contractual,
1-based policy year at whose end the election falls, so that end is the end of period e and the
start of period e + 1 = bfz_year.
pu_single_prem(t) is the first-order single premium for one unit of paid-up endowment over the
remaining term, so bfz_si_pp is the beitragsfreie Versicherungssumme the § 169 value will buy —
exactly what § 165 prescribes, “auf der Grundlage des Rückkaufswertes nach § 169 Abs. 3 bis 5” R3.
Three rules ride on those four lines:
The Stornoabzug bites on the guaranteed value only, not on the Überschussguthaben: Debeka’s published deduction is a percentage of the Deckungskapital [S3] R30 (pitfall 6).
term_surr_share = 0in the base run std — the accrued Schlussüberschussanteil is paid at the Ablauf and on death, not on surrender (product-spec.md, footnote 12); the parameter is exposed.The Mindestversicherungsleistung test: if
bfz_si_pp < bfz_min_si(2,500 EUR std) the election is not a Beitragsfreistellung — § 165 VVG obliges the insurer to pay the § 169 value instead, so the model converts the point to a surrender at the end of yeare = bfz_year − 1and the projection terminates there R3 (pitfall 8). Model point 12 exercises that branch.
Where the election succeeds the contract stays in force with bfz_si_pp in place of SE, no further
premium and a reserve bfz_si_pp · pu_single_prem(t). Because the § 169 floor generally exceeds the
Zillmer reserve, the paid-up sum bought is worth more than the Zillmer reserve released; that
difference is bfz_uplift_pp, which enters the roll-forward identity so check_res_roll_fwd() still
closes in the election year.
The Überschussbeteiligung#
Declared annually, as a percentage of the Deckungskapital, allocated at the period end [S7] [S18] [S9]:
zins_ueberschuss_rate(t) = max( 0, decl_rate(t) − rechnungszins )
surplus_base_pp(t) = max( res_pp_at(t, "AFT_INT"), 0 )
surplus_credit_pp(t) = zins_ueberschuss_rate(t) · surplus_base_pp(t)
term_bonus_pp(t+1) = term_bonus_pp(t) + term_rate(t) · surplus_base_pp(t)
res_pp_at(t, "AFT_INT") is the closing guaranteed reserve of policy year t, before this year’s
surplus is applied. That is a std reading of a base the wordings state three ways: Gothaer’s
“maßgebliches Deckungskapital” is undefined in the wording [S7]; VPV takes the reserve “um ein Jahr mit
dem Rechnungszins abgezinst”, i.e. an opening rather than a closing balance [S18]; and die Bayerische
accrues monthly on “das am Anfang des Monats vorhandene DECKUNGSKAPITAL (inklusive eines ggf. fälligen
Beitrags, abzüglich der zum Monatsbeginn fälligen Kosten)” [S9]. On a one-year grid the closing
balance is the natural annual analogue of a monthly accrual over the year, and the difference against
VPV’s opening balance is one year’s interest on the base. The max(0, ·)
on the base is load-bearing: the gezillmerte Deckungskapital is negative in the early years, and a
positive rate on a negative base would credit a negative surplus (pitfall 3). It follows that a
gezillmert contract earns no interest surplus in its first years even though § 153 entitlement
runs from inception where the wording grants it from inception [S9] — economically right, because
there is no fund to earn on, and worth saying
because it looks like a bug. The max(0, ·) on the rate is the other half: in the nil scenario the
declared rate is below the guarantee, which the reserve roll-forward still meets in full, so the surplus
is zero and not negative (pitfall 1).
Then the three Überschussverwendung systems:
ansammlung: av_sur_pp(k+1) = av_sur_pp(k) · (1 + ans_rate(k)) + surplus_credit_pp(k)
bonus: bonus_si_pp(k+1) = bonus_si_pp(k) + surplus_credit_pp(k) / pu_single_prem(k+1)
beitragsverrechnung: prem_offset_pp(k) = min( prem_charged_pp(k), surplus_credit_pp(k-1) ) for k > k_start
= 0 at k = k_start
All three are policy-year ledgers, and the monthly grid does not subdivide any of them: the declaration is an annual act.
Under ansammlung the surplus compounds at ans_rate and raises the maturity benefit; under bonus
it buys paid-up insurance at first-order rates, raising the death benefit immediately by the full
bonus sum but accumulating only at rechnungszins; under beitragsverrechnung it reduces the
Zahlbeitrag and neither balance grows. Because ans_rate > rechnungszins the first gives a higher
maturity benefit and the second a higher death benefit — exactly the asymmetry R28 states, and
the test that distinguishes them (pitfall 15).
Published identities#
Ten check_*() cells, each taking no argument, returning a bool and carrying a per-argument
residual at check_*_resid. The residual’s argument says which clock the identity lives on: the
three that state an annual identity — the Fackler roll-forward, the surplus ledgers and the § 169
floor — take a policy year k; the other seven take a month t. The conventions suite calls every one
on every model point.
Identity |
What it asserts |
|---|---|
|
delib’s first ruling. |
|
|
|
|
|
The Fackler recursion on the guaranteed Deckungskapital, per policy year: |
|
The active surplus vehicle’s ledger closes, per policy year: |
|
§ 169 Abs. 3, per policy year: |
|
The Rückkaufswert is non-negative in every month. Added with the monthly grid, which quotes one in the eleven months of each policy year the annual grid never priced — months paid on the last anniversary’s § 169 value, which is a different and smaller number |
|
The first-order pricing equivalence closes: |
|
The two DeckRV cohort ceilings: |
The last two are parameter invariants rather than roll-forward identities, and they live here rather than in a build script because a German model point’s cohort is an assumption: a 4,00 % guarantee on a 2026 issue year is not a stress, it is a data error.
Processing order#
Two loops, one inside the other. The annual one runs over k = k_start() … n − 1 and is exactly
the order the annual-step model ran in; the monthly one runs over the twelve months of each policy
year and is what the frame publishes.
The annual layer, for policy year k:
Open the year.
x(k) = issue_age + k; carry inres_pp(k),av_sur_pp(k),bonus_si_pp(k),term_bonus_pp(k),is_paid_up(k).Decide whether a premium is due:
k < prem_termand notis_paid_up(k)— themannual premiums fall ink = 0 … m − 1. Applyφonly whereunterjaehrig_form = unecht.Apply the Beitragsverrechnung offset, where elected: last year’s declared surplus reduces this year’s Zahlbeitrag, floored at zero. That fixes the year’s annual
prem_paid_pp(k).Roll the guaranteed Deckungskapital forward one year on the first-order basis — interest at
rechnungszins, mortality release at the unisex tariff ratemort_rate_at_age(x(k))— tores_pp_at(k, "AFT_INT"), the closing guaranteed reserve. This is the allocation-date Deckungskapital.Declare and credit the surplus at the anniversary:
z(k) = max(0, d(k) − i₁), basemax(res_pp_at(k, "AFT_INT"), 0), creditC(k), and accrueterm_rate(k)on the same base.Apply the surplus per
surplus_use— accumulate it, buy bonus sum insured, or carry it forward as next year’s premium offset.The Beitragsfreistellung election, where
k = bfz_year − 1: strikeres_guar_pp(k), buybfz_si_pp, and test it againstbfz_min_si— below the minimum the election becomes a surrender, and it falls in that policy year’s last month.Strike the § 169 value
res_guar_pp(k)at the year’s end, and roll forwardres_pp(k+1),av_sur_pp(k+1),bonus_si_pp(k+1),term_bonus_pp(k+1),is_paid_up(k+1).
The monthly layer, for t = t_start() … 12n − 1 with k = duration(t):
Open the month. Carry in
pols_if(t); read the year’s annual ratesq(t)andw(t)and the monthly rates derived from them,qᵐ(t)andwᵐ(t).Collect the premium instalment in advance, where
prem_due(t):premiums(t) = prem_inst_pp(t) × pols_if(t). A life that dies or surrenders later in the month has already paid that instalment; do not net it again (pitfall 11).Charge beginning-of-month expenses and commission on the in-force: one twelfth of the maintenance expense, and the renewal commission on the instalment charged. The acquisition expense and the initial commission fall in month
t_start(), and only for a new-business point — as single amounts, not twelfths.End of month, deaths at the best-estimate monthly
qᵐ(t): the benefit is the guaranteed death sum plus the three surplus balances standing at the end of that month, with the § 161 substitution of the Rückkaufswert on the suicide share forduration(t) < 3— the first thirty-six months.End of month, maturity or surrender. At
t = 12n − 1the survivors of that month’s mortality mature and take the Erlebensfallleistung; the projection stops. Otherwisewᵐ(t)applies to the survivors of mortality and payssurr_value_pp(t), on the § 169 value standing at the last anniversary.Roll forward
pols_if(t+1).
The two layers meet at the anniversary, month 12k + 11: the annual layer’s step 5 credit and step 8
value are the balances the monthly layer’s steps 4 and 5 pay in that month and in no other.
The annual layer’s step order is the one thing a reader should check first. The surplus is declared on
the reserve after the year’s interest, so a policy dying at the anniversary closing policy year
k receives that year’s declared surplus — which follows the sources, the allocation being made at the
Bilanzstichtag to the contracts then in force [S9], and is the generous reading. A policy dying in
any of that year’s other eleven months does not, and that is the conversion’s own decision, stated
under Model scope and conventions: the declaration has not happened yet, so the balances standing are
the last anniversary’s.
Known modeling pitfalls#
These are the specific ways an implementation of this product looks right and is wrong. Each one is
a test in tests/test_kapitallebensversicherung_de.py.
Adding the declared rate on top of the guarantee. The laufende Verzinsung is the Garantieverzinsung plus the laufende Zinsüberschussbeteiligung REG-R53, so a declared 2,70 % on a 1,00 % guarantee is a 1,70 pp surplus credit and not 2,70 pp on top of 1,00 pp. Assert
zins_ueberschuss_rate(k) == max(0, decl_rate(k) − rechnungszins)in every policy year, and that on thenilscenario it is exactly 0 while the reserve still rolls forward at the fullrechnungszins.Applying the surplus rate to the sum insured or to the premium. The base is the Deckungskapital at the allocation date [S3]. Assert
surplus_credit_pp(k) == zins_ueberschuss_rate(k) · max(res_pp_at(k, "AFT_INT"), 0)and thatsurplus_credit_ppis invariant tosum_assuredonce the reserve is held fixed — the quickest way to catch a× sum_assuredwhere a× res_ppbelongs.Crediting surplus on an un-floored negative reserve. The gezillmerte Deckungskapital is negative at issue R28. Assert
surplus_base_pp(k) ≥ 0in every policy year and thatsurplus_credit_pp(k) == 0whereverres_pp_at(k, "AFT_INT") < 0. On the shipped 25 ‰ basis that set is empty, because the base is the closing reserve and it is positive from policy year 1 — so the assertion holds vacuously on every shipped model point, and it is stated here as what it is: a guard against a parameter this run does not use (the pre-2015 40 ‰ ceiling, or a long term with a short Beitragszahlungsdauer), not a behaviour the base run exhibits. The test should therefore also assert the guard directly, by evaluating the credit against a negative base. Entitlement from inception [S9] does not mean a positive credit from inception.Implementing one reserve where the product has three.
res_zill_ppis what the insurer reserves,res_min_ppis the § 169 Abs. 3 floor and normally binds, andres_guar_ppis their maximum and what the customer gets. Assertres_guar_pp(k) ≥ res_zill_pp(k+1)and≥ res_min_pp(k+1)in every policy year, that the floor is strictly binding at some duration on the anchor cell, and that on model point 13 (zillmer_on = 0) all three coincide.Conflating the § 169 five-year spreading with the § 4 DeckRV 25 ‰ cap. § 169 Abs. 3 VVG fixes how the acquisition cost is spread for the surrender floor — a floor on the value — while § 4 DeckRV fixes how much may be zillmered at all — a cap on the charge R2 R7 REG-R16 REG-R28 (gap 5). Assert
check_zillmer_cap()against the cohort ceiling andcheck_surr_floor()against the five-year schedule, separately.Deducting the Stornoabzug from the Überschussguthaben. Debeka’s published deduction is a percentage of the Deckungskapital [S3] R30. Assert
surr_value_pp(t) − av_sur_close_pp(t) == res_guar_close_pp(t) · (1 − storno_rate(duration(t)))in every month of the base run, so the accumulated surplus passes through undeducted — and note that the deduction band is a policy-year band and steps on the anniversary while the value it bites on is the one standing at the end of the month.Paying nil on a suicide inside the three-year window. § 161 VVG makes the insurer leistungsfrei and obliges it to pay the Rückkaufswert including Überschussanteile under § 169 R4 REG-R26: the German rule is a benefit substitution, not a forfeiture, unlike art. L. 132-7 of the French code. Assert
benefit_death_pp(t) == 0.98 · benefit_full_pp(t) + 0.02 · surr_value_pp(t)forduration(t) < 3— policy years 1 to 3, the first thirty-six months, the window being measured in whole years so that its boundary falls on an anniversary — and== benefit_full_pp(t)from month 36, and thatbenefit_death_pp(0) > 0even wheresurr_value_pp(0)is nil, which on a gezillmert contract it is through the whole first policy year.Offering Beitragsfreistellung without the Mindestversicherungsleistung test. § 165 VVG makes the election a surrender where the minimum is not reached R3. Assert that model point 11 (
bfz_year = 10) continues in force toproj_len() − 1withprem_paid_pp(k) == 0fromk = 10— the election falls at the end of policy year 10,k= 9, month 119 — and that model point 12 (bfz_year = 3, small sum) instead terminates in month 35 with aclaims_lapsepayment and nothing thereafter. That month, and not the first month of the election year, is wherelapse_rate_mthplaces the statutory 1.0: the election falls at the end of a Versicherungsperiode and spreading an annual 1.0 geometrically would empty the cohort eleven months early.Removing the paid-up policy from
pols_if. Beitragsfreistellung keeps the contract alive with a reduced sum insured R3 [S7]; only a Kündigung removes it. Assertpols_if(t)is unaffected bybfz_yearon model point 11 relative to the anchor, whileprem_paid_ppandbenefit_maturity_ppboth fall.Calibrating the surrender decrement to GDV’s headline Stornoquote. The GDV publishes one figure, “Die Stornoquote (Anzahl) stieg im Jahr 2023 leicht auf 2,56 % (Vorjahr: 2,51 %)” R20: a count measure over all German life business, not a surrender rate, not endowment-specific and not split by duration. It is the wrong quantity in three ways at once, and duration is the one that bites hardest — BaFin’s finding is that lapse is concentrated “speziell in den ersten Jahren nach Vertragsabschluss” R18, which no single annual average can express. Assert that
lapse_ratecomes fromlapse_table.csv, that it is the annual rate of the policy year and is flat across its twelve months, that twelve oflapse_rate_mthcompound back to it exactly, and that its provenance column says std, not R20.Double-counting the premium-cessation rule. Premiums are in advance and decrements are at the period end, so a decedent has already paid the year’s premium. The rule behind this is contract termination, not a special clause: in the ordinary endowment the death payment ends the contract (“Mit der Auszahlung endet der Vertrag”) and no further premium can fall due [S7] § 3 I (5). The express stipulation “Bei Tod der versicherten Person vor dem Ablauftermin werden keine Beiträge mehr fällig” belongs to the Termfixversicherung [S7] § 3 II, where the benefit is payable at the fixed date irrespective of survival and the contract does not end on death — the one variant where premium cessation has to be said. Assert
premiums(t) == prem_inst_pp(t) · pols_if(t)with no(1 − qᵐ)factor. The finer grid narrows the error — 0,15 € in month 0 against 1,80 € in the first policy year on the annual grid — without removing the trap: there are now twelve times as many chances to apply it.Letting the Risikozuschlag reach the wrong quantity.
rating_factorscales the first-order mortality in the death leg of the pricing only R5. Assert thatbenefit_death_ppis invariant torating_factor, thatmort_rate(t)(the best estimate) is invariant to it, and thatprem_gross_pprises with it.Using one mortality table as if it were prudent for both legs. The direction of prudence forks: a death benefit wants mortality assumed higher than expected, a survival benefit lower REG-R47 REG-R48. The model uses one first-order table for both and says so; assert that the single table is in fact used for both legs, so the compromise stays visible.
Crossing the first- and second-order bases.
mort_rate_at_ageprices and reserves, on the unisex blend;mort_rate_baseis this policy’s own sex-specific table rate andmort_rateprojects. Assertmort_rate(t) == mort_rate_base(t) · mort_be_factorwithmort_be_factor = 0.75, thatres_ppis invariant tomort_be_factor, and thatpols_deathmoves with it. A model that reserves on the best estimate has thrown away the Sicherheitszuschlag that is the source of the Risikoüberschuss REG-R47.Expecting the two surplus systems to give the same benefits. “Compared with the Bonussystem, the verzinsliche Ansammlung leads to a higher payment at maturity, while the Bonussystem produces higher death benefits” R28. Assert exactly that between model point 1 (
ansammlung) and model point 8 (bonus). It holds becauseans_rate > rechnungszins, and a model that sets them equal fails it — correctly.Treating the Zahlbeitrag as guaranteed. Under Beitragsverrechnung the policyholder pays the Bruttobeitrag less a discretionary surplus offset, withdrawable without invoking § 163 VVG at all REG-R27 REG-R53. Assert on model point 9 that
prem_paid_pp(t) < prem_charged_pp(t)while surplus is being declared, thatprem_charged_pp(t)is unchanged from the anchor, and that on thenilscenario the offset is zero and the two coincide.Letting
sexinto the premium. Unisex since 21 December 2012 REG-R34. Assert thatprem_gross_ppis identical for two otherwise-identical model points differing only insex(points 1 and 7 both price at 2 004,0420 €), whilemort_ratediffers. This is why the pricing readsmort_rate_at_age, the fixed unisex portfolio blend — itself std — and notmort_rate_base, which is the policy’s own row; reading one where the other belongs is silent, and it moved the anchor’s premium by 9,15 € when it was first written that way.Running past the Ablauf, or letting a final-year surrender collide with the maturity.
proj_len() = 12 · policy_termis the frame’s exclusive end, so the last row ist = proj_len() − 1and there is not = proj_len()row.lapse_rateis 0 through the whole last policy year std, so the survivors of that last month’s mortality all leave as a maturity — and unlike a term product the two exits do not pay the same thing, a surrender paying the § 169 value and a maturity the sum insured plus surplus, so this is a real payment decision. Assertlapse_rate(t) == 0through months12(n − 1) … 12n − 1,pols_maturity(12n − 1) == pols_if(12n − 1) · (1 − mort_rate_mth(12n − 1)), and closure to 1e-12.
Policyholder behaviour modelling#
All formulas are std; no German calibration evidence exists for any of them.
Base surrender. The duration table above: shape driven by the tax thresholds — twelve years and age 60 or 62 R10 REG-R45 — levels unsourced. The anchor cell’s Ablauf at attained age 62 makes the two thresholds coincide, which is why a German buyer is sold that term and why the surrender rate collapses in the run-up to it.
The Beitragsfreistellung election is deterministic — a model-point column, not a decrement. The corpus establishes the right in full R3 and gives no take-up rate at all, and the one aggregate that would bear on it mixes the paid-up route in with surrenders and cannot be split R20. Modelling it as a scheduled election keeps the unsourced number out of the base run; what that costs is stated — a real book converts a material, duration-dependent share to beitragsfrei, and this model shows that path only where a model point elects it.
Two dynamic modules, both std and both off in the base run. Premium-shock lapse is inert on the base contract, whose Bruttobeitrag is level, but live under Beitragsverrechnung, where a fall in the declared rate raises the Zahlbeitrag:
M_shock(k) = 1 + β_shock · max(0, prem_paid_pp(k)/prem_paid_pp(k−1) − 1 − g0)on the annual Zahlbeitrag of consecutive policy years,g0 = 0.05,β_shock = 1.5, base runβ_shock = 0. Rate-gap lapse keys on the gap between the declared rate and what is available elsewhere:lapse_add(k) = a · max(0, ref_rate − decl_rate(k) − tol),a = 3.0,tol = 0.5 pp,ref_ratea model Reference, base runa = 0. Both compare annual declarations, which is what they are about; neither becomes a monthly comparison. No German calibration of any of these numbers exists in the corpus, which is why both ship off. Selective lapsation is not modelled either: surrenders on an endowment are wealth- and tax-driven rather than health-driven.What the model deliberately does not do. No premium-default path (§§ 37/38 VVG unresearched, gap 20); no Widerruf decrement (§ 152 VVG unresearched); no dynamic Beitragsverrechnung take-up; and no management action on the declared rate — the rate is a scenario, and the RfB and its Schlussüberschussanteilfonds REG-R54 that would smooth it are outside this model.
Worked example#
Configuration. Model point 1, the anchor cell of model_point_table.csv: policy_id
DE-KLV-0001; sex M; smoker N; issue_year 2026; issue_age 37;
duration_init 0, so t_start() = 0 and the projection opens at issue; pols_if_init 1.0;
policy_term 25, so proj_len_y() = 25 and proj_len() = 300, the frame is t = 0 … 299
months and the annual table below — the monthly frame summed into policy years — is the
entire projection, with the
Ablauf at attained age 62 — the age the half-income tax rule requires for a contract concluded
after 31 December 2011 R10 REG-R45; prem_term 25, the full term, so the contract is
premium-paying to the Ablauf; sum_assured 50,000.00 EUR; death_ratio 1.00, so the
guaranteed death sum equals the guaranteed survival sum and the contract is the gemischte Versicherung
auf den Todes- und Erlebensfall proper; prem_freq annual and unterjaehrig_form unecht, so
prem_freq_load = 1.000 and the Ratenzahlungszuschlag is inert; rechnungszins 1.00%, the
Höchstrechnungszins for new business written from 1 January 2025 R7 REG-R15; zillmer_on 1;
cost_id std_2026; surplus_use ansammlung; scenario_id base; rating_factor
1.00; av_sur_pp_init 0.00; bonus_si_init 0.00; bfz_year 0, so no
Beitragsfreistellung is elected. The Bruttobeitrag is not a model point column: it is derived
by the equivalence principle above and reported in the table, because no German endowment premium
rate table is public, for any carrier (gap 16).
Assumptions, each tagged. First order. Interest i₁ = 1.00% R7 R15 REG-R14 REG-R15.
Mortality mort_rate_1st(M, x) = 0.00022 + B · 1.10^x, B fixed by the anchor
mort_rate_1st(M, 37) = 0.001200 exactly std, standing in for DAV 2008 T, which is not
public and is not shipped R14 REG-R47 REG-R48; the tariff prices and reserves on the unisex
blend mort_rate_at_age(37) = ½ · 0.001200 + ½ · 0.000896288505 = 0.001048144253 std
REG-R34, and the anchor cell’s own decrement is mort_rate(0) = 0.001200 × 0.75 = 0.000900. Zillmersatz alpha_rate = 25 ‰ of the
Beitragssumme — the § 4 DeckRV ceiling R7 REG-R16, the level std. Premium loading
beta_rate = 3.0% of the Bruttobeitrag over the Beitragszahlungsdauer — the form is the one the
corpus establishes R28, the level std. Sum loading gamma_rate = 1.5 ‰ of the
Versicherungssumme p.a. over the Versicherungsdauer — the form itself is not established (gap
17) and both form and level are std. Ratenzahlungszuschlag prem_freq_load = 1.000 on the
annual mode R28.
Insurer-discretionary. Declared laufende Verzinsung decl_rate = 2.70% p.a. level — Allianz’s
2025 declaration for its combined classic life-and-annuity book as reported by the trade press
R26, the nearest thing in the corpus to a manufacturer figure touching an endowment book, the
level-forever assumption std; hence zins_ueberschuss_rate = max(0, 2.70% − 1.00%) = 1.70%, derived and
never added on top of the guarantee REG-R53. Schlussüberschussanteilsatz term_rate = 0.40% p.a.
of the Deckungskapital, accrued and paid at the Ablauf and on death, not on surrender
(term_surr_share = 0) — std, no rate of any kind having been established (gap 1).
Ansammlungszinssatz ans_rate = 2.70%, equal to the declared rate — std. Stornoabzug
storno_rate 10% of the guaranteed value in policy years 1–5, 7.5% in 6–10, 5% in 11–15 and 2.5% from
16 — std, against three observed carrier schedules on three incompatible bases: 0–20 % of the
Deckungskapital, decaying to nil over the last ten years, at Debeka and under collective action
after a BGH remittal [S3] R22 R30; 50 € + 0,15 % of premiums paid times the years remaining at die
Bayerische [S9]; and 100 € + 0,2 % of the gap between sum insured and Rückkaufswert at VPV [S18]. Bewertungsreserven bwr_rate = 0.00% —
std R1 R8 REG-R9.
Second order. Mortality mort_rate(t) = mort_rate_base(t) × 0.75 on this policy’s own
sex-specific row, mort_be_factor = 0.75 std
— a 33 % first-order safety loading, whose systematic release is the Risikoüberschuss REG-R47.
Surrender lapse_rate 5.0% in policy years 1–2, 3.5% in 3–8, 2.0% in 9–11, 6.0% in policy year 12
— the twelve-year tax threshold R10 REG-R45 — 2.5% from policy year 13, and 0 through the whole
of policy year 25, the Ablauf year — all std and all annual, no endowment-specific or
duration-specific German lapse rate having been established (gap 10); the schedule is keyed by the
1-based policy_year(t) = duration(t) + 1, and each annual rate is spread to the month at
1 − (1 − w)^(1/12) std.
Suicide share suicide_share = 0.02 for policy years 1 to 3, with the
Rückkaufswert substituted for the sum insured on that share R4 REG-R26 — the first
thirty-six months on the monthly frame, the window being measured in whole years so that its
boundary falls on an anniversary — the share std.
Expenses std throughout: acq_expense = 300.00 EUR at issue, comm_init_rate = 2.5% of the
Beitragssumme at issue — set at the 25 ‰ zillmering ceiling R7, which does not cap commission
R29, and with no carrier commission rate established anywhere in the corpus — maint_expense = 45.00 EUR per in-force policy p.a. inflating at expense_infl = 1.8% p.a.,
comm_renew_rate = 1.5% of the Bruttobeitrag from year 2, and claim_expense = 120.00 EUR per
death, maturity or surrender claim. No behaviour modules: β_shock = 0, a = 0.
All amounts in euros; pols_if to six decimals, cash flows and balances to the cent. Totals are summed
at full precision and then rounded, not summed from the rounded cells.
The derived tariff. The equivalence gives a Bruttobeitrag of 2 004,04 € a year, a
Beitragssumme of 50 101,05 €, alpha_cost 1 252,53 €, prem_net_level_pp
1 811,15 € and prem_zill_pp 1 868,92 €, on pv_death_1st = 3 611,698493 €,
pv_maturity_1st = 35 655,282574 € and ann_due_prem_1st = ann_due_term_1st = 21,680698 —
the two annuities coinciding because the Beitragszahlungsdauer is the whole
Versicherungsdauer.
The projection, policy year by policy year#
Transcribed from KLV_DE_S.Projection[1].result_cf_annual(), the monthly frame summed into policy
years. pols_if is the count at the start of the policy year — the number the annual-step model
carried on the same row, unchanged by the conversion; every other column is that year’s euro flow.
expenses excludes commission, so the six flow columns sum to net_cf exactly. The table is the
whole contract, policy years 1 to 25.
policy year |
age |
pols_if |
premiums |
claims_death |
claims_maturity |
claims_lapse |
expenses |
commissions |
net_cf |
|---|---|---|---|---|---|---|---|---|---|
1 |
37 |
1.000000 |
2,004.04 |
43.08 |
0.00 |
2.88 |
350.04 |
1,252.53 |
355.51 |
2 |
38 |
0.949145 |
1,902.13 |
44.26 |
0.00 |
40.88 |
48.26 |
28.53 |
1,740.20 |
3 |
39 |
0.900810 |
1,805.26 |
45.90 |
0.00 |
86.60 |
45.20 |
27.08 |
1,600.47 |
4 |
40 |
0.868365 |
1,740.24 |
49.00 |
0.00 |
142.18 |
44.30 |
26.10 |
1,478.66 |
5 |
41 |
0.837014 |
1,677.41 |
51.41 |
0.00 |
195.02 |
43.41 |
25.16 |
1,362.41 |
6 |
42 |
0.806716 |
1,616.69 |
54.04 |
0.00 |
251.21 |
42.54 |
24.25 |
1,244.66 |
7 |
43 |
0.777431 |
1,558.00 |
56.89 |
0.00 |
293.79 |
41.68 |
23.37 |
1,142.27 |
8 |
44 |
0.749121 |
1,501.27 |
60.00 |
0.00 |
334.28 |
40.84 |
22.52 |
1,043.63 |
9 |
45 |
0.721747 |
1,446.41 |
63.83 |
0.00 |
213.02 |
38.97 |
21.70 |
1,108.90 |
10 |
46 |
0.706081 |
1,415.02 |
68.58 |
0.00 |
237.51 |
38.78 |
21.23 |
1,048.91 |
11 |
47 |
0.690646 |
1,384.08 |
73.79 |
0.00 |
268.03 |
38.60 |
20.76 |
982.91 |
12 |
48 |
0.675431 |
1,353.59 |
78.01 |
0.00 |
876.44 |
40.95 |
20.30 |
337.88 |
13 |
49 |
0.633469 |
1,269.50 |
82.09 |
0.00 |
378.76 |
36.95 |
19.04 |
752.66 |
14 |
50 |
0.616105 |
1,234.70 |
88.23 |
0.00 |
404.57 |
36.56 |
18.52 |
686.82 |
15 |
51 |
0.599079 |
1,200.58 |
94.94 |
0.00 |
429.56 |
36.17 |
18.01 |
621.91 |
16 |
52 |
0.582376 |
1,167.11 |
102.28 |
0.00 |
464.10 |
35.77 |
17.51 |
547.45 |
17 |
53 |
0.565979 |
1,134.25 |
110.30 |
0.00 |
487.85 |
35.37 |
17.01 |
483.71 |
18 |
54 |
0.549875 |
1,101.97 |
119.08 |
0.00 |
510.74 |
34.97 |
16.53 |
420.66 |
19 |
55 |
0.534048 |
1,070.25 |
128.67 |
0.00 |
532.76 |
34.56 |
16.05 |
358.22 |
20 |
56 |
0.518483 |
1,039.06 |
139.15 |
0.00 |
553.89 |
34.14 |
15.59 |
296.29 |
21 |
57 |
0.503165 |
1,008.36 |
150.61 |
0.00 |
574.14 |
33.71 |
15.13 |
234.78 |
22 |
58 |
0.488079 |
978.13 |
163.12 |
0.00 |
593.48 |
33.28 |
14.67 |
173.58 |
23 |
59 |
0.473210 |
948.33 |
176.78 |
0.00 |
611.91 |
32.84 |
14.22 |
112.58 |
24 |
60 |
0.458543 |
918.94 |
191.69 |
0.00 |
629.39 |
32.39 |
13.78 |
51.69 |
25 |
61 |
0.444064 |
889.92 |
210.36 |
28,750.90 |
0.00 |
83.85 |
13.35 |
-28,168.54 |
Total |
16.648981 |
33,365.26 |
2,446.09 |
28,750.90 |
9,112.99 |
1,314.12 |
1,722.94 |
-9,981.79 |
The Total row is summed at full precision and then rounded, not summed from the rounded cells
above it, and on this cell the two differ. Adding the printed column gives 33,365.24 for
premiums against 33,365.26, 1,314.13 for expenses against 1,314.12 and −9,981.78 for net_cf
against −9,981.79 — the accumulation of twenty-five roundings of at most half a cent each.
pols_if behaves the same way: 16.648981 at full precision against 16.648982 from the printed
column. The other columns agree to the cent. Where a reader needs the totals to reconcile with
the printed cells rather than with the model, it is the printed cells that are the approximation.
The first policy year, month by month#
The view the annual grid could not show, from result_cf(). Month 0 collects the whole year’s
Beitrag — this cell is an annual payer — and bears the acquisition expense and the initial
commission; the other eleven collect nothing, carry a death claim and a twelfth of the maintenance
expense, and pay a surrender nothing guaranteed: the § 169 value standing before the first
anniversary is the one struck at issue, which on a gezillmert contract is zero. Only month 11
carries a surrender claim at all.
t |
pols_if |
premiums |
claims_death |
claims_lapse |
expenses |
commissions |
net_cf |
|---|---|---|---|---|---|---|---|
0 |
1.000000 |
2,004.04 |
3.68 |
0.00 |
304.27 |
1,252.53 |
443.57 |
1 |
0.995660 |
0.00 |
3.66 |
0.00 |
4.25 |
0.00 |
-7.91 |
2 |
0.991339 |
0.00 |
3.64 |
0.00 |
4.23 |
0.00 |
-7.88 |
3 |
0.987036 |
0.00 |
3.63 |
0.00 |
4.22 |
0.00 |
-7.84 |
4 |
0.982753 |
0.00 |
3.61 |
0.00 |
4.20 |
0.00 |
-7.81 |
5 |
0.978487 |
0.00 |
3.60 |
0.00 |
4.18 |
0.00 |
-7.78 |
6 |
0.974241 |
0.00 |
3.58 |
0.00 |
4.16 |
0.00 |
-7.74 |
7 |
0.970012 |
0.00 |
3.57 |
0.00 |
4.14 |
0.00 |
-7.71 |
8 |
0.965803 |
0.00 |
3.55 |
0.00 |
4.12 |
0.00 |
-7.68 |
9 |
0.961611 |
0.00 |
3.54 |
0.00 |
4.11 |
0.00 |
-7.64 |
10 |
0.957438 |
0.00 |
3.52 |
0.00 |
4.09 |
0.00 |
-7.61 |
11 |
0.953282 |
0.00 |
3.51 |
2.88 |
4.07 |
0.00 |
-10.46 |
Year 1 |
1.000000 |
2,004.04 |
43.08 |
2.88 |
350.04 |
1,252.53 |
355.51 |
The shape is worth naming. The first policy year very nearly washes — +355,51 € — the Beitrag of 2 004,04 € almost exactly meeting the initial commission of 1 252,53 € plus the 300 € acquisition expense, so the new-business strain of a gezillmert German endowment is in the reserve and not in the cash flow: the Deckungskapital opens at −1 252,53 €. The margin then runs near a thousand euros a year and decays with the cohort, dipping visibly in policy year 12 — 337,88 € against 982,91 € — where the surrender rate spikes to 6,0 % at the twelve-year tax threshold. The last year is a single outflow of −28 168,54 €.
The state behind it#
The same projection’s Deckungskapital, its surplus and what a surrender would pay, at ten
durations, from result_surplus(). res_pp(t) is the guaranteed reserve at the start of
year t; surplus_base_pp(t) is the same reserve at the end of that year, which is the
Deckungskapital at the allocation date; surr_value_pp(t) is what a surrender at the end of
year t receives.
t |
res_pp |
surplus_base_pp |
surplus_credit_pp |
av_sur_pp |
term_bonus_pp |
surr_value_pp |
|---|---|---|---|---|---|---|
0 |
-1,252.53 |
570.75 |
9.70 |
0.00 |
0.00 |
708.73 |
1 |
570.75 |
2,410.10 |
40.97 |
9.70 |
2.28 |
2,590.38 |
2 |
2,410.10 |
4,265.63 |
72.52 |
50.94 |
11.92 |
4,518.89 |
4 |
6,137.47 |
8,025.74 |
136.44 |
232.53 |
53.54 |
8,521.62 |
9 |
15,747.00 |
17,720.63 |
301.25 |
1,321.31 |
290.92 |
18,779.50 |
11 |
19,712.27 |
21,722.40 |
369.28 |
2,038.12 |
440.65 |
23,755.21 |
14 |
25,800.39 |
27,869.68 |
473.78 |
3,450.48 |
725.75 |
31,007.41 |
19 |
36,372.42 |
38,561.55 |
655.55 |
6,811.60 |
1,367.70 |
45,521.12 |
23 |
45,313.89 |
47,636.03 |
809.81 |
10,540.47 |
2,038.44 |
58,136.33 |
24 |
47,636.03 |
50,000.00 |
850.00 |
11,634.87 |
2,228.98 |
61,549.01 |
Two rows carry the product. At t = 0 the reserve is −1 252,53 € — exactly −alpha_cost,
the whole Zillmerung unrecovered — while the closing reserve the surplus is declared on is
already 570,75 €, so the credit is a small positive 9,70 € rather than the negative amount
an un-floored base would have produced from the opening figure. At t = 24 the closing reserve
is 50 000,00 € exactly: the last year’s Deckungskapital is the Erlebensfallleistung.
Three independent checks, and a closure identity#
Each rebuilds a cell of the tables above a different way, in arithmetic a reader can follow on a calculator. None of them re-runs the model’s own path to the number.
1. The Bruttobeitrag, from the equivalence. The premium is not an input; it is the
solution of B (1 − β) ä_m − α B m = pv_benefit_1st + γ SE ä_n. Numerator:
pv_benefit_1st = 3 611,698493 + 35 655,282574 = 39 266,981067, plus
γ SE ä_n = 0,0015 × 50 000 × 21,680698 = 1 626,052368, giving 40 893,033435.
Denominator: 0,97 × 21,680698 = 21,030277, less 0,025 × 25 = 0,625, giving 20,405277.
Then 40 893,033435 ÷ 20,405277 = 2 004,0420 €, the table’s Bruttobeitrag. The two
reserving premiums follow without touching the projection: prem_net_level_pp =
39 266,981067 ÷ 21,680698 = 1 811,1493 €, and prem_zill_pp = 1 811,1493 + 1 252,5263 ÷
21,680698 = 1 811,1493 + 57,7715 = 1 868,9208 €.
2. The reserve at the first anniversary, by Fackler. The state table gives
res_pp(1) = 570,75 € prospectively, as a present value of what remains. Rebuild it
retrospectively, forwards from the opening reserve. The unisex first-order rate at age 37 is
½ × 0,001200000000 + ½ × 0,000896288505 = 0,001048144253. Then
(−1 252,5263 + 1 868,9208) × 1,01 = 616,3945 × 1,01 = 622,5584; deduct the year’s death
outgo 0,001048144253 × 50 000 = 52,4072; divide the remaining 570,1512 by the survivors
1 − 0,001048144253 = 0,998951856, and the answer is 570,7495 €. The two agree to eight
figures, which is what check_res_roll_fwd() asserts in every policy year — and it is the strongest
statement in the model, because it holds only if the premium, the first-order mortality, the
Rechnungszins and the prospective formula are mutually consistent.
3. The surplus credited in policy year 2 (k = 1), and the Überschussguthaben it builds. The declared
rate is 2,70 % and the guarantee 1,00 %, so zins_ueberschuss_rate = 1,70 pp — derived by
subtraction, never added on top. The base is that year’s closing reserve, 2 410,101960 €, so
the credit is 0,017 × 2 410,101960 = 40,9717 €, the state table’s figure. It then compounds:
av_sur_pp(2) = 9,702741 × 1,027 + 40,971733 = 9,964715 + 40,971733 = 50,9364 €, and the
terminal share accrues on the same base, term_bonus_pp(2) = 2,282998 + 0,004 × 2 410,101960 =
2,282998 + 9,640408 = 11,9234 €. Both match the table to the cent.
4. The policy-year-12 surrender payment, from its three parts. Policy year 12 is k = 11,
months 132 to 143, and claims_lapse over it is 876,44 € — the one year where the § 169 floor, the
Stornoabzug and the surrender spike all bite at once. Count: the 0,675431 in force at the start
of the year decrement month by month at the 6,0 % annual spike spread to
1 − 0,94^(1/12), giving 0,04047664 surrenders over the twelve months, against 0,04043417 on
the annual grid — the difference being the monthly interleaving of the two decrements. Amount, at
the anniversary: the § 169 value at the end of that year is the floor, res_min_pp(12) =
22 413,4564 €, which exceeds the Zillmer reserve res_zill_pp(12) = 21 722,3990 € by 691,06 €
— the floor is binding, and this is what a model publishing only the Zillmer reserve would lose.
Apply the 5 % Stornoabzug to that and nothing else: 22 413,4564 × 0,95 = 21 292,7836 €, then add
the Überschussguthaben undeducted, 2 462,4255 €, for a Rückkaufswert of 23 755,2091 €.
The eleven other months are paid the value struck at the previous anniversary, 21 467,9479 €,
which is why the year’s claim is 876,44 € and not 960,52 €.
The closure identities. Over the whole projection the cohort accounts for itself exactly:
deaths 0,04355790, surrenders 0,51566656 and maturities 0,44077554 sum to
1,000000000000 — check_decrement_closure(). The maturing cohort is the annual-step model’s
own figure to the last digit, lapse being zero through the whole final policy year under either
grid; the split between the first two moved by 0,00054, which is what interleaving the two
decrements monthly genuinely changes. And the cash flow statement closes row by row; summed over
policy year 12, 1 353,591433 − 78,012539 − 0 − 876,440599 − 40,954555 − 20,303871 =
337,879869 € — check_net_cf(), this library’s first ruling, asserted in every month from
result_cf()’s own published columns rather than from the cells behind them.
The variant: the Einmalbeitrag#
Model point 2 is the anchor cell with prem_term changed from 25 to 1 and nothing else, so it
isolates the second premium form. The single premium is 43 273,05 €; the Beitragssumme is
that same amount, so the 25 ‰ Zillmersatz buys only 1 081,83 € of zillmered cost against
1 252,53 € on the level-premium form, and ann_due_prem_1st collapses to exactly 1.
policy year |
pols_if |
premiums |
claims_death |
claims_maturity |
claims_lapse |
expenses |
commissions |
net_cf |
|---|---|---|---|---|---|---|---|---|
1 |
1.000000 |
43,273.05 |
43.19 |
0.00 |
147.82 |
350.04 |
1,081.83 |
41,650.17 |
2 |
0.949145 |
0.00 |
45.68 |
0.00 |
1,728.58 |
48.26 |
0.00 |
-1,822.52 |
3 |
0.900810 |
0.00 |
48.10 |
0.00 |
1,181.37 |
45.20 |
0.00 |
-1,274.68 |
24 |
0.458543 |
0.00 |
236.84 |
0.00 |
813.28 |
32.39 |
0.00 |
-1,082.51 |
25 |
0.444064 |
0.00 |
260.17 |
35,570.54 |
0.00 |
83.85 |
0.00 |
-35,914.55 |
Total |
16.648981 |
43,273.05 |
2,894.48 |
35,570.54 |
22,825.77 |
1,314.12 |
1,081.83 |
-20,413.68 |
Four consequences are visible in five rows. The § 169 floor is slack from the first
anniversary — res_zill_pp(1) = 39 648,80 € against res_min_pp(1) = 38 783,34 €, the reverse
of the level-premium ordering, a single premium leaving almost nothing to amortise. The
surrender outflow is far larger throughout, 22 825,77 € in total against 9 112,99 €, every
surrendering policy carrying a reserve built in the first year. The monthly grid bites hardest
exactly here: policy year 1’s surrender claim falls from 1 816,26 € on the annual grid to
147,82 €, because the eleven months before the first anniversary are paid the § 169 value struck
at issue, which is zero — an Einmalbeitrag contract surrendered in its first months gets its
Überschussguthaben and nothing else, which is what the statute says and what the annual grid
could not express. And the maturity benefit is much higher, 80 699,89 € against 65 227,99 €.
The two forms’ net_cf totals are not comparable: the equivalence holds in present value on
tariff survivorship, not in undiscounted totals over a lapsing cohort.
The variant: the three Überschussverwendung systems#
Model points 8 and 9 differ from the anchor in surplus_use alone. The same surplus is
credited in all three; what differs is where it lands.
model point |
|
maturity benefit per policy |
death benefit per policy, month 59 |
premiums collected |
|
|---|---|---|---|---|---|
1 |
|
65,227.99 |
50,460.89 |
33,365.26 |
-9,981.79 |
8 |
|
63,562.77 |
50,532.10 |
33,365.26 |
-8,089.89 |
9 |
|
52,428.98 |
50,085.64 |
28,016.10 |
-8,318.08 |
The death benefit is read at month 59, the anniversary closing policy year 5 — the instant the annual grid priced, and unchanged by the conversion. A death earlier in that policy year is paid the balances standing at the previous anniversary and is strictly smaller on all three systems; the asymmetry between them survives that, which is what makes it a property of the product rather than of the grid.
That is exactly the asymmetry the sources describe, and it is arithmetic rather than
coincidence: the verzinsliche Ansammlung accumulates at ans_rate = 2,70 % and the
Bonussystem at rechnungszins = 1,00 %, so the first wins at the Ablauf by 1 665,22 €;
but the Bonussystem buys paid-up insurance, whose whole face amount is payable on death
at once, so the second wins on an early death by 71,21 €. A model that set the two rates equal
would lose the distinction, correctly. Beitragsverrechnung moves the surplus out of the
benefit stream entirely: premiums collected fall by 5 349,16 € and the maturity benefit falls to
the guaranteed sum plus the accrued terminal share alone.
What the conversion to a monthly step changed in these notes#
The model was moved from an annual grid to a monthly one after these notes were written, and the sentences that stopped being true were restated rather than left standing.
The frame.
tcounts policy months,proj_len() = 12 · policy_term, and the worked example is now two tables — the whole run summed into policy years byresult_cf_annual(), which is the view every figure quoted here is stated on, and the twelve months of policy year 1 beside it.Two clocks. Annual cells take a policy year
kand monthly cells a montht; the decrement rates taketand return the year’s annual rate, withmort_rate_mthandlapse_rate_mththe monthly rates actually applied, each1 − (1 − r)^(1/12)std.Nothing annual moved. The equivalence, all three reserves, the § 169 value, the paid-up purchase and every part of the Überschussbeteiligung are bit-identical to the annual-step model’s at every duration, because the monthly rates compound back to the annual ones and leave
pols_ifat every anniversary where it was.result_surplus()is unchanged, row for row.What a mid-year exit is paid. A claim in a non-anniversary month is now paid the balances standing at the last anniversary, which on a gezillmert contract makes the guaranteed leg of a surrender exactly zero through the whole first policy year. The annual grid had to pay a month-0 surrender the value the coming anniversary would close at.
The Zahlweise became real. A Beitrag is collected in instalments on its own cycle, so the four fractionated model points collect less than the annual grid charged them — and the
echt/unechtdistinction, which lived entirely in a multiplier, is now a difference in the frame as well.The totals the timing moved on the anchor: death claims 2 506,85 → 2 446,09 €, surrender claims 10 104,99 → 9 112,99 €, expenses 1 327,88 → 1 314,12 €,
net_cf−11 048,31 → −9 981,79 €, and policy year 1 +320,89 → +355,51 €.premiumsand the Ablauf payment are unchanged.The closure identity’s split. Deaths and surrenders now interleave month by month, so the anchor reads 0,04355790 and 0,51566656 against 0,04409376 and 0,51513070; the maturing cohort 0,44077554 and the total 1,00000000 are unchanged.
A tenth published identity.
check_surr_nonneg()asserts the Rückkaufswert non-negative in every month, the monthly grid quoting one in eleven months of each year the annual grid never priced.The § 165 failure is a month-specific event.
lapse_rateis 1.0 for the election year andlapse_rate_mthplaces the whole of it in that year’s last month, where the election falls. Spreading an annual 1.0 geometrically would have emptied the cohort eleven months early.
What was corrected in these notes#
The worked example is the model’s own output, and building the model found five places where these notes and the implementation disagreed. In each the model was right and the notes above have been corrected, rather than the table being fitted to the prose.
q₁named two different quantities and the notation table conflated them. The tariff must be unisex, so what prices and reserves is a fixed portfolio blend of the two table rows —mort_rate_at_age(x), ½ / ½ std — while the decrement is the policy’s own sex-specific ratemort_rate_base(t), scaled bymort_be_factor. Pricing off the policy’s own row madeprem_gross_ppdiffer between model points 1 and 7, which is pitfall 17 exactly.check_res_roll_fwd()’s identity carries the Risikozuschlag. Becauserating_factorloads the death leg and not the survivorship, the Fackler recursion readsf · q₁(x(t)) · SDon the right and(1 − q₁(x(t)))on the left. As first written it was correct only atrating_factor = 1.00, which model point 14 is not.The gezillmerte Deckungskapital does not stay negative for several years at the 25 ‰ ceiling — it is positive from the first anniversary. Pitfall 3’s assertion is therefore vacuous on every shipped model point, and both places now say so rather than implying a behaviour the base run does not show.
result_cf()publishes a ninth column,liability_cf. The eight specified columns are unchanged and in the stated order and the six flow columns still sum tonet_cf; the ninth is appended because the conventions suite reads it from the frame to assertnet_cf(t) == −liability_cf(t).res_zill_pp,res_min_ppandres_net_ppare the premium-paying constructions throughout, on the fullsum_assured; onlyres_ppswitches to the paid-up basis. Writing all four as switching makesbfz_si_ppdepend on itself, the § 169 value that buys the paid-up sum being struck on the contract as it still is. For the same reasoncheck_surr_floor()comparesres_guar_ppwith the other two only while the contract is premium-paying.
Valuation and reserve pointers#
This library projects gross best-estimate-style liability cash flows, undiscounted, on a declared grid. The valuation layers consume them and are cited, never reproduced.
The German statutory Deckungsrückstellung. § 341f HGB requires it to be formed at the versicherungsmathematisch berechneter Wert, including profit shares already allocated but excluding verzinslich angesammelte Überschussanteile, and after deducting the present value of future premiums, by the prospective method REG-R54.
res_pp(t) × pols_if(t)is this model’s contribution to that line andav_sur_pp(t) × pols_if(t)is explicitly not part of it. Three things the model does not do: it does not floor the reserve at zero as the balance sheet does, so the negative early gezillmert values stay visible; it does not apply the § 4 DeckRV ceiling as a reserving constraint separate from the tariff, the shippedalpha_ratealready sitting at it; and it carries no Verwaltungskostenrückstellung for the period after the Beitragszahlungsdauer, where thegamma_ratecost runs on with nobeta_rateincome — the pricing equation funds it, and the classical reserve convention here assumes the ongoing loadings meet the ongoing costs.The Zinszusatzreserve. An HGB reserve arising when the § 5 Abs. 3 DeckRV Referenzzins falls below a contract’s tariff rate, financed out of the result and, under § 140 VAG’s second escape hatch, out of the free RfB REG-R10 REG-R17. It exists in no other jurisdiction in this repository and this model does not compute it, but it matters here: the ZZR is how a high-guarantee cohort consumes the surplus that would otherwise be declared, which is why a delib path is a scenario.
The RfB, the Schlussüberschussanteilfonds and the MindZV. The surplus this model credits is the output of the insurer’s declaration policy, not the MindZV minimum, which is a transfer to the RfB — 90 % of the Kapitalanlageergebnis after the Rechnungszinsen, 90 % of the Risikoergebnis, 50 % of the übriges Ergebnis, Direktgutschrift deducted, Alt- and Neubestand separate R6 REG-R18 — with the RfB REG-R10, its collective part REG-R19 and the Schlussüberschussanteilfonds of § 28 RechVersV REG-R54 between it and the policy. None of that is modelled.
Solvabilität II. Technical provisions are a best estimate — the probability-weighted average of future cash flows discounted at the relevant risk-free term structure — plus a risk margin REG-R1 REG-R2 REG-R6, with EIOPA publishing the curves monthly and § 83 VAG making their use binding REG-R4.
BEL = Σ_t v(t) · liability_cf(t)over the recursion above. The future discretionary benefits — the declared Zinsüberschuss, the Schlussüberschussanteil and the Ansammlung — are the substance of the best estimate here, and the crediting rule above is exactly the management action a market-consistent valuation must model. No cost-of-capital rate, contract boundary rule or standard-formula shock in this library was read from a retrieved instrument, so every such figure is std REG-R2. Under IFRS 17 this is the archetypal direct-participating contract, measured under the variable fee approach on this same fulfilment-cash-flow engine; grouping, CSM and risk adjustment are out of scope REG-R55.The guarantee is an option. A guaranteed sum insured plus a guaranteed Rechnungszins is a written put on the Sicherungsvermögen, and the deterministic path above prices none of it; a stochastic-on-deterministic run is what a time-value-of-options-and-guarantees calculation consumes. The outer boundary is the Sicherungsfonds: a fund-level 5 % haircut under § 222 VAG and an uncapped reduction under § 314 VAG, which also lets the supervisor temporarily prohibit the Rückkauf REG-R12. A mass-surrender run here produces the values the contract owes, not the ones that would be paid if § 314 were in force.
Key sensitivities and model risks#
In rough order of leverage on this product.
The declared-rate path.
decl_ratesetszins_ueberschuss_rateone-for-one above the guarantee, and the credit compounds atans_ratefor up to twenty-five years, so it dominates the maturity benefit and every surrender value after the early durations. The base run is one carrier’s 2025 rate held level forever, and that rate is trade-press reporting of a declaration covering “die klassischen Lebens- und Rentenversicherungen” jointly R26; thelowandnilscenarios exist so the range is exercisable. No endowment-specific declared rate exists in the corpus at all — the market averages are stated by Assekurata to be for the klassische private Rentenversicherung R25, and the base rate is for a mixed book, so that an endowment shares the annuity’s declaration remains unverified (gap 2).The Zillmerung and the § 169 floor together.
alpha_rateat the 25 ‰ ceiling drives the negative early reserve, the whole early-duration surrender-value profile, the year-one strain and the duration at which the contract first earns any interest surplus at all. The ceiling is cited R7 REG-R16; the level is std and no German carrier’s actual acquisition cost is public (gap 7). Halving it moves the first five surrender values by more than any other single parameter.The mortality basis, in two directions at once. The proxy’s level and slope are both unsourced, and the same table serves a death leg and a survival leg whose directions of prudence are opposite REG-R47 REG-R48. The survival leg dominates a twenty-five-year endowment’s reserve, so a level error matters less than on a term cover — but
mort_be_factormoves the Risikoüberschuss the model does not compute, so the sensitivity is understated by construction, and the proxy carries no selection, which overstates early deaths on newly written business.The lapse shape. Cumulative surrender over twenty-five years removes a large part of the cohort before the Ablauf, and on an endowment the late years are the profitable ones, so the assumption governs how much of the loaded tail is collected. The duration-12 spike is the one feature the evidence supports R10 REG-R45; the levels are unsourced, the market aggregates are not surrender rates R20, and a user with experience data should replace the table.
The terminal bonus, and the Überschussverwendung choice.
term_rate = 0.40%has no source at all (gap 1), accrues on the reserve for the whole term, and its payability on surrender — zero here — is a second unsourced choice that would move surrender values most. And switchingansammlung→bonusmoves benefit between death and maturity without changing the surplus credited, while→ beitragsverrechnungmoves it out of the benefit stream into the premium stream; the corpus does not establish which system the market uses R28 (gap 4), so this is a structural rather than a parametric sensitivity.Two unmodelled paths: the Beitragsfreistellung take-up, and the balance-sheet levers. The paid-up election is deterministic because no take-up rate exists in the corpus, yet a real German book converts a material share R20 REG-R28, and a projection showing none overstates future premium income and future benefits together. Alongside it, the Bewertungsreserven share is set to zero on the reasoning that the Sicherungsbedarf has routinely exhausted it R8 REG-R9, and the ZZR — how a high-guarantee cohort depresses the declared rate for everyone REG-R17 — is not computed. All three would move the answer and none is a gross liability cash flow.
Data provenance. Every charge level, every behavioural rate, the terminal bonus, the Ansammlungszinssatz, the Stornoabzug schedule, the entry age, the sum insured and the mortality proxy are std; the corpus’s only quantified carrier terms are Debeka’s Stornoabzug, sub judice [S3] R22 R30, and Allianz’s declared rate [S11]. A calibration pass against a Produktinformationsblatt, a PRIIP-Basisinformationsblatt and a named insurer’s § 28 RechVersV Anhang disclosure REG-R54 is required before any quantitative use.