diff --git a/src/aggregation.cpp b/src/aggregation.cpp index e9d676f..e5050d8 100644 --- a/src/aggregation.cpp +++ b/src/aggregation.cpp @@ -1,12 +1,17 @@ #include "aggregation.hpp" #include "utils.hpp" -#include + #include +#include #include +#include std::vector aggregate_periods(const std::vector& records) { - int64_t interval = get_aggregation_interval(); - + const int64_t interval = get_aggregation_interval(); + + std::vector result; + if (records.empty()) return result; + struct PeriodAccumulator { double avg_sum = 0.0; double open_min = std::numeric_limits::max(); @@ -14,37 +19,57 @@ std::vector aggregate_periods(const std::vector& records) { double close_min = std::numeric_limits::max(); double close_max = std::numeric_limits::lowest(); int64_t count = 0; + + void add(const Record& r) { + const double avg = (r.low + r.high) / 2.0; + avg_sum += avg; + open_min = std::min(open_min, r.open); + open_max = std::max(open_max, r.open); + close_min = std::min(close_min, r.close); + close_max = std::max(close_max, r.close); + ++count; + } }; - - std::map periods; - - for (const auto& r : records) { - PeriodIndex period = static_cast(r.timestamp) / interval; - auto& acc = periods[period]; - - double avg = (r.low + r.high) / 2.0; - acc.avg_sum += avg; - acc.open_min = std::min(acc.open_min, r.open); - acc.open_max = std::max(acc.open_max, r.open); - acc.close_min = std::min(acc.close_min, r.close); - acc.close_max = std::max(acc.close_max, r.close); - acc.count++; + + PeriodIndex current_period = + static_cast(records[0].timestamp) / interval; + + PeriodAccumulator acc; + acc.add(records[0]); + + for (size_t i = 1; i < records.size(); ++i) { + const Record& r = records[i]; + const PeriodIndex period = + static_cast(r.timestamp) / interval; + + if (period != current_period) { + PeriodStats stats; + stats.period = current_period; + stats.avg = acc.avg_sum / static_cast(acc.count); + stats.open_min = acc.open_min; + stats.open_max = acc.open_max; + stats.close_min = acc.close_min; + stats.close_max = acc.close_max; + stats.count = acc.count; + result.push_back(stats); + + current_period = period; + acc = PeriodAccumulator{}; + } + + acc.add(r); } - - std::vector result; - result.reserve(periods.size()); - - for (const auto& [period, acc] : periods) { - PeriodStats stats; - stats.period = period; - stats.avg = acc.avg_sum / static_cast(acc.count); - stats.open_min = acc.open_min; - stats.open_max = acc.open_max; - stats.close_min = acc.close_min; - stats.close_max = acc.close_max; - stats.count = acc.count; - result.push_back(stats); - } - + + // последний период + PeriodStats stats; + stats.period = current_period; + stats.avg = acc.avg_sum / static_cast(acc.count); + stats.open_min = acc.open_min; + stats.open_max = acc.open_max; + stats.close_min = acc.close_min; + stats.close_max = acc.close_max; + stats.count = acc.count; + result.push_back(stats); + return result; }