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

Replicating the AAA equtity generator

This notebook replicates the model and parameters for the real world equity generator described in this AAA 2005 reference paper.

using Distributions
using Random
using LabelledArrays

Stochastic Log Volatility Model

Note that the @. and other broadcasting (. symbol) allows us to operate on multiple funds at once.

function v(v_prior,params,Zₜ) 
    (;σ_v, σ_m,σ_p,σ⃰,ϕ,τ) = params
    
    v_m = log.(σ_m)
    v_p = log.(σ_p)
    v⃰ = log.(σ⃰)

    # vol are the odd values in the random array
    ṽ =  @. min(v_p, (1 - ϕ) * v_prior + ϕ * log(τ) ) + σ_v * Zₜ[[1,3,5,7]]
    
    v = @. max(v_m, min(v⃰,ṽ))

    return v
end
v (generic function with 1 method)
function scenario(params,Z;months=1200)
    (;σ_v,σ_0, ρ,A,B,C) = params

    n_funds = size(params,2)
    
    #initilize/pre-allocate
    Zₜ = rand(Z)
    v_t = log.(σ_0)
    σ_t = zeros(n_funds)
    μ_t = zeros(n_funds)
    
    log_returns = map(1:months) do t
        Zₜ = rand!(Z,Zₜ)
        v_t .= v(v_t,params,Zₜ)

        σ_t .= exp.(v_t)

        @. μ_t =  A + B * σ_t + C * (σ_t)^2

        # return are the even values in the random array
        log_return = @. μ_t / 12 + σ_t / sqrt(12) * Zₜ[[2,4,6,8]]
    end

    # convert vector of vector to matrix
    reduce(hcat,log_returns)
end
scenario (generic function with 1 method)

Scenarios and validation

A single scenario

x = scenario(params,Z;months=1200)
4×1200 Matrix{Float64}:
 -0.0328665  -0.0126225  -0.0205485   …   0.0266938   0.00851183  0.0831278
  0.0134244   0.0179725  -0.0314215       0.0576454   0.0174838   0.0307883
 -0.10297     0.0207088  -0.0391713       0.0231305   0.00612645  0.0968145
 -0.08964     0.0202982   0.00053222     -0.00105492  0.0287865   0.0774308

Validation of summary statistics

The summary statistics expected (per paper Table 8):

These computed values match very closely:

# generate 1000 scenarios 
scens = [scenario(params,Z) for _ in 1:1000];
let
    # compute summary statistics
    μ = vec(mean(mean(x,dims=2) for x in scens))
    σ = vec(mean(std(x,dims=2) for x in scens))
    (;μ,σ)
end
(μ = [0.0060431989496125835, 0.006185811839010164, 0.006289265872131668, 0.006462537162096842], σ = [0.043540417636768906, 0.04908847920116854, 0.059096677232561706, 0.07240146588182594])

Plotting some scenarios

using CairoMakie, ColorSchemes
let 
    f = Figure()
    n = 25
    colors = ColorSchemes.Johnson
    ax = Axis(f[1,1],yscale=log10,ylabel="index value",
        title="$n realizations of 4 correlated equity funds per AAA ESG")
    for s in scens[1:n]
        for i in 1:4
        lines!(ax,cumprod(exp.(s[i,:])), color=(colors[i],0.3),label="fund $i")
        end
    end
    axislegend(ax,unique=true,position=:lt)
    f
end

Appendices

Model Parameters

# use a labelled array for easy reference of the parameters 
params = @LArray [
    0.12515 0.14506 0.16341 0.20201 		# τ
    0.35229 0.41676 0.3632 0.35277 			# ϕ
    0.32645 0.32634 0.35789 0.34302 		# σ_v
    -0.2488 -0.1572 -0.2756 -0.2843 		# ρ
    0.055 0.055 0.055 0.055 				# A
    0.56 0.466 0.67 0.715 					# B
    -0.9 -0.9 -0.95 -1.0 					# C
    0.1476 0.1688 0.2049 0.2496 			# σ_0
    0.0305 0.0354 0.0403 0.0492 			# σ_m
    0.3 0.3 0.4 0.55 						# σ_p
    0.7988 0.4519 0.9463 1.1387 			# σ⃰
] ( 
    # define the regions each label refers to
    τ = (1,:),
    ϕ = (2,:),
    σ_v = (3,:),
    ρ = (4,:),
    A = (5,:),
    B = (6,:),
    C = (7,:),
    σ_0 = (8,:),
    σ_m = (9,:),
    σ_p = (10,:),
    σ⃰ = (11,:)
)
11×4 LabelledArrays.LArray{Float64, 2, Matrix{Float64}, (τ = (1, Colon()), ϕ = (2, Colon()), σ_v = (3, Colon()), ρ = (4, Colon()), A = (5, Colon()), B = (6, Colon()), C = (7, Colon()), σ_0 = (8, Colon()), σ_m = (9, Colon()), σ_p = (10, Colon()), σ⃰ = (11, Colon()))}:
   :τ => 0.12515    :τ => 0.14506  …    :τ => 0.20201
   :ϕ => 0.35229    :ϕ => 0.41676       :ϕ => 0.35277
 :σ_v => 0.32645  :σ_v => 0.32634     :σ_v => 0.34302
   :ρ => -0.2488    :ρ => -0.1572       :ρ => -0.2843
      ⋮                            ⋱  
 :σ_m => 0.0305   :σ_m => 0.0354      :σ_m => 0.0492
 :σ_p => 0.3      :σ_p => 0.3         :σ_p => 0.55
   :σ⃰ => 0.7988     :σ⃰ => 0.4519   …    :σ⃰ => 1.1387

The Multivariate normal and covariance matrix

    Z = MvNormal(
        zeros(11), #means for return and volatility
        cov_matrix # covariance matrix
        # full covariance matrix in AAA Excel workook on Parameters tab
    )
FullNormal(
dim: 11
μ: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Σ: [1.0 -0.249 … 0.075 0.08; -0.249 1.0 … 0.192 0.393; … ; 0.075 0.192 … 1.0 0.697; 0.08 0.393 … 0.697 1.0]
)
# 11 columns because it's got the bond returns in it
cov_matrix = [
    1.000	-0.249	0.318	-0.082	0.625	-0.169	0.309	-0.183	0.023	0.075	0.080;
    -0.249	1.000	-0.046	0.630	-0.123	0.829	-0.136	0.665	-0.120	0.192	0.393;
    0.318	-0.046	1.000	-0.157	0.259	-0.050	0.236	-0.074	-0.066	0.034	0.044;
    -0.082	0.630	-0.157	1.000	-0.063	0.515	-0.098	0.558	-0.105	0.130	0.234;
    0.625	-0.123	0.259	-0.063	1.000	-0.276	0.377	-0.180	0.034	0.028	0.054;
    -0.169	0.829	-0.050	0.515	-0.276	1.000	-0.142	0.649	-0.106	0.067	0.267;
    0.309	-0.136	0.236	-0.098	0.377	-0.142	1.000	-0.284	0.026	0.006	0.045;
    -0.183	0.665	-0.074	0.558	-0.180	0.649	-0.284	1.000	0.034	-0.091	-0.002;
    0.023	-0.120	-0.066	-0.105	0.034	-0.106	0.026	0.034	1.000	0.047	-0.028;
    0.075	0.192	0.034	0.130	0.028	0.067	0.006	-0.091	0.047	1.000	0.697;
    0.080	0.393	0.044	0.234	0.054	0.267	0.045	-0.002	-0.028	0.697	1.000;
]
11×11 Matrix{Float64}:
  1.0    -0.249   0.318  -0.082   0.625  …   0.309  -0.183   0.023   0.075   0.08
 -0.249   1.0    -0.046   0.63   -0.123     -0.136   0.665  -0.12    0.192   0.393
  0.318  -0.046   1.0    -0.157   0.259      0.236  -0.074  -0.066   0.034   0.044
 -0.082   0.63   -0.157   1.0    -0.063     -0.098   0.558  -0.105   0.13    0.234
  0.625  -0.123   0.259  -0.063   1.0        0.377  -0.18    0.034   0.028   0.054
 -0.169   0.829  -0.05    0.515  -0.276  …  -0.142   0.649  -0.106   0.067   0.267
  0.309  -0.136   0.236  -0.098   0.377      1.0    -0.284   0.026   0.006   0.045
 -0.183   0.665  -0.074   0.558  -0.18      -0.284   1.0     0.034  -0.091  -0.002
  0.023  -0.12   -0.066  -0.105   0.034      0.026   0.034   1.0     0.047  -0.028
  0.075   0.192   0.034   0.13    0.028      0.006  -0.091   0.047   1.0     0.697
  0.08    0.393   0.044   0.234   0.054  …   0.045  -0.002  -0.028   0.697   1.0

Built with Julia 1.8.5 and

CairoMakie 0.10.6
ColorSchemes 3.21.0
Distributions 0.25.98
LabelledArrays 1.14.0

Run this Pluto Notebook

To run this page locally, download this file and open it with Pluto.jl.

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.