Pricing — the formulas
Two worked examples carry this page:
- the sample price program, for the statistics;
- the sample compliance check, for the guideline.
Every formula is quoted from source. Every number is recomputed from the operands shown. Where a test pins the number, the test is named.
Part 1 — the statistics of a simulated distribution
Source: Pricing/SimulationResult/Source/SimulationResult.cs. Take the C# fixture's gross loss
S1-GrossLoss from Pricing/SampleData/Source/SamplePricings.cs: the distribution is
{10, 20, 30, 40, 50}.
Mean
Mean = Distribution.Length == 0 ? 0 : Distribution.Sum() / Distribution.Length
(10 + 20 + 30 + 40 + 50) / 5 = 150 / 5 = 30. The test EmbeddedResults_ExposeStatistics
pins "gross mean = 30".
Standard deviation (population, divide by n)
variance = Distribution.Sum(x => (x - mean) * (x - mean)) / Distribution.Length
StandardDeviation = Math.Sqrt(variance) // 0 for an empty distribution
The deviations are −20, −10, 0, 10, 20. Their squares are 400, 100, 0, 100, 400, which sum to 1,000.
- variance = 1,000 / 5 = 200
- standard deviation = √200 = 14.1421
This is the population form, dividing by n and not by n − 1. The sample form would give
√250 = 15.81. The test MeanAndStdDev_AreCorrect pins {1, 2, 3, 4, 5} → standard deviation √2.
Quantile (empirical VaR, linear interpolation between order statistics)
if (p <= 0) return sorted[0]; if (p >= 1) return sorted[^1];
h = (n - 1) * p; lo = floor(h); hi = ceil(h)
Quantile(p) = sorted[lo] + (h - lo) * (sorted[hi] - sorted[lo])
For p = 0.9 on {10, 20, 30, 40, 50}:
- h = 4 × 0.9 = 3.6, so lo = 3 and hi = 4.
- Q = 40 + 0.6 × (50 − 40) = 46.
| p | h | Quantile |
|---|---|---|
| 0.5 | 2.0 | 30 (the test pins "gross median = 30") |
| 0.9 | 3.6 | 46 |
| 0.99 | 3.96 | 40 + 0.96 × 10 = 49.6 |
| ≤ 0 or ≥ 1 | — | clamps to 10 / 50 (test Quantile_IsEmpiricalVaR) |
This interpolation differs from the stop-loss engine's nearest-rank Percentile
(Loss Modelling formulas). On the same five draws, nearest rank gives
sorted[ceil(0.9 × 5) − 1] = sorted[4] = 50.
The same statistics on the shipped node
The SamplePriceProgram node's results (the node carries different draws from the C# fixture):
| Result | Draws | Mean | Std dev | Q(0.5) | Q(0.9) |
|---|---|---|---|---|---|
S1-GrossLoss |
20, 45, 70, 95, 140 | 74 | √1,714 = 41.40 | 70 | 95 + 0.6 × 45 = 122 |
S1-CededLoss (40 xs 60) |
0, 0, 10, 35, 40 | 17 | √296 = 17.20 | 10 | 35 + 0.6 × 5 = 38 |
fixture S1-CededLoss |
0, 0, 5, 15, 25 | 9 (test pins "ceded mean = 9") | √94 = 9.70 | 5 | 21 |
The node's ceded mean is 17, which is 23 % of the gross mean of 74. These are illustrative draws. They apply only the 40 xs 60 layer. The linked section also carries an annual aggregate deductible of 5 and an annual aggregate limit of 120, which they do not apply. So 17 is not the expected loss under the section's full terms.
Part 2 — the program's total reinsurance premium
Source: Pricing/Program/Source/Program.cs.
TotalReinsurancePremium(premiumByAcceptanceId) =
AcceptancesById.Keys.Sum(id => premiumByAcceptanceId.TryGetValue(id, out var premium) ? premium : 0d)
The premiums live on the acceptance nodes, so the caller resolves them and passes the map in. An acceptance missing from the map contributes 0.
Worked: the fixture SamplePricings.AcceptancePremiums() gives PropertyCat2023 1,200,000 and
PropertyRisk2023 450,000. The total is 1,200,000 + 450,000 = 1,650,000; the test
TotalReinsurancePremium_SumsAcceptances pins it. With only PropertyCat2023 in the map the total is
1,200,000. An empty Program gives 0.
Those two premiums are fixture values: in source they are described as "as they would be read off the
acceptance nodes". The shipped acceptance nodes carry cover × premiumRate instead:
PropertyCat2023 is 40 × 0.25 = 10, and
PropertyRisk2023 is 20 × 0.15 = 3. No code in Pricing
derives the map from the nodes.
Part 3 — the underwriting guideline
Sources: Pricing/Guideline/Source/Guideline.cs (the scope), PricingChecks.cs (the rules as
RuleResults), GuidelineTables.cs (the caps and the rating ladder) and RuleResult.cs. The proxy
memoises every member, so a member that others read (Escalations) is evaluated once.
The placement is the sample compliance check: Property Cat, gross line €62,000,000, combined ratio 1.08, 24 months, cedent A-, standard wording. Its live Compliance area renders the table below.
Note: the Compliance area always evaluates the built-in sample,
GuidelineSampleData.Sample()(Pricing/Guideline/Source/ComplianceArea.cs), not the content of the node it is opened on. The sample node holds the same values, so the table matches it here. On any other Guideline node it still shows this sample.
Subscribers see this result live; below is the same worked example as a static table.
Property Cat · gross line €62,000,000 · combined ratio 108.0 % · term 24 months · cedent A-
| Guideline check | Result |
|---|---|
| Four eyes (§4.2): gross line ≥ 4m | ❌ second underwriter |
| Capacity (§4.2): gross line > 50m | ❌ CUO |
| Line-of-business cap (§6): Property Cat 50m | ❌ CUO |
| Loss making (§8): combined ratio > 105 % | ❌ CUO |
| Below profitability (§6.1): 100 % < combined ratio ≤ 105 % | ✅ |
| Multi-year (§10): term > 36 months | ✅ |
| Weak cedent (§7): below BBB- | ✅ |
| Wording deviation (§10.1) | ✅ |
| Verdict | ⚠️ Refer to CUO |
| Share action | ⬇️ Decrease |
This summarises the outcome of each rule. The live area prints each rule's own sentence instead. The
outcomes are the ones the test ReferToCuo_TheSample pins.
The checks, one by one
| Member | Formula as in source | Sample | Trips? |
|---|---|---|---|
FourEyes (§4.2) |
GrossLine >= 4_000_000 |
62m ≥ 4m | yes, so SecondUnderwriter |
Capacity (§4.2) |
> 100_000_000 → UnderwritingCommittee; > 50_000_000 → Cuo; else None |
62m > 50m, ≤ 100m | Cuo |
LoBCapBreached (§6) |
LobCap(state) is double cap && GrossLine > cap |
"Property Cat" → key propertycat → 50,000,000; 62m > 50m |
yes, so Cuo |
LossMaking (§8) |
CombinedRatio > 1.05 |
1.08 > 1.05 | yes, so Cuo |
BelowProfitability (§6.1) |
CombinedRatio > 1.00 && CombinedRatio <= 1.05 |
1.08 > 1.05 | no |
MultiYear (§10) |
TermMonths > 36 |
24 | no |
WeakCedent (§7) |
RatingNotch(rating) > 9 (BBB- / Baa3 is notch 9) |
A- is notch 6 | no |
WordingDeviation (§10.1) |
MandatoryExclusionRemoved \|\| NonStandardClause |
false, false | no |
LobCap(state) reads state.Caps when it is non-empty: the row whose Label or an Alias
normalises to the same key, giving its MaxGrossLine. Otherwise it reads the built-in §6 table.
The key is lower-case and alphanumerics only. A line of business in neither has no cap: the
§6 rule then reports NoData, and LoBCapBreached stays false.
The rating ladder is index-aligned:
- S&P:
AAA, AA+, AA, AA-, A+, A, A-, BBB+, BBB, BBB-, BB+, … - Moody's:
AAA, AA1 … BAA3, BA1, …
An unknown rating has no notch, so it is not "weak". An empty rating reports NoData on §7.
Escalations, verdict, share action
Escalations = (FourEyes ? SecondUnderwriter : None) | Capacity | (LossMaking ? Cuo : None)
| (BelowProfitability ? HeadOfLoB : None) | (MultiYear ? Cuo | UnderwritingCommittee : None)
| (WeakCedent ? Cuo : None) | (WordingDeviation ? Cuo | Legal : None) | (LoBCapBreached ? Cuo : None)
EscalatesToCuoOrCommittee = (Escalations & (Cuo | UnderwritingCommittee)) != None
Verdict = CombinedRatio > 1.20 ? Decline
: (CombinedRatio > 1.05 || EscalatesToCuoOrCommittee) ? ReferToCuo : Write
ShareAction = Verdict == Decline ? Decline : Verdict == ReferToCuo ? Decrease
: CombinedRatio < 0.85 ? Increase : Maintain
Worked:
- Escalations = SecondUnderwriter | Cuo = flags 1 + 4 = 5.
- Verdict: is 1.08 > 1.20? No. Is 1.08 > 1.05? Yes. So ReferToCuo.
- Share action: Decrease.
The test ReferToCuo_TheSample pins exactly this: trips {FourEyes, Capacity, LossMaking,
LoBCapBreached}, capacity Cuo, verdict ReferToCuo, share Decrease.
The rule result (RuleResult)
Each clause is one value. It is built fluently: RuleResult.For(clause, title), then
.Escalating(e), .NoDataWhen(...), .BreachedWhen(cond, because) and .Noting(...).
Breachednever overrides aNoDataorNotApplicablestatus.RaisedEscalation = IsBreach ? Escalation : None.- The glyphs are ✓ Passed, ✗ Breached, – NotApplicable and ? NoData.
RuleResults.Escalations()ORs the raised escalations of all results.
On the sample, four rows are ✗: §4.2 ×2, §6 and §8. Four are ✓: §6.1, §10, §7 and §10.1.
Check yourself
Q1. Recompute the sample placement with a combined ratio of 1.03 and a gross line of €45,000,000. Everything else stays the same. What are the trips, the verdict and the share action?
A1.
- FourEyes trips (45m ≥ 4m).
- Capacity is None (45m is not > 50m).
- The Property Cat cap is not breached (45m ≤ 50m).
- LossMaking does not trip (1.03 is not > 1.05).
- BelowProfitability trips (1.00 < 1.03 ≤ 1.05).
Escalations = SecondUnderwriter | HeadOfLoB, which reaches neither Cuo nor the Committee. The
verdict is Write. The share action is Maintain, because 1.03 is not < 0.85. The test
BelowProfitability_StaysWrite pins that a Head-of-LoB escalation alone keeps the verdict at
Write.
Q2. What is Quantile(0.25) of the node's gross draws {20, 45, 70, 95, 140}?
A2. h = 4 × 0.25 = 1.0, so lo = hi = 1, and the quantile is sorted[1] = 45.
Reference
| Member | Formula | File | Pinned by |
|---|---|---|---|
SimulationResult.Mean |
Σx / n, 0 if empty |
SimulationResult/Source/SimulationResult.cs |
MeanAndStdDev_AreCorrect, EmbeddedResults_ExposeStatistics |
SimulationResult.StandardDeviation |
√(Σ(x − mean)² / n) |
same | MeanAndStdDev_AreCorrect |
SimulationResult.Quantile(p) |
s[lo] + (h − lo)(s[hi] − s[lo]), h = (n−1)p, clamped |
same | Quantile_IsEmpiricalVaR |
Program.TotalReinsurancePremium |
Σ premium[id] over AcceptancesById, missing = 0 |
Program/Source/Program.cs |
TotalReinsurancePremium_SumsAcceptances |
Program.Address |
pricing/{Id} |
Program/Source/Program.cs, Source/PricingAddress.cs |
Address_AndPricingAddress |
Guideline.FourEyes … LoBCapBreached |
see the table above | Guideline/Source/Guideline.cs |
GuidelineTests (Boundaries_AreExact pins every threshold) |
Guideline.Escalations / Verdict / ShareAction |
see above | Guideline/Source/Guideline.cs |
GuidelineTests |
PricingChecks.Evaluate |
one RuleResult per clause |
Guideline/Source/PricingChecks.cs |
GuidelineTests |
GuidelineTables.LobCap / IsBelowInvestmentGrade |
state caps ▸ §6 table; notch > 9 | Guideline/Source/GuidelineTables.cs |
GuidelineTests |
Related: