CatXL Financial Modelling Step-By-Step¶
This step-by-step guide illustrates how a CatXL contract type is modelled in Graphene. It assumes a conventional CatXL contract which may have one or more reinstatements, including the modelling of up-front premium and reinstatement premium income as well as any brokerage expenses. Also the CatXL contract may or may not have franchise deductible. This example does not take multiple currencies or currency exchange rates into account.
There may be more than one way to express a CatXL contract model in Graphene and this illustrates only one way. There may also exist slight variations in how Graphene users may want to model specific aspects of a CatXL for their own purposes and this guide should illustrate how those customizations can be easily achieved using Graphene template capabilities.
Objective¶
For this guide, the objective is to model a conventional CatXL with the following terms:
Term |
Value |
---|---|
Attachment |
1,000,000 USD |
Limit |
30,000 USD |
Franchise Deductible |
10,000 USD |
n-thness |
Second Event |
Reinstatements |
1st: 75% premium, 10% brokerage 2nd: 35% premium, 15% brokerage |
Participation |
20% |
Upfront Premium |
3,000 USD |
Upfront Brokerage |
10% |
Inception Date |
2019-01-01T00:00:00Z |
Expiry Date |
2020-01-01T00:00:00Z |
We express this contract definition in Graphene’s business model network as a node with the following definition:
{
"_schema": "CatXL_1.0",
"inception_date": 1546300800,
"expiration_date": 1577836800,
"attachment_value": 1000000,
"limit_value": 30000,
"franchise_deductible_value": 1500000,
"nth": 2,
"premium_value": 3000,
"brokerage": 0.1,
"share": 0.2,
"reinstatements": [
{
"premium_value": 0.75,
"brokerage": 0.1
},
{
"premium_value": 0.35,
"brokerage": 0.15
}
]
}
We then use templates to generate the financial model graph for this CatXL definition. This graph is finally evaluated by the Graphene financial engine.
Step-By-Step Breakdown¶
In order to better understand the individual elements of the financial model graph illustrated above, let’s decompose the graph into separate components.
Layering of Loss Claims¶
The primary layering of loss claims is performed in this subgraph:
The graph consists of a number of core operations that are applied to the input Ledger in sequential order:
Do not consider records past the expiry date. Only keep records before the expiry date.
Do not consider records before the inception date. Only keep records on or after the inception date.
For layering only consider losses as subjects. All other records such as upstream premiums or fees are not subject to the layering.
Apply a franchise deductible of 1,500,000. The franchise deductible is applied to the sum of values of all records with identical
Trial
,Time
, and occurrence key values. If the franchise deductible is not exceeded by the sum of occurrence records, the records of that occurrence are not subject to subsequent terms and are set to zero. On the other hand, if the franchise deductible is exceeded by the sum of occurrence records, the unmodified occurrence records are subject to subsequent terms.Apply an occurrence attachment of 1,000,000. The attachment is applied to the sum of values of all records with identical
Trial
,Time
, and occurrence key values. Once the attachment is applied, the result is proportionally allocated to all records included in the group of records that makes up the occurrence.Apply an occurrence limit of 30,000. The limit is applied to the sum of values of all records with identical
Trial
,Time
, and occurrence key values. Once the limit is applied, the result is proportionally allocated to all records included in the group of records that makes up the occurrence.Only consider the second event. This is typically modelled as an aggregate attachment equal to the occurrence limit as shown here.
Allow the limit to be reinstated twice. This is modelled as an aggregate limit equal to the occurrence limit times the number of reinstatements plus 1, here 90,000.
Finally we apply the participation using a simple scaling function.
Passing Through all Non-Loss Records¶
All other input records to the layer, such as premiums and fees from source layers, are passed through as-is only being subject to the inception and expiration dates of the layer and its participation.
Select only records that are not of type
Loss
and pass them on to apply the contract participation.
Putting it back together¶
In order to model the complete CatXL contract, all components are combined together and collectively produce a single Ledger that contains:
A single upfront premium income record on inception of the contract
A single brokerage fee expense record on inception of the contract
Any loss records that represent a loss expense to the contract
Any reinstatement premium records that represent premium income for reinstating the occurrence limit
Any reinstatement brokerage fee records that represent brokerage fee expense on reinstatement premium received
Any other non-loss records received from the subject source filtered inception / expiration dates and with participation applied.
Core operations¶
The entire CatXL contract structure consists of the following core operations:
Templates¶
Using Graphene template capabilities, we can build out the appropriate templates to generate the financial model shown above from the initial JSON definition:
{
"_schema": "CatXL_1.0",
"inception_date": 1546300800,
"expiration_date": 1577836800,
"franchise_deductible_value": 1500000,
"attachment_value": 1000000,
"limit_value": 30000,
"nth": 2,
"premium_value": 3000,
"brokerage": 0.1,
"share": 0.2,
"reinstatements": [
{
"premium_value": 0.75,
"brokerage": 0.1
},
{
"premium_value": 0.35,
"brokerage": 0.15
}
]
}
We will use one primary template called CatXL. This template, in turn, uses additional templates to encapsulate some common functionality, such as:
TimeCoverage: Filtering records based on inception and expiration date.
OccurrenceCoverage: Apply occurrence attachment and limit.
AggregateCoverage: Apply aggregate attachment and limit.
The CatXL main structure:
{
vertices: [
# Vertex 0
{
_schema: "TimeCoverage_1.0",
inception_date: .inception_date,
expiration_date: .expiration_date
},
# Vertex 1
{
_schema: "RecordTypeFilter_1.0",
op: "EQUAL",
value: "Loss"
},
# Vertex 2
(
if .franchise_deductible_value then (
{
_schema: "OccurrenceFranchiseDeductible_1.0",
franchise_deductible: .franchise_deductible_value
}
) else {} end
),
# Vertex 3
{
_schema: "OccurrenceCoverage_1.0",
attachment: .attachment_value,
limit: .limit_value
},
# Vertex 4
{
_schema: "AggregateCoverage_1.0",
attachment: (.limit_value * (.nth - 1)),
limit: (.limit_value * ((.reinstatements | length) + 1))
},
# Vertex 5
{
_schema: "Record_1.0",
_internal_terminal: true,
time: .inception_date,
type: "BrokerageFee",
value: (.premium_value * .brokerage * -1.0)
},
# Vertex 6
{
_schema: "Record_1.0",
_internal_terminal: true,
time: .inception_date,
type: "Premium",
value: .premium_value
},
# Vertex 7
{
_schema: "RecordTypeFilter_1.0",
op: "NOT_EQUAL",
value: "Loss"
},
# Vertex 8
{
_schema: "Scale_1.0",
factor: .share
},
# Reinstatments
(. as $parent | range(.reinstatements | length) |
{
_schema: "AggregateCoverage_1.0",
attachment: (. * $parent.limit_value),
limit: $parent.limit_value
},
{
_schema: "Scale_1.0",
factor: ($parent.reinstatements[.].premium_value * $parent.premium_value / $parent.limit_value * -1.0)
},
{
_schema: "SetRecordType_1.0",
value: "ReinstatementPremium"
},
{
_schema: "Scale_1.0",
factor: ($parent.reinstatements[.].brokerage * -1.0)
},
{
_schema: "SetRecordType_1.0",
value: "ReinstatementBrokerageFee"
}
)
],
edges: [
{
from: 0,
to: 1
},
{
from: 1,
to: 2
},
{
from: 2,
to: 3
},
{
from: 3,
to: 4
},
{
from: 0,
to: 7
},
{
from: 4,
to: 8
},
{
from: 5,
to: 8
},
{
from: 6,
to: 8
},
{
from: 7,
to: 8
},
# Reinstatments
(range(.reinstatements | length) |
{
from: 4,
to: (8 + (. * 5) + 1 )
},
{
from: (8 + (. * 5) + 1),
to: (8 + (. * 5) + 2)
},
{
from: (8 + (. * 5) + 2),
to: (8 + (. * 5) + 3)
},
{
from: (8 + (. * 5) + 3),
to: 8
},
{
from: (8 + (. * 5) + 2),
to: (8 + (. * 5) + 4)
},
{
from: (8 + (. * 5) + 4),
to: (8 + (. * 5) + 5)
},
{
from: (8 + (. * 5) + 5),
to: 8
}
)
]
}