Source code for annuallife.TradLife_A.Assumptions
# modelx: pseudo-python
# This file is part of a modelx model.
# It can be imported as a Python module, but functions defined herein
# are model formulas and may not be executable as standard Python.
"""Assumption input and calculations for individual policies.
This Space holds assumption parameters and rates used by
:mod:`~annuallife.TradLife_A.Projection` and its base spaces.
Most cells in this Space return per-policy NumPy arrays whose layout
matches the rows of
:func:`~annuallife.TradLife_A.InputData.policy_data`, so callers index
into them with the integer policy index ``idx``. A few cells, such as
:func:`asmp_tables` and :func:`mortality_tables`, return tables shared
across all policies.
Parameters and References
-------------------------
Attributes:
input_data: Alias for :mod:`~annuallife.TradLife_A.InputData`.
Per-policy assumptions are read from the ``AssumptionTable``
range in *input.xlsx* via
:func:`~annuallife.TradLife_A.InputData.assumption`,
and mortality / lapse tables from
:func:`~annuallife.TradLife_A.InputData.assumption_tables` and
:func:`~annuallife.TradLife_A.InputData.mortality_tables`.
return_array(:obj:`bool`): When ``True`` (the default), helper
functions inherited from
:mod:`~annuallife.TradLife_A.Utilities` return NumPy arrays
instead of pandas objects.
.. rubric:: Inherited helpers
Inherited from :mod:`~annuallife.TradLife_A.Utilities`:
* :func:`~annuallife.TradLife_A.Utilities.pandas_to_array`
* :func:`~annuallife.TradLife_A.Utilities.map_to_policies`
.. rubric:: Child spaces
* :mod:`~annuallife.TradLife_A.Assumptions.AsmpID`: Enum-style codes
identifying entries in the ``AsmpByDuration`` table.
Cells Summary
-------------
Commission Assumptions
^^^^^^^^^^^^^^^^^^^^^^
Per-policy initial and renewal commission rates and the renewal
commission term.
.. autosummary::
~comm_init_prem
~comm_ren_prem
~comm_ren_term
Expense Assumptions
^^^^^^^^^^^^^^^^^^^
Per-policy acquisition and maintenance expense assumptions, expressed
per annualized premium, per policy and per sum assured.
.. autosummary::
~exps_acq_ann_prem
~exps_acq_pol
~exps_acq_sa
~exps_maint_ann_prem
~exps_maint_pol
~exps_maint_sa
Tax and Inflation Assumptions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The consumption tax rate and the expense inflation rate.
.. autosummary::
~cnsmp_tax
~inflation_rate
Mortality
^^^^^^^^^
The mortality-table block and the per-policy indices that select each
policy's base mortality rates and its last mortality age.
.. autosummary::
~mortality_tables
~mort_table_index
~mort_array_index
~last_mort_age
Mortality Factor and Lapse
^^^^^^^^^^^^^^^^^^^^^^^^^^
The assumption-by-duration table and the per-policy indices that
select mortality factors and lapse rates, together with its row count.
.. autosummary::
~asmp_tables
~mort_factor_index
~lapse_rate_index
~asmp_table_len
"""
from modelx.serialize.jsonvalues import *
_formula = None
_bases = [
".Utilities"
]
_allow_none = None
_spaces = [
"AsmpID"
]
# ---------------------------------------------------------------------------
# Cells
[docs]
def cnsmp_tax():
"""Consumption tax rate"""
return input_data.const_params()['CnsmpTax']
[docs]
def comm_init_prem():
"""Initial commission per premium"""
return pandas_to_array(map_to_policies(input_data.assumption('CommInitPrem')))
[docs]
def comm_ren_prem():
"""Renewal commission per premium"""
return pandas_to_array(map_to_policies(input_data.assumption('CommRenPrem')))
[docs]
def comm_ren_term():
"""Renewal commission term"""
return pandas_to_array(map_to_policies(input_data.assumption('CommRenTerm')))
[docs]
def exps_acq_ann_prem():
"""Acquisition expense per annualized premium"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsAcqAnnPrem')))
[docs]
def exps_acq_pol():
"""Acquisition expense per policy"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsAcqPol')))
[docs]
def exps_acq_sa():
"""Acquisition expense per sum assured"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsAcqSA')))
[docs]
def exps_maint_ann_prem():
"""Maintenance expense per annualized premium"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsMaintPrem')))
[docs]
def exps_maint_pol():
"""Maintenance expense per policy"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsMaintPol')))
[docs]
def exps_maint_sa():
"""Maintenance expense per sum assured"""
return pandas_to_array(map_to_policies(input_data.assumption('ExpsMaintSA')))
[docs]
def inflation_rate():
"""Inflation rate"""
return input_data.const_params()['InflRate']
[docs]
def mortality_tables():
"""Mortality tables read from *input.xlsx*.
Returns the full mortality-table block from the ``MortalityTables``
range as a 2-D NumPy array (when ``return_array`` is ``True``),
where rows are indexed by age and columns by ``(MortTable, Sex)``.
"""
tables = input_data.mortality_tables()
return pandas_to_array(tables)
[docs]
def mort_table_index():
"""Per-policy mortality table identifier.
Maps the ``BaseMort`` assumption keyed by the model point lookup
(product, policy type, gen) to each row of
:func:`~annuallife.TradLife_A.InputData.policy_data`.
"""
return map_to_policies(input_data.assumption('BaseMort'))
[docs]
def mort_array_index():
"""Per-policy column index into :func:`mortality_tables`.
Returns a 1-D integer array of column positions in
:func:`~annuallife.TradLife_A.InputData.mortality_tables` for each
policy's ``(mort_table_index, sex)`` pair.
"""
columns = input_data.mortality_tables().columns
# Get the column positions in input_data.mortality_tables for each (MortID, sex) pair
return columns.get_indexer(
pd.MultiIndex.from_arrays([mort_table_index(), input_data.policy_data()['Sex']])
)
[docs]
def last_mort_age():
"""Last mortality age per policy (first age where mortality reaches 1)."""
last_ages = input_data.mort_table_last_ages()
keys = pd.MultiIndex.from_arrays(
[mort_table_index(), input_data.policy_data()['Sex']]
)
result = pd.Series(last_ages.reindex(keys).values,
index=input_data.policy_data().index)
return pandas_to_array(result)
[docs]
def asmp_tables():
"""Assumption tables by duration.
Returns the ``AsmpByDuration`` range from *input.xlsx* as a 2-D
NumPy array indexed by duration (rows) and assumption ID (columns).
Used by :func:`~annuallife.TradLife_A.BaseProj.mort_factor` and
:func:`~annuallife.TradLife_A.BaseProj.lapse_rate` together with
:func:`mort_factor_index` and :func:`lapse_rate_index`.
"""
return pandas_to_array(input_data.assumption_tables())
[docs]
def mort_factor_index():
"""Per-policy column index into :func:`asmp_tables` for mortality factors.
Resolves each policy's ``MortFactor`` assumption (referencing an
:mod:`~annuallife.TradLife_A.Assumptions.AsmpID`) to its column
position in the ``AsmpByDuration`` table.
"""
key_to_idx = {getattr(AsmpID, v): i for i, v in enumerate(input_data.assumption_tables().columns)}
indexes = input_data.assumption('MortFactor').map(lambda s: getattr(AsmpID, s)).map(key_to_idx)
return pandas_to_array(map_to_policies(indexes))
[docs]
def lapse_rate_index():
"""Per-policy column index into :func:`asmp_tables` for lapse rates.
Resolves each policy's ``Surrender`` assumption (referencing an
:mod:`~annuallife.TradLife_A.Assumptions.AsmpID`) to its column
position in the ``AsmpByDuration`` table.
"""
key_to_idx = {getattr(AsmpID, v): i for i, v in enumerate(input_data.assumption_tables().columns)}
indexes = input_data.assumption('Surrender').map(lambda s: getattr(AsmpID, s)).map(key_to_idx)
return pandas_to_array(map_to_policies(indexes))
[docs]
def asmp_table_len():
"""Number of rows (durations) in :func:`asmp_tables`."""
return len(asmp_tables())
# ---------------------------------------------------------------------------
# References
input_data = ("Interface", ("..", "InputData"), "auto")
return_array = True