JuliaActuary
Practical, extensible, and open-source actuarial modeling and analysis.

Packages

These packages are available for use in your project. Scroll down for more information on each one.

MortalityTables.jl

Easily work with standard tables and parametric models with common survival calculations.

LifeContingencies.jl

Insurance, annuity, premium, and reserve maths.

ActuaryUtilities.jl

Robust and fast calculations for internal_rate_of_return, duration, convexity, present_value, breakeven, and more.

ExperienceAnalysis.jl

Meeting your exposure calculation needs.

Yields.jl

Simple and composable yield curves and calculations.

EconomicScenarioGenerators.jl

Easy-to-use scenario generation that's Yields.jl compatible.

For consistency, you can lock any package in its current state and not worry about breaking changes to any code that you write. Julia's package manager lets you exactly recreate a set of code and its dependencies. (More).

Adding and Using Packages

There are two ways to add packages:

More info can be found at the Pkg manager documentation.

To use packages in your code:

using PackageName

MortalityTables.jl

Hassle-free mortality and other rate tables.

Features

Quickstart

Load and see information about a particular table:

julia> vbt2001 = MortalityTables.table("2001 VBT Residual Standard Select and Ultimate - Male Nonsmoker, ANB")

MortalityTable (Insured Lives Mortality):
   Name:
       2001 VBT Residual Standard Select and Ultimate - Male Nonsmoker, ANB
   Fields:
       (:select, :ultimate, :metadata)
   Provider:
       Society of Actuaries
   mort.SOA.org ID:
       1118
   mort.SOA.org link:
       https://mort.soa.org/ViewTable.aspx?&TableIdentity=1118
   Description:
       2001 Valuation Basic Table (VBT) Residual Standard Select and Ultimate Table -  Male Nonsmoker.
       Basis: Age Nearest Birthday. 
       Minimum Select Age: 0. 
       Maximum Select Age: 99. 
       Minimum Ultimate Age: 25. 
       Maximum Ultimate Age: 120

The package revolves around easy-to-access vectors which are indexed by attained age:

julia> vbt2001.select[35]          # vector of rates for issue age 35
 0.00036
 0.00048
 โ‹ฎ
 0.94729
 1.0
 
julia> vbt2001.select[35][35]      # issue age 35, attained age 35
 0.00036
 
julia> vbt2001.select[35][50:end] # issue age 35, attained age 50 through end of table
0.00316
0.00345
 โ‹ฎ
0.94729
1.0

julia> vbt2001.ultimate[95]        # ultimate vectors only need to be called with the attained age
 0.24298

Calculate the force of mortality or survival over a range of time:

julia> survival(vbt2001.ultimate,30,40) # the survival between ages 30 and 40
0.9894404665434904

julia> decrement(vbt2001.ultimate,30,40) # the decrement between ages 30 and 40
0.010559533456509618

Non-whole periods of time are supported when you specify the assumption (Constant(), Uniform(), or Balducci()) for fractional periods:

julia> survival(vbt2001.ultimate,30,40.5,Uniform()) # the survival between ages 30 and 40.5
0.9887676470262408

Parametric Models

Over 20 different models included. Example with the Gompertz model

m = MortalityTables.Gompertz(a=0.01,b=0.2)

m[20]                 # the mortality rate at age 20
decrement(m,20,25)    # the five year cumulative mortality rate
survival(m,20,25) # the five year survival rate


MortalityTables package on Github ๐Ÿกญ

ActuaryUtilities.jl

A collection of common functions/manipulations used in Actuarial Calculations.

A collection of common functions/manipulations used in Actuarial Calculations.

Quickstart

cfs = [5, 5, 105]
times    = [1, 2, 3]

discount_rate = 0.03

present_value(discount_rate, cfs, times)           # 105.65
duration(Macaulay(), discount_rate, cfs, times)    #   2.86
duration(discount_rate, cfs, times)                #   2.78
convexity(discount_rate, cfs, times)               #  10.62

Features

Financial Maths

Options Pricing

Risk Measures

Insurance mechanics


ActuaryUtilities package on GitHub ๐Ÿกญ

LifeContingencies.jl

Common life contingent calculations with a convenient interface.

Features

Package Overview

the mortality calculations

Examples

Basic Functions

Calculate various items for a 30-year-old male nonsmoker using 2015 VBT base table and a 5% interest rate

using LifeContingencies
using MortalityTables
using Yields
import LifeContingencies: V, aฬˆ     # pull the shortform notation into scope

# load mortality rates from MortalityTables.jl
vbt2001 = MortalityTables.table("2001 VBT Residual Standard Select and Ultimate - Male Nonsmoker, ANB")

issue_age = 30
life = SingleLife(                 # The life underlying the risk
    mort = vbt2001.select[issue_age],    # -- Mortality rates
)

yield = Yields.Constant(0.05)      # Using a flat 5% interest rate

lc = LifeContingency(life, yield)  # LifeContingency joins the risk with interest


ins = Insurance(lc)                # Whole Life insurance
ins = Insurance(life, yield)       # alternate way to construct

With the above life contingent data, we can calculate vectors of relevant information:

cashflows(ins)                     # A vector of the unit cashflows
timepoints(ins)                    # The timepoints associated with the cashflows
survival(ins)                      # The survival vector
benefit(ins)                       # The unit benefit vector
probability(ins)                   # The probability of benefit payment

Some of the above will return lazy results. For example, cashflows(ins) will return a Generator which can be efficiently used in most places you'd use a vector of cashflows (e.g. pv(...) or sum(...)) but has the advantage of being non-allocating (less memory used, faster computations). To get a computed vector instead of the generator, simply call collect(...) on the result: collect(cashflows(ins)).

Or calculate summary scalars:

present_value(ins)                 # The actuarial present value
premium_net(lc)                    # Net whole life premium 
V(lc,5)                            # Net premium reserve for whole life insurance at time 5

Other types of life contingent benefits:

Insurance(lc,10)                 # 10 year term insurance
AnnuityImmediate(lc)               # Whole life annuity due
AnnuityDue(lc)                     # Whole life annuity due
aฬˆ(lc)                              # Shortform notation
aฬˆ(lc, 5)                           # 5 year annuity due
aฬˆ(lc, 5, certain=5,frequency=4)    # 5 year annuity due, with 5 year certain payable 4x per year
...                                # and more!

Constructing Lives

SingleLife(vbt2001.select[50])                 # no keywords, just a mortality vector
SingleLife(vbt2001.select[50],issue_age = 60)  # select at 50, but now 60
SingleLife(vbt2001.select,issue_age = 50)      # use issue_age to pick the right select vector
SingleLife(mortality=vbt2001.select,issue_age = 50) # mort can also be a keyword


LifeContingencies package on GitHub ๐Ÿกญ

Yields.jl

Flexible and composable yield curves and interest functions.

Yields.jl provides a simple interface for constructing, manipulating, and using yield curves for modeling purposes.

It's intended to provide common functionality around modeling interest rates, spreads, and miscellaneous yields across the JuliaActuary ecosystem (though not limited to use in JuliaActuary packages).

Quickstart

using Yields

riskfree_maturities = [0.5, 1.0, 1.5, 2.0]
riskfree    = [5.0, 5.8, 6.4, 6.8] ./ 100     #spot rates, annual effective if unspecified

spread_maturities = [0.5, 1.0, 1.5, 3.0]      # different maturities
spread    = [1.0, 1.8, 1.4, 1.8] ./ 100       # spot spreads

rf_curve = Yields.Zero(riskfree,riskfree_maturities)
spread_curve = Yields.Zero(spread,spread_maturities)


yield = rf_curve + spread_curve               # additive combination of the two curves

discount(yield,1.5)                           # 1 / (1 + 0.064 + 0.014) ^ 1.5

Usage

Rates

Rates are types that wrap scalar values to provide information about how to determine discount and accumulation factors.

There are two CompoundingFrequency types:

Examples
Continuous(0.05)       # 5% continuously compounded
Periodic(0.05,2)       # 5% compounded twice per period

These are both subtypes of the parent Rate type and are instantiated as:

Rate(0.05,Continuous())       # 5% continuously compounded
Rate(0.05,Periodic(2))        # 5% compounded twice per period

Broadcast over a vector to create Rates with the given compounding:

Periodic.([0.02,0.03,0.04],2) 
Continuous.([0.02,0.03,0.04])

Rates can also be constructed by specifying the CompoundingFrequency and then passing a scalar rate:

Periodic(1)(0.05)
Continuous()(0.05)
Conversion

Convert rates between different types with convert. E.g.:

r = Rate(Yields.Periodic(12),0.01)             # rate that compounds 12 times per rate period (ie monthly)

convert(Yields.Periodic(1),r)                  # convert monthly rate to annual effective
convert(Yields.Continuous(),r)          # convert monthly rate to continuous
Arithmetic

Adding, subtracting, and comparing rates is supported.

Curves

There are a several ways to construct a yield curve object. If maturities is omitted, the method will assume that the timepoints corresponding to each rate are the indices of the rates (e.g. generally one to the length of the array for standard, non-offset arrays).

Fitting Curves to Rates

There is a set of constructor methods which will return a yield curve calibrated to the given inputs.

Fitting techniques

There are multiple curve fitting methods available:

To specify which fitting method to use, pass the object to as the first parameter to the above set of constructors, for example: Yields.Par(NelsonSiegel(),rates,maturities).

Kernel Methods
Other Curves

Functions

Most of the above yields have the following defined (goal is to have them all):

Combinations

Different yield objects can be combined with addition or subtraction. See the Quickstart for an example.

When adding a Yields.AbstractYield with a scalar or vector, that scalar or vector will be promoted to a yield type via Yield(). For example:

y1 = Yields.Constant(0.05)
y2 = y1 + 0.01                # y2 is a yield of 0.06

Forward Starting Curves

Constructed curves can be shifted so that a future timepoint becomes the effective time-zero for a said curve.

julia> zero = [5.0, 5.8, 6.4, 6.8] ./ 100
julia> maturity = [0.5, 1.0, 1.5, 2.0]
julia> curve = Yields.Zero(zero, maturity)
julia> fwd = Yields.ForwardStarting(curve, 1.0)

julia> discount(curve,1,2)
0.9275624570410582

julia> discount(fwd,1) # `curve` has effectively been reindexed to `1.0`
0.9275624570410582


Yields package on GitHub ๐Ÿกญ

ExperienceAnalysis.jl

Meeting your exposure calculation needs.

Quickstart

using ExperienceAnalysis
using Dates

issue = Date(2016, 7, 4)
termination = Date(2020, 1, 17)
basis = ExperienceAnalysis.Anniversary(Year(1))
exposure(basis, issue, termination)

This will return an array of tuples with a from and to date:

4-element Array{NamedTuple{(:from, :to),Tuple{Date,Date}},1}:
 (from = Date("2016-07-04"), to = Date("2017-07-04"))
 (from = Date("2017-07-04"), to = Date("2018-07-04"))
 (from = Date("2018-07-04"), to = Date("2019-07-04"))
 (from = Date("2019-07-04"), to = Date("2020-01-17"))

Available Exposure Basis

Where period is a Period Type from the Dates standard library.

Calculate exposures with exposures(basis,from,to,continue_exposure).


ExperienceAnalysis package on GitHub ๐Ÿกญ

EconomicScenarioGenerators.jl

Easy-to-use scenario generation that's Yields.jl compatible.

Models

Interest Rate Models

EquityModels

Interest Rate Model Examples

Vasicek

m = Vasicek(0.136,0.0168,0.0119,Continuous(0.01)) # a, b, ฯƒ, initial Rate
s = ScenarioGenerator(
        1,  # timestep
        30, # projection horizon
        m,  # model
    )

This can be iterated over, or you can collect all of the rates like:

rates = collect(s)

or

for r in s
    # do something with r
end

And the package integrates with Yields.jl:

YieldCurve(s)

will produce a yield curve object:

โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €Yield Curve (Yields.BootstrapCurve)โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €           
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           
         0.03 โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ คโ คโ ”โ ’โ ‰โ ‰โ ’โ ’โ ’โ ’โ ’โ คโฃ„โฃ€โ”‚ Zero rates
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ คโ ’โ ’โ ‰โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ ”โ Šโ โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ ”โ ‹โ โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โข€โฃ€โฃ€โ €โ €โฃ€โกคโ –โ Šโ ‰โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ คโ –โ ‹โ โ €โ €โ ‰โ ‰โ โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โ ”โ ‹โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
   Continuous โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃ€โกคโ ’โ “โ ฆโ คโ –โ ‰โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โขฐโ ‹โ โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โฃ€โ –โ ขโก€โกฐโ ƒโ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ ‰โ ‰โ โ €โ €โ ‰โ โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
            0 โ”‚โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ”‚           
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           
              โ €0โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €timeโ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €30โ €


EconomicScenarioGenerators package on GitHub ๐Ÿกญ

Community

Learn

Resources to help get started.

Programming and Julia

Actuarial Usage and Examples

Documentation

Each package includes examples on the Github site and in the documentation.

Walkthroughs and tutorials

Benchmarks

Benchmarks of Actuarial workflows can be found on the Benchmarks page.

Miscellaneous

Help mode

You can also access help text when using the packages in the REPL by activating help mode, e.g.:

julia> ? survival
    survival(mortality_vector,to_age)
    survival(mortality_vector,from_age,to_age)


  Returns the survival through attained age to_age. The start of the 
  calculation is either the start of the vector, or attained age `from_age` 
  and `to_age` need to be Integers. 

  Add a DeathDistribution as the last argument to handle floating point 
  and non-whole ages:

    survival(mortality_vector,to_age,::DeathDistribution)
    survival(mortality_vector,from_age,to_age,::DeathDistribution)


  If given a negative to_age, it will return 1.0. Aside from simplifying the code, 
  this makes sense as for something to exist in order to decrement in the first place, 
  it must have existed and survived to the point of being able to be decremented.

  Examples
  โ‰กโ‰กโ‰กโ‰กโ‰กโ‰กโ‰กโ‰กโ‰กโ‰ก

  julia> qs = UltimateMortality([0.1,0.3,0.6,1]);

  julia> survival(qs,0)
  1.0
  julia> survival(qs,1)
  0.9

  julia> survival(qs,1,1)
  1.0
  julia> survival(qs,1,2)
  0.7

  julia> survival(qs,0.5,Uniform())
  0.95

Other Repositories of Interest for Actuaries

The packages in JuliaActuary are open-source and liberally licensed (MIT License) to allow wide private and commercial usage of the packages, like the base Julia language and many other packages in the ecosystem. See terms of this site.