ActuaryUtilities.Utilities.accum_offsetMethod
accum_offset(x; op=*, init=1.0)

A shortcut for the common operation wherein a vector is scanned with an operation, but has an initial value and the resulting array is offset from the traditional accumulate.

This is a common pattern when calculating things like survivorship given a mortality vector and you want the first value of the resulting vector to be 1.0, and the second value to be 1.0 * x[1], etc.

Two keyword arguments:

  • op is the binary (two argument) operator you want to use, such as * or +
  • init is the initial value in the returned array

Examples

julia> accum_offset([0.9, 0.8, 0.7])
3-element Array{Float64,1}:
 1.0
 0.9
 0.7200000000000001

julia> accum_offset(1:5) # the product of elements 1:n, with the default `1` as the first value
5-element Array{Int64,1}:
  1
  1
  2
  6
 24

julia> accum_offset(1:5,op=+)
5-element Array{Int64,1}:
  1
  2
  4
  7
 11
ActuaryUtilities.Utilities.years_betweenFunction
Years_Between(d1::Date, d2::Date)

Compute the number of integer years between two dates, with the first date typically before the second. Will return negative number if first date is after the second. Use third argument to indicate if calendar anniversary should count as a full year.

Examples

julia> d1 = Date(2018,09,30);

julia> d2 = Date(2019,09,30);

julia> d3 = Date(2019,10,01);

julia> years_between(d1,d3) 
1
julia> years_between(d1,d2,false) # same month/day but `false` overlap
0 
julia> years_between(d1,d2) # same month/day but `true` overlap
1 
julia> years_between(d1,d2) # using default `true` overlap
1 
ActuaryUtilities.durationMethod
duration(d1::Date, d2::Date)

Compute the duration given two dates, which is the number of years since the first date. The interval [0,1) is defined as having duration 1. Can return negative durations if second argument is before the first.

julia> issue_date  = Date(2018,9,30);

julia> duration(issue_date , Date(2019,9,30) ) 
2
julia> duration(issue_date , issue_date) 
1
julia> duration(issue_date , Date(2018,10,1) ) 
1
julia> duration(issue_date , Date(2019,10,1) ) 
2
julia> duration(issue_date , Date(2018,6,30) ) 
0
julia> duration(Date(2018,9,30),Date(2017,6,30)) 
-1
ActuaryUtilities.FinancialMath.KeyRateType
KeyRate(timepoints,shift=0.001)

A convenience constructor for KeyRateZero.

Extended Help

KeyRateZero is chosen as the default constructor because it has more attractive properties than KeyRatePar:

  • rates after the key timepoint remain unaffected by the shift
    • e.g. this causes a 6-year zero coupon bond would have a negative duration if the 5-year par rate was used
ActuaryUtilities.FinancialMath.KeyRateParType
KeyRatePar(timepoint,shift=0.001) <: KeyRateDuration

Shift the par curve by the given amount at the given timepoint. Use in conjunction with duration to calculate the key rate duration.

Unlike other duration statistics which are computed using analytic derivatives, KeyRateDurations are computed via a shift-and-compute the yield curve approach.

KeyRatePar is more commonly reported (than KeyRateZero) in the fixed income markets, even though the latter has more analytically attractive properties. See the discussion of KeyRateDuration in the FinanceModels.jl docs.

ActuaryUtilities.FinancialMath.KeyRateZeroType
KeyRateZero(timepoint,shift=0.001) <: KeyRateDuration

Shift the par curve by the given amount at the given timepoint. Use in conjunction with duration to calculate the key rate duration.

Unlike other duration statistics which are computed using analytic derivatives, KeyRateDuration is computed via a shift-and-compute the yield curve approach.

KeyRateZero is less commonly reported (than KeyRatePar) in the fixed income markets, even though the latter has more analytically attractive properties. See the discussion of KeyRateDuration in the FinanceModels.jl docs.

ActuaryUtilities.FinancialMath.breakevenFunction
breakeven(yield, cashflows::Vector)
breakeven(yield, cashflows::Vector,times::Vector)

Calculate the time when the accumulated cashflows breakeven given the yield.

Assumptions:

  • cashflows occur at the end of the period
  • cashflows evenly spaced with the first one occuring at time zero if times not given

Returns nothing if cashflow stream never breaks even.

julia> breakeven(0.10, [-10,1,2,3,4,8])
5

julia> breakeven(0.10, [-10,15,2,3,4,8])
1

julia> breakeven(0.10, [-10,-15,2,3,4,8]) # returns the `nothing` value

ActuaryUtilities.FinancialMath.convexityMethod
convexity(yield,cfs,times)
convexity(yield,valuation_function)

Calculates the convexity. - yield should be a fixed effective yield (e.g. 0.05). - times may be omitted and it will assume cfs are evenly spaced beginning at the end of the first period.

Examples

Using vectors of cashflows and times

julia> times = 1:5
julia> cfs = [0,0,0,0,100]
julia> duration(0.03,cfs,times)
4.854368932038834
julia> duration(Macaulay(),0.03,cfs,times)
5.0
julia> duration(Modified(),0.03,cfs,times)
4.854368932038835
julia> convexity(0.03,cfs,times)
28.277877274012614

Using any given value function:

julia> lump_sum_value(amount,years,i) = amount / (1 + i ) ^ years
julia> my_lump_sum_value(i) = lump_sum_value(100,5,i)
julia> duration(0.03,my_lump_sum_value)
4.854368932038835
julia> convexity(0.03,my_lump_sum_value)
28.277877274012617
ActuaryUtilities.FinancialMath.moicMethod
moic(cashflows<:AbstractArray)

The multiple on invested capital ("moic") is the un-discounted sum of distributions divided by the sum of the contributions. The function assumes that negative numbers in the array represent contributions and positive numbers represent distributions.

Examples

julia> moic([-10,20,30])
5.0
ActuaryUtilities.FinancialMath.present_valuesFunction
present_values(interest, cashflows, timepoints)

Efficiently calculate a vector representing the present value of the given cashflows at each period prior to the given timepoint.

Examples

julia> present_values(0.00, [1,1,1])
[3,2,1]

julia> present_values(ForwardYield([0.1,0.2]), [10,20],[0,1]) # after `using FinanceModels`
2-element Vector{Float64}:
 28.18181818181818
 18.18181818181818
ActuaryUtilities.FinancialMath.priceMethod
price(...)

The absolute value of the present_value(...).

Extended help

Using price can be helpful if the directionality of the value doesn't matter. For example, in the common usage, duration is more interested in the change in price than present value, so price is used there.

ActuaryUtilities.FinancialMath.spreadFunction
spread(curve1,curve2,cashflows)

Return the solved-for constant spread to add to curve1 in order to equate the discounted cashflows with curve2

Examples

spread(0.04, 0.05, cfs)
Rate{Float64, Periodic}(0.010000000000000009, Periodic(1))
ActuaryUtilities.durationMethod
duration(keyrate::KeyRateDuration,curve,cashflows)    
duration(keyrate::KeyRateDuration,curve,cashflows,timepoints)
duration(keyrate::KeyRateDuration,curve,cashflows,timepoints,krd_points)

Calculate the key rate duration by shifting the zero (not par) curve by the kwarg shift at the timepoint specified by a KeyRateDuration(time).

The approach is to carve up the curve into krd_points (default is the unit steps between 1 and the last timepoint of the casfhlows). The zero rate corresponding to the timepoint within the KeyRateDuration is shifted by shift (specified by the KeyRateZero or KeyRatePar constructors. A new curve is created from the shifted rates. This means that the "width" of the shifted section is ± 1 time period, unless specific points are specified via krd_points.

The curve may be any FinanceModels.jl curve (e.g. does not have to be a curve constructed via FinanceModels.Zero(...)).

!!! Experimental: Due to the paucity of examples in the literature, this feature does not have unit tests like the rest of JuliaActuary functionality. Additionally, the API may change in a future major/minor version update.

Examples

julia> riskfree_maturities = [0.5, 1.0, 1.5, 2.0];

julia> riskfree    = [0.05, 0.058, 0.064,0.068];

julia> rf_curve = FinanceModels.Zero(riskfree,riskfree_maturities);

julia> cfs = [10,10,10,10,10];

julia> duration(KeyRate(1),rf_curve,cfs)
8.932800152336995

Extended Help

Key Rate Duration is not a well specified topic in the literature and in practice. The reference below suggest that shocking the par curve is more common in practice, but that the zero curve produces more consistent results. Future versions may support shifting the par curve.

References:

ActuaryUtilities.durationMethod
duration(Macaulay(),interest_rate,cfs,times)
duration(Modified(),interest_rate,cfs,times)
duration(DV01(),interest_rate,cfs,times)
duration(interest_rate,cfs,times)             # Modified Duration
duration(interest_rate,valuation_function)    # Modified Duration

Calculates the Macaulay, Modified, or DV01 duration. times may be ommitted and the valuation will assume evenly spaced cashflows starting at the end of the first period.

Note that the calculated duration will depend on the periodicity convention of the interest_rate: a Periodic yield (or yield model with that convention) will be a slightly different computed duration than a Continous which follows from the present value differing according to the periodicity.

When not given Modified() or Macaulay() as an argument, will default to Modified().

  • Modified duration: the relative change per point of yield change.
  • Macaulay: the cashflow-weighted average time.
  • DV01: the absolute change per basis point (hundredth of a percentage point).

Examples

Using vectors of cashflows and times

julia> times = 1:5;

julia> cfs = [0,0,0,0,100];

julia> duration(0.03,cfs,times)
4.854368932038835

julia> duration(Periodic(0.03,1),cfs,times)
4.854368932038835

julia> duration(Continuous(0.03),cfs,times)
5.0

julia> duration(Macaulay(),0.03,cfs,times)
5.0

julia> duration(Modified(),0.03,cfs,times)
4.854368932038835

julia> convexity(0.03,cfs,times)
28.277877274012614

Using any given value function:

julia> lump_sum_value(amount,years,i) = amount / (1 + i ) ^ years
julia> my_lump_sum_value(i) = lump_sum_value(100,5,i)
julia> duration(0.03,my_lump_sum_value)
4.854368932038835
julia> convexity(0.03,my_lump_sum_value)
28.277877274012617
ActuaryUtilities.RiskMeasures.CTEType
CTE(α)::RiskMeasure
CTE(α)(risk)::T (where T is the type of values sampled in risk)

The Conditional Tail Expectation (CTE) at level α is the expected value of the risk distribution above the αth quantile. risk can be a univariate distribution or an array of outcomes. Assumes more positive values are higher risk measures, so a higher p will return a more positive number.

CTE(α) returns a functor which can then be called on a risk distribution.

Parameters

  • α: [0,1.0)

Examples

julia> CTE(0.95)(rand(1000))
0.9766218612020593

julia> rm = CTE(0.95)
CTE{Float64}(0.95)

julia> rm(rand(1000))
0.9739835010268733
ActuaryUtilities.RiskMeasures.DualPowerType
DualPower(v)::RiskMeasure
DualPower(v)(risk)::T (where T is the type of values sampled in risk)

The Dual Power distortion risk measure is defined as $1 - (1 - x)^v$, where x is the cumulative distribution function (CDF) of the risk distribution and v is a positive parameter. risk can be a univariate distribution or an array of outcomes.

DualPower(v) returns a functor which can then be called on a risk distribution.

ActuaryUtilities.RiskMeasures.ExpectationType
Expectation()::RiskMeasure
Expectation()(risk)::T (where T is the type of values sampled in `risk`)

The expected value of the risk.

Expectation() returns a functor which can then be called on a risk distribution.

Examples

julia> RiskMeasures.Expectation(rand(1000))
0.4793223308812537

julia> rm = RiskMeasures.Expectation()
ActuaryUtilities.RiskMeasures.Expectation()

julia> rm(rand(1000))
0.4941708036889741
ActuaryUtilities.RiskMeasures.ProportionalHazardType
ProportionalHazard(y)::RiskMeasure
ProportionalHazard(y)(risk)::T (where T is the type of values sampled in risk)

The Proportional Hazard distortion risk measure is defined as $x^(1/y)$, where x is the cumulative distribution function (CDF) of the risk distribution and y is a positive parameter. risk can be a univariate distribution or an array of outcomes. ProportionalHazard(y) returns a functor which can then be called on a risk distribution.

Examples

julia> ProportionalHazard(2)(rand(1000))
0.6659603556774121

julia> rm = ProportionalHazard(2)
ProportionalHazard{Int64}(2)

julia> rm(rand(1000))
0.6710587338367799
ActuaryUtilities.RiskMeasures.VaRType
 VaR(α)::RiskMeasure
 VaR(α)(risk)::T (where T is the type of values sampled in `risk`)

The αth quantile of the risk distribution is the Value at Risk, or αth quantile. risk can be a univariate distribution or an array of outcomes. Assumes more positive values are higher risk measures, so a higher p will return a more positive number. For a discrete risk, the VaR returned is the first value above the αth percentile.

VaR(α) returns a functor which can then be called on a risk distribution.

Parameters

  • α: [0,1.0)

Examples

julia> VaR(0.95)(rand(1000))
0.9561843082268024

julia> rm = VaR(0.95)
VaR{Float64}(0.95)

julia> rm(rand(1000))
0.9597070153670079
ActuaryUtilities.RiskMeasures.WangTransformType
WangTransform(α)::RiskMeasure
WangTransform(α)(risk)::T (where T is the type of values sampled in risk)

The Wang Transform is a distortion risk measure that transforms the cumulative distribution function (CDF) of the risk distribution using a normal distribution with mean Φ⁻¹(α) and standard deviation 1. risk can be a univariate distribution or an array of outcomes.

WangTransform(α) returns a functor which can then be called on a risk distribution.

Parameters

  • α: [0,1.0]

In the literature, sometimes λ is used where $\lambda = \Phi^{-1}(\alpha)$.

Examples

julia> WangTransform(0.95)(rand(1000))
0.8799465543360105

julia> rm = WangTransform(0.95)
WangTransform{Float64}(0.95)

julia> rm(rand(1000))
0.8892245759705852

References

  • "A Risk Measure That Goes Beyond Coherence", Shaun S. Wang, 2002
ActuaryUtilities.RiskMeasures.cdf_funcMethod
cdf_function(risk)

Returns the appropriate cumulative distribution function depending on the type, specifically:

cdf_func(S::AbstractArray{<:Real}) = StatsBase.ecdf(S)
cdf_func(S::Distributions.UnivariateDistribution) = x -> Distributions.cdf(S, x)