Skip to content

Instantly share code, notes, and snippets.

@bobular
Created March 14, 2018 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bobular/d39472996ec5ec7ad7f6b85fbd983d72 to your computer and use it in GitHub Desktop.
Save bobular/d39472996ec5ec7ad7f6b85fbd983d72 to your computer and use it in GitHub Desktop.
Pension costing model, now including annual payrise parameter
#!/usr/bin/env perl
# -*- mode: cperl -*-
#
# The purpose of this little model is to figure out what kind of
# investment returns the pension fund needs to make in order to meet
# its defined benefits promises.
#
# It assumes a single employee with their own "pot" and a fixed payout
# period. I'm not suggesting euthanasia... Obviously in reality the
# longevity risk is shared by the many thousands of scheme
# members. I'm trying to keep this simple...
#
# Salary progresses through early career to a fixed level until
# retirement. A very simple career-averaged earnings approach is used
# to calculate the pension payout.
#
# This is 100% defined benefit. There is no 55k cap (as found in the
# USS scheme). No in-service death benefits are included.
#
# In v3 - an annual payrise parameter is added, and the lump sum and payout parameters
# are changed to be expressed as annual accrual fractions
#
# ./pension-funding-model-v3.pl 0.23 0.02 35000 20 60000 20 0.02 3/75 1/75 0.02 25
#
# 0.23 = C, fraction of salary contribution total (employer+employee)
# 0.02 = I, expected annual asset investment return (e.g. 4%)
# 35000 = S, starting salary
# 20 = X, number of years working with linear annual salary increments
# 60000 = T, salary after X years of increments
# 20 = Y, number of years working at fixed salary T until retirement
# 0.02 = R, annual above-inflation payrise
# 3/75 = L, lump sum accrual rate
# 1/75 = A, annual pension accrual rate
# 0.02 = J, expected annual asset return in drawdown period*
# 25 = Z, number of years retirement
#
# (* in a large and long-running scheme with good cashflow there is no
# need to de-risk and be more prudent here, but I give the option anyway)
#
# example output shows that CPI+2% investment returns and
# 21% contributions will fund current benefits
# 1/75 accrual rate, 3/75 accrual of lump sum
#
# ./pension-funding-model-v3.pl 0.21 0.02 35000 20 60000 20 0 3/75 1/75 0.02 25
#
# Starting salary was 35000 and after 20y it was 60000
# Career averaged salary over 40 years is 53437
# Pot is 655327 after 40y contributions at 21% of salary and 2% annual growth of pot
# Lump sum payout of 1.6 x career avg salary = 85500 upon retirement
# After 25y retirement paying out 53% of career-averaged salary, the pot (with 2% annual return) is 3741
#
#
use strict;
use warnings;
my ($contrib, $growth, $start_salary, $years_1, $end_salary, $years_2,
$payrise, $lump_sum_accrual, $accrual, $growth_2, $years_retired) = @ARGV;
$lump_sum_accrual = eval $lump_sum_accrual;
$accrual = eval $accrual;
my $pot = 0;
my $salary = $start_salary;
my $annual_increment = ($end_salary-$start_salary)/$years_1;
my $sum_salary = 0; # for calculating career-averaged salary
my $total_years = $years_1+$years_2;
for (1 .. $years_1) {
$pot *= 1+$growth;
$pot += $salary*$contrib;
$sum_salary += $salary;
$salary += $annual_increment;
$salary *= 1+$payrise;
}
for (1 .. $years_2) {
# same as above but without the annual increment
$pot *= 1+$growth;
$pot += $salary*$contrib;
$sum_salary += $salary;
$salary *= 1+$payrise;
}
printf "Starting salary was %d and after %dy it was %d\n",
$start_salary, $years_1, $salary;
my $career_averaged_salary = $sum_salary/$total_years;
printf "Career averaged salary over %d years is %d\n",
$total_years, $career_averaged_salary;
printf "Pot is %d after %dy contributions at %d%% of salary and %d%% annual growth of pot\n",
$pot, $total_years, $contrib*100, $growth*100;
my $lump_sum = $career_averaged_salary*$total_years*$lump_sum_accrual;
$pot -= $lump_sum;
printf "Lump sum payout of %.1f x career avg salary = %d upon retirement\n",
$total_years*$lump_sum_accrual, $lump_sum;
for (1 .. $years_retired) {
$pot -= $career_averaged_salary*$total_years*$accrual;
$pot *= 1+$growth_2;
}
printf "After %dy retirement paying out %d%% of career-averaged salary, the pot (with %d%% annual return) is %d\n",
$years_retired, 100*$total_years*$accrual, $growth_2*100, $pot;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment