На CPU вычисления
This commit is contained in:
87
src/aggregation.cpp
Normal file
87
src/aggregation.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "aggregation.hpp"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
std::vector<DayStats> aggregate_days(const std::vector<Record>& records) {
|
||||
// Группируем записи по дням
|
||||
std::map<DayIndex, std::vector<const Record*>> day_records;
|
||||
|
||||
for (const auto& r : records) {
|
||||
DayIndex day = static_cast<DayIndex>(r.timestamp) / 86400;
|
||||
day_records[day].push_back(&r);
|
||||
}
|
||||
|
||||
std::vector<DayStats> result;
|
||||
result.reserve(day_records.size());
|
||||
|
||||
for (auto& [day, recs] : day_records) {
|
||||
// Сортируем по timestamp для определения first/last
|
||||
std::sort(recs.begin(), recs.end(),
|
||||
[](const Record* a, const Record* b) {
|
||||
return a->timestamp < b->timestamp;
|
||||
});
|
||||
|
||||
DayStats stats;
|
||||
stats.day = day;
|
||||
stats.low = std::numeric_limits<double>::max();
|
||||
stats.high = std::numeric_limits<double>::lowest();
|
||||
stats.open = recs.front()->open;
|
||||
stats.close = recs.back()->close;
|
||||
stats.first_ts = recs.front()->timestamp;
|
||||
stats.last_ts = recs.back()->timestamp;
|
||||
|
||||
for (const auto* r : recs) {
|
||||
stats.low = std::min(stats.low, r->low);
|
||||
stats.high = std::max(stats.high, r->high);
|
||||
}
|
||||
|
||||
stats.avg = (stats.low + stats.high) / 2.0;
|
||||
|
||||
result.push_back(stats);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DayStats> merge_day_stats(const std::vector<DayStats>& all_stats) {
|
||||
// Объединяем статистику по одинаковым дням (если такие есть)
|
||||
std::map<DayIndex, DayStats> merged;
|
||||
|
||||
for (const auto& s : all_stats) {
|
||||
auto it = merged.find(s.day);
|
||||
if (it == merged.end()) {
|
||||
merged[s.day] = s;
|
||||
} else {
|
||||
// Объединяем данные за один день
|
||||
auto& m = it->second;
|
||||
m.low = std::min(m.low, s.low);
|
||||
m.high = std::max(m.high, s.high);
|
||||
|
||||
// open берём от записи с меньшим timestamp
|
||||
if (s.first_ts < m.first_ts) {
|
||||
m.open = s.open;
|
||||
m.first_ts = s.first_ts;
|
||||
}
|
||||
|
||||
// close берём от записи с большим timestamp
|
||||
if (s.last_ts > m.last_ts) {
|
||||
m.close = s.close;
|
||||
m.last_ts = s.last_ts;
|
||||
}
|
||||
|
||||
m.avg = (m.low + m.high) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Преобразуем в отсортированный вектор
|
||||
std::vector<DayStats> result;
|
||||
result.reserve(merged.size());
|
||||
|
||||
for (auto& [day, stats] : merged) {
|
||||
result.push_back(stats);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user