public static double CheckOverall( List <SingleRunResult> results, ref int failures, ref int successes) { failures = 0; successes = 0; foreach (SingleRunResult r in results) { if (r.TrailingAmount <= 1000 || r.InsufficientWdRrate > Globals.Singleton().AllowedInsufficientRate) { failures++; } else { successes++; } } if (successes + failures == 0) { return(0.0); } else { return((double)successes / (double)(successes + failures)); } }
public static string ResultDir(string prefix) { return(String.Format("{0}\\{1}-{2:00}{3:00}{4:00}-{5:00}{6:00}{7:00}", Globals.Singleton().ResultLocation, prefix, DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second)); }
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 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 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 void PerCountryAnalysis( ConcurrentBag <ModelResult> modelResults, string summaryFile, Object printLock) { IEnumerable <ModelResult> sortedResults = modelResults.OrderBy( mr => (mr.productivity)); Dictionary <string, double> bestReliableProd = new Dictionary <string, double>(); Dictionary <string, Model> bestReliableModel = new Dictionary <string, Model>(); foreach (ModelResult mr in sortedResults) { if (mr.overallSuccessRate >= Globals.Singleton().CutoffPercent / 100.0) { if (!bestReliableProd.ContainsKey(mr.model.CountryName) || mr.productivity >= bestReliableProd[mr.model.CountryName]) { bestReliableProd[mr.model.CountryName] = mr.productivity; bestReliableModel[mr.model.CountryName] = mr.model; } } } using (StreamWriter sw = new StreamWriter(summaryFile)) { sw.WriteLine("Country,Strategy,Eq,Bo,WorldShare,WdRate,Best_Reliable_Productivity_Effective"); foreach (string c in bestReliableModel.Keys) { sw.WriteLine("{0},{1},{2},{3},{4:F2},{5:F2},{6:F2},", c.Replace(".JPG", ""), bestReliableModel[c].Strategy, bestReliableModel[c].StartEq, bestReliableModel[c].StartBo, bestReliableModel[c].WorldShare, bestReliableModel[c].YearlyWithdrawal, bestReliableProd[c]); } } }
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 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); }
public static bool IsWorld(string c) { return(c.ToLower().Trim().CompareTo(Globals.Singleton().DoubleWorldName.ToLower().Trim()) == 0); }
static void Main(string[] args) { string globalFileName, modelsFilename, countriesFileName; Portfolio portfolio = Portfolio.Single; SweepMode sweepMode = SweepMode.No; SweepParameters[] sweeps = new SweepParameters[1]; int nFactors = 0; const int maxFactors = 10; Factor[] factors = new Factor[maxFactors]; int cp = 0; for (int f = 0; f < factors.Length; f++) { factors[f] = Factor.None; } // Global params file if (args.Length <= cp) { Console.Write("Usage: <globals.csv> <countries.csv> <models.csv> [single|dual] [sweep N factor-1 ... factor-n]"); return; } globalFileName = args[cp++]; Globals.ReadParams(globalFileName); string resultPrefix = "R_" + Globals.Singleton().Prefix; // Countries file if (args.Length <= cp) { Console.Write("Second parameter must point to the countries file"); return; } countriesFileName = args[cp++]; List <Country> countries = Country.ReadCountries(countriesFileName, false); // Models file if (args.Length <= cp) { Console.Write("Third parameter must point to the models file"); return; } modelsFilename = args[cp++]; List <Model> models = Model.ReadModels(modelsFilename); // Portfolio Composition Mode if (args.Length > cp) { if (args[cp].ToLower().Trim() == "single") { Console.WriteLine("The whole portfolio is managed as one thing"); portfolio = Portfolio.Single; resultPrefix += "_Single"; } else if (args[cp].ToLower().Trim() == "double") { portfolio = Portfolio.Double; Console.WriteLine("The portfolio is composed of 2 separate parts: all countries except last, and last"); resultPrefix += "_Double"; } else { Console.WriteLine("First parameter can be only 'single' or 'double'. It defines portfolio composition"); return; } cp++; } // Sweep mode if (args.Length > cp) { if (args[cp].ToLower().Trim() != "sweep") { Console.WriteLine("This parameter can be only 'sweep'. It would request sweep by few listed parameters."); return; } else { sweepMode = SweepMode.SweepNoCountry; resultPrefix += "_Sweep"; } cp++; } if (sweepMode != SweepMode.No) { // Sweep factors counter if (args.Length > cp) { nFactors = int.Parse(args[cp]); if (nFactors >= maxFactors) { Console.WriteLine("You cannot Sweep by more than {0} factors", maxFactors); return; } Console.WriteLine("Sweep is requested for {0} factors", nFactors); cp++; } else { Console.WriteLine("This parameter can be only sweep factor count"); return; } for (int i = 0; i < nFactors; i++) { //Country| Strategy | Withdrawal | DualShare | Eq | Bo switch (args[cp].ToLower().Trim()) { case "country": sweepMode = SweepMode.SweepAndCountry; resultPrefix += "_Country"; break; case "str": factors[i] = Factor.Strategy; resultPrefix += "_Strategy"; break; case "world": factors[i] = Factor.WorldShare; resultPrefix += "_World"; break; case "wd": factors[i] = Factor.Withdrawal; resultPrefix += "_Withdrawal"; break; case "eq": factors[i] = Factor.Equity; resultPrefix += "_Equity"; break; case "bo": factors[i] = Factor.Bonds; resultPrefix += "_Bonds"; break; default: Console.Write("This parameter can be only Country| Strategy | Withdrawal | WorldShare | Equity | Bonds"); return; } cp++; } } // Prepare sweep parameters if (sweepMode != SweepMode.No) { sweeps = Utils.Factorize(factors, countries); Console.WriteLine("You requested to sweep across {0} combinations", sweeps.Length); } // Create results dir and copy controling files Utils.CreateResultDir(resultPrefix, globalFileName, countriesFileName, modelsFilename); Utils.SaveCommand(Utils.CommandFileName(resultPrefix), args); // Run simulations Execute( countries, models, portfolio, sweepMode, sweeps, Utils.ResultFileName(resultPrefix), Utils.PerCountryFileName(resultPrefix), Utils.CrossCountryFileName(resultPrefix)); }
public static SweepParameters[] Factorize(Factor[] factors, List <Country> countries) { SweepParameters[] sweeps = new SweepParameters[1]; sweeps[0].Strategy = -1; sweeps[0].Equity = -1; sweeps[0].Bonds = -1; sweeps[0].WorldShare = (double)Globals.Singleton().DoubleWorldWeight / (double)(Globals.Singleton().DoubleWorldWeight + Globals.Singleton().DoubleCountryWeight); sweeps[0].WithdrawalRate = -1; sweeps[0].Country = -1; int nCountries = countries.Count; for (int f = 0; f < factors.Length; f++) { switch (factors[f]) { case Factor.Strategy: { SweepParameters[] oldSweeps = sweeps; sweeps = new SweepParameters[oldSweeps.Length * Globals.Singleton().SweepStrategies.Length]; int c = 0; for (int o = 0; o < oldSweeps.Length; o++) { for (int n = 0; n < Globals.Singleton().SweepStrategies.Length; n++) { sweeps[c] = oldSweeps[o]; sweeps[c].Strategy = Globals.Singleton().SweepStrategies[n]; c++; } } } break; case Factor.Withdrawal: { SweepParameters[] oldSweeps = sweeps; sweeps = new SweepParameters[oldSweeps.Length * Globals.Singleton().SweepWithdrawalRates.Length]; int c = 0; for (int o = 0; o < oldSweeps.Length; o++) { for (int n = 0; n < Globals.Singleton().SweepWithdrawalRates.Length; n++) { sweeps[c] = oldSweeps[o]; sweeps[c].WithdrawalRate = Globals.Singleton().SweepWithdrawalRates[n]; c++; } } } break; case Factor.WorldShare: { SweepParameters[] oldSweeps = sweeps; sweeps = new SweepParameters[oldSweeps.Length * Globals.Singleton().SweepWorldShares.Length]; int c = 0; for (int o = 0; o < oldSweeps.Length; o++) { for (int n = 0; n < Globals.Singleton().SweepWorldShares.Length; n++) { sweeps[c] = oldSweeps[o]; sweeps[c].WorldShare = Globals.Singleton().SweepWorldShares[n]; c++; } } } break; case Factor.Equity: { SweepParameters[] oldSweeps = sweeps; sweeps = new SweepParameters[oldSweeps.Length * Globals.Singleton().SweepEquities.Length]; int c = 0; for (int o = 0; o < oldSweeps.Length; o++) { for (int n = 0; n < Globals.Singleton().SweepEquities.Length; n++) { sweeps[c] = oldSweeps[o]; sweeps[c].Equity = Globals.Singleton().SweepEquities[n]; c++; } } } break; case Factor.Bonds: { SweepParameters[] oldSweeps = sweeps; sweeps = new SweepParameters[oldSweeps.Length * Globals.Singleton().SweepBonds.Length]; int c = 0; for (int o = 0; o < oldSweeps.Length; o++) { for (int n = 0; n < Globals.Singleton().SweepBonds.Length; n++) { sweeps[c] = oldSweeps[o]; sweeps[c].Bonds = Globals.Singleton().SweepBonds[n]; c++; } } } break; case Factor.None: break; } } List <SweepParameters> sweeps1 = new List <SweepParameters>(); int count = 0; for (int i = 0; i < sweeps.Length; i++) { if (sweeps[i].Equity + sweeps[i].Bonds <= 100) { sweeps1.Add(sweeps[i]); count++; } } sweeps = new SweepParameters[count]; int cn = 0; foreach (SweepParameters s in sweeps1) { sweeps[cn++] = s; } return(sweeps); }
// 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 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); }