private void SetWD(Model m, double[] withdrawals) { double essentialWD = Globals.Singleton().EssentialsPercent / 100.0 * Globals.Singleton().StartSum * Market.NormativeStepWD(m); int nSmallishWD = 0; foreach (var w in withdrawals) { if (w < essentialWD) nSmallishWD++; } this.InsufficientWdRrate = (double)nSmallishWD * 100.0 / (double)withdrawals.Length; double[] binCounts = new double[Globals.Singleton().WDBins]; for (int i = 0; i < binCounts.Length; i++) binCounts[i] = 0.0; this.WithdrawalAver = withdrawals.Average(); this.WithdrawalMax = withdrawals.Max(); this.WithdrawalMin = withdrawals.Min(); double count = 0; double norm = Globals.Singleton().StartSum * Market.NormativeStepWD(m); foreach (double wd in withdrawals) { int ind = Globals.Singleton().Quantile(wd / norm); binCounts[ind] = binCounts[ind] + 1.0; count = count + 1.0; } this.WDistrib = new double[Globals.Singleton().WDBins]; for (int i = 0; i < Globals.Singleton().WDBins; i++) WDistrib[i] = binCounts[i] / count; }
public SingleRunResult(string country, Model m, double trailingAmount, double[] withdrawals) { this.Country = country; this.TrailingAmount = trailingAmount; SetWD(m, withdrawals); }
public SingleRunResult(string country, Model m, double trailingAmount, double[] withdrawals1, double[] withdrawals2) { this.Country = country; this.TrailingAmount = trailingAmount; int len = withdrawals1.Length; if (len != withdrawals2.Length) throw new Exception("Wrong lens"); double[] withdrawals = new double[len]; for (int i = 0; i < len; i++) withdrawals[i] = withdrawals1[i] + withdrawals2[i]; SetWD(m, withdrawals); }
public static Model SweepModel(Model mp, SweepParameters sw, Country c) { Model m = new Model(mp.Strategy, mp.StartEq, mp.StartBo, mp.YearlyWithdrawal, mp.RebalanceEvery, c.Filename); if (sw.Strategy >= 0) m.Strategy = sw.Strategy; if (sw.Equity >= 0) m.StartEq = sw.Equity; if (sw.Bonds >= 0) m.StartBo = sw.Bonds; if (sw.WithdrawalRate >= 0) m.YearlyWithdrawal = sw.WithdrawalRate; if (sw.WorldShare >= 0) m.WorldShare = sw.WorldShare; return m; }
public static void WriteResult(StreamWriter sw, Model mm, ModelResult mr, object printlock) { lock (printlock) { Utils.WriteResult(sw, mm.CountryName, mm.Strategy, mm.StartEq, mm.StartBo, mm.YearlyWithdrawal, mm.RebalanceEvery, mm.WorldShare, mr.trailAverage, mr.trailMax, mr.trailMin, mr.withdrawalAverage, mr.withdrawalMax, mr.withdrawalMin, mr.WDistrib, mr.productivity, mr.trailSuccessRate, mr.withdrawalSuccessRate, mr.overallSuccessRate); } }
public ModelResult(Model m, List<SingleRunResult> results) { this.model = m; this.WDistrib = new double[Globals.Singleton().WDBins]; for (int i = 0; i < Globals.Singleton().WDBins; i++) { this.WDistrib[i] = 0; foreach (var r in results) this.WDistrib[i] = this.WDistrib[i] + r.WDistrib[i]; this.WDistrib[i] /= results.Count; } int failures = 0, successes = 0; trailSuccessRate = Market.CheckTrailingAmount(results, ref failures, ref successes); withdrawalSuccessRate = Market.CheckWithdrawals(results, ref failures, ref successes); trailAverage = withdrawalAverage = 0; trailMin = withdrawalMin = double.MaxValue; trailMax = withdrawalMax = double.MinValue; overallSuccessRate = Market.CheckOverall(results, ref failures, ref successes); int count = 0; foreach (var sr in results) { trailAverage += sr.TrailingAmount; trailMax = Math.Max(trailMax, sr.TrailingAmount); trailMin = Math.Min(trailMin, sr.TrailingAmount); withdrawalAverage += sr.WithdrawalAver; withdrawalMax = Math.Max(withdrawalMax, sr.WithdrawalMax); withdrawalMin = Math.Min(withdrawalMin, sr.WithdrawalMin); count++; } this.trailAverage /= (count * 1000000.0); this.trailMax = trailMax / 1000000.0; this.trailMin = trailMin / 1000000.0; this.withdrawalAverage /= count; this.withdrawalAverage *= (Utils.StepsInYear / 1000.0); this.withdrawalMax *= (Utils.StepsInYear / 1000.0); this.withdrawalMin *= (Utils.StepsInYear / 1000.0); this.productivity = this.withdrawalAverage * 1000.0 / Globals.Singleton().StartSum * 100.0; }
public static void RunSingleStep( int c, int r, Model m, double initialWithdrawal, ref double eq, ref double bo, ref double bi, Distro distroEq, Distro distroBo, Distro distroBi, ref double[] prior, ref double curWithdrawal, ref List<double> withdrawals) { // Market play eq *= (1.0 + distroEq.Play()); bo *= (1.0 + distroBo.Play()); bi *= (1.0 + distroBi.Play()); // Calculate desired withdrawal on this step switch(m.Strategy) { case 1: curWithdrawal = initialWithdrawal; break; case 2: curWithdrawal = (eq + bo + bi) * NormativeStepWD(m); break; case 3: if (c >= (int)(3 * Utils.StepsInYear) && c % ((int)Utils.StepsInYear) == 0) curWithdrawal = prior.Average() * NormativeStepWD(m); break; default: throw new Exception("Unknown strategy"); } // Calculate actual total step withdrawal double actualWithdrawal = Math.Min(eq + bo + bi, curWithdrawal); double allocated = 0; if (bi > 0) { double d = Math.Min(bi, actualWithdrawal * (bi / (eq + bo + bi))); allocated += d; bi -= d; } if (bo > 0) { double d = Math.Min(bo, actualWithdrawal * (bo / (eq + bo + bi))); allocated += d; bo -= d; } if (eq > 0) { double d = Math.Min(eq, actualWithdrawal * (eq / (eq + bo + bi))); allocated += d; eq -= d; } if (allocated < actualWithdrawal) { double d = Math.Min(bi, actualWithdrawal - allocated); bi -= d; allocated += d; d = Math.Min(bo, actualWithdrawal - allocated); bo -= d; allocated += d; d = Math.Min(eq, actualWithdrawal - allocated); eq -= d; allocated += d; } withdrawals.Add(actualWithdrawal); double total = eq + bo + bi; // Rebalance evert X steps, if requested if (m.RebalanceEvery > 0 && r % m.RebalanceEvery == 0) { eq = total * m.StartEq / 100.0; bo = total * m.StartBo / 100.0; bi = total - eq - bo; } // Remember priors for (int y = 1; y < prior.Length; y++) { prior[y - 1] = prior[y]; } prior[prior.Length - 1] = total; }
public static List<SingleRunResult> RunDoublePortfolioExperiment( Model m, double share2, Distro distroEq1, Distro distroBo1, Distro distroBi1, Distro distroEq2, Distro distroBo2, Distro distroBi2) { int rebalanceEvery = m.RebalanceEvery; double initWD = Globals.Singleton().StartSum * NormativeStepWD(m); double initWD1 = initWD * (1.0 - share2); double initWD2 = initWD * (share2); double curWD1 = initWD1; double curWD2 = initWD2; double[] prior1 = new double[3 * (int)Utils.StepsInYear]; double[] prior2 = new double[3 * (int)Utils.StepsInYear]; List<SingleRunResult> results = new List<SingleRunResult>(); for (int r = 0; r < Globals.Singleton().Repeats; r++) { double eq1 = (1.0 - share2) * Globals.Singleton().StartSum * m.StartEq / 100; double bo1 = (1.0 - share2) * Globals.Singleton().StartSum * m.StartBo / 100; double bi1 = (1.0 - share2) * Globals.Singleton().StartSum * (100 - m.StartEq - m.StartBo) / 100; if (eq1 < 0 || bo1 < 0 || bi1 < 0) throw new Exception("Bad parameters"); double eq2 = share2 * Globals.Singleton().StartSum * m.StartEq / 100; double bo2 = share2 * Globals.Singleton().StartSum * m.StartBo / 100; double bi2 = share2 * Globals.Singleton().StartSum * (100 - m.StartEq - m.StartBo) / 100; if (eq2 < 0 || bo2 < 0 || bi2 < 0) throw new Exception("Bad parameters"); //List<double> withdrawals = new List<double>(); List<double> withdrawals1 = new List<double>(); List<double> withdrawals2 = new List<double>(); double curWd1 = initWD1; double curWd2 = initWD2; for (int c = 0; c < Globals.Singleton().Cycles; c++) { RunSingleStep(c, r, m, initWD1, ref eq1, ref bo1, ref bi1, distroEq1, distroBo1, distroBi1, ref prior1, ref curWD1, ref withdrawals1); RunSingleStep(c, r, m, initWD2, ref eq2, ref bo2, ref bi2, distroEq2, distroBo2, distroBi2, ref prior2, ref curWD2, ref withdrawals2); //TODO: here comes portfolio parts re balancing } results.Add( new SingleRunResult( m.CountryName, m, eq1 + bo1 + bi1 + eq2 + bo2 + bi2, withdrawals1.ToArray(), withdrawals2.ToArray())); } return results; }
public static double NormativeStepWD(Model m) { return m.YearlyWithdrawal / 100.0 / Utils.StepsInYear; }
public static List<SingleRunResult> RunSinglePortfolioExperiment( Model m, Distro distroEq, Distro distroBo, Distro distroBi) { int rebalanceEvery = m.RebalanceEvery; double initWD = Globals.Singleton().StartSum * NormativeStepWD(m); double[] prior = new double[3 * (int)Utils.StepsInYear]; List<SingleRunResult> singleRunResults = new List<SingleRunResult>(); for (int r = 0; r < Globals.Singleton().Repeats; r++) { double eq = Globals.Singleton().StartSum * m.StartEq / 100; double bo = Globals.Singleton().StartSum * m.StartBo / 100; double bi = Globals.Singleton().StartSum * (100 - m.StartEq - m.StartBo) / 100; if (eq < 0 || bo < 0 || bi < 0) throw new Exception("Bad parameters"); List<double> withdrawals = new List<double>(); double curWd = initWD; for (int c = 0; c < Globals.Singleton().Cycles; c++) { // Market play RunSingleStep(c, r, m, initWD, ref eq, ref bo, ref bi, distroEq, distroBo, distroBi, ref prior, ref curWd, ref withdrawals); } singleRunResults.Add(new SingleRunResult("", m, eq + bo + bi, withdrawals.ToArray())); } return singleRunResults; }