20#include "fastmm/sim/md_source.hpp"
32using sim::kMaxSourceEventBytes;
36concept DataSourceLike =
requires(S& s) {
37 { s.next() } -> std::same_as<const EventHeader*>;
50 std::uint64_t
seq = 0;
58 template <
class Prov
ider>
60 if (!have_row_ && !fetch(provide))
return nullptr;
62 const Row first = row_;
68 t.price = first.
price;
70 t.trade_id = first.
seq;
71 t.aggressor = first.
side;
78 t.bid_px = first.
price;
79 t.bid_qty = first.
qty;
82 t.ask_px = row_.
price;
100 if (!fetch(provide))
break;
119 d.first_update_id = d.last_update_id = first.
seq;
120 d.prev_update_id = 0;
121 if (nb > 0) std::memcpy(d.levels(), bids_, nb *
sizeof(
Level));
122 if (na > 0) std::memcpy(d.levels() + nb, asks_, na *
sizeof(
Level));
128 void reset() noexcept { have_row_ =
false; }
131 static constexpr std::uint32_t kMaxLevels = 256;
132 template <
class Prov
ider>
133 bool fetch(Provider& provide) {
134 have_row_ = provide(row_);
139 h.t0_cycles =
Cycles{
static_cast<std::uint64_t
>(r.ts)};
145 bool have_row_ =
false;
147 Level bids_[kMaxLevels];
148 Level asks_[kMaxLevels];
154class ChainSource final :
public MdSource {
156 explicit ChainSource(std::vector<MdSource*> sources) : sources_(std::move(sources)) {}
158 while (at_ < sources_.size()) {
164 void reset()
override {
165 for (MdSource* s : sources_) s->reset();
169 return sources_.empty() ?
Timestamp{} : sources_.front()->start_ts();
173 std::vector<MdSource*> sources_;
183class TimeSliceSource final :
public MdSource {
198 std::unique_ptr<Primer> primer_;
200 bool started_ =
false;
210 explicit MergedSource(std::vector<MdSource*> sources) : sources_(std::move(sources)) {
211 heads_.assign(sources_.size(),
nullptr);
212 for (std::size_t i = 0; i < sources_.size(); ++i) heads_[i] = sources_[i]->
next();
215 if (last_ != kNone) {
216 heads_[last_] = sources_[last_]->next();
219 std::size_t best = kNone;
221 for (std::size_t i = 0; i < heads_.size(); ++i) {
222 if (heads_[i] ==
nullptr)
continue;
224 if (best == kNone || ts < best_ts) {
229 if (best == kNone)
return nullptr;
233 void reset()
override {
234 for (std::size_t i = 0; i < sources_.size(); ++i) {
235 sources_[i]->reset();
236 heads_[i] = sources_[i]->next();
243 for (
const MdSource* s : sources_) {
245 if (st.
valid() && (!t.valid() || st < t)) t = st;
250 return h.exch_ts.
valid() ? h.exch_ts : h.recv_ts;
254 static constexpr std::size_t kNone =
static_cast<std::size_t
>(-1);
255 std::vector<MdSource*> sources_;
256 std::vector<const EventHeader*> heads_;
257 std::size_t last_ = kNone;
261class OwnedMergedSource final :
public MdSource {
264 : owned_(std::move(sources)), merged_(raw(owned_)) {}
270 static std::vector<MdSource*> raw(
const std::vector<std::unique_ptr<MdSource>>& v) {
271 std::vector<MdSource*> out;
272 out.reserve(v.size());
273 for (
const auto& s : v) out.push_back(s.get());
276 std::vector<std::unique_ptr<MdSource>> owned_;
Concatenation of sources that cover consecutive spans of time (one file per day).
Definition data_source.hpp:156
const EventHeader * next() override
Definition data_source.hpp:159
Timestamp start_ts() const override
Definition data_source.hpp:170
void reset() override
Definition data_source.hpp:166
k-way merge of several sources by event time (stable: lower source index first on ties).
Definition data_source.hpp:210
Timestamp start_ts() const override
Earliest start among the inputs (invalid if none reports one).
Definition data_source.hpp:243
static Timestamp time_of(const EventHeader &h) noexcept
Definition data_source.hpp:251
const EventHeader * next() override
Definition data_source.hpp:216
void reset() override
Definition data_source.hpp:235
MergedSource over sources it owns: open_data() of several specs ("a; b"), one per venue.
Definition data_source.hpp:263
void reset() override
Definition data_source.hpp:268
const EventHeader * next() override
Definition data_source.hpp:267
Timestamp start_ts() const override
Definition data_source.hpp:269
Builds messages from a row stream. Provider is bool(Row&) returning false at end.
Definition data_source.hpp:56
void reset() noexcept
Definition data_source.hpp:130
const EventHeader * next(Provider &&provide)
Definition data_source.hpp:61
The events of inner in [t0, t1) of event time (exch_ts, recv_ts when unset), for walk-forward folds.
Definition data_source.hpp:185
TimeSliceSource(MdSource &inner, Timestamp t0, Timestamp t1)
Timestamp start_ts() const override
Definition data_source.hpp:193
const EventHeader * next() override
TimeSliceSource & operator=(const TimeSliceSource &)=delete
~TimeSliceSource() override
Event bus message structs (5.5).
Definition backtest_config.hpp:39
RowType
Definition data_source.hpp:43
constexpr void init_header(M &m, EventType type, InstrumentId inst={}, VenueId venue={}, std::uint32_t len=static_cast< std::uint32_t >(sizeof(M))) noexcept
For fixed-size messages len defaults to sizeof(M); BookDeltaMsg passes size_for().
Definition messages.hpp:75
Side
Definition enums.hpp:12
StrongId< struct VenueTag, std::uint8_t > VenueId
Definition strong_id.hpp:39
Bids then asks follow the fixed part as a flexible array of Level (bid_count + ask_count).
Definition messages.hpp:99
static constexpr std::uint32_t size_for(std::uint32_t bids, std::uint32_t asks) noexcept
Definition messages.hpp:107
Definition messages.hpp:150
One price level. Shared by book messages and the L2 book.
Definition messages.hpp:30
static constexpr Timestamp max() noexcept
Definition time.hpp:56
constexpr bool valid() const noexcept
Definition time.hpp:55
Definition messages.hpp:140
Definition data_source.hpp:45
std::uint32_t inst
Definition data_source.hpp:48
Price price
Definition data_source.hpp:50
RowType type
Definition data_source.hpp:47
Qty qty
Definition data_source.hpp:51
Side side
Definition data_source.hpp:49
std::int64_t ts
Definition data_source.hpp:46
std::uint64_t seq
Definition data_source.hpp:52