Source code for projectionmodels.premium

"""
Premium roll-forward -- the stored premium projected by known factors.
======================================================================
Premiums come from the database; they are NOT rebuilt from loss experience (that is
`ratingmodels`). This just rolls the stored figure forward:

    projected_pmpm = (current_premium / current_member_months)
                     * (1 + rate_action) * (1 + plan_change)

Premium is level per member-month (it earns evenly), so `.premium(membership)`
scales by membership with no seasonal shape -- unlike claims.
"""
from __future__ import annotations

from dataclasses import dataclass

import numpy as np


@dataclass(frozen=True)
class PremiumResult:
    current_pmpm: float
    rate_action: float
    plan_change: float
    projected_pmpm: float


[docs] class PremiumRollforward: """Roll the stored premium forward by known factors -- never rebuilt from losses. ``projected_pmpm = (current_premium / current_member_months) * (1 + rate_action) * (1 + plan_change)``. Premium is level per member-month (it earns evenly), so :meth:`premium` scales by the membership vector with no seasonal shape -- unlike claims. Rebuilding premium from loss experience is ``ratingmodels``' job; this projects the figure the database already holds. The build-up sits on ``result`` (:class:`PremiumResult`). Parameters ---------- current_premium, current_member_months : float The stored premium and its member-months; their ratio is the current PMPM. rate_action, plan_change : float, optional Renewal rate action and plan-value change, as decimals (default 0). """ def __init__(self, *, current_premium, current_member_months, rate_action=0.0, plan_change=0.0): current_pmpm = current_premium / current_member_months projected = current_pmpm * (1.0 + rate_action) * (1.0 + plan_change) self.result = PremiumResult(float(current_pmpm), float(rate_action), float(plan_change), float(projected)) @property def projected_pmpm(self) -> float: return self.result.projected_pmpm
[docs] def premium(self, membership): """Projected premium dollars by prospective month (level per member-month).""" return self.result.projected_pmpm * np.asarray(membership, float)
def roll_forward_premium(**kwargs) -> PremiumResult: """Functional form: returns the :class:`PremiumResult`.""" return PremiumRollforward(**kwargs).result