Proration and Premium Allocation

The Proration plugin controls how premiums, commissions, taxes, and fees are prorated when coverage periods are reduced by either endorsement or cancellation.

In an endorsement, existing peril characteristics are split and premium is prorated to determine the amount to be allocated to the segment before the split timestamp (this is called the “pre-split amount.”) For non-premium bearing endorsements, this also determines the post-split amount (equal to the original amount minus the pre-split amount).

For example, if a characteristics object that covers January 1 2021 to January 1 2022 and has $1000 of allocated premium is endorsed on July 1, approximately half of the premium should be allocated to the January 1 to July 1 segment. You may want to have more nuance:

  • Prorate by months: The premium will be 6 / 12 * 1000, or $500.00

  • Prorate by days: The premium will be 181 / 365 * 1000, $495.89

  • Prorate by milliseconds: The premium (in a daylight savings timezone in the northern hemisphere) will be 15634800000 / 31536000000 * 1000, or $495.78

The proration plugin can handle these and similar scenarios.

Cancellations work similarly but post-split characteristics will not be generated because the coverage is terminated.

Note

The plugin also handles “holdbacks” for retaining extra amounts beyond the proration calculation. This is useful for scenarios like cancellation short rates. See the Proration Holdbacks topic for details.

Plugin Details

Enabling the plugin

To enable the plugin, follow the steps in the plugins topic. Also, turn on the Proration Plugin feature flag in config.json:

"features" : {
  "timezone": "America/Los_Angeles",
  "currency": "USD",
  "features" : { "property.proration.plugin.enabled": true }
}

This feature flag will not be needed in an upcoming release.

The plugin script

The proration plugin requires a plugin script called prorater.js that exports a function called getProrationResult.

The data object

The data object passed to the plugin looks like this:

ProrationPluginData
required
segmentSplitTimestamp timestamp
operation string creation | endorsement | renewal | cancellation | reinstatement | withdrawal | action
paymentScheduleName string
tenantTimeZone string

optional
cancellationCategory string
cancellationComments string
cancellationType string
ProrationPolicyInfo
required
locator string
policyholderLocator string
productName string

Each proration item looks like this:

ProrationPluginItem
required
id string
segmentEndTimestamp timestamp
segmentStartTimestamp timestamp
amount number
followingAmount number
type string premium | tax | commission | fee | technicalPremium | premiumHoldback | taxHoldback | feeHoldback | commissionHoldback | premiumHoldbackReversal | taxHoldbackReversal | feeHoldbackReversal | commissionHoldbackReversal

optional
perilName string
perilCharacteristicsLocator string
fieldValues map<string,[string]>
commissionLocator string
commissionRecipient string
feeLocator string
feeName string
taxLocator string
taxName string

Note

The id property of the proration item is a transient value used to key the plugin input to the response. It is not saved in the database nor is it consistent across calls.

Note

Numeric values sent to the plugin are passed as strings to ensure no loss of precision.

The Plugin Response Object

The plugin requires that the response from the plugin looks like this:

ProrationPluginResponse
required

Where each ProrationResponseItem looks like this:

ProrationResponseItem
required
id string
holdbackAmount number
proratedAmount number

optional
holdbackMetadata string

Validation

The response from the plugin must conform to the following criteria:

  • The id for each ProrationResponseItem must match that in the corresponding ProrationPluginItem in the input.

  • An output item’s proratedAmount must not exceed the amount of the input item.

  • The holdbackAmount is required. Set its value to 0 if you do not want to create a holdback.

  • You may include holdbackMetadata only if you are also including a positive holdbackAmount in the ProrationResponseItem.

Sample Script (Simple)

This script implements the proration plugin using linear (millisecond-based) proration.

function getProrationResult(data)
{
  console.log("Hello simple proration world!!! Operation: " + data.operation);
  return { items: data.items.map(item => prorateItem(data, item)) };
}
function prorateItem(data, item)
{
  return {
    id: item.id,
    proratedAmount: round2(parseFloat(item.amount) * getLinearFraction(data, item)),
    holdbackAmount: 0
  };
}
function getLinearFraction(data, item)
{
  return (parseInt(data.segmentSplitTimestamp) - parseInt(item.segmentStartTimestamp))
  / (parseInt(item.segmentEndTimestamp) - parseInt(item.segmentStartTimestamp));
}
function round2(num)
{
  return Math.round(num * 100) / 100.0;
}

exports.getProrationResult = getProrationResult;

Sample Script (Advanced)

This script implements the proration plugin using linear proration for upfront, every_week, and every_two_weeks payment schedules, and monthly proration for other schedules.

A zip file containing date support files is here. Unzip these files to a subfolder called lib. This subfolder should be in the same folder as installments.js.

let dates = require('./lib/dates.js');

function getProrationResult(data)
{
  return { items: data.items.map(item => prorateItem(data, item)) };
}

function prorateItem(data, item)
{
  let fraction;
  switch (data.paymentPlan)
  {
    case "total":
    case "every_week":
    case "every_two_weeks":
      fraction = getLinearFraction(data, item);
      break;
    default:
      fraction = getMonthlyFraction(data, item);
      break;
  }

  let amount = round2(fraction * parseFloat(item.amount));

  return {id: item.id, proratedAmount: amount, holdbackAmount: 0 };
}

function getMonthlyFraction(data, item)
{
  return Math.max(0,
                  Math.min(1.0,
                           dates.monthCountByTimestamp(item.segmentStartTimestamp, data.segmentSplitTimestamp, data.tenantTimeZone) /
                           dates.monthCountByTimestamp(item.segmentStartTimestamp, item.segmentEndTimestamp, data.tenantTimeZone)));
}

function getLinearFraction(data, item)
{
  return Math.max(0,
                  Math.min(1.0,
                           (parseInt(data.segmentSplitTimestamp) - parseInt(item.segmentStartTimestamp)) /
                           (parseInt(item.segmentEndTimestamp) - parseInt(item.segmentStartTimestamp))));
}

function round2(num)
{
  return Math.round(num * 100) / 100.0;
}

exports.getProrationResult = getProrationResult;

Note

Socotra does not make any guarantee about how proration items are batched. If there are ten proration items to be processed, the plugin may be called once with the list of all ten, or it could be called multiple times with a subset processed on each call.

Legacy Proration

If the proration plugin is not implemented, the system will behave as follows:

During endorsements and cancellations, Socotra allocates premium to each coverage period using a single method, so all calculations are consistent.

  • If periods start and end at 00:00:00 (midnight), actual-millisecond proration is the same as actual-day

  • When allocating premium to billing periods, Socotra assigns the same amount to each whole billing period and then uses actual-millisecond proration for partial billing periods.

For up-front, weekly, and every other week payment schedules, Socotra will use milliseconds-based proration. For other schedules, Socotra will use monthly-based proration based on the number of months (see below).

Month Counting

Consider the following scenario where a cancellation is processed before the end of the policy term:

  • The policy period is from June 13th for a one year term

  • The total premium for the year is $1200

  • The policyholder requests a cancellation effective September 19th

Resulting calculations:

  1. The remaining coverage period is from June 13th until September 19th, which is 3 months and 6 days.

  2. Since September 13th to October 13th is 30 days, the coverage period is 3 + 6/30 = 3.2 months long.

  3. 3.2 months will be used for monthly proration.