From e84d1e9fe366abbdafbd83dee5377128799cf0e9 Mon Sep 17 00:00:00 2001 From: Arity-T Date: Tue, 16 Dec 2025 14:16:40 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=B0=D0=B3=D1=80=D0=B5?= =?UTF-8?q?=D0=B3=D0=B0=D1=86=D0=B8=D1=8E=20=D0=BD=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=BE=D1=80=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/aggregation.cpp | 91 +++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 33 deletions(-) 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; }