public static void Prepare( List <int> equityChanges, List <int> bondChanges, List <int> billChanges, Distro distroEquities, Distro distroBonds, Distro distroBills, Object printlock) { int[] cases = { 1, 2, 3 }; var res1 = Parallel.ForEach( cases, (t) => { List <int> testValues = new List <int>(); Distro distroTest = new Distro(Globals.Singleton().Bins); switch (t) { case 1: Distro.PrepareDistribution( equityChanges, distroEquities, Globals.Singleton().Bins, "DistroEquities.csv", printlock); break; case 2: Distro.PrepareDistribution( bondChanges, distroBonds, Globals.Singleton().Bins, "DistroBonds.csv", printlock); break; case 3: Distro.PrepareDistribution( billChanges, distroBills, Globals.Singleton().Bins, "DistroBills.csv", printlock); break; } }); }
// Sweep run for a single portfolio public static void ExecuteSweepSingle( List <Country> countries, List <Model> models, SweepParameters[] sweeps, ConcurrentBag <ModelResult> modelResults, StreamWriter swr, Object printlock) { Country c = new Country("", 0, 0, 0.0, 0.0, 0.0, 0.0, 0); List <int> equityChanges = new List <int>(); List <int> bondChanges = new List <int>(); List <int> billChanges = new List <int>(); GraphAcquierer.Acquire(countries, equityChanges, bondChanges, billChanges, printlock); Distro distroEquities = new Distro(Globals.Singleton().Bins); Distro distroBonds = new Distro(Globals.Singleton().Bins); Distro distroBills = new Distro(Globals.Singleton().Bins); Distro.Prepare( equityChanges, bondChanges, billChanges, distroEquities, distroBonds, distroBills, printlock); Distro.Test( distroEquities, distroBonds, distroBills, printlock); lock (printlock) { Console.WriteLine(Utils.ResultHeader); } var res2 = Parallel.ForEach( models, (m) => { var res1 = Parallel.ForEach( sweeps, (sw) => { Model mm = Model.SweepModel(m, sw, c); if (mm.Validate()) { List <SingleRunResult> result = Market.RunSinglePortfolioExperiment( mm, distroEquities, distroBonds, distroBills); ModelResult mr = new ModelResult(mm, result); modelResults.Add(mr); Utils.WriteResult(null, mm, mr, printlock); Utils.WriteResult(swr, mm, mr, printlock); } }); }); }
public static void PrepareDistribution( List <int> changes, Distro distro, int bins, string resultPath, Object printLock) { int minChange = changes.Min(); int maxChange = changes.Max(); int span = maxChange - minChange; if (span == 0) { lock (printLock) { Console.WriteLine("CANNOT CREATE {0} - no changes: {1} , { 2}", resultPath, minChange, maxChange); } return; } int[] counts = new int[bins]; for (int i = 0; i < bins; i++) { counts[i] = 0; } int binSize = span / bins + 1; foreach (int c in changes) { int binNo = (c - minChange) / binSize; counts[binNo]++; } using (StreamWriter sw = new StreamWriter(resultPath)) { for (int j = 0; j < bins; j++) { double mid = minChange + binSize / 2 + binSize * j; double binProb = (double)counts[j] / (double)changes.Count; sw.WriteLine("{0:F2},{1:F2},", mid, binProb * 100.0); distro.AddBin(mid, binProb); } } lock (printLock) { Console.WriteLine("Accumulated: {0}", distro.GetAccumulation()); } }
public static void Test( Distro distroEquities, Distro distroBonds, Distro distroBills, Object printlock) { int[] tests = { 1, 2, 3 }; var res1 = Parallel.ForEach( tests, (t) => { List <int> testValues = new List <int>(); Distro distroTest = new Distro(Globals.Singleton().Bins); switch (t) { case 1: for (int i = 0; i < 10000000; i++) { testValues.Add((int)(distroEquities.Play() * Utils.PercentageScale)); } Distro.PrepareDistribution( testValues, distroTest, Globals.Singleton().Bins, "testEq.csv", printlock); break; case 2: for (int i = 0; i < 10000000; i++) { testValues.Add((int)(distroBonds.Play() * Utils.PercentageScale)); } Distro.PrepareDistribution( testValues, distroTest, Globals.Singleton().Bins, "testBo.csv", printlock); break; case 3: for (int i = 0; i < 10000000; i++) { testValues.Add((int)(distroBills.Play() * Utils.PercentageScale)); } Distro.PrepareDistribution( testValues, distroTest, Globals.Singleton().Bins, "testBi.csv", printlock); break; } }); }
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); }
// One run for a 2-part portfolio public static void ExecuteDouble( List <Country> countries, List <Model> models, ConcurrentBag <ModelResult> modelResults, StreamWriter swr, Object printlock) { // Separate countries into 2 groups: 2=WORLD, 1=all others double weight1 = 0.0, weight2 = 0.0; List <Country> countries1 = new List <Country>(); List <Country> countries2 = new List <Country>(); foreach (Country c in countries) { if (Globals.IsWorld(c.Filename)) { countries2.Add(c); weight2 += c.Weight; } else { countries1.Add(c); weight1 += c.Weight; } } if (weight1 <= 0 || weight2 <= 0) { throw new Exception("Cannot find the world or others"); } // Group2 is just the World List <int> equityChanges2 = new List <int>(); List <int> bondChanges2 = new List <int>(); List <int> billChanges2 = new List <int>(); GraphAcquierer.Acquire(countries2, equityChanges2, bondChanges2, billChanges2, printlock); Distro distroEquities2 = new Distro(Globals.Singleton().Bins); Distro distroBonds2 = new Distro(Globals.Singleton().Bins); Distro distroBills2 = new Distro(Globals.Singleton().Bins); Distro.Prepare( equityChanges2, bondChanges2, billChanges2, distroEquities2, distroBonds2, distroBills2, printlock); // Group1 is all except World List <int> equityChanges1 = new List <int>(); List <int> bondChanges1 = new List <int>(); List <int> billChanges1 = new List <int>(); GraphAcquierer.Acquire(countries1, equityChanges1, bondChanges1, billChanges1, printlock); Distro distroEquities1 = new Distro(Globals.Singleton().Bins); Distro distroBonds1 = new Distro(Globals.Singleton().Bins); Distro distroBills1 = new Distro(Globals.Singleton().Bins); Distro.Prepare( equityChanges1, bondChanges1, billChanges1, distroEquities1, distroBonds1, distroBills1, printlock); lock (printlock) { Console.WriteLine(Utils.ResultHeader); } var res = Parallel.ForEach( models, (m) => { if (m.Validate()) { List <SingleRunResult> result = Market.RunDoublePortfolioExperiment( m, weight2 / (weight1 + weight2), distroEquities1, distroBonds1, distroBills1, distroEquities2, distroBonds2, distroBills2); ModelResult mr = new ModelResult(m, result); modelResults.Add(mr); Utils.WriteResult(null, m, mr, printlock); Utils.WriteResult(swr, m, mr, printlock); } }); }
// Sweep run for a double-part portfolio by country public static void ExecuteSweepDoubleByCountry( List <Country> countries, List <Model> models, SweepParameters[] sweeps, ConcurrentBag <ModelResult> modelResults, StreamWriter swr, Object printlock) { // Group2 is just the World List <Country> countries2 = new List <Country>(); foreach (Country c in countries) { if (Globals.IsWorld(c.Filename)) { countries2.Add(c); countries2.Last().Weight = 1; } } List <int> equityChanges2 = new List <int>(); List <int> bondChanges2 = new List <int>(); List <int> billChanges2 = new List <int>(); GraphAcquierer.Acquire(countries2, equityChanges2, bondChanges2, billChanges2, printlock); Distro distroEquities2 = new Distro(Globals.Singleton().Bins); Distro distroBonds2 = new Distro(Globals.Singleton().Bins); Distro distroBills2 = new Distro(Globals.Singleton().Bins); Distro.Prepare( equityChanges2, bondChanges2, billChanges2, distroEquities2, distroBonds2, distroBills2, printlock); // Now enumerate countries; Group1 each time will carry just one foreach (var c in countries) { if (Globals.IsWorld(c.Filename)) { continue; } List <Country> countries1 = new List <Country>(); countries1.Add(c); countries1.Last().Weight = 1; // Group1 is just one country List <int> equityChanges1 = new List <int>(); List <int> bondChanges1 = new List <int>(); List <int> billChanges1 = new List <int>(); GraphAcquierer.Acquire(countries1, equityChanges1, bondChanges1, billChanges1, printlock); Distro distroEquities1 = new Distro(Globals.Singleton().Bins); Distro distroBonds1 = new Distro(Globals.Singleton().Bins); Distro distroBills1 = new Distro(Globals.Singleton().Bins); Distro.Prepare( equityChanges1, bondChanges1, billChanges1, distroEquities1, distroBonds1, distroBills1, printlock); lock (printlock) { Console.WriteLine(Utils.ResultHeader); } var res2 = Parallel.ForEach( models, (m) => { var res1 = Parallel.ForEach( sweeps, (sw) => { Model mm = Model.SweepModel(m, sw, c); if (mm.Validate()) { if (mm.StartEq + mm.StartBo <= 100) { List <SingleRunResult> result = Market.RunDoublePortfolioExperiment( mm, sw.WorldShare, distroEquities1, distroBonds1, distroBills1, distroEquities2, distroBonds2, distroBills2); ModelResult mr = new ModelResult(mm, result); modelResults.Add(mr); Utils.WriteResult(null, mm, mr, printlock); Utils.WriteResult(swr, mm, mr, printlock); } } }); }); c.Weight = 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); }