fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <iomanip>
  6.  
  7. double percentile(const std::vector<double>& data, double p) {
  8. if (data.empty()) return NAN;
  9. double idx = p * (data.size() - 1);
  10. size_t i = static_cast<size_t>(idx);
  11. double frac = idx - i;
  12. return data[i] * (1.0 - frac) + data[std::min(i + 1, data.size() - 1)] * frac;
  13. }
  14.  
  15. void rolling_cagr_stats_dca_correct(const std::vector<double>& returns, int duration) {
  16. size_t n = returns.size();
  17. if (n < duration) {
  18. std::cout << "Not enough data for the specified duration.\n";
  19. return;
  20. }
  21.  
  22. std::vector<double> cagr_list;
  23.  
  24. for (size_t start = 0; start <= n - duration; ++start) {
  25. double total_value = 0.0;
  26.  
  27. for (int j = 0; j < duration; ++j) {
  28. double compounded = 1.0;
  29. for (int t = j; t < duration; ++t) {
  30. compounded *= (1.0 + returns[start + t]);
  31. }
  32. total_value += compounded;
  33. }
  34.  
  35. double cagr = std::pow(total_value / duration, 1.0 / duration) - 1.0;
  36. cagr_list.push_back(cagr);
  37. }
  38.  
  39. std::sort(cagr_list.begin(), cagr_list.end());
  40.  
  41. auto percentile = [](const std::vector<double>& data, double p) {
  42. double idx = p * (data.size() - 1);
  43. size_t i = static_cast<size_t>(idx);
  44. double frac = idx - i;
  45. return data[i] * (1 - frac) + data[std::min(i + 1, data.size() - 1)] * frac;
  46. };
  47.  
  48. double min_cagr = cagr_list.front();
  49. double max_cagr = cagr_list.back();
  50. double median_cagr = percentile(cagr_list, 0.50);
  51. double bottom_15 = percentile(cagr_list, 0.15);
  52. double top_15 = percentile(cagr_list, 0.85);
  53.  
  54. std::cout << "=== DCA Mode (Corrected Logic) ===\n";
  55. std::cout << "Duration: " << duration << " years\n";
  56. std::cout << "Number of periods: " << cagr_list.size() << "\n";
  57. std::cout << "Min CAGR: " << std::fixed << std::setprecision(2) << min_cagr * 100 << "%\n";
  58. std::cout << "Bottom 15th percentile CAGR: " << bottom_15 * 100 << "%\n";
  59. std::cout << "Median CAGR: " << median_cagr * 100 << "%\n";
  60. std::cout << "Top 85th percentile CAGR: " << top_15 * 100 << "%\n";
  61. std::cout << "Max CAGR: " << max_cagr * 100 << "%\n";
  62. }
  63.  
  64.  
  65. int main() {
  66. std::vector<double> returns = {
  67. -0.04, 0.14, 0.15, -0.14, -0.19, 0.26, 0.28, 0.04, 0.08, 0.28,
  68. 0.08, -0.06, 0.24, 0.22, -0.01, 0.26, 0.14, -0.02, 0.14, 0.16,
  69. -0.16, 0.29, 0.15, 0.18, -0.03, 0.20, 0.13, 0.20, 0.02, 0.08,
  70. -0.04, 0.04, -0.07, 0.33, 0.12, 0.06, 0.15, 0.01, -0.26, 0.31,
  71. 0.22, -0.03, 0.15, 0.19, 0.08, -0.06, 0.16, 0.13, -0.11, 0.21,
  72. 0.13, 0.12, -0.18, 0.15, 0.12
  73. };
  74.  
  75. int duration = 18;
  76. rolling_cagr_stats_dca_correct(returns, duration);
  77.  
  78. return 0;
  79. }
  80.  
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
=== DCA Mode (Corrected Logic) ===
Duration: 18 years
Number of periods: 38
Min CAGR: 2.80%
Bottom 15th percentile CAGR: 3.86%
Median CAGR: 5.01%
Top 85th percentile CAGR: 6.44%
Max CAGR: 6.92%