modelx: Actuarial Models as Code

modelx is the open-source actuarial modeling system for Python. Build transparent, auditable models with spreadsheet-like formulas — dependency-traced, version-controlled with Git, and readable by humans and AI agents alike. Deploy them as self-contained pure-Python packages that run without modelx, and compile them to native code with modelx-cython.

General-purpose at its core, modelx is developed with actuarial and financial modeling as its primary domain. It powers lifelib, the open-source library of actuarial model examples. A GUI for modelx, spyder-modelx, is available as a plugin for the Spyder IDE.

In continuous development since 2017 · LGPLv3 · Distributed on PyPI and conda-forge

PyPI version PyPI downloads per month conda-forge version GitHub stars License: LGPL-3.0

Build a model with formulas

import modelx as mx

model = mx.new_model(name="TermLife")
proj = mx.new_space(name="Projection")

proj.premium_pp = 120      # annual premium per policy
proj.sum_assured = 50_000
proj.q = 0.002             # mortality rate
proj.lapse = 0.05          # lapse rate

@mx.defcells
def pols_if(t):
    """Policies in force at t"""
    return 1.0 if t == 0 else pols_if(t - 1) * (1 - q - lapse)

@mx.defcells
def premiums(t):
    return premium_pp * pols_if(t)

@mx.defcells
def claims(t):
    return sum_assured * q * pols_if(t)

@mx.defcells
def net_cf(t):
    return premiums(t) - claims(t)

Run it, trace it, ship it

>>> net_cf(10)      # calculation order resolved automatically
11.725013975627874

>>> net_cf.preds(10)   # trace what this value depends on
[TermLife.Projection.premiums(t=10)=70.3500838537673,
 TermLife.Projection.claims(t=10)=58.62506987813943]

>>> mx.write_model(model, "TermLife")  # plain text: diff it, Git it

>>> model.export("TermLife_ex")   # self-contained pure-Python package

>>> from TermLife_ex import mx_model    # runs without modelx
>>> mx_model.Projection.net_cf(10)
11.725013975627874
  • Automatic dependency resolution — no run scripts to write.
  • Full tracing for validation — every value knows its precedents and dependents.
  • Models saved as plain text — ready for Git and AI agents.
  • Exports as a pure-Python package with no modelx dependency.
  • Exported models compile to native code with modelx-cython.

Install

pip install modelx
# or
conda install -c conda-forge modelx

Prefer a zero-setup Windows bundle? Get the lifelib + modelx distribution →


Highlights

From model to native code

Ship models as plain Python, and compile them to native code when you need speed. No step requires modelx at runtime—or any proprietary system.


graph LR
A(Build in modelx) -- "model.export()" --> B(Pure-Python package
runs without modelx) B -- mx2cy --> C(Native-compiled model)
$ mx2cy TermLife_ex   # exported model -> Cython -> native code

Export to pure Python »  ·  Native compilation »

A GUI in your IDE

spyder-modelx embeds modelx in the Spyder IDE: browse the model as a tree in MxExplorer with each formula a click away, inspect results as DataFrames in MxDataViewer, and trace precedents and dependents interactively.

One model, every scenario

Write a space once, then apply it to arbitrary combinations of inputs—no changes to the formulas.

>>> space.parameters = ("Rate", "Term")

>>> space[3, 10].Payment()
117.23050660515952

Parameterization »

Why modelx — all features →