Workers' compensation

A per-class-code workers' compensation model with a state load and experience modification.

A default model in Ptally. Commercial Workers' Compensation: Per-Class-Code is one of the default models you can select when you start a new project in Ptally. It comes with its rate tables, rules and 6 tests, ready to adapt to your own product.
The line of business

Workers' compensation

Workers' compensation covers employees' medical costs and lost wages after a work injury. In the US it is rated on payroll by class code, with each class reflecting the hazard of the work, and an experience modification for the employer's own loss record.

Methodology

How the model rates

A child model calculates the manual premium for each class code from its payroll. The parent model sums the manual premiums, then applies a state load and the employer's experience modification, plus a policy fee.

Policies with no class codes or very small payrolls are declined. High experience modifications and very large payrolls are referred.

Three further factors adjust the premium: a certified safety programme, a return to work programme and the number of recent claims.

6inputs
8steps
4lookup tables
6tests

Inputs

6 fields
FieldLabelTypeDefaultAllowed values
stateStatestringCACA, NY, TX, FL, IL
experience_modExperience modification factordecimal10.8, 1, 1.25, 1.5
class_codesClass codesarraylistA list of items, each rated by the child model
safety_programCertified safety programmebooleanfalsefalse, true
return_to_workReturn to work programmebooleanfalsefalse, true
claims_count_3yClaims in the last 3 yearsinteger00, 1, 3, 6
The model

Step by step

Steps run in order. Each one can use the inputs and the outputs of every step before it.

01Lookup table
State load factor

Overall state loading applied to the manual premium (proxy for state assessment differences).

{
  "id": "state_load_rates",
  "key": "state_load_rates",
  "step": "collection",
  "name": "State load factor",
  "retain": true,
  "collection": [
    ["state", "state_load"],
    ["CA", 1.15],
    ["NY", 1.12],
    ["TX", 1],
    ["FL", 1.05],
    ["IL", 1.08]
  ],
  "format": {
    "state_load": {
      "key": "state_load",
      "label": "State load factor",
      "exp": "collection.filter(state=={{state}}).map(state_load).first()",
      "type": "decimal",
      "def": 1
    }
  }
}
02Modules
Per-class-code rating

Iterate class_codes[]. Child model returns manual premium per class code; parent sums into manual premium total.

Child model: Per-Class-Code Rating (child)

Prices a single class code = (rate per $100 payroll × payroll).

Class-code rate lookup. Rate per $100 of payroll by NCCI class code. Higher-hazard codes carry higher rates.

Manual premium. (Payroll / 100) × rate per $100.

{
  "id": "per_class_rating",
  "key": "per_class_rating",
  "step": "modules",
  "name": "Per-class-code rating",
  "format": {
    "manual_premium_total": {
      "key": "manual_premium_total",
      "label": "Manual premium total",
      "exp": "collection.sum(result)",
      "type": "decimal",
      "def": 0
    },
    "total_payroll": {
      "key": "total_payroll",
      "label": "Total payroll",
      "exp": "collection.sum(payroll)",
      "type": "decimal",
      "def": 0
    },
    "classes_count": {
      "key": "classes_count",
      "label": "Number of class codes",
      "exp": "collection.count()",
      "type": "integer",
      "def": 0
    }
  },
  "child_model_steps": [
    {
      "id": "code_rates",
      "key": "code_rates",
      "step": "collection",
      "name": "Class-code rate lookup",
      "retain": true,
      "collection": [
        ["code", "code_rate_per_100"],
        ["8810", 0.25],
        ["8871", 0.18],
        ["5403", 4.8],
        ["9082", 2.4],
        ["9014", 3.1]
      ],
      "format": {
        "code_rate_per_100": {
          "key": "code_rate_per_100",
          "label": "Class code rate per $100",
          "exp": "collection.filter(code=={{code}}).map(code_rate_per_100).first()",
          "type": "decimal",
          "def": 1
        }
      }
    },
    {
      "id": "manual_premium",
      "key": "manual_premium",
      "step": "calculation",
      "name": "Manual premium",
      "def": 0,
      "formula": "round(({{payroll}} / 100) * {{code_rate_per_100}}, 2)"
    }
  ]
}
03Lookup table
Safety programme factor

A certified workplace safety programme reduces the frequency of injuries.

{
  "id": "wc_safety_rates",
  "key": "wc_safety_rates",
  "step": "collection",
  "name": "Safety programme factor",
  "retain": true,
  "collection": [
    ["safety_program_value", "wc_safety_factor_rel"],
    [false, 1],
    [true, 0.95]
  ],
  "format": {
    "wc_safety_factor": {
      "key": "wc_safety_factor",
      "label": "Safety programme factor",
      "exp": "collection.filter(safety_program_value=={{safety_program}}).map(wc_safety_factor_rel).first()",
      "type": "decimal",
      "def": 1
    }
  }
}
04Lookup table
Return to work factor

Getting injured employees back to suitable work quickly reduces lost wage costs.

{
  "id": "rtw_rates",
  "key": "rtw_rates",
  "step": "collection",
  "name": "Return to work factor",
  "retain": true,
  "collection": [
    ["return_to_work_value", "rtw_factor_rel"],
    [false, 1],
    [true, 0.97]
  ],
  "format": {
    "rtw_factor": {
      "key": "rtw_factor",
      "label": "Return to work factor",
      "exp": "collection.filter(return_to_work_value=={{return_to_work}}).map(rtw_factor_rel).first()",
      "type": "decimal",
      "def": 1
    }
  }
}
05Lookup table
Claims frequency factor

A high number of recent claims points to frequency problems the experience mod may not yet show.

{
  "id": "wc_frequency_rates",
  "key": "wc_frequency_rates",
  "step": "collection",
  "name": "Claims frequency factor",
  "retain": true,
  "collection": [
    ["claims_count_3y_min", "claims_count_3y_max", "wc_frequency_factor_rel"],
    [0, 1, 1],
    [2, 4, 1.08],
    [5, 999, 1.2]
  ],
  "format": {
    "wc_frequency_factor": {
      "key": "wc_frequency_factor",
      "label": "Claims frequency factor",
      "exp": "collection.filter(claims_count_3y_min<={{claims_count_3y}}).filter(claims_count_3y_max>={{claims_count_3y}}).map(wc_frequency_factor_rel).first()",
      "type": "decimal",
      "def": 1
    }
  }
}
06Calculation
Policy premium

Manual premium × state load × experience mod, plus $250 policy fee. Multiplied by the safety programme factor, return to work factor, claims frequency factor.

{
  "id": "policy_premium",
  "key": "policy_premium",
  "step": "calculation",
  "name": "Policy premium",
  "def": 0,
  "formula": "round(({{manual_premium_total}} * {{state_load}} * {{experience_mod}} * {{wc_safety_factor}} * {{rtw_factor}} * {{wc_frequency_factor}}) + 250, 2)"
}
07Decline rules
Workers comp exclusions

Decline policies with no class codes or total payroll under $10k (below minimum earned premium threshold).

{
  "id": "wc_exclusions",
  "key": "wc_exclusions",
  "step": "exclusion",
  "name": "Workers comp exclusions",
  "def": false,
  "items": [
    {
      "id": "no_class_codes",
      "name": "No class codes supplied",
      "exp": "{{classes_count}} == 0",
      "def": false
    },
    {
      "id": "payroll_too_low",
      "name": "Total payroll below $10k",
      "exp": "{{total_payroll}} < 10000",
      "def": false
    }
  ]
}
08Refer rules
Workers comp refers

Refer high-experience-mod employers or very large payrolls to underwriter review.

{
  "id": "wc_refers",
  "key": "wc_refers",
  "step": "refer",
  "name": "Workers comp refers",
  "def": false,
  "items": [
    {
      "id": "high_mod",
      "name": "Experience mod at or above 1.40",
      "exp": "{{experience_mod}} >= 1.40",
      "def": false
    },
    {
      "id": "large_payroll",
      "name": "Total payroll over $5m",
      "exp": "{{total_payroll}} > 5000000",
      "def": false
    }
  ]
}
Worked example

Worked example: employer with safety and return to work programmes

This quote was priced by the Ptally rating engine. The trace below follows it through every step to the final result.

Quote input
{
  "state": "CA",
  "experience_mod": 1,
  "class_codes": [
    {
      "code": "8810",
      "payroll": 300000
    }
  ],
  "safety_program": true,
  "return_to_work": true,
  "claims_count_3y": 3
}
Result1,108.38VALID
Calculation trace
  1. State load factorLookup table
    state_load = 1.15
  2. Per-class-code ratingModules
    Item 1 {"code":"8810","payroll":300000} → 750manual_premium_total = 750 · total_payroll = 300,000 · classes_count = 1
  3. Safety programme factorLookup table
    wc_safety_factor = 0.95
  4. Return to work factorLookup table
    rtw_factor = 0.97
  5. Claims frequency factorLookup table
    wc_frequency_factor = 1.08
  6. Policy premiumCalculation
    round((750 * 1.15 * 1 * 0.95 * 0.97 * 1.08) + 250, 2) = 1,108.38
  7. Workers comp exclusionsDecline rules
    No class codes supplied: not firedTotal payroll below $10k: not fired
  8. Workers comp refersRefer rules
    Experience mod at or above 1.40: not firedTotal payroll over $5m: not fired
Start from this model

Select workers' compensation as the default model for a new project, then change the rates, rules and tests to match your product. Our consultants can do this for you, with no implementation fee.

Talk to our team