Created
March 14, 2018 23:15
-
-
Save bobular/d39472996ec5ec7ad7f6b85fbd983d72 to your computer and use it in GitHub Desktop.
Pension costing model, now including annual payrise parameter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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