The Salty Economist

Things I Should Have Learned in High School
posts - 56, comments - 0, trackbacks - 0

F# Retirement Calculator

Well, against my better judgment, I decided to write a retirement calculator.  The idea here is to calculate my monthly living allowance when I retire.  How depressing.  So here goes...

The problem is to take certain assumptions:

Current Age:    let age = 45.0
Retirement Age: let retirementAge = 65.0
Current Wealth: let currentWealth = 200000.0
Rate of Return: let rr = 0.05
Age at Death:   let death = 85.0
Annual Savings: let savings = 20000.0
Inflation:      let pi = 0.02
Real RoR:       let ir = rr - pi

And calculate the amount we can consume each month of retirement, leaving exactly zero behind.  We have no heirs, except possibly the University of California.  We need to work in 'real' terms so that we ignore the effect of inflation and calculate the future monthly amount in today's dollars.  The real rate of return (Real RoR) is the nominal rate of return less the inflation rate (pi).  For you home gamers, economists use pi as an abbreviation for inflation (who knows why?).

This problem is really solved in two parts:

(1)  Figure out our accumulated wealth at the time of retirement (in real dollars), and then

(2)  Take this amount an figure out the monthly level payment (in real dollars) for over the retirement period.


let wAnnual x0 rr save =
    (x0 * (rr + 1.0)) + save

let nr = 1+(int)death-(int)retirementAge
let n = (int)retirementAge-(int)age

let rec wAccum x0 rr savings n =
    match n with
    | 0 -> let k = wAnnual x0 rr savings
           printfn "k: %10.7f" k
    | _ -> let k = wAnnual x0 rr savings
           printfn "k: %10.7f" k
           wAccum k rr savings (n-1)

let wRetire = wAccum currentWealth rr savings (n-1)


The function wAnnual is just a function that grows a current period's wealth by the rate of return (provided as an argument) and current period savings.  For example, if I start with $200,000, it grows by the real rate of return of 3% plus a year's savings, giving us $226,000 at the end of year 1. 

nr is the number of years in retirement; n is the number of years left until retirement.

The function wAccum just takes our initial assumptions and recursively calls the wAnnual  function, with each year's ending amount providing the starting point for the next period.

The results are:

Age 46:   230,000.00
Age 47:   261,500.00
Age 48:   294,575.00
Age 49:   329,303.75
Age 50:   365,768.94
Age 51:   404,057.38
Age 52:   444,260.25
Age 53:   486,473.27
Age 54:   530,796.93
Age 55:   577,336.78
Age 56:   626,203.61
Age 57:   677,513.80
Age 58:   731,389.49
Age 59:   787,958.96
Age 60:   847,356.91
Age 61:   909,724.75
Age 62:   975,210.99
Age 63: 1,043,971.54
Age 64: 1,116,170.12
Age 65: 1,191,978.62

There you have it.  We'll be a millionaire before we retire.

OK, now its time to consume all this dough.

The question is:  How much can I take out of savings each month (in real dollars) and leave nothing left over when I die?

The wrinkle here is that my monthly allowance must grow by the rate of inflation in order to stay constant in real terms.

For example, if I take out $1,000 in month 1; in month 2 I need to take out $1,000 * (1 + (pi/12)); in month 3, I need to take out $1,000 * (1 + (pi/12))^2;   in month 4, I need to take out $1,000 * (1 + (pi/12))^3, and so on.

Of course, I need to take into account that my savings will still grow at the nominal rate of return.

So how much can I take out?

This problem is exactly the reverse of the mortgage amortization problem except the parties are reversed.  (See my earlier post  "F# Mortgage Amortization".)  Instead of you paying the bank a level monthly payment, think of the reverse where the bank pays you a level payment until your money is used up.  You just tell the bank when you're going to die and they'll make sure there is exactly nothing left.  Your reverse mortgage has been paid off!

There are two approaches to solving this problem:  the Hard Way and the Simple Way, but you get to approximately the same place.

The hard way:


let ones = List.init (nr*12) (fun one -> 1.0)

let rec RRList aList (pi : float) (n : float) =
    match aList with
    | [] -> []
    | h::t -> h * (1.0+(pi/12.0))**n :: RRList t pi (n+1.0)

let onesRR = RRList ones pi 0.0

let pv1 = presentValue onesRR (rr/12.0)
let levelPayment1 = wRetire / pv1

printfn "Monthly Payment: %10.3f" levelPayment1


We create a list of ones which has a length equal to the total months we have in retirement.  We then use the function RRList to modify the list so that each period's value in incremented by the monthly rate of inflation (pi/12).  Once we have this list we compute it's present value pv1.

How do we interpret pv1?  It is the amount of savings we would have to have to generate a $1.00 of income per month, that grows by the rate of inflation over time.  In the example above, the amount is $187.35.  So if $187.35 generates a level stream of $1.00, how much will $1,191,978.62 (our retirement wealth) yield?  Just divide: $1,191,978.62 by $187.35 and we get: $6,362.30 -- that's our monthly allowance.  And we leave nothing left over.

The easy way:


let ones = List.init (nr*12) (fun one -> 1.0)

let pv0 = presentValue ones (ir/12.0)
let levelPayment0 = wRetire / pv0

printfn "Monthly Payment: %10.3f" levelPayment0


Again, we create a list of ones which has a length equal to the total months we have in retirement.  But, then we recognize that if we grow the stream at the rate of inflation (pi) and discount it by the nominal interest rate rr which just equals the real rate ir plus pi, we can achieve the same goal by not growing the stream and by discounting the the real rate instead of the nominal rate.  In effect, we are canceling out the effect of inflation in both the numerator and in the denominator.  The simple approach is definitely easier.

 Thus, we expect our value of pv0 to be about the same as pv1.  It is: $187.26 versus $187.35.

Using the same approach as above to calculate our monthly allowance, the amount comes out to be $6,365.27.

There you go.







Print | posted on Thursday, July 16, 2009 4:13 PM |

Powered by:
Powered By Subtext Powered By ASP.NET