CCDM Procedure

Example 7.1 Estimating the Probability Distribution of Insurance Payments

The primary outcome of running the CCDM procedure is the estimate of the compound distribution of aggregate loss, given the distributions of frequency and severity of the individual losses. This aggregate loss is often referred to as the ground-up loss. If you are an insurance company or a bank, you are also interested in acting on the ground-up loss by computing an entity that is derived from the ground-up loss. For example, you might want to estimate the distribution of the amount that you are expected to pay for the losses or the distribution of the amount that you can offload to another organization, such as a reinsurance company. PROC CCDM enables you to specify a severity adjustment program, which is a sequence of SAS programming statements that adjust the severity of the individual loss event to compute the entity of interest. Your severity adjustment program can use external information that is recorded as variables in the observations of the DATA= data table in addition to placeholder symbols for information that PROC CCDM generates internally, such as the severity of the current loss event (_SEV_) and the sum of the adjusted severity values of the events that have been simulated thus far for the current sample point (_ADJSEVSUM_). If you are analyzing a scenario that contains more than one observation, then you can also access the cumulative severity and cumulative adjusted severity for the current observation by using the _SEVSUMFOROBS_ and _ADJSEVSUMFOROBS_ symbols.

This example continues the example of the section Scenario Analysis to illustrate how you can estimate the distribution of the aggregate amount that is paid to a group of policyholders. Let the amount that is paid to an individual policyholder be computed by using what is usually referred to as a disappearing deductible (Klugman, Panjer, and Willmot 1998, Ch. 2). If X denotes the ground-up loss that a policyholder incurs, d denotes the lower limit on the deductible, d prime denotes the upper limit on the deductible, and u denotes the limit on the total payments that are made to a policyholder in a year, then Y, the amount that is paid to the policyholder for each loss event, is defined as follows:

upper Y equals StartLayout Enlarged left-brace 1st Row 1st Column 0 2nd Column upper X less-than-or-equal-to d 2nd Row 1st Column d prime StartFraction upper X minus d Over d prime minus d EndFraction 2nd Column d less-than upper X less-than-or-equal-to d Superscript prime Baseline 3rd Row 1st Column upper X 2nd Column d prime less-than upper X less-than-or-equal-to u 4th Row 1st Column u 2nd Column upper X greater-than u EndLayout

You can use a set of SAS programming statements to encode this logic.

The following DATA step extends the data table mylib.GroupOfPolicies from the example in the section Scenario Analysis to include three additional variables for each policyholder: LowDeductible to record d, HighDeductible to record d prime, and Limit to record u.

/* Generate the scenario data table for multiple policyholders */
data groupOfPolicies(keep=policyholderId age gender carType annualMiles
                          education carSafety income
                          lowDeductible highDeductible limit annualLimit);
   call streaminit(67897);

   do policyholderId=1 to 5;
      age = MAX(int(rand('NORMAL', 35, 15)),16)/50;

      if (rand('UNIFORM') < 0.5) then gender = 1; * female;
      else gender = 2; * male;

      if (rand('UNIFORM') < 0.7) then carType = 1; * sedan;
      else carType = 2; * SUV;

      annualMiles = MAX(1000, int(rand('NORMAL', 12000, 5000)))/5000;

      educationLevel = rand('UNIFORM');
      if (educationLevel < 0.5) then education = 1; *high school graduate;
      else if (educationLevel < 0.85) then education = 2; *college graduate;
      else education = 3; *advanced degree;

      carSafety = rand('UNIFORM'); /* scaled to be between 0 & 1 */

      income = MAX(15000,int(rand('NORMAL', education*30000, 50000)))/100000;

      lowDeductible = 100*(1+floor(rand('UNIFORM')*5));
      highDeductible = lowDeductible + 500*(1+floor(rand('UNIFORM')*2));
      limit = 2500*(1+floor(rand('UNIFORM')*3));
      annualLimit = 10000*(1+floor(rand('UNIFORM')*2));

      output;
   end;
run;

/* Load the data */
data mylib.groupOfPolicies;
  set groupOfPolicies;
run;

The data table contains the observations as shown in Output 7.1.1.

Output 7.1.1: Scenario Analysis Data for Multiple Policyholders with Policy Provisions

policyholderIdagegendercarTypeannualMileseducationcarSafetyincomelowDeductiblehighDeductiblelimitannualLimit
11.18212.294830.995321.598704001400750010000
20.66222.814810.056250.675393001300250020000
30.82121.613020.841461.059401001100500010000
40.44111.228030.143240.24110300800500020000
50.44110.967020.086560.659791001100500020000


The following PROC CCDM step estimates the compound distributions of the aggregate loss and the aggregate amount that is paid to the group of policyholders in the data table mylib.GroupOfPolicies by using the count model that is stored in the item store mylib.CountregModel and the lognormal severity model that is stored in the data table mylib.SevRegEst:

/* Simulate the aggregate loss distribution and aggregate adjusted
   loss distribution for the scenario of multiple policyholders */
proc ccdm data=mylib.groupOfPolicies nreplicates=10000 seed=13579 print=all
          countstore=mylib.countregmodel severityest=mylib.sevregest
          nperturbedSamples=50 adjustedseverity=amountPaid;
   severitymodel logn;

   if (_sev_ <= lowDeductible) then
      amountPaid = 0;
   else do;
      if (_sev_ <= highDeductible) then
         amountPaid = highDeductible *
            (_sev_-lowDeductible)/(highDeductible-lowDeductible);
      else
         amountPaid = MIN(_sev_, limit); /* imposes per-loss payment limit */
   end;
run;

The preceding step uses a severity adjustment program to compute the value of the symbol AmountPaid and specifies that symbol in the ADJUSTEDSEVERITY= option in the PROC CCDM step. The program is executed for each simulated loss event. The PROC CCDM supplies your program with the value of the severity in the _SEV_ placeholder symbol.

The "Sample Summary Statistics" table in Output 7.1.2 shows the summary statistics of the compound distribution of the aggregate ground-up loss. The "Adjusted Sample Summary Statistics" table shows the summary statistics of the compound distribution of the aggregate AmountPaid.

Output 7.1.2: Summary Statistics of Compound Distributions of the Total Loss and Total Amount Paid

The CCDM Procedure
 
Severity Model: Logn
Count Model: NegBin(p=2)

Compound Distribution Information
Severity ModelLognormal Distribution
Scale Model EffectscarSafety carType income
Count ModelNegBin(p=2) Model in Item Store COUNTREGMODEL

The CCDM Procedure
 
Severity Model: Logn
Count Model: NegBin(p=2)

Sample Summary Statistics
Mean5904.2Median4702.3
Standard Deviation4820.3Interquartile Range5196.5
Variance23235325.2Minimum0
Skewness2.47224Maximum72844.8
Kurtosis13.78076Sample Size10000

The CCDM Procedure
 
Severity Model: Logn
Count Model: NegBin(p=2)

Summary Statistics for amountPaid
Mean4352.6Median3744.0
Standard Deviation3168.6Interquartile Range4095.4
Variance10039734.9Minimum0
Skewness1.15304Maximum31285.3
Kurtosis2.05121Sample Size10000


The perturbation summary of the distribution of AmountPaid is shown in Output 7.1.3. It shows that you can expect to pay a median amount to this group of five policyholders in a year.

Output 7.1.3: Perturbation Summary of the Total Amount Paid

Percentile Perturbation Analysis
for amountPaid
PercentileEstimateStandard
Error
10.350772.45538
5391.3147157.78032
251988.2164.12121
503781.8247.83745
756131.5344.12552
9510433.8508.50465
9914094.6663.38390
99.515570.8727.38674
Number of Perturbed Samples = 50
Size of Each Sample = 10000


Now consider that, in the future, you want to modify your company’s policy provisions to add a limit on the total amount of payment that an individual policyholder receives in one year and to impose a group limit of 15,000 on the total amount of payments the group as a whole receives in one year. You can analyze the effects of these modified policy provisions on the distribution of the aggregate paid amount by recording the individual policyholder’s annual limit in the variable AnnualLimit of the input data table and then modifying your severity adjustment program by using the placeholder symbols _ADJSEVSUMFOROBS_ and _ADJSEVSUM_, as in the following PROC CCDM step:

/* Simulate the aggregate loss distribution and aggregate adjusted
   loss distribution for the modified set of policy provisions */
proc ccdm data=mylib.groupOfPolicies nreplicates=10000 seed=13579 print=all
          countstore=mylib.countregmodel severityest=mylib.sevregest
          nperturbedSamples=50 adjustedseverity=amountPaid;
   severitymodel logn;

   if (_sev_ <= lowDeductible) then
      amountPaid = 0;
   else do;
      if (_sev_ <= highDeductible) then
         amountPaid = highDeductible *
            (_sev_-lowDeductible)/(highDeductible-lowDeductible);
      else
         amountPaid = MIN(_sev_, limit); /* imposes per-loss payment limit */

      /* impose policyholder's annual limit */
      amountPaid = MIN(amountPaid, MAX(0,annualLimit - _adjsevsumforobs_));

      /* impose group's annual limit */
      amountPaid = MIN(amountPaid, MAX(0,15000 - _adjsevsum_));
   end;
run;

The results of the perturbation analysis for these modified policy provisions are shown in Output 7.1.4. When you compare them to the results in Output 7.1.3, you see that the additional policy provisions of restricting the total payment to the policyholder and the group have reduced the median payment and the worst-case payment (99.5th percentile).

Output 7.1.4: Perturbation Summary of the Total Amount Paid after Modified Policy Provisions

The CCDM Procedure
 
Severity Model: Logn
Count Model: NegBin(p=2)

Percentile Perturbation Analysis
for amountPaid
PercentileEstimateStandard
Error
10.515452.12215
5391.9814061.77616
251994.5167.82065
503788.2230.84670
756133.3318.88793
9510392.7453.75218
9913894.2614.89744
99.514840.0317.91901
Number of Perturbed Samples = 50
Size of Each Sample = 10000


Last updated: July 09, 2026