compare pairs two programs on a population and summarize totals the
pairs by segment, with optional percentiles, change buckets and premium per
unit of exposure. rateability counts how much of the population each
program rated. policy_draw_ranges and group_draw_ranges give the spread
of a study’s draws. rank and rank_summary place several programs side
by side. search_lever finds the value of one rating parameter that meets a
premium target. calibrate_weights post-stratifies or rakes policy-count
weights to target counts. double_lift compares each program’s premium
with actual losses, grouped by price ratio. PremiumAnalysis and PremiumRanking offer the
same calculations on typed records.
Calibration
weights holds one calibrated weight per row, in input order.
method is post-stratification for one attribute and raking for
several. effective_size is (Σw)² / Σw², the number of equally weighted
rows carrying the same information (Kish); min_factor and max_factor are the
smallest and largest ratio of calibrated to source weight among rows with
source weight. analysis is the reweighted analysis when called through
PremiumAnalysis.calibrate.
CalibrationTarget
DrawRanges
GroupDrawRange
draw_count counts draws holding the
group and paired_draw_count those with paired support.
LeverSearch
search_lever.
value is the rated value whose objective came closest to target,
and achieved that objective. converged says whether it is within
the tolerance; stop_reason is tolerance, bracket (the bracket
narrowed to one quantum, as rounding can make an exact match impossible) or
max_iterations. population_count is the fixed population: contexts
the reference and both bracket ends rated. trace lists every rated
value in order, with its support.
LeverStep
LiftGroup
group is q1 upward for equal-weight groups, or a ratio bucket
label. ratio_min and ratio_max bound the observed candidate over
baseline ratios. Loss ratio relativities divide each program’s group loss
ratio by its loss ratio over all groups. Claim and credibility fields fill
when the population carries claim counts. Empty groups hold missing values.
PolicyChange
delta and delta_percent use candidate minus baseline and stay
missing for excluded rows. missing_source denotes absent provenance.
The original exposure and quotes retain context, attributes and reasons.
Status is paired, unrated, missing_source, invalid_premium,
missing_basis or basis_mismatch.
PolicyDrawRange
PolicyExposure
attributes holds scalar facts such as state, exposure band and deductible.
profile_id names a repeated source archetype, when supplied. Weight one
represents one policy in the selected population, rather than earned exposure.
exposure is the policy’s exposure base, such as payroll or vehicle years,
in exposure_unit: a denominator for premium per unit, separate from the weight.
losses and claim_count hold the policy’s actual incurred losses and
claims over its experience period, for PremiumAnalysis.double_lift.
Attributes are copied and read-only. Missing facts use None.
PolicyKey
draw_id is a nonnegative integer.
scenario_id defaults to baseline for a single supplied population.
PolicyQuote
Decimal; missing output uses None. Success with missing terms,
provenance or a nonpositive baseline remains visible as an exclusion.
Negative finite premiums also remain visible for analytical validation.
A failed quote’s amount stays outside paired premium calculations.
Status is succeeded, invalid_book, mapping_failed,
invalid_inputs, refused, rating_failed, prediction_failed or
read_failed.
PremiumAnalysis
PolicyExposure rows and at most one PolicyQuote per
context/program. Every quote belongs to the population. Exactly the two
named programs are accepted. Missing quotes retain their population rows.
The object snapshots the iterables and performs local analysis only.
It reads supplied actual terms and provenance, with data loading left to you.
Monetary methods reuse the dataframe compare and summarize kernels.
Exposure attributes hold policy-level segment facts; choose their definitions
explicitly for policies with multiple insured assets. Matching terms is subject to review.
Each attribute name keeps a consistent scalar kind across the population.
PremiumAnalysis.pair_results
PremiumAnalysis.from_book
segments maps attribute names to submission column names. weight
and profile name submission columns; omitted weight means one policy.
Aggregate asset-level facts onto submissions explicitly before calling.
Study populations use each realized scenario/draw’s submission facts.
Missing quotes retain their population rows. Numeric dataframe scalars
become Python integers or Decimal; missing attributes become None.
Weights express policy counts. exposure names a submission column
holding each policy’s exposure base, such as payroll, labelled by
exposure_unit; summaries then report premium per unit of exposure.
losses and claim_count name columns of each policy’s actual
incurred losses and claims, which double_lift compares with premium.
Supply quotes corresponding to this book; matching identities alone
establishes membership, rather than rating fidelity.
PremiumAnalysis.from_market
premium names the amount column, or maps each selected program to
its amount column. terms maps each successful result row to actual
PremiumTerms, or None for unknown terms. The callback receives a detached,
read-only row mapping; its errors propagate with policy/context/program
information. Failed quotes skip this callback. Term evidence may come
from output columns or an explicitly keyed source captured by the callback.
Each result’s bundle_id becomes its rater_bundle provenance. Missing
provenance remains missing. Other programs are ignored; duplicate or
out-of-population selected results raise ValueError. Results and population
must share the same Book/Study context shape. Aggregate item-level results
explicitly before calling. Premium and weight numeric scalars become Decimal.
Segment, weight, profile, exposure and loss mappings follow from_book. Correspondence
between the supplied results and book remains the caller’s responsibility.
PremiumAnalysis.check_comparability
PremiumAnalysis.premium_changes
PremiumAnalysis.with_weights
PremiumAnalysis.calibrate
targets maps exposure attribute names to target counts by value, as in
analysis.calibrate_weights: one attribute is post-stratified exactly and
several are raked. The population must hold one scenario/draw. Returns the
Calibration with its diagnostics, whose analysis reuses every quote
with the calibrated weights. Changed risk facts still need rerating.
PremiumAnalysis.to_pandas
check_comparability.
missing_source preserves absent user or bundle provenance.
PremiumAnalysis.summarize
by names user exposure attributes. Supplied count weights apply once;
scenarios and draws stay separate. Dataframe kernel denominators, source
profile support and missing-statistic rules apply unchanged.
percentiles and buckets add the distribution of policy changes as
in analysis.summarize. When the population carries exposure, each
summary also reports premium per unit of exposure; every exposure must
share one unit.
PremiumAnalysis.double_lift
from_book(losses=...) or
PolicyExposure.losses. groups, edges and full_credibility
follow analysis.double_lift. Returns one LiftGroup per
scenario/draw and group, in ratio order.
PremiumAnalysis.rateability
PremiumAnalysis.draw_ranges
Study: each policy’s premiums and changes
across its paired draws, and each scenario and segment’s totals and
portfolio change across draws, summarized draw by draw first. Draw 0
(the reported book) is left out unless include_draw_zero.
paired_in_every_draw keeps only policies paired in every draw of
their scenario. These describe simulated spread, rather than confidence
intervals; see analysis.policy_draw_ranges and
analysis.group_draw_ranges.
PremiumRanking
PolicyExposure rows and at most one PolicyQuote per
context and program; every quote belongs to the population and to one of
programs. The first program is the reference for ratio_to_first.
Quotes are paired on the same rules as PremiumAnalysis: a quote counts
when it succeeded, has provenance, a premium of zero or more and complete
terms that match the context’s reference terms. The object snapshots its
inputs and analyzes locally.
PremiumRanking.from_market
Market.rate results for several programs.
Arguments follow PremiumAnalysis.from_market, with programs
naming every program to rank, in order; premium names one amount
column or maps each program to its column.
PremiumRanking.to_pandas
analysis.rank.
Provenance appears as source_id, and a missing one as
missing_source. complete_only is as in analysis.rank.
PremiumRanking.summarize
analysis.rank_summary.
PremiumSummary
None.
Counts include zero-weight rows; profile counts describe positive-weight
support. segments retains the selected grouping values.
premium_cheaper_share is the share of weighted baseline premium where the
candidate is cheaper. Percentiles are keyed by level; bucket shares by the
bucket’s label, such as "-10_to_0". Exposure fields are filled when the
population carries exposure, and stay empty otherwise.
PremiumTerms
values contains explicit scalar terms, such as property.deductible and
liability.limit. Monetary terms use Decimal in currency.
Supply a shared field vocabulary across programs. Empty maps, blank text,
missing fields and None terms produce incomplete comparisons.
Numeric Decimal and integer terms compare numerically; booleans stay distinct.
Matching supplied terms establishes declared equality, subject to review.
QuotePair
RankSummary
cheapest_share splits ties equally; cheapest_premium_share weights
each context by the first program’s premium; ratio_to_first divides the
program’s weighted premium total by the first program’s.
Rateability
comparison counts each comparison status, such as paired or
basis_mismatch; missing_source covers absent provenance.
RatingSource
rater_bundle identifies a compiled bundle. user_supplied identifies
supplied quote evidence, such as a versioned file or quote reference.
This records provenance; the analyst establishes the source’s fidelity.
StatusCounts
ineligible counts refusals; unratable counts invalid books,
mapping and input failures and rating, read or prediction failures;
not_attempted counts contexts lacking a quote. reason_codes counts
the reason codes of every unsuccessful quote.
TermDifference
TermsCheck
matches describes terms alone. Pricing and quote-status checks occur
in premium_changes; matching terms alone establishes a declared basis.
TermsCheck.matches
calibrate_weights
rows holds one row per policy (or policy context) with the attribute
columns. targets maps each attribute column to the target count for
every value it takes, such as {"band": {"small": 600, "large": 400}}; use
None as the key for rows whose value is missing. weight names the
source weight column; omitted means one per row.
One attribute is post-stratified exactly. Several attributes are raked:
each is matched in turn until every relative residual is within
tolerance or max_iterations passes are done; converged says
which. Raking needs every attribute’s targets to share one total.
A target value absent from the rows, a row value that lacks a target, or a
positive target with zero source weight raises ValueError, rather than
dropping a constraint or inventing rows. Arithmetic uses a
fixed 38-digit decimal context. The rows themselves are left unchanged.
The methods follow Deming and Stephan (1940) for raking and Deville and
Särndal (1992) for calibration estimators. effective_size is Kish’s
(1965) effective sample size.
compare
results is the submission-level table from Market.rate. premium
names its amount column. basis names a nonempty sequence of columns
whose nonblank string values must match, such as currency, term, coverage
limits, deductibles and valuation basis, or a reviewed terms fingerprint.
Include currency and premium_basis in basis to state units.
Each successful result also needs its immutable bundle_id.
population has unique submission_id rows, plus scenario_id and
draw_id together for study results. Include weights, segment labels and
source profile IDs here. Every selected result must belong to it.
Every population row remains visible, including missing results.
A study needs its full contextual population.
A policy with multiple insured assets needs an explicitly selected policy-level segment.
Returns population columns, each program’s status, reason_code,
reason, bundle_id, premium and basis columns suffixed with
_baseline or _candidate. comparison_status records paired,
unrated, missing_bundle, invalid_premium, missing_basis or
basis_mismatch in that priority. Only paired rows have delta and
delta_percent (candidate minus baseline); the baseline must be positive.
Missing program rows have missing_result status and missing amounts.
Refused premiums remain missing in the paired view even if supplied.
Arithmetic uses a fixed 38-digit decimal context, independent of the caller.
Malformed keys, duplicate results, absent columns, colliding population
columns and blank program names raise ValueError before analysis.
baseline_program and candidate_program retain the program names.
Inputs remain unchanged. Group the returned rows with summarize or pandas.
double_lift
pairs holds
analysis.compare rows whose population carries each policy’s actual
losses in the losses column, in the premium’s currency. Rows sort by
the price ratio: candidate premium over baseline premium. groups splits
them into that many groups of equal policy-count weight, labelled q1
upward; each row joins the group holding the midpoint of its weight, and
ties sort by submission ID. edges replaces those groups with
fixed ratio edges, such as (1,) for cheaper and dearer, labelled like
summarize buckets.
Each group reports its policy count and weight, both programs’ weighted
premium, weighted losses and each program’s loss ratio. Each loss ratio
also appears as a relativity to that program’s loss ratio over all groups.
A baseline relativity that rises with the ratio means the candidate’s
rating tracks these losses more closely. A flat one means the baseline’s
rating tracks them at least as well. Low baseline loss ratios where the
candidate is cheaper mark profitable business at risk.
claim_count names a column of claim counts. Each group then reports
its weighted claims and a square-root-rule credibility against
full_credibility claims; 1,082 is the classical standard for
frequency. weight names a policy-count weight; omitted means one per
row. Studies keep each scenario and draw separate.
Paired positive-weight rows with a missing loss or claim count are
excluded and counted in losses_excluded_count. Empty groups keep their
row with missing statistics. Arithmetic uses a fixed 38-digit decimal
context. Invalid weights, premiums, losses or columns raise ValueError.
group_draw_ranges
analysis.summarize (by and weight
as there), then returns one row per scenario and segment: draw_count
(draws holding the group), paired_draw_count (draws with paired
support), the lowest and highest paired weight share, and draw quantiles
of the baseline and candidate premium totals, delta, portfolio change and
the cheaper shares, as portfolio_change_percent_p50 and so on. Totals
are summed within each draw before quantiles are taken; per-policy
quantiles stay separate from these totals.
paired_in_every_draw keeps only the policies paired in every draw of
their scenario, so each draw compares the same policies. Draw 0 is left out
unless include_draw_zero is true. Scenarios stay separate. These are
spreads of simulated draws, rather than confidence intervals.
policy_draw_ranges
pairs is analysis.compare output for a Study. Returns one row
per scenario and submission: draw_count, paired_draw_count, and
for baseline premium, candidate premium, delta and percentage change the
draw quantiles over the draws where the policy was paired, as
premium_baseline_p10, delta_percent_p90 and so on. Each measure’s
quantiles are computed on their own: the quantile of a change differs from the
change between quantiles. Each draw counts once, and a quantile is the
smallest observed value whose share of draws reaches the level.
Draw 0 is the reported book, whose blanks stay blank, so it is left out
unless include_draw_zero is true. Scenarios stay separate. These are
spreads of simulated draws, rather than confidence intervals.
rank
results is Market.rate output; programs names two or more of
its programs, in order; premium names the amount column; basis
names the comparison-term columns as in compare, including currency
and premium_basis. population has one row per submission (or
study context), as in compare; every population row stays visible.
Returns one row per population row and program, in population order and
then program order, with the population columns and: rank_status
(quoted, missing_result, unrated, missing_bundle,
invalid_premium, missing_basis or basis_mismatch), the result’s
status, reason_code, reason, bundle_id and premium;
rank (1 is cheapest; tied programs share the lowest rank),
cheapest_programs (every tied cheapest program), gap_to_cheapest
and gap_to_cheapest_percent; quoted_count; and market_status:
complete when every program quoted, partial when some did, and
empty when every program failed to quote.
The first program whose quote is otherwise usable sets the context’s
comparison basis; another program with a different basis is
basis_mismatch there, and the context is partial. A premium may be zero
or more; a refused or failed quote keeps a missing premium. By
default only complete contexts are ranked; complete_only=False ranks
the quoted programs of partial contexts too. Contexts and scenarios stay
separate. Arithmetic uses a fixed 38-digit decimal context.
rank_summary
rank rows per context, segment and program.
Returns one row per scenario/draw, segment and program, with
population_count, complete_count (contexts where every program
quoted), and over complete contexts: cheapest_share, the weighted share
of contexts where the program is cheapest, with ties split equally;
cheapest_premium_share, the same share weighted by the first program’s
premium; premium_total, the program’s weighted premium total; and
ratio_to_first, that total divided by the first program’s. weight
names a finite nonnegative policy-count weight column; omitted means one
per population row. Shares are missing when the complete contexts carry
zero total weight.
rateability
pairs is the output of analysis.compare (or
PremiumAnalysis.to_pandas). Returns one row per scenario/draw and
segment group: population_count; for each side, baseline_… and
candidate_…, its program name and how many contexts succeeded,
were ineligible (refused), unratable (invalid_book,
mapping_failed, invalid_inputs, rating_failed, read_failed
or prediction_failed), not_attempted (absent result) or ended in any
other status, plus …_reason_codes, a mapping from each reason code
of the unsuccessful quotes to its count; and one
comparison_<status> count per comparison status. A missing bundle or
source counts as comparison_missing_source.
Counts are of population contexts, whatever their weight. Report them with
every result, so readers see a subset of the book as a subset.
search_lever
make_program(value) returns a new Program for one value of the
parameter, usually by editing a table with rater.with_tables and
program.with_rater; it must build a fresh program each call, because
the search closes it after rating. reference is the program to compare
against, such as a competitor’s; it is rated once and left open.
The objective is computed over a fixed population: the contexts that the
reference and the programs at both low and high rated. By default
it is the ratio of the candidate’s premium total to the reference’s, so
target=1 finds premium parity. A custom objective receives the two
programs’ premiums by context, over the contexts both rated, and returns a
Decimal. If a value loses support, meaning a context it stops rating, its
step records how many contexts it lost.
The search bisects between low and high, rounding each value to
quantum. The objective at the two ends must straddle target, or it
raises ValueError. It stops when the objective is within tolerance
of the target, when the bracket narrows to one quantum, or after
max_iterations values; rounding makes premiums step, so the closest value
may miss the target slightly. Values, targets and tolerances are Decimal or int.
Each step recompiles one rater and rates the whole book.
summarize
analysis.compare rows by context and chosen segments.
by names population columns, such as state, length band or deductible.
Study scenario_id and draw_id always stay separate, even with empty
by. Missing segment values form their own group. weight names a
finite nonnegative policy-count weight; omitted means one per population
row. Pure mix changes reuse the same paired premiums with different weights.
A policy’s annual premium is weighted once, rather than multiplied by its
earned exposure. Changed rating inputs require rerating before comparison.
Returns population and paired counts/weights; paired baseline and candidate
premium totals; total and mean delta; portfolio change as 100 times the ratio
of weighted premium totals minus one; weighted candidate-cheaper and tie
shares; and premium_cheaper_share, the share of weighted baseline premium
in policies where the candidate is cheaper. profile adds distinct
source-profile counts for all and paired rows, counting positive-weight rows
with known profiles. Counts describe support, rather than statistical
independence or credibility.
percentiles lists levels between 0 and 1, such as (0.1, 0.5, 0.9),
and adds weighted percentiles of each policy’s percentage change as
delta_percent_p10 and so on: the smallest observed change whose
cumulative weight share reaches the level, so each one is an observed change.
buckets lists increasing edges in percent, such as (-10, 0, 10),
and adds each bucket’s share of weight (bucket_share_lt_-10,
bucket_share_-10_to_0, bucket_share_0_to_10,
bucket_share_ge_10) and of weighted baseline premium
(bucket_premium_share_…). Buckets include their lower edge and exclude
their upper edge.
exposure names a population column holding each policy’s exposure, such
as payroll or vehicle years, and exposure_unit labels it, such as
"USD payroll". The summary then adds exposure_total and each program’s
premium per unit of exposure (weighted premium over weighted exposure) over
paired policies with positive exposure, and exposure_excluded_count for
paired policies whose exposure is missing or zero. Exposure is a
denominator, separate from the weights. A negative exposure raises.
Premium statistics use positive-weight paired rows. An empty paired group
has missing premium statistics, rather than zero totals. An all-zero-weight
group retains counts and has missing shares. Arithmetic uses a fixed
38-digit decimal context. Scenario/draw rows remain individual realizations;
this function produces descriptive results rather than confidence intervals.
Each group requires a single program pair, currency and premium basis.
Their labels are retained in the summary; select consistent units first.
Invalid weights, duplicate policy/context keys, invalid paired premiums or
unknown columns raise ValueError. The input remains unchanged.