fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <iomanip>
  6. #include <tuple>
  7.  
  8. using namespace std;
  9.  
  10. using Portfolio = vector<int>; // weights in percent, size = 6
  11.  
  12. double percentile15(vector<double>& data) {
  13. sort(data.begin(), data.end());
  14. size_t index = static_cast<size_t>(floor(0.15 * data.size()));
  15. if (index >= data.size()) index = data.size() - 1;
  16. return data[index];
  17. }
  18.  
  19. double lumpSumCAGR(const vector<double>& returns) {
  20. double compound = 1.0;
  21. for (double r : returns) {
  22. compound *= (1.0 + r);
  23. }
  24. return pow(compound, 1.0 / returns.size()) - 1.0;
  25. }
  26.  
  27. double portfolioReturn(const vector<vector<double>>& assets, const Portfolio& weights, int year) {
  28. double result = 0.0;
  29. for (int i = 0; i < weights.size(); ++i) {
  30. result += (weights[i] / 100.0) * assets[i][year];
  31. }
  32. return result;
  33. }
  34.  
  35. void generatePortfolios(vector<Portfolio>& portfolios, Portfolio current, int pos, int totalWeight, int maxAssets) {
  36. if (pos == current.size()) {
  37. if (totalWeight == 100) {
  38. int nonZero = count_if(current.begin(), current.end(), [](int w) { return w > 0; });
  39. if (nonZero <= maxAssets) {
  40. portfolios.push_back(current);
  41. }
  42. }
  43. return;
  44. }
  45. for (int w = 0; w <= 100 - totalWeight; w += 5) {
  46. current[pos] = w;
  47. generatePortfolios(portfolios, current, pos + 1, totalWeight + w, maxAssets);
  48. }
  49. }
  50.  
  51. int main() {
  52. const int numAssets = 6;
  53. const int maxAssets = 3; // Limit to 3-asset portfolios
  54. const int step = 5;
  55.  
  56. vector<string> assetNames = {"scv60Lcg15", "scv95", "vti", "11all", "33gld", "newAsset"};
  57.  
  58. vector<vector<double>> assets = {
  59. // Asset 1
  60. {-0.04,0.14,0.15,-0.14,-0.19,0.26,0.28,0.04,0.08,0.28,0.08,-0.06,0.24,0.22,-0.01,0.26,0.14,-0.02,0.14,0.16,
  61. -0.16,0.29,0.15,0.18,-0.03,0.20,0.13,0.20,0.02,0.08,-0.04,0.04,-0.07,0.33,0.12,0.06,0.15,0.01,-0.26,0.31,
  62. 0.22,-0.03,0.15,0.19,0.08,-0.06,0.16,0.13,-0.11,0.21,0.13,0.12,-0.18,0.15,0.12},
  63.  
  64. // Asset 2
  65. {-0.03,0.13,0.06,-0.29,-0.31,0.43,0.46,0.08,0.07,0.21,0.12,0.06,0.31,0.38,0.02,0.31,0.12,-0.08,0.23,0.14,
  66. -0.22,0.37,0.24,0.19,-0.02,0.24,0.17,0.31,-0.06,0.02,0.04,0.11,-0.13,0.41,0.17,0.04,0.15,-0.09,-0.32,0.33,
  67. 0.23,-0.06,0.18,0.32,0.09,-0.06,0.23,0.09,-0.15,0.20,0.03,0.19,-0.16,0.11,0.08},
  68.  
  69. // Asset 3
  70. {-0.02,0.11,0.12,-0.25,-0.36,0.30,0.21,-0.11,-0.01,0.05,0.16,-0.11,0.19,0.19,0.01,0.28,0.15,-0.02,0.12,0.24,
  71. -0.10,0.29,0.06,0.08,-0.01,0.34,0.19,0.30,0.24,0.19,-0.13,-0.09,-0.25,0.30,0.08,0.02,0.12,0.01,-0.37,0.26,
  72. 0.16,-0.02,0.14,0.31,0.12,0.00,0.11,0.19,-0.07,0.28,0.19,0.18,-0.24,0.22,0.20},
  73.  
  74. // Asset 4
  75. {-0.02,0.12,0.14,-0.13,-0.19,0.22,0.26,0.04,0.06,0.19,0.07,-0.07,0.20,0.20,0.03,0.26,0.19,0.00,0.14,0.15,
  76. -0.16,0.24,0.10,0.20,-0.02,0.19,0.12,0.17,0.01,0.05,0.01,0.02,-0.06,0.32,0.14,0.07,0.17,-0.01,-0.25,0.25,
  77. 0.20,0.00,0.14,0.15,0.11,-0.04,0.13,0.12,-0.10,0.20,0.07,0.12,-0.19,0.10,0.08},
  78.  
  79. // Asset 5
  80. {-0.01,0.11,0.19,0.03,-0.05,0.13,0.23,0.07,0.10,0.44,0.08,-0.13,0.20,0.14,-0.04,0.19,0.16,0.02,0.06,0.08,
  81. -0.15,0.17,0.08,0.16,-0.03,0.17,0.11,0.12,0.00,0.02,-0.01,0.02,-0.02,0.30,0.11,0.07,0.19,0.03,-0.21,0.25,
  82. 0.23,0.00,0.13,0.08,0.09,-0.06,0.13,0.10,-0.08,0.20,0.10,0.11,-0.14,0.11,0.14},
  83.  
  84. // Asset 6 (new)
  85. {-0.03,0.13,0.12,-0.22,-0.30,0.25,0.24,-0.02,0.00,0.07,0.08,-0.09,0.14,0.20,0.07,0.26,0.15,-0.02,0.16,0.24,
  86. -0.13,0.33,0.10,0.21,-0.03,0.22,0.16,0.21,0.05,0.15,-0.05,-0.02,-0.12,0.32,0.14,0.08,0.17,0.02,-0.32,0.29,
  87. 0.17,-0.01,0.14,0.17,0.13,-0.03,0.11,0.16,-0.09,0.23,0.11,0.14,-0.24,0.14,0.11}
  88. };
  89.  
  90. int numYears = assets[0].size();
  91.  
  92. for (int duration = 1; duration <= 31; duration += 2) {
  93. cout << "----------\n----------\nDuration:\t" << duration << "\n--------------------\n";
  94.  
  95. vector<Portfolio> portfolios;
  96. generatePortfolios(portfolios, Portfolio(numAssets, 0), 0, 0, maxAssets);
  97.  
  98. vector<tuple<Portfolio, double>> portfolioResults;
  99.  
  100. for (const Portfolio& p : portfolios) {
  101. vector<double> cagrList;
  102.  
  103. for (int start = 0; start <= numYears - duration; ++start) {
  104. vector<double> subReturns;
  105. for (int i = 0; i < duration; ++i) {
  106. double portRet = portfolioReturn(assets, p, start + i);
  107. subReturns.push_back(portRet);
  108. }
  109. double cagr = lumpSumCAGR(subReturns);
  110. cagrList.push_back(cagr);
  111. }
  112.  
  113. double bottom15 = percentile15(cagrList);
  114. portfolioResults.emplace_back(p, bottom15);
  115. }
  116.  
  117. sort(portfolioResults.begin(), portfolioResults.end(),
  118. [](const auto& a, const auto& b) {
  119. return get<1>(a) > get<1>(b);
  120. });
  121.  
  122. cout << fixed << setprecision(2);
  123. for (int i = 0; i < 2 && i < portfolioResults.size(); ++i) {
  124. auto [weights, cagr] = portfolioResults[i];
  125. cout << "Portfolio " << i + 1 << ":\n";
  126. for (int j = 0; j < numAssets; ++j) {
  127. if (weights[j] > 0)
  128. cout << " " << assetNames[j] << ": " << weights[j] << "%\n";
  129. }
  130. cout << " Bottom 15th Percentile CAGR: " << cagr * 100 << "%\n\n";
  131. }
  132. }
  133.  
  134. return 0;
  135. }
  136.  
Success #stdin #stdout 1.29s 5284KB
stdin
Standard input is empty
stdout
----------
----------
Duration:	1
--------------------
Portfolio 1:
  11all: 35%
  33gld: 65%
  Bottom 15th Percentile CAGR: -2.65%

Portfolio 2:
  vti: 5%
  11all: 25%
  33gld: 70%
  Bottom 15th Percentile CAGR: -2.65%

----------
----------
Duration:	3
--------------------
Portfolio 1:
  scv95: 20%
  vti: 35%
  33gld: 45%
  Bottom 15th Percentile CAGR: 2.71%

Portfolio 2:
  scv95: 15%
  vti: 35%
  33gld: 50%
  Bottom 15th Percentile CAGR: 2.67%

----------
----------
Duration:	5
--------------------
Portfolio 1:
  scv60Lcg15: 55%
  33gld: 45%
  Bottom 15th Percentile CAGR: 4.39%

Portfolio 2:
  scv60Lcg15: 40%
  33gld: 50%
  newAsset: 10%
  Bottom 15th Percentile CAGR: 4.37%

----------
----------
Duration:	7
--------------------
Portfolio 1:
  scv60Lcg15: 15%
  scv95: 35%
  33gld: 50%
  Bottom 15th Percentile CAGR: 6.15%

Portfolio 2:
  scv60Lcg15: 25%
  scv95: 30%
  33gld: 45%
  Bottom 15th Percentile CAGR: 6.15%

----------
----------
Duration:	9
--------------------
Portfolio 1:
  scv60Lcg15: 10%
  scv95: 30%
  33gld: 60%
  Bottom 15th Percentile CAGR: 7.01%

Portfolio 2:
  scv95: 35%
  33gld: 65%
  Bottom 15th Percentile CAGR: 7.00%

----------
----------
Duration:	11
--------------------
Portfolio 1:
  scv60Lcg15: 20%
  scv95: 65%
  33gld: 15%
  Bottom 15th Percentile CAGR: 6.75%

Portfolio 2:
  scv60Lcg15: 25%
  scv95: 60%
  33gld: 15%
  Bottom 15th Percentile CAGR: 6.74%

----------
----------
Duration:	13
--------------------
Portfolio 1:
  scv60Lcg15: 80%
  vti: 15%
  33gld: 5%
  Bottom 15th Percentile CAGR: 6.59%

Portfolio 2:
  scv60Lcg15: 15%
  scv95: 70%
  33gld: 15%
  Bottom 15th Percentile CAGR: 6.58%

----------
----------
Duration:	15
--------------------
Portfolio 1:
  scv60Lcg15: 90%
  scv95: 10%
  Bottom 15th Percentile CAGR: 7.21%

Portfolio 2:
  scv60Lcg15: 85%
  scv95: 5%
  33gld: 10%
  Bottom 15th Percentile CAGR: 7.20%

----------
----------
Duration:	17
--------------------
Portfolio 1:
  scv60Lcg15: 85%
  scv95: 5%
  33gld: 10%
  Bottom 15th Percentile CAGR: 7.03%

Portfolio 2:
  scv60Lcg15: 80%
  scv95: 5%
  33gld: 15%
  Bottom 15th Percentile CAGR: 7.02%

----------
----------
Duration:	19
--------------------
Portfolio 1:
  scv60Lcg15: 15%
  scv95: 85%
  Bottom 15th Percentile CAGR: 6.90%

Portfolio 2:
  scv60Lcg15: 10%
  scv95: 90%
  Bottom 15th Percentile CAGR: 6.90%

----------
----------
Duration:	21
--------------------
Portfolio 1:
  scv60Lcg15: 20%
  scv95: 75%
  newAsset: 5%
  Bottom 15th Percentile CAGR: 7.70%

Portfolio 2:
  scv60Lcg15: 20%
  scv95: 70%
  newAsset: 10%
  Bottom 15th Percentile CAGR: 7.70%

----------
----------
Duration:	23
--------------------
Portfolio 1:
  scv95: 90%
  newAsset: 10%
  Bottom 15th Percentile CAGR: 7.28%

Portfolio 2:
  scv95: 95%
  newAsset: 5%
  Bottom 15th Percentile CAGR: 7.27%

----------
----------
Duration:	25
--------------------
Portfolio 1:
  scv95: 45%
  vti: 20%
  newAsset: 35%
  Bottom 15th Percentile CAGR: 7.74%

Portfolio 2:
  scv95: 50%
  vti: 25%
  newAsset: 25%
  Bottom 15th Percentile CAGR: 7.74%

----------
----------
Duration:	27
--------------------
Portfolio 1:
  scv95: 100%
  Bottom 15th Percentile CAGR: 8.36%

Portfolio 2:
  scv95: 95%
  newAsset: 5%
  Bottom 15th Percentile CAGR: 8.36%

----------
----------
Duration:	29
--------------------
Portfolio 1:
  scv95: 80%
  vti: 5%
  newAsset: 15%
  Bottom 15th Percentile CAGR: 8.56%

Portfolio 2:
  scv95: 75%
  vti: 5%
  newAsset: 20%
  Bottom 15th Percentile CAGR: 8.56%

----------
----------
Duration:	31
--------------------
Portfolio 1:
  scv95: 70%
  vti: 20%
  newAsset: 10%
  Bottom 15th Percentile CAGR: 8.37%

Portfolio 2:
  scv95: 70%
  vti: 15%
  newAsset: 15%
  Bottom 15th Percentile CAGR: 8.37%