84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
#include "intervals.hpp"
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
#include <ctime>
|
|
|
|
std::vector<Interval> find_intervals(const std::vector<DayStats>& days, double threshold) {
|
|
if (days.empty()) {
|
|
return {};
|
|
}
|
|
|
|
std::vector<Interval> intervals;
|
|
|
|
size_t start_idx = 0;
|
|
double price_base = days[start_idx].avg;
|
|
|
|
for (size_t i = 1; i < days.size(); i++) {
|
|
double price_now = days[i].avg;
|
|
double change = std::abs(price_now - price_base) / price_base;
|
|
|
|
if (change >= threshold) {
|
|
Interval interval;
|
|
interval.start_day = days[start_idx].day;
|
|
interval.end_day = days[i].day;
|
|
interval.start_avg = price_base;
|
|
interval.end_avg = price_now;
|
|
interval.change = change;
|
|
|
|
// Находим min(Open) и max(Close) в интервале
|
|
interval.min_open = days[start_idx].open;
|
|
interval.max_close = days[start_idx].close;
|
|
|
|
for (size_t j = start_idx; j <= i; j++) {
|
|
interval.min_open = std::min(interval.min_open, days[j].open);
|
|
interval.max_close = std::max(interval.max_close, days[j].close);
|
|
}
|
|
|
|
intervals.push_back(interval);
|
|
|
|
// Начинаем новый интервал
|
|
start_idx = i + 1;
|
|
if (start_idx >= days.size()) {
|
|
break;
|
|
}
|
|
price_base = days[start_idx].avg;
|
|
}
|
|
}
|
|
|
|
return intervals;
|
|
}
|
|
|
|
std::string day_index_to_date(DayIndex day) {
|
|
time_t ts = static_cast<time_t>(day) * 86400;
|
|
struct tm* tm_info = gmtime(&ts);
|
|
|
|
std::ostringstream oss;
|
|
oss << std::setfill('0')
|
|
<< (tm_info->tm_year + 1900) << "-"
|
|
<< std::setw(2) << (tm_info->tm_mon + 1) << "-"
|
|
<< std::setw(2) << tm_info->tm_mday;
|
|
|
|
return oss.str();
|
|
}
|
|
|
|
void write_intervals(const std::string& filename, const std::vector<Interval>& intervals) {
|
|
std::ofstream out(filename);
|
|
|
|
out << std::fixed << std::setprecision(2);
|
|
out << "start_date,end_date,min_open,max_close,start_avg,end_avg,change\n";
|
|
|
|
for (const auto& iv : intervals) {
|
|
out << day_index_to_date(iv.start_day) << ","
|
|
<< day_index_to_date(iv.end_day) << ","
|
|
<< iv.min_open << ","
|
|
<< iv.max_close << ","
|
|
<< iv.start_avg << ","
|
|
<< iv.end_avg << ","
|
|
<< std::setprecision(6) << iv.change << "\n";
|
|
}
|
|
}
|
|
|