// Receives the goal string from the Investing class after sending parameters private string GetGoal() { bool pegToInflation = chkInflationRetirementSpendingPeg.Checked; bool incomeGrowthExcessOfInflation = chkInflationIncomeGrowthPeg.Checked; double bondAllocation = double.Parse(txtBondFraction.Text) / 100; double stockAllocation = double.Parse(txtStockFraction.Text) / 100; double bReturns = double.Parse(txtBondReturns.Text) / 100; double sReturns = double.Parse(txtStockReturns.Text) / 100; double withdrawlRate = double.Parse(txtWithdrawlRate.Text) / 100; double taxRate = double.Parse(txtTaxRate.Text) / 100; double inflation = double.Parse(txtInflation.Text) / 100; double incomeGrowthRate = double.Parse(txtIncomeGrowth.Text) / 100 + (incomeGrowthExcessOfInflation ? inflation : 0); double savingsGrowthRateFraction = double.Parse(txtSavingFractionGrowth.Text) / 100; double savingsGrowthRate = savingsGrowthRateFraction * incomeGrowthRate; double averageReturn = Investing.PortfolioWeightedAverageReturn(bondAllocation, stockAllocation, bReturns, sReturns); decimal initialSavings = decimal.Parse(txtIncome.Text, NumberStyles.Currency) - decimal.Parse(txtSpending.Text, NumberStyles.Currency); decimal spending = decimal.Parse(txtRetirementSpending.Text, NumberStyles.Currency); decimal currentInvestments = decimal.Parse(txtPrincipal.Text, NumberStyles.Currency); return(Investing.CalculateGoal(withdrawlRate, taxRate, currentInvestments, spending, initialSavings, averageReturn, savingsGrowthRate, pegToInflation, inflation)); }
private void GenerateReturns() { // Set parameters bool incomeGrowthExcessOfInflation = chkInflationIncomeGrowthPeg.Checked; int projectionType = cboProjection.SelectedIndex; int paymentFrequency = Investing.recurringInvestingFrequency; double bondAllocation = double.Parse(txtBondFraction.Text) / 100; double stockAllocation = double.Parse(txtStockFraction.Text) / 100; double inflationMean = double.Parse(txtInflation.Text) / 100; double incomeGrowthRate = double.Parse(txtIncomeGrowth.Text) / 100 + (incomeGrowthExcessOfInflation ? inflationMean : 0); double savingsGrowthRateFraction = double.Parse(txtSavingFractionGrowth.Text) / 100; double bReturns = double.Parse(txtBondReturns.Text) / 100; double sReturns = double.Parse(txtStockReturns.Text) / 100; double savingsGrowthRate = savingsGrowthRateFraction * incomeGrowthRate; double time = 0; decimal currentInvestments = decimal.Parse(txtPrincipal.Text, NumberStyles.Currency); decimal initialSavings = decimal.Parse(txtIncome.Text, NumberStyles.Currency) - decimal.Parse(txtSpending.Text, NumberStyles.Currency); decimal goal = decimal.Parse(txtSavingsGoal.Text, NumberStyles.Currency); carcInvestment.Series.Clear(); // 0 = fixed returns, 1 = monte-carlo; TODO: 2 = historical cycles if (projectionType == 0) { // Fixed Returns double averageReturn = Investing.PortfolioWeightedAverageReturn(bondAllocation, stockAllocation, bReturns, sReturns); double timeToRetire = Investing.GetTimeToGoal(goal, currentInvestments, initialSavings, averageReturn, savingsGrowthRate); decimal[] total = new decimal[(int)timeToRetire + 5]; decimal[] returns = new decimal[(int)timeToRetire + 5]; decimal[] principal = new decimal[(int)timeToRetire + 5]; // Generate return arrays for (int i = 0; i < (int)timeToRetire + 5; i++) { principal[i] += currentInvestments; total[i] += FinanceCalculations.FutureValue(currentInvestments, i, averageReturn, 365); if (savingsGrowthRate > 0) { total[i] += FinanceCalculations.FutureVariableAnnuityValue(initialSavings, i, averageReturn, savingsGrowthRate, 365, 0, paymentFrequency); principal[i] += FinanceCalculations.FutureVariableAnnuityValue(initialSavings, i, 0, savingsGrowthRate, 365, 0, paymentFrequency); } else { total[i] += FinanceCalculations.FutureFixedAnnuityValue(initialSavings, i, averageReturn, 365, 0, paymentFrequency); principal[i] += initialSavings * i; } returns[i] = total[i] - principal[i]; } GenerateChart(total, "Total"); GenerateChart(returns, "Return"); GenerateChart(principal, "Principal", goal, timeToRetire); time = timeToRetire; } else if (projectionType == 1) { // Monte-Carlo int simulations = 50000; //double inflationVolatility = 0.0119; double stockVolatility = 0.5; double bondVolatility = 0.03; double[] percentileList = { 0.9, 0.75, 0.5, 0.25, 0.1 }; double[] lengths = new double[simulations]; double[] percentileLengths = new double[percentileList.Length]; double[] averageRatesOfGrowth = new double[percentileList.Length]; decimal[][] percentileReturns = new decimal[percentileList.Length][]; //Run the simulations to find lengths for (int i = 0; i < simulations; i++) { decimal x = currentInvestments; Random r = new Random(DateTime.Now.Ticks.GetHashCode()); lengths[i] = 0; while (x < goal) { // Randomly generated return of the portfolio double pReturn = Investing.CalculateRandomPortfolioReturn(bReturns, bondVolatility, bondAllocation, sReturns, stockVolatility, stockAllocation, r); // Caluculate portfolio value at the end of the year x *= 1 + (decimal)pReturn; // Add savings to portfolio if (savingsGrowthRate > 0) { x += FinanceCalculations.FutureValue(initialSavings, lengths[i], savingsGrowthRate, 1); } else { x += initialSavings * i; } lengths[i]++; } } for (int i = 0; i < percentileList.Length; i++) { // Get length percentiles percentileLengths[i] = FinanceCalculations.Percentile(lengths, percentileList[i]); // Find equivelant growth rate averageRatesOfGrowth[i] = Investing.GetRateOfGrowth(goal, currentInvestments, initialSavings, savingsGrowthRate, percentileLengths[i]); // Initialize the array with the 90th percentile in length + 2 percentileReturns[i] = new decimal[(int)percentileLengths[0] + 2]; //Calculate return array for (int j = 0; j < (int)percentileLengths[0] + 2; j++) { percentileReturns[i][j] += FinanceCalculations.FutureValue(currentInvestments, j, averageRatesOfGrowth[i], 365); if (savingsGrowthRate > 0) { percentileReturns[i][j] += FinanceCalculations.FutureVariableAnnuityValue(initialSavings, j, averageRatesOfGrowth[i], savingsGrowthRate, 365, 0, paymentFrequency); } else { percentileReturns[i][j] += FinanceCalculations.FutureFixedAnnuityValue(initialSavings, j, averageRatesOfGrowth[i], 365, 0, paymentFrequency); } } } for (int i = 0; i < percentileLengths.Length; i++) { int k = percentileList.Length - i - 1; GenerateChart(percentileReturns[k], (100 * percentileList[i]).ToString("0") + "th Percentile Returns", goal, percentileLengths[2]); } time = percentileLengths[2]; } PrintResults(time); }