#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
double percentile( const std:: vector < double > & data, double p) {
if ( data.empty ( ) ) return NAN;
double idx = p * ( data.size ( ) - 1 ) ;
size_t i = static_cast < size_t > ( idx) ;
double frac = idx - i;
return data[ i] * ( 1.0 - frac) + data[ std:: min ( i + 1 , data.size ( ) - 1 ) ] * frac;
}
void rolling_cagr_stats_dca_correct( const std:: vector < double > & returns, int duration) {
size_t n = returns.size ( ) ;
if ( n < duration) {
std:: cout << "Not enough data for the specified duration.\n " ;
return ;
}
std:: vector < double > cagr_list;
for ( size_t start = 0 ; start <= n - duration; ++ start) {
double total_value = 0.0 ;
for ( int j = 0 ; j < duration; ++ j) {
double compounded = 1.0 ;
for ( int t = j; t < duration; ++ t) {
compounded * = ( 1.0 + returns[ start + t] ) ;
}
total_value + = compounded;
}
double cagr = std:: pow ( total_value / duration, 1.0 / duration) - 1.0 ;
cagr_list.push_back ( cagr) ;
}
std:: sort ( cagr_list.begin ( ) , cagr_list.end ( ) ) ;
auto percentile = [ ] ( const std:: vector < double > & data, double p) {
double idx = p * ( data.size ( ) - 1 ) ;
size_t i = static_cast < size_t > ( idx) ;
double frac = idx - i;
return data[ i] * ( 1 - frac) + data[ std:: min ( i + 1 , data.size ( ) - 1 ) ] * frac;
} ;
double min_cagr = cagr_list.front ( ) ;
double max_cagr = cagr_list.back ( ) ;
double median_cagr = percentile( cagr_list, 0.50 ) ;
double bottom_15 = percentile( cagr_list, 0.15 ) ;
double top_15 = percentile( cagr_list, 0.85 ) ;
std:: cout << "=== DCA Mode (Corrected Logic) ===\n " ;
std:: cout << "Duration: " << duration << " years\n " ;
std:: cout << "Number of periods: " << cagr_list.size ( ) << "\n " ;
std:: cout << "Min CAGR: " << std:: fixed << std:: setprecision ( 2 ) << min_cagr * 100 << "%\n " ;
std:: cout << "Bottom 15th percentile CAGR: " << bottom_15 * 100 << "%\n " ;
std:: cout << "Median CAGR: " << median_cagr * 100 << "%\n " ;
std:: cout << "Top 85th percentile CAGR: " << top_15 * 100 << "%\n " ;
std:: cout << "Max CAGR: " << max_cagr * 100 << "%\n " ;
}
int main( ) {
std:: vector < double > returns = {
- 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 ,
- 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 ,
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
} ;
int duration = 18 ;
rolling_cagr_stats_dca_correct( returns, duration) ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxpb21hbmlwPgoKZG91YmxlIHBlcmNlbnRpbGUoY29uc3Qgc3RkOjp2ZWN0b3I8ZG91YmxlPiYgZGF0YSwgZG91YmxlIHApIHsKICAgIGlmIChkYXRhLmVtcHR5KCkpIHJldHVybiBOQU47CiAgICBkb3VibGUgaWR4ID0gcCAqIChkYXRhLnNpemUoKSAtIDEpOwogICAgc2l6ZV90IGkgPSBzdGF0aWNfY2FzdDxzaXplX3Q+KGlkeCk7CiAgICBkb3VibGUgZnJhYyA9IGlkeCAtIGk7CiAgICByZXR1cm4gZGF0YVtpXSAqICgxLjAgLSBmcmFjKSArIGRhdGFbc3RkOjptaW4oaSArIDEsIGRhdGEuc2l6ZSgpIC0gMSldICogZnJhYzsKfQoKdm9pZCByb2xsaW5nX2NhZ3Jfc3RhdHNfZGNhX2NvcnJlY3QoY29uc3Qgc3RkOjp2ZWN0b3I8ZG91YmxlPiYgcmV0dXJucywgaW50IGR1cmF0aW9uKSB7CiAgICBzaXplX3QgbiA9IHJldHVybnMuc2l6ZSgpOwogICAgaWYgKG4gPCBkdXJhdGlvbikgewogICAgICAgIHN0ZDo6Y291dCA8PCAiTm90IGVub3VnaCBkYXRhIGZvciB0aGUgc3BlY2lmaWVkIGR1cmF0aW9uLlxuIjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiBjYWdyX2xpc3Q7CgogICAgZm9yIChzaXplX3Qgc3RhcnQgPSAwOyBzdGFydCA8PSBuIC0gZHVyYXRpb247ICsrc3RhcnQpIHsKICAgICAgICBkb3VibGUgdG90YWxfdmFsdWUgPSAwLjA7CgogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgZHVyYXRpb247ICsraikgewogICAgICAgICAgICBkb3VibGUgY29tcG91bmRlZCA9IDEuMDsKICAgICAgICAgICAgZm9yIChpbnQgdCA9IGo7IHQgPCBkdXJhdGlvbjsgKyt0KSB7CiAgICAgICAgICAgICAgICBjb21wb3VuZGVkICo9ICgxLjAgKyByZXR1cm5zW3N0YXJ0ICsgdF0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRvdGFsX3ZhbHVlICs9IGNvbXBvdW5kZWQ7CiAgICAgICAgfQoKICAgICAgICBkb3VibGUgY2FnciA9IHN0ZDo6cG93KHRvdGFsX3ZhbHVlIC8gZHVyYXRpb24sIDEuMCAvIGR1cmF0aW9uKSAtIDEuMDsKICAgICAgICBjYWdyX2xpc3QucHVzaF9iYWNrKGNhZ3IpOwogICAgfQoKICAgIHN0ZDo6c29ydChjYWdyX2xpc3QuYmVnaW4oKSwgY2Fncl9saXN0LmVuZCgpKTsKCiAgICBhdXRvIHBlcmNlbnRpbGUgPSBbXShjb25zdCBzdGQ6OnZlY3Rvcjxkb3VibGU+JiBkYXRhLCBkb3VibGUgcCkgewogICAgICAgIGRvdWJsZSBpZHggPSBwICogKGRhdGEuc2l6ZSgpIC0gMSk7CiAgICAgICAgc2l6ZV90IGkgPSBzdGF0aWNfY2FzdDxzaXplX3Q+KGlkeCk7CiAgICAgICAgZG91YmxlIGZyYWMgPSBpZHggLSBpOwogICAgICAgIHJldHVybiBkYXRhW2ldICogKDEgLSBmcmFjKSArIGRhdGFbc3RkOjptaW4oaSArIDEsIGRhdGEuc2l6ZSgpIC0gMSldICogZnJhYzsKICAgIH07CgogICAgZG91YmxlIG1pbl9jYWdyID0gY2Fncl9saXN0LmZyb250KCk7CiAgICBkb3VibGUgbWF4X2NhZ3IgPSBjYWdyX2xpc3QuYmFjaygpOwogICAgZG91YmxlIG1lZGlhbl9jYWdyID0gcGVyY2VudGlsZShjYWdyX2xpc3QsIDAuNTApOwogICAgZG91YmxlIGJvdHRvbV8xNSA9IHBlcmNlbnRpbGUoY2Fncl9saXN0LCAwLjE1KTsKICAgIGRvdWJsZSB0b3BfMTUgPSBwZXJjZW50aWxlKGNhZ3JfbGlzdCwgMC44NSk7CgogICAgc3RkOjpjb3V0IDw8ICI9PT0gRENBIE1vZGUgKENvcnJlY3RlZCBMb2dpYykgPT09XG4iOwogICAgc3RkOjpjb3V0IDw8ICJEdXJhdGlvbjogIiA8PCBkdXJhdGlvbiA8PCAiIHllYXJzXG4iOwogICAgc3RkOjpjb3V0IDw8ICJOdW1iZXIgb2YgcGVyaW9kczogIiA8PCBjYWdyX2xpc3Quc2l6ZSgpIDw8ICJcbiI7CiAgICBzdGQ6OmNvdXQgPDwgIk1pbiBDQUdSOiAiIDw8IHN0ZDo6Zml4ZWQgPDwgc3RkOjpzZXRwcmVjaXNpb24oMikgPDwgbWluX2NhZ3IgKiAxMDAgPDwgIiVcbiI7CiAgICBzdGQ6OmNvdXQgPDwgIkJvdHRvbSAxNXRoIHBlcmNlbnRpbGUgQ0FHUjogIiA8PCBib3R0b21fMTUgKiAxMDAgPDwgIiVcbiI7CiAgICBzdGQ6OmNvdXQgPDwgIk1lZGlhbiBDQUdSOiAiIDw8IG1lZGlhbl9jYWdyICogMTAwIDw8ICIlXG4iOwogICAgc3RkOjpjb3V0IDw8ICJUb3AgODV0aCBwZXJjZW50aWxlIENBR1I6ICIgPDwgdG9wXzE1ICogMTAwIDw8ICIlXG4iOwogICAgc3RkOjpjb3V0IDw8ICJNYXggQ0FHUjogIiA8PCBtYXhfY2FnciAqIDEwMCA8PCAiJVxuIjsKfQoKCmludCBtYWluKCkgewogICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiByZXR1cm5zID0gewogICAgICAgIC0wLjA0LCAwLjE0LCAwLjE1LCAtMC4xNCwgLTAuMTksIDAuMjYsIDAuMjgsIDAuMDQsIDAuMDgsIDAuMjgsCiAgICAgICAgMC4wOCwgLTAuMDYsIDAuMjQsIDAuMjIsIC0wLjAxLCAwLjI2LCAwLjE0LCAtMC4wMiwgMC4xNCwgMC4xNiwKICAgICAgICAtMC4xNiwgMC4yOSwgMC4xNSwgMC4xOCwgLTAuMDMsIDAuMjAsIDAuMTMsIDAuMjAsIDAuMDIsIDAuMDgsCiAgICAgICAgLTAuMDQsIDAuMDQsIC0wLjA3LCAwLjMzLCAwLjEyLCAwLjA2LCAwLjE1LCAwLjAxLCAtMC4yNiwgMC4zMSwKICAgICAgICAwLjIyLCAtMC4wMywgMC4xNSwgMC4xOSwgMC4wOCwgLTAuMDYsIDAuMTYsIDAuMTMsIC0wLjExLCAwLjIxLAogICAgICAgIDAuMTMsIDAuMTIsIC0wLjE4LCAwLjE1LCAwLjEyCiAgICB9OwoKICAgIGludCBkdXJhdGlvbiA9IDE4OwogICAgcm9sbGluZ19jYWdyX3N0YXRzX2RjYV9jb3JyZWN0KHJldHVybnMsIGR1cmF0aW9uKTsKCiAgICByZXR1cm4gMDsKfQo=