Function totalReturn(ByVal contrib As Double, yr As Long, rHist As Range, rPctStk As Range, Optional adjRtn As Boolean = False) As Double
' contrib is inflation-adjusted amount invested at beginning of each year
' yr is year number of first year (1928, 1929, etc) of 30yr period, or up to end of vHist
' vHist(i,1) is year number (1928, 1929, etc)
' vHist(i,2) is inflation rate (costs of i-th yr over prev yr)
' vHist(i,3) is rate of return for stocks
' vHist(i,4) is rate of return for bonds
' vPctStk(i,1) is percent of stock in portfolio; 1-vPctStk(i,1) is percent of bonds
' portRtn is portfolio rate of return: weighted average of rates of return for stocks
' and bonds, weighted by percent allocation (vPctStk)
' totalReturn is cumulative year-end balance after portfolio rate of return
Dim vHist As Variant, vPctStk As Variant
Dim yr1 As Long, yrN As Long, i As Long, j As Long, nHist As Long
Dim portRtn As Double
Dim wf As Object
Set wf = WorksheetFunction
' copy ranges into arrays for more efficient access
vHist = rHist
vPctStk = rPctStk
nHist = UBound(vHist, 1)
' look up yr in 1st column of vHist
' yr1 is index of vHist row corresponding to yr (1928, 1929, etc)
' yrN is index of last vHist row corresponding to 30yr period
' (or less, if there are less than 29 yrs after yr1
yr1 = wf.Match(yr, wf.Index(vHist, 0, 1), 0)
yrN = yr1 + 29
If yrN > nHist Then yrN = UBound(vHist, 1)
' for 1st yr, total return is:
' initial contrib, ignoring 1st yr inflation rate
' then apply portfolio rate of return (weighted average)
portRtn = vHist(yr1, 3) * vPctStk(1, 1) + vHist(yr1, 4) * (1 - vPctStk(1, 1))
If adjRtn Then portRtn = (1 + portRtn) / (1 + vHist(yr1, 2)) - 1
totalReturn = contrib * (1 + portRtn)
j = 1
For i = yr1 + 1 To yrN
' for each subsequent yr, accumulate total return by:
' add contrib, using prev yr contrib times curr yr inflation rate
' then apply curr yr portfolio rate of return (weighted average)
j = j + 1
contrib = contrib * (1 + vHist(i, 2))
portRtn = vHist(i, 3) * vPctStk(j, 1) + vHist(i, 4) * (1 - vPctStk(j, 1))
If adjRtn Then portRtn = (1 + portRtn) / (1 + vHist(i, 2)) - 1
totalReturn = (totalReturn + contrib) * (1 + portRtn)
Next
End Function
I assume that you might want to calculate both the actual and the inflation-adjusted total returns. So I added an optional parameter (adjRtn). It defaults to FALSE, the actual total return.
Bookmarks