Skip to main content
A book holds what was reported about each household. A study holds each version of the book that you want to price. This split keeps reported facts, assumptions and sampled values apart, so each premium traces back to its source.

A book belongs to every carrier

Each carrier asks for the same household in its own shape. One carrier wants an age, and another wants years licensed. The book stores the fact behind both: a birth date and a first licensed date. Each program derives what its carrier asks for. One book then serves each carrier, and a new carrier needs a new prepare only. For the same reason, a core column holds a fact with one meaning, such as birth_date. A value that a rater derives, such as an age or a violation class, belongs to the program that derives it. Keep additional facts in columns or tables of your own. The programs that need those facts read them there.

A line is a schema

A line of business is a schema object. Book(tables, schema=ppa.SCHEMA) checks the tables against the PPA schema: the required tables, the keys and the core columns. The examples use the included personal auto schema, ppa.SCHEMA. Extend it with typed columns and tables for your own programs. A plain book, Book(tables), keeps arbitrary tables and infers keys from _id columns. Studies and the rating examples require a line schema, supplied explicitly when you construct or load the book. print(book.schema) shows the line’s tables and columns, then your own. Each column’s origin is line, declared or observed. An observed column has the type its values have. The PPA book schema lists each table, key and core column of ppa.SCHEMA.

Declare your own columns

A column that only your programs read can still have a type. Declare it on the schema, and each book built with that schema types and checks it like a core column. The result is the same line, so studies and programs take the book.
A book reports each problem at once, in one BookError. Each problem names its table, column and rule, counts the rows that break it, and shows up to five of their keys. error.to_pandas() holds the same problems as rows.
Declared columns receive the same typing and validation as core columns. Pandas stores whole numbers as Int64, numbers as Float64, dates as datetime64, and booleans as boolean. Use a text column for codes whose spelling matters, including alphanumeric vehicle symbols and codes with leading zeros.

A book knows where it came from

book.source is the directory Book.read_csv read, a URI you pass as source=, or None for a book built in code. A changed book, such as one from with_tables, has the source None, because the source holds the earlier book. book.hash is a SHA-256 hash of the tables as to_csv writes them, so the same content has the same hash wherever it came from. A result or a study can then name the exact book it priced.

A book stays the same

A book is checked once, when you build it, and stays the same after that. Each table property returns a copy. To change a book, you change a copy in pandas and build a new book with with_tables. Each result then refers to exactly one set of facts, and an earlier book stays valid beside a later one.

A study is a recipe

A study stores how to build each version of the book, and builds one version at a time. Memory holds one version, the base book and the current scenario, however large the grid.
A study refers to each step by its import path and its parameters, such as {"fn": "scenarios:age_drivers", "params": {"years": 1}}. Define each step at the top level of a module. study.to_json() writes the recipe, and Study.from_json reads it back. The same JSON and the same code build books with the same hashes.
A study checks each version as it builds it:
  • A scenario returns a book of the same schema, with the same submissions in the same order.
  • A draw keeps each row in its place and changes only the columns its sampler fills.
  • A draw keeps each reported value present. It may change a reported value, which is then modeled.
  • Study.from_json checks the book’s hash, so a study reads only the data it was written for.

Scenarios and draws answer different questions

A sampler names the columns it fills. Each of these columns gets a <column>_source column, reported or modeled, in each version, so a modeled value stays visible as modeled. Draw k uses the same random stream in each scenario. This is the method of common random numbers. A fact that a scenario leaves unchanged gets the same modeled value in each scenario, which reduces sampling noise in paired scenario comparisons. Keep the sampling procedure and row order consistent across scenarios to preserve that pairing.

Where a value goes

A study works for each line

A study keeps the schema of the book you give it. The scenario and draw checks read the book’s tables, so a book for another line of business follows the same rules.

A sampler draws one stream per draw

Draw k gives the sampler the same generator in each scenario. A sampler that draws one value per row, in row order, gives an unchanged row the same value in each scenario. A scenario that adds a row moves later values in the stream, so draw by row key when a scenario adds rows.

The book defines what a comparison represents

A market basket represents the profiles and weights you selected. A portfolio extract represents its observed mix, subject to the retained rating population. Carry your own segment dimensions through the book and join them to results by key. Report matched counts and rating exceptions beside premium statistics so each result has a clear population.