ExitTable#
ExitTable extends DecrementTable
for exit / turnover tables. The governing decrement is the exit rate
\(o_x\), which represents the probability that a contract or member aged \(x\)
exits within one year (employment termination, withdrawal, lapse, or surrender).
Exit tables are used in persistency analysis, lapse-risk pricing, and
multi-decrement models for group pension and collective insurance products.
Table files carry \(o_x\) columns (prefixed ox_m, ox_f, or ox_u) and may include
generational improvement factors for cohort-based exit rates.
See also
Table Taxonomy — Overview of all table types and decrement conventions.
Using Actuarial Tables — Loading and inspecting tables.
Modifying Decrements — Scaling, aggravated risk, and table_combination.
Mortality Improvement (MI) — Generational tables and improvement factors.
- class lactuca.ExitTable(table_name: str | list | tuple, sex: Literal['m', 'f', 'u'] | Sequence[Literal['m', 'f', 'u']] | None = None, cohort: int | Sequence | None = None, unisex_blend: object = None, duration: int | str | Sequence | None = None, cartesian: bool = False, return_dict: bool = False, pending: bool = False, **_kw)#
Bases:
DecrementTableConcrete implementation of DecrementTable for exit/turnover tables.
ExitTable represents actuarial tables for exit/turnover probabilities (\(o_x\)), where \(o_x\) denotes the probability of exiting employment between ages \(x\) and \(x+1\). It provides all standard actuarial functions (
lx,px,dx,tpx,tqx) but uses exit-specific nomenclature and blocks access to mortality and disability-specific methods.To build combined multiple decrement models (mortality + exit + disability), use
modify_qx()on theLifeTablewith thisExitTableas a combination argument;ExitTableitself only combines with otherExitTableinstances.Construction accepts scalar arguments for a single instance, or sequences for vectorial creation (families, scenarios, pricing grids). See
__new__()for full dispatch details.- Parameters:
table_name (str, list, or tuple) – Name of one or more exit table files (without
.ltkextension). A list or tuple enables multi-table vectorial creation.sex (str or sequence of str) – Single sex (
'm','f','u') or sequence for vectorial creation.cohort (int, sequence of int, or None, optional) – Birth year(s) for generational tables. If
None, loads a period table. Broadcast and zip-alignment rules match__new__().unisex_blend (float, list of float, or None, optional) – Male weight for unisex blending in \([0, 1]\) (
0.0= all female,1.0= all male). A list is accepted in zip mode (cartesian=False) to assign a distinct blend to each instance; scalarsex='u'broadcasts to the list length. See__new__().duration (int,
'ult', sequence, or None, optional) – Duration slice for select-ultimate tables. Pass an integer>= start_durationfor a select column,'ult'for the ultimate column, orNonefor non-select tables.cartesian (bool, optional) – If
True, create the full Cartesian product of alltable_name,sex,cohort, anddurationvalues. All table names must share the same generational structure and the same select structure. Withcartesian=True, aunisex_blendsequence is allowed only when everysexvalue is'u'(fifth cartesian axis). A scalarunisex_blendis replicated uniformly to all combinations wheresex='u'. Default isFalse(zip/broadcast alignment).return_dict (bool, optional) – If
True, return adictmappingTableKeyto eachExitTableinstance instead of a plaintuple. Default isFalse.
- Returns:
Single
ExitTablewhensexis a scalar string,table_nameis a bare string (not alist/tuple),cohortanddurationare scalar orNone, no sequence dimensions are provided, andreturn_dict=False. Atuplewhen any parameter is a sequence orcartesian=Trueandreturn_dict=False(including length-1 tuples). Adictkeyed byTableKeywhenreturn_dict=True.- Return type:
Notes
ExitTable uses \(o_x\) internally where
LifeTableuses \(q_x\) andDisabilityTableuses \(i_x\).All probability calculations (
px,tpx,tqx) work identically to other decrement tables.Can be combined with other
ExitTableinstances viamodify_ox()for competitive exit decrements.Inherits the modification system from
DecrementTable.Zip mode (default):
table_name,sex,cohort, anddurationare aligned element-wise (or broadcast when length is 1).Cartesian mode (
cartesian=True): every combination is created — suited to sensitivity grids and pricing studies, not sparse portfolio processing.A
ResourceWarningis emitted when more than 100 instances are created in a single constructor call.
- Raises:
FileNotFoundError – If a table file does not exist in the actuarial tables directory.
ValueError – If the table is not an exit table; if
cohort,sex, ordurationsequences have incompatible lengths; ifunisex_blendis out of \([0, 1]\) or provided whensexis not'u'; ifsex='u'and the table lacks a native unisex column whileunisex_blendisNone; ifcartesian=Trueand table names mix generational and period tables or mix select and non-select tables; or ifcartesian=Trueandunisex_blendis a sequence whilesexcontains any value other than'u'.TypeError – If
cohort,duration,sex, orunisex_blendarguments have invalid types.NotImplementedError – If
qx(),ix(),ex(), ormodify_qx()are called.
See also
DecrementTableAbstract base class providing core decrement logic.
TableKeyStructured lookup key for
return_dict=Trueresults.LifeTableMortality table implementation.
DisabilityTableDisability incidence table implementation.
Examples
>>> from lactuca import ExitTable, TableKey >>> et = ExitTable('DummyEXIT', sex='m') >>> et.ox(30) >= 0.0 True >>> # Zip mode: two sexes >>> et_m, et_f = ExitTable('DummyEXIT', ('m', 'f')) >>> # Cartesian product: 2 sexes → 2 instances (scalar cohort) >>> tables = ExitTable('DummyEXIT', ('m', 'f'), cartesian=True) >>> len(tables) 2 >>> # Dict return keyed by TableKey >>> d = ExitTable('DummyEXIT', ('m', 'f'), return_dict=True) >>> et_m = d[TableKey('DummyEXIT', 'm')]
- ex(x: object = None, m: Literal[1, 2, 3, 4, 6, 12, 14, 24, 26, 52, 365] = 1) None#
Blocked method: not available for ExitTable.
- Raises:
NotImplementedError – Always raised. Life expectancy (
ex) is not applicable to exit tables.
Notes
Life expectancy is a mortality-specific concept.
ExitTable focuses on exit/turnover probabilities, not life expectancy.
For life expectancy calculations, use
LifeTable.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> try: ... et.ex(30) ... except NotImplementedError: ... pass
See also
LifeTableMortality table class with
ex(life expectancy) support.
- ex_curtate(x: object = None) None#
Blocked method: not available for ExitTable.
- Raises:
NotImplementedError – Always raised. Curtate life expectancy (
ex_curtate) is not applicable to exit tables.
Notes
Life expectancy is a mortality-specific concept.
ExitTable focuses on exit/turnover probabilities, not life expectancy.
For curtate life expectancy, use
LifeTable.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> try: ... et.ex_curtate(30) ... except NotImplementedError: ... pass
See also
LifeTableMortality table class with
ex_curtatesupport.
- ix(x: object = None, m: Literal[1, 2, 3, 4, 6, 12, 14, 24, 26, 52, 365] = 1) None#
Blocked method: not available for ExitTable.
- Raises:
NotImplementedError – Always raised. Use
ox()instead for exit probabilities.
Notes
ExitTable does not support disability incidence rates (
ix).Use
oxfor exit/turnover probabilities.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> try: ... et.ix(30) ... except NotImplementedError as exc: ... 'ox' in str(exc) True
See also
ExitTable.oxExit probability.
DisabilityTableUse DisabilityTable class for disability incidence (\(i_x\)).
- modify_ox(modifications: ModifyDecrement) None#
Apply modifications to exit rates (ox) for turnover/exit tables.
This method allows actuarial adjustments to the base exit table, such as scaling rates, shifting ages, applying aggravated risk factors, or combining with other ExitTable instances using independent competitive risks. All modifications are applied to a copy of the base rates and can be reset with
reset_modifications().- Parameters:
modifications (dict) –
Dictionary specifying one or more modification operations. See ModifyDecrement TypedDict for supported keys:
- ’age_shift’int
Shift all ages by N years (drops first N ages).
- ’decrement_multiplier’float
Multiply all \(o_x\) values by a constant factor.
- ’decrement_geometric_increase’tuple[float, int]
Apply geometric growth to tail: (growth_rate, start_age).
- ’aggravated_risk’float
Apply aggravated risk transform: \(p_x \to p_x^f\), where \(f\) is the aggravated risk factor value.
- ’table_combination’Union[ExitTable, list, tuple]
Combine with one or more ExitTables using independent competitive risks (default) or UDD when
combination_mode='udd'. ExitTable can only combine with ExitTable (e.g., voluntary vs. involuntary turnover). Age alignment, host length, implicit zero beyond shorter tables, and rejection rules are identical tomodify_qx()— see Modifying Decrements.
- ’combination_mode’
'independent'or'udd' Optional actuarial assumption for
table_combination; seemodify_qx().
- ’combination_mode’
- Raises:
ValueError – If modification parameters are invalid or produce non-actuarial results.
TypeError – If modification keys or values have incorrect types.
Notes
Modifications are applied in iteration order (dict order in Python 3.7+).
ExitTable can only combine with ExitTable (e.g., voluntary vs. involuntary turnover). For combined Life+Exit or Life+Exit+Disability (Masa Activa) models, use
modify_qxon the LifeTable.Combined tables must have matching sex.
Final results are rounded to configured decimals (
config.decimals.ox).Use
reset_modifications()to restore original base rates.Non-accumulative: each call to
modify_oxreplaces any previous modification entirely — it always restarts from the unmodified base rates. To accumulate multiple operations, pass all keys in a single call as a dict, or callreset_modifications()explicitly between independent experiments.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable("DummyEXIT", sex="m") >>> base = et.ox(30) >>> et.modify_ox({"decrement_multiplier": 0.8}) >>> et.ox(30) <= base True
See also
DecrementTable.reset_modificationsRestore original base rates.
- modify_qx(modifications: object = None) None#
Blocked method: not available for ExitTable.
- Raises:
NotImplementedError – Always raised. Use
modify_ox()instead for exit rate modifications.
Notes
ExitTable uses
modify_oxfor actuarial adjustments.All modification functionality available via
modify_ox.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> try: ... et.modify_qx({'decrement_multiplier': 0.9}) ... except NotImplementedError as exc: ... 'modify_ox' in str(exc) True
See also
ExitTable.modify_oxApply actuarial modifications to exit rates.
- ox(x: object = None, m: Literal[1, 2, 3, 4, 6, 12, 14, 24, 26, 52, 365] = 1) object#
Return exit/turnover probability at age x.
Computes the probability that an active employee aged \(x\) exits (terminates employment) before age \(x + 1/m\), using \(o_x = 1 - p_x\) where \(p_x\) is the probability of retention. For fractional periods, uses \(\ell_x\) interpolation.
- Parameters:
x (float, int, sequence of float, NDArray[np.float64], or None, optional) – Entry age(s). Pandas and Polars Series are accepted. If None, returns
oxfor all integer ages in the table.m (PaymentFrequencyLiteral, optional) – Number of periods per year (1, 2, 3, 4, 6, 12, 14, 24, 26, 52, or 365). Default is 1.
- Returns:
Exit probability(ies). Returns scalar if x is scalar, otherwise array matching x shape.
- Return type:
float or np.ndarray
Notes
For integer ages and m=1, returns the precomputed \(o_x\) value from the table.
For fractional ages or m>1, uses \(\ell_x\) interpolation: \(o_x = 1 - \ell_{x+1/m} / \ell_x\)
If
xis None, returns the full rounded decrement array (ages 0 to \(\omega\)).All results rounded to
config.decimals.ox.Consistent with international actuarial practice.
- Raises:
ValueError – If any age in
xis negative.TypeError – If
xis not numeric, or ifmis not a scalar integer.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> et.ox(30) >= 0.0 True >>> bool(et.ox(30, m=12) >= 0.0) True >>> vals = et.ox([25, 30, 35]) >>> vals.shape (3,)
See also
DecrementTable.pxProbability of retention (complement of \(o_x\)).
DecrementTable.lxNumber of active employees at age \(x\).
DecrementTable.tqxProbability of exit within t years.
- qx(x: object = None, m: Literal[1, 2, 3, 4, 6, 12, 14, 24, 26, 52, 365] = 1) None#
Blocked method: not available for ExitTable.
- Raises:
NotImplementedError – Always raised. Use
ox()instead for exit probabilities.
Notes
ExitTable uses \(o_x\) (exit probability) instead of \(q_x\) (mortality).
All
qx-related functionality is replaced byoxmethods.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> try: ... et.qx(30) ... except NotImplementedError as exc: ... 'ox' in str(exc) True
See also
ExitTable.oxExit probability (replacement for \(q_x\)).
LifeTableUse LifeTable class for mortality rates.
- summary() str#
Return a formatted summary of the exit table state and sample ox values.
Calls
summary()for the common header block, then appends:Decimals: ox=<n>Sample ox values for the first and last 5 ages. When a modification is active, each line shows both the current and the original base value:
ox(30) = 0.064 (original: 0.080)
Without a modification the parenthetical is omitted.
- Returns:
Multi-line summary string.
- Return type:
str
Examples
>>> from lactuca import ExitTable >>> et = ExitTable("DummyEXIT", sex="m") >>> summary = et.summary() >>> "Decimals: ox=" in summary True >>> "Sample ox values (first 5):" in summary True
See also
DecrementTable.reset_modificationsRestore base rates and clear modification state.
ExitTable.modify_oxApply modifications.
- property decimals: _DecimalsConfig#
Access decimal precision settings for exit table actuarial functions.
This property provides convenient attribute-based access to global decimal precision configuration. All values are proxied dynamically from the
Configsingleton — no state is stored locally in the table instance. Commutation functions, mortality, life-expectancy, and disability-rate attributes are blocked and raiseAttributeError.- Returns:
Decimal-precision proxy with attributes for exit-table actuarial columns. Available attributes:
ox: int — Exit rate \(o_x\) precisionlx: int — Survival function \(\ell_x\) precisiondx: int — Decrements \(d_x\) precisionpx: int — Survival probability \(p_x\) precisiontpx: int — Multi-year survival \({}_t p_x\) precisiontqx: int — Multi-year decrement \({}_t q_x\) precision
- Return type:
object
- Raises:
AttributeError – If accessing a blocked property:
qx,ix,ex,Lx,Tx,Dx,Nx,Sx,Cx,Mx,Rx,annuities, orinsurances.
Notes
Read-only proxy:
self.decimals.xxx = valueraisesAttributeErrorby design; useConfig().decimals.xxx = valueto change precision globally.Global scope: Changes to
Config.decimalsare immediately visible through all table instances.For permanent changes, use
Config().decimals.ox = valueorConfig().set('decimals_ox', value).
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> isinstance(et.decimals.ox, int) True >>> isinstance(et.decimals.px, int) True
See also
Config.decimalsGlobal decimal precision configuration.
- property table_type: str#
Return the type identifier for this decrement table.
- Returns:
Always returns ‘exit’ for ExitTable instances.
- Return type:
str
Notes
Immutable property; cannot be modified after instantiation.
Examples
>>> from lactuca import ExitTable >>> et = ExitTable('DummyEXIT', sex='m') >>> et.table_type 'exit'
See also
DecrementTableBase class providing core decrement logic.
ExitTable-specific members#
These members are defined on ExitTable itself and are
not present on DecrementTable.
Actuarial methods#
Return exit/turnover probability at age x. |
Modification#
Apply modifications to exit rates (ox) for turnover/exit tables. |
Inherited from DecrementTable#
The following members are inherited from DecrementTable.
See the DecrementTable reference for full documentation
of each member.
Note
qx, ix, ex, ex_curtate, and modify_qx are not available on ExitTable — the primary decrement is ox
(exit / turnover rate). Calling any of the blocked methods raises NotImplementedError.
Actuarial methods#
Return lx values (number of lives at age x) for the specified age(s). |
|
Return probability of surviving one period (px) at age x. |
|
Return interval survival probability tpx for all (x, t) combinations. |
|
Return interval death probability tqx for all (x, t) combinations. |
|
Return \(d_x\) values (number of decrements between ages \(x\) and \(x+1\)). |
Modification#
Restore decrement to the original base values and clear all caches. |
|
Return a deep copy of the instance. |
Display#
State#
Current sex used for calculations. |
|
Current cohort (year of birth) for generational tables. |
|
Return the current policy duration for select or non-select tables. |
|
Male weight used to blend male/female rates into unisex rates. |
|
Current upper age limit (omega), accounting for modifications. |
|
True if a modification is currently active on this table. |
|
List of modification descriptors applied in the current call. |
|
Return True if the underlying table is a select-ultimate table. |
|
True when required metadata has not yet been supplied via configure() or setters. |
Deferred construction#
Configure table metadata atomically with a single rebuild. |
|
Context manager to batch multiple setter assignments into one rebuild. |
See also TableRegistry and configure_all() in
Table registry utilities and Deferred construction: pending, configure, and TableRegistry in Using Actuarial Tables.
Table metadata#
Name of the underlying actuarial table. |
|
Access the underlying TableSource instance with table data and metadata. |
|
Whether the table includes cohort-based improvement factors. |
|
Base year for generational improvement. |
|
Original terminal age from metadata (immutable). |
|
Minimum defined age in the original table. |
|
Human-readable table description from metadata. |
|
Valid sexes for this table (e.g. |
|
Whether rates are identical for both sexes. |
|
Generational improvement formula type. |
|
Whether this is a select-ultimate table. |
|
Select period in years. |
|
Calendar-year index for generational improvement on select columns. |
|
Minimum integer duration. |
|
Whether improvement factors are stored by policy duration. |
|
Mortality improvement column layout tag. |
|
Projection calendar years for year-indexed MI tables. |
|
Basename of the loaded table file. |
|
Absolute path to the loaded table file. |
|
Raw underlying table data (all columns, all sexes). |
|
Raw metadata dictionary from the table file. |