1// BarSeries — OHLCV bars for one instrument (columnar), with session structure derived from the MarketCalendar.2#pragma once3#include <vector>4#include <span>5#include <string>6#include "raid/core/types.hpp"7#include "raid/data/calendar.hpp"8#include "raid/data/quality.hpp"910namespace raid {1112struct BarSeries {13 std::string symbol;14 std::string instrument_id;15 Interval interval{Interval::m1};16 std::string adjustment{"raw"};17 std::vector<Timestamp> t_open; // bar OPEN, UTC18 std::vector<Date> session; // exchange-local session date19 std::vector<f64> open, high, low, close, volume;20 std::vector<u32> flags; // bitmask (see QualityFlag)21 // Session index: session_offsets[k]..session_offsets[k+1] are the bars of session k (built by index_sessions()).22 std::vector<i64> session_offsets;23 std::vector<Date> session_dates;2425 usize size() const { return close.size(); }26 bool empty() const { return close.empty(); }27 void reserve(usize n) { t_open.reserve(n); session.reserve(n); open.reserve(n); high.reserve(n); low.reserve(n); close.reserve(n); volume.reserve(n); flags.reserve(n); }28 void push_back(Timestamp t, f64 o, f64 h, f64 l, f64 c, f64 v, u32 f = 0) {29 t_open.push_back(t); session.push_back(MarketCalendar::session_of(t)); open.push_back(o); high.push_back(h); low.push_back(l); close.push_back(c); volume.push_back(v); flags.push_back(f);30 }31 usize n_sessions() const { return session_dates.size(); }32 std::span<const f64> session_closes(usize k) const { return std::span<const f64>(close).subspan(static_cast<usize>(session_offsets[k]), static_cast<usize>(session_offsets[k + 1] - session_offsets[k])); }33 std::span<const Timestamp> session_times(usize k) const { return std::span<const Timestamp>(t_open).subspan(static_cast<usize>(session_offsets[k]), static_cast<usize>(session_offsets[k + 1] - session_offsets[k])); }3435 /// Sorts by time, drops exact duplicate timestamps (keeps the first), rebuilds the session index. Returns counts.36 struct NormalizeStats { usize duplicates_removed; usize reordered; };37 NormalizeStats normalize();38 void index_sessions();39 /// Validates OHLCV, interval grid, session membership and coverage; does not modify data.40 QualityReport validate(const MarketCalendar& cal, SessionPolicy policy = SessionPolicy::regular, f64 jump_threshold = 0.25) const;41 /// Keeps only bars of the requested session policy (regular: 09:30 ≤ open ≤ close time, i.e. includes the 16:00 print).42 BarSeries filter_session(const MarketCalendar& cal, SessionPolicy policy) const;43};4445enum QualityFlag : u32 {46 kFlagOhlcInconsistent = 1u << 0, kFlagNonpositivePrice = 1u << 1, kFlagNegativeVolume = 1u << 2, kFlagZeroVolume = 1u << 3,47 kFlagOffInterval = 1u << 4, kFlagOutsideSession = 1u << 5, kFlagNonTradingDay = 1u << 6, kFlagPriceJump = 1u << 7, kFlagVendorFlag = 1u << 8,48};4950} // namespace raid51