fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <iomanip>
  6. #include <tuple>
  7. #include <string>
  8. #include <sstream>
  9.  
  10. using namespace std;
  11.  
  12. using Portfolio = vector<int>; // weights in percent, size = 6
  13.  
  14. double percentile15(vector<double>& data) {
  15. sort(data.begin(), data.end());
  16. size_t index = static_cast<size_t>(floor(0.15 * data.size()));
  17. if (index >= data.size()) index = data.size() - 1;
  18. return data[index];
  19. }
  20.  
  21. double lumpSumCAGR(const vector<double>& returns) {
  22. double compound = 1.0;
  23. for (double r : returns) {
  24. compound *= (1.0 + r);
  25. }
  26. return pow(compound, 1.0 / returns.size()) - 1.0;
  27. }
  28.  
  29. double portfolioReturn(const vector<vector<double>>& assets, const Portfolio& weights, int year) {
  30. double result = 0.0;
  31. for (int i = 0; i < weights.size(); ++i) {
  32. result += (weights[i] / 100.0) * assets[i][year];
  33. }
  34. return result;
  35. }
  36.  
  37. void generatePortfolios(vector<Portfolio>& portfolios, Portfolio current, int pos, int totalWeight, int maxAssets) {
  38. if (pos == current.size()) {
  39. if (totalWeight == 100) {
  40. int nonZero = count_if(current.begin(), current.end(), [](int w) { return w > 0; });
  41. if (nonZero <= maxAssets) {
  42. portfolios.push_back(current);
  43. }
  44. }
  45. return;
  46. }
  47. for (int w = 0; w <= 100 - totalWeight; w += 5) {
  48. current[pos] = w;
  49. generatePortfolios(portfolios, current, pos + 1, totalWeight + w, maxAssets);
  50. }
  51. }
  52.  
  53. int main() {
  54. const int numAssets = 6;
  55. const int maxAssets = 3;
  56. const int step = 5;
  57.  
  58. vector<string> assetNames = {"scv60Lcg15", "scv95", "vti", "11all", "33gld", "lcbtilted"};
  59.  
  60. vector<vector<double>> assets = {
  61. // Asset 1
  62. {-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,
  63. -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,
  64. 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},
  65.  
  66. // Asset 2
  67. {-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,
  68. -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,
  69. 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},
  70.  
  71. // Asset 3
  72. {-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,
  73. -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,
  74. 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},
  75.  
  76. // Asset 4
  77. {-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,
  78. -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,
  79. 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},
  80.  
  81. // Asset 5
  82. {-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,
  83. -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,
  84. 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},
  85.  
  86. // Asset 6
  87. {-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,
  88. -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,
  89. 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}
  90. };
  91.  
  92. for (int duration = 1; duration <= 31; duration += 1) {
  93. int numYears = assets[0].size();
  94. vector<Portfolio> portfolios;
  95. generatePortfolios(portfolios, Portfolio(numAssets, 0), 0, 0, maxAssets);
  96.  
  97. vector<tuple<Portfolio, double>> portfolioResults;
  98.  
  99. for (const Portfolio& p : portfolios) {
  100. vector<double> cagrList;
  101. for (int start = 0; start <= numYears - duration; ++start) {
  102. vector<double> subReturns;
  103. for (int i = 0; i < duration; ++i) {
  104. double portRet = portfolioReturn(assets, p, start + i);
  105. subReturns.push_back(portRet);
  106. }
  107. double cagr = lumpSumCAGR(subReturns);
  108. cagrList.push_back(cagr);
  109. }
  110. double bottom15 = percentile15(cagrList);
  111. portfolioResults.emplace_back(p, bottom15);
  112. }
  113.  
  114. sort(portfolioResults.begin(), portfolioResults.end(),
  115. [](const auto& a, const auto& b) {
  116. return get<1>(a) > get<1>(b);
  117. });
  118.  
  119. cout << "\n================ Duration: " << duration << " years ================\n";
  120. cout << left
  121. << setw(6) << "Rank"
  122. << setw(10) << "Duration"
  123. << setw(60) << "Portfolio Weights"
  124. << "Bottom 15% CAGR\n";
  125. cout << string(100, '-') << '\n';
  126.  
  127. for (int i = 0; i < 2 && i < portfolioResults.size(); ++i) {
  128. auto [weights, cagr] = portfolioResults[i];
  129. stringstream weightDesc;
  130. for (int j = 0; j < numAssets; ++j) {
  131. if (weights[j] > 0) {
  132. weightDesc << assetNames[j] << ": " << weights[j] << "% ";
  133. }
  134. }
  135. cout << setw(6) << i + 1
  136. << setw(10) << duration
  137. << setw(60) << weightDesc.str()
  138. << fixed << setprecision(2) << (cagr * 100) << "%\n";
  139. }
  140. }
  141.  
  142. return 0;
  143. }
  144.  
Success #stdin #stdout 3.42s 5280KB
stdin
Standard input is empty
stdout
================ Duration: 1 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     1         11all: 35%  33gld: 65%                                      -2.65%
2     1         vti: 5%  11all: 25%  33gld: 70%                             -2.65%

================ Duration: 2 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     2         scv95: 30%  vti: 10%  33gld: 60%                            1.09%
2     2         scv60Lcg15: 30%  scv95: 25%  33gld: 45%                     1.08%

================ Duration: 3 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     3         scv95: 20%  vti: 35%  33gld: 45%                            2.71%
2     3         scv95: 15%  vti: 35%  33gld: 50%                            2.67%

================ Duration: 4 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     4         scv60Lcg15: 20%  33gld: 80%                                 4.50%
2     4         scv60Lcg15: 15%  11all: 5%  33gld: 80%                      4.47%

================ Duration: 5 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     5         scv60Lcg15: 55%  33gld: 45%                                 4.39%
2     5         scv60Lcg15: 40%  33gld: 50%  lcbtilted: 10%                 4.37%

================ Duration: 6 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     6         scv60Lcg15: 45%  33gld: 50%  lcbtilted: 5%                  5.59%
2     6         scv60Lcg15: 50%  33gld: 50%                                 5.56%

================ Duration: 7 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     7         scv60Lcg15: 15%  scv95: 35%  33gld: 50%                     6.15%
2     7         scv60Lcg15: 25%  scv95: 30%  33gld: 45%                     6.15%

================ Duration: 8 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     8         scv60Lcg15: 50%  vti: 5%  33gld: 45%                        6.34%
2     8         scv60Lcg15: 45%  scv95: 10%  33gld: 45%                     6.34%

================ Duration: 9 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     9         scv60Lcg15: 10%  scv95: 30%  33gld: 60%                     7.01%
2     9         scv95: 35%  33gld: 65%                                      7.00%

================ Duration: 10 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     10        scv60Lcg15: 95%  scv95: 5%                                  6.45%
2     10        scv60Lcg15: 100%                                            6.44%

================ Duration: 11 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     11        scv60Lcg15: 20%  scv95: 65%  33gld: 15%                     6.75%
2     11        scv60Lcg15: 25%  scv95: 60%  33gld: 15%                     6.74%

================ Duration: 12 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     12        scv60Lcg15: 75%  33gld: 25%                                 6.84%
2     12        scv60Lcg15: 70%  scv95: 5%  33gld: 25%                      6.83%

================ Duration: 13 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     13        scv60Lcg15: 80%  vti: 15%  33gld: 5%                        6.59%
2     13        scv60Lcg15: 15%  scv95: 70%  33gld: 15%                     6.58%

================ Duration: 14 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     14        scv60Lcg15: 85%  scv95: 10%  vti: 5%                        7.07%
2     14        scv60Lcg15: 90%  scv95: 5%  vti: 5%                         7.06%

================ Duration: 15 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     15        scv60Lcg15: 90%  scv95: 10%                                 7.21%
2     15        scv60Lcg15: 85%  scv95: 5%  33gld: 10%                      7.20%

================ Duration: 16 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     16        scv60Lcg15: 100%                                            6.98%
2     16        scv60Lcg15: 95%  scv95: 5%                                  6.98%

================ Duration: 17 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     17        scv60Lcg15: 85%  scv95: 5%  33gld: 10%                      7.03%
2     17        scv60Lcg15: 80%  scv95: 5%  33gld: 15%                      7.02%

================ Duration: 18 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     18        scv60Lcg15: 65%  scv95: 35%                                 7.05%
2     18        scv60Lcg15: 60%  scv95: 40%                                 7.05%

================ Duration: 19 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     19        scv60Lcg15: 15%  scv95: 85%                                 6.90%
2     19        scv60Lcg15: 10%  scv95: 90%                                 6.90%

================ Duration: 20 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     20        scv95: 90%  33gld: 10%                                      7.33%
2     20        scv95: 85%  33gld: 15%                                      7.33%

================ Duration: 21 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     21        scv60Lcg15: 20%  scv95: 75%  lcbtilted: 5%                  7.70%
2     21        scv60Lcg15: 20%  scv95: 70%  lcbtilted: 10%                 7.70%

================ Duration: 22 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     22        scv60Lcg15: 100%                                            7.26%
2     22        scv60Lcg15: 95%  scv95: 5%                                  7.25%

================ Duration: 23 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     23        scv95: 90%  lcbtilted: 10%                                  7.28%
2     23        scv95: 95%  lcbtilted: 5%                                   7.27%

================ Duration: 24 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     24        scv60Lcg15: 95%  scv95: 5%                                  7.53%
2     24        scv60Lcg15: 90%  scv95: 5%  vti: 5%                         7.53%

================ Duration: 25 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     25        scv95: 45%  vti: 20%  lcbtilted: 35%                        7.74%
2     25        scv95: 50%  vti: 25%  lcbtilted: 25%                        7.74%

================ Duration: 26 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     26        scv95: 85%  vti: 15%                                        8.01%
2     26        scv95: 80%  vti: 15%  lcbtilted: 5%                         8.00%

================ Duration: 27 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     27        scv95: 100%                                                 8.36%
2     27        scv95: 95%  lcbtilted: 5%                                   8.36%

================ Duration: 28 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     28        scv95: 65%  vti: 30%  lcbtilted: 5%                         8.37%
2     28        scv95: 70%  vti: 30%                                        8.36%

================ Duration: 29 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     29        scv95: 80%  vti: 5%  lcbtilted: 15%                         8.56%
2     29        scv95: 75%  vti: 5%  lcbtilted: 20%                         8.56%

================ Duration: 30 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     30        scv95: 75%  lcbtilted: 25%                                  8.34%
2     30        scv95: 70%  lcbtilted: 30%                                  8.34%

================ Duration: 31 years ================
Rank  Duration  Portfolio Weights                                           Bottom 15% CAGR
----------------------------------------------------------------------------------------------------
1     31        scv95: 70%  vti: 20%  lcbtilted: 10%                        8.37%
2     31        scv95: 70%  vti: 15%  lcbtilted: 15%                        8.37%