"""The main space in the Smith-Wilson model
``SmithWilson`` is the only space in the Smith-Wilson model.
The Smith-Wilson method is used for extrapolating risk-free interest rates under the Solvency II framework.
The method is described in
*"QIS 5 Risk-free interest rates – Extrapolation method"*,
a technical paper issued by CEIOPS (the predecessor of EIOPA).
The technical paper is available on `EIOPA's web site`_.
Cells in this space are named consistently
with the mathematical symbols in `the technical paper`_.
.. rubric:: References
Attributes:
    log: `log <https://docs.python.org/3/library/math.html#math.log>`_ function from `the standard math library`_
    exp: `exp <https://docs.python.org/3/library/math.html#math.exp>`_ function from `the standard math library`_
    np: `Numpy`_ module
    N: Number of durations for which the observed spot rates are available
    spot_rates: List of the observed spot rates (annual compound)
    UFR: The ultimate forward rate (continuous compound)
    alpha: The convergence parameter :math:`\alpha`
.. _Numpy : https://numpy.org/
.. _EIOPA's web site: https://wayback.archive-it.org/org-1495/20191229100044/https:/eiopa.europa.eu/publications/qis/insurance/insurance-quantitative-impact-study-5/background-documents
.. _the technical paper: https://wayback.archive-it.org/org-1495/20191229100044/https:/eiopa.europa.eu/Publications/QIS/ceiops-paper-extrapolation-risk-free-rates_en-20100802.pdf
.. _the standard math library: https://docs.python.org/3/library/math.html
"""
from modelx.serialize.jsonvalues import *
_formula = None
_bases = []
_allow_none = None
_spaces = []
# ---------------------------------------------------------------------------
# Cells
[docs]def u(i):
    """Time (:math:`u_i`)
    :func:`u` is a series of discrete time points.
    ``i`` is a 1-based index. By default, :func:`u` just returns ``i``.
    For i = 1, ..., :attr:`N`, :func:`u` corresponds to
    :math:`u_i` in `the technical paper`_,
    The time to maturities of the observed zero-coupon bond prices.
    :attr:`spot_rates`, the observed spot rates must exist at each
    ``u(i)`` from i = 1 to :attr:`N`. Note that :attr:`spot_rates` is
    0-based, so the sport rate at ``u(i)`` is ``spot_rates[i-1]``.
    Args:
        i: The time index (1, 2, ...)
    """
    return i 
[docs]def m(i):
    """Observed zero-coupon bond prices at time :math:`u_i`.
    :func:`m` is calculated from :attr:`spot_rates` as
    :math:`(1 + spot\_rates[i-1])^{-u_i}`
    Args:
        i(int): Time index (1, 2, ..., :attr:`N`)
    """
    return (1 + spot_rates[i-1]) ** (-u[i]) 
[docs]def mu(i):
    """Ultimate Forward Rate (UFR) discount factors
    :func:`mu` is defined as :math:`e^{-UFR\cdot u_i}`.
    Args:
        i(int): Time index (1, 2, ...)
    """
    return exp(-UFR * u[i]) 
[docs]def W(i, j):
    """The Wilson functions.
    :func:`W` corresponds to formula (2) on page 16 in `the technical paper`_
    defined as:
    .. math::
        W(t, u_j)=  \\
            e^{-UFR\cdot (t+u_j)}\cdot  \\
            \left\{   \\
                \\alpha\cdot\min(t, u_j) \\
                -0.5\cdot e^{-\\alpha\cdot\max(t, u_j)}\cdot(    \\
                    e^{\\alpha\cdot\min(t, u_j)}     \\
                    -e^{-\\alpha\cdot\min(t, u_j)}    \\
                    )   \\
            \\right\}
    where :math:`t = u_i`.
    Args:
        i(int): Time index (1, 2, ..., :attr:`N`)
        j(int): Time index (1, 2, ..., :attr:`N`)
    """
    t = u[i]
    uj = u[j]
    return exp(-UFR * (t+uj)) * (
            alpha * min(t, uj) - 0.5 * exp(-alpha * max(t, uj)) * (
                    exp(alpha*min(t, uj)) - exp(-alpha*min(t, uj))
            )) 
[docs]def m_vector():
    """The :func:`m` vector.
    :func:`m` as 1-dimensional :attr:`N` length numpy array.
    """
    return np.array([m(i) for i in range(1, N+1)]) 
[docs]def mu_vector():
    """The :func:`mu` vector.
    :func:`mu` as 1-dimensional :attr:`N` length numpy array.
    """
    return np.array([mu(i) for i in range(1, N+1)]) 
[docs]def W_matrix():
    """The :func:`W` matrix.
    :func:`W` as a 2-dimensional :attr:`N` x :attr:`N` numpy array.
    """
    return np.array([[W(i, j) for j in range(1, N+1)] for i in range(1, N+1)]) 
[docs]def zeta_vector():
    """The :func:`zeta` vector.
    :func:`zeta_vector` returns :math:`\zeta` parameters calculated
    by formula (5) on page 17 in `the technical paper`_, which is
    .. math::
        \\bf \zeta= W^{-1}(p-\mu)
    """
    return np.linalg.inv(W_matrix()) @ (m_vector() - mu_vector()) 
[docs]def zeta(i):
    """The :math:`\zeta_i` parameters fitted to the observed spot rates.
    Args:
        i(int): Time index (1, 2, ..., :attr:`N`)
    """
    return zeta_vector()[i-1] 
[docs]def P(i):
    """Zero-coupon bond prices extrapolated by the Smith-Wilson method.
    :func:`P` corresponds to formula (1) on page 16 or formula (6)
    on page 18 in `the technical paper`_, defined as:
    .. math::
        P(t) = e^{-UFR\cdot t}+\sum_{j=1}^{N}\zeta_{j}\cdot W(t, u_j)
    substituting :math:`t` with :math:`u_i`.
    The values of :func:`P` for ``i=1, ..., N`` should be the same
    as the values of :func:`m`, the observed bond prices.
    Args:
        i(int): Time index (1, 2, ...)
    """
    return mu(i) + sum(zeta(j) * W(i, j) for j in range(1, N+1)) 
[docs]def R(i):
    """The extrapolated annual compound sport rates.
    :func:`R` corresponds to :math:`R_t` defined as:
    .. math::
        R_t = \left(\\frac{1}{P(t)}\\right)^\left(\\frac{1}{t}\\right)-1
    on page 18 in `the technical paper`_,
    substituting :math:`t` with :math:`u_i`.
    The values of :func:`R` for ``i=1,...,N`` should be same as the values
    of the observed spot rates :attr:`spot_rates` for 0, ... ,N-1.
    Args:
        i(int): Time index (1, 2, ...)
    """
    return (1 / P(i)) ** (1 / u(i)) - 1 
# ---------------------------------------------------------------------------
# References
np = ("Module", "numpy")
log = ("Pickle", 2074070178376)
exp = ("Pickle", 2074070177016)
UFR = 0.028587456851912472
alpha = 0.128562
N = 25
spot_rates = ("Pickle", 2072439860616)