Random Portfolio Returns

Overview


Typically, retirement portfolios are a mix of equities and fixed income. When modeling the portfolio then, both equities and fixed income need to be modeled. Additionally, the analyst needs to determine a relative percentage of each asset class.

This example sets up a script for simulating a portfolio given an initial wealth and a yearly withdrawal amount.

Rates


Interest rates are simulated as a simple Ito Process.

 let rates=ito.generate(50, dt, ()=>sigma, initRate);
					

Equities


The equities portion of the portfolio is simulating using a Brownian Bridge

let ito = await import('/lib/statistics/simulations/v1.0.0/ito.mjs');

for(let i=0;i<100;i++){ 
  let bridge = ito.brownianBridge(50, ()=>0.15, final, init);
  
}
					

Portfolio


The portfolio is assumed to be a mix of equities and fixed income (60% vs 405%), which is rebalance yearly. For the purposes of the simulation, that means each period, we calculate a blended rate of return between equity and fixed income. This blended rate is applied to the total portfolio wealth.


let blendedRate = 0.6*(bridge[1] - bridge[0]) + 0.4 * rates[j];
					

Number of Years


The final step is to caculate how many years the portfolio lasts before it is depleted. That is, we take note of what year the portfolio goes to zero. We set the variable index to -1. Then, we reset it to the index of the year in which the portfolio goes to zero.


if(wealth1 <= 0){
      index = j;
      break;
    }
					
This result is then saved to the data array, which at the end contains the year in which the portfolio is depleted in each scenario. The distribution of the depletion years can then be examined. A -1 represents the scenario where the portfolio was not depleted over the simulated years.

Simulating a Retirement Portfolio



let ito = await import('/lib/statistics/simulations/v1.0.0/ito.mjs');
let wealth = 500000;
let init = 1;
let final = Math.log(Math.exp(0.1*50)); 
let withdrawal = 40000;
let data = [];
let log = Math.log(wealth);

let a = 0.2;
let b = 0.05;
let sigma = 0.005;
let initRate = 0.05;

let dt = function(points){
  return a*(b - points[points.length-1])
}

for(let i=0;i<100;i++){ 
  let bridge = ito.brownianBridge(50, ()=>0.15, final, init);
  let rates=ito.generate(50, dt, ()=>sigma, initRate);
  let index = -1;
  let sum = 0;
  let wealth1 = wealth;
  for(let j=1;j<bridge.length;j++){
    let blendedRate = 0.6*(bridge[1] - bridge[0]) + 0.4 * rates[j];
    wealth1 = wealth1 * (1+blendedRate) - withdrawal;
    if(wealth1 <= 0){
      index = j;
      break;
    }
  }
  data.push(index);
}
					
Try it!