FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
journal_source.hpp
Go to the documentation of this file.
1#pragma once
2// JournalSource: market-data events of an .fmj journal (BookDelta / BookSnapshot / Trade /
3// BookTicker records, in sequence order). Everything else the journal holds (order events,
4// timers, outbound copies) is skipped: the backtest re-derives those.
5//
6// parts: a session recorded with [engine] journal_max_bytes is several files, `x.fmj` then
7// `x.1.fmj`, `x.2.fmj`, ... (JournalFileWriter::part_path), each a complete journal that repeats
8// the prologue. Given `x.fmj`, the source reads the later parts after it, in order, until one is
9// missing, as one stream; their prologues are never events, so nothing repeats. A part of another
10// session (its session_id differs) is refused. The sequence numbers continue across parts; a part
11// whose first does not follow the previous part's last is read anyway, and seq_gaps() / note()
12// say so: a part is missing in between, or the previous one was cut short.
13//
14// strip_own: the journal is a live session's, whose venue feed shows the session's own resting
15// orders; take them out of the depth and top of book (OwnOrderStripper, own_orders.hpp) so the
16// backtest does not see its live twin as someone else's liquidity. A BookTicker whose best bid or
17// ask was only ours is dropped. Public trades are kept, our own fills included: the aggressor
18// existed whether or not our order did, and without it would have traded with the next order at
19// that price, which is what a simulated order there stands for.
20//
21// remap: the journal numbers its instruments as the recording session did, so two recordings of
22// different instrument sets both count from 0 and, merged, overwrite each other's books. Given the
23// backtest configuration's table, every event's instrument id becomes that of the instrument with
24// the same symbol there (the recording's venue first, else any venue listing the symbol) and its
25// venue that instrument's; an event whose symbol the configuration lacks is dropped, and note()
26// counts them. The copy holds up to kMaxMsgBytes: a recorded snapshot can be deeper than an
27// EventBuf. Remap applies after strip_own.
29#include "fastmm/backtest/own_orders.hpp"
31#include "fastmm/core/journal.hpp"
32#include "fastmm/sim/sim_account.hpp"
33
34#include <cstdint>
35#include <memory>
36#include <string>
37#include <string_view>
38#include <vector>
39
40namespace fastmm::bt {
41
42class JournalSource final : public MdSource {
43 public:
44 // Throws std::runtime_error if a file cannot be opened/validated. parts = false reads `path`
45 // alone.
46 // remap: the configuration's instrument table (see above); null leaves the ids as recorded.
47 explicit JournalSource(const std::string& path,
48 bool strip_own = false,
49 bool parts = true,
50 const InstrumentTable* remap = nullptr);
51 const EventHeader* next() override;
52 void reset() override;
53 [[nodiscard]] Timestamp start_ts() const override { return first_ts_; }
54 // The first part: its header, instrument table and configuration are every part's.
55 [[nodiscard]] const JournalReader& reader() const noexcept { return parts_.front(); }
56 // The files read, in order; the first is `path`.
57 [[nodiscard]] const std::vector<std::string>& paths() const noexcept { return paths_; }
58 // Parts whose first sequence number did not follow the previous part's last.
59 [[nodiscard]] std::size_t seq_gaps() const noexcept { return seq_gaps_; }
60 [[nodiscard]] std::size_t md_events() const noexcept { return md_events_; }
61 // Null unless strip_own.
62 [[nodiscard]] const OwnOrderStripper* stripper() const noexcept { return stripper_.get(); }
63 // remap: events dropped so far because the configuration lacks their symbol.
64 [[nodiscard]] std::size_t dropped() const noexcept { return dropped_; }
65 [[nodiscard]] std::string note() const override;
66 // The first balance snapshot the journal recorded for each venue (the BalanceMsg rows from its
67 // first kSnapshot message to the kSnapshotEnd), each asset at its total; account rows
68 // (kAccount) are left out. Empty when the journal has none.
69 [[nodiscard]] const std::vector<sim::SimAccountConfig>* balance_snapshots() const override {
70 return &balances_;
71 }
72 // journal_start_state() of the parts read (journal_state.hpp).
73 [[nodiscard]] const sim::SessionStart* session_start() const override { return &start_; }
74 // Its ParamUpdate records and the first part's parameter table.
75 [[nodiscard]] const sim::RecordedParams* recorded_params() const override { return &params_; }
76
77 [[nodiscard]] static bool is_market_data(EventType t) noexcept {
80 }
81
82 private:
83 void open_part(const std::string& path);
84
85 std::vector<JournalReader> parts_;
86 std::vector<std::string> paths_;
87 std::size_t at_ = 0; // the part next() is reading
88 std::size_t seq_gaps_ = 0;
89 std::string gap_; // the first gap, for note()
90 Timestamp first_ts_{};
91 std::size_t md_events_ = 0;
92 std::unique_ptr<OwnOrderStripper> stripper_;
93 std::size_t orders_ = 0;
94 EventBuf buf_;
95 std::vector<sim::SimAccountConfig> balances_;
96 sim::SessionStart start_;
97 sim::RecordedParams params_;
98 // remap: per journal instrument id, the configured id (kUnmapped: dropped) and its venue.
99 static constexpr std::uint32_t kUnmapped = 0xFFFF'FFFF;
100 bool remap_ = false;
101 std::vector<std::uint32_t> map_;
102 std::vector<VenueId> map_venue_;
103 std::size_t unmapped_ = 0; // journal instruments the configuration lacks
104 std::size_t dropped_ = 0;
105 std::vector<std::uint64_t> rbuf_; // the remapped event, a copy of up to kMaxMsgBytes
106};
107
108// Writes the events of `source` (all, or the first `max_events` when non-zero) to a fresh
109// .fmj with JournalFileWriter (instrument table + header stamped with `seed`); used to
110// produce fixtures. Returns the number of events written.
111std::uint64_t write_md_journal(MdSource& source,
112 const std::string& path,
113 const InstrumentTable& instruments,
114 std::uint64_t seed,
115 std::string_view strategy = "data",
116 std::uint64_t max_events = 0);
117
118} // namespace fastmm::bt
Dense-by-id table built at startup; symbol lookup is a sorted FlatMap keyed by (venue,...
Definition instrument.hpp:141
Definition journal_source.hpp:44
const sim::SessionStart * session_start() const override
journal_start_state() of the parts read (journal_state.hpp).
Definition journal_source.hpp:75
const JournalReader & reader() const noexcept
The first part: its header, instrument table and configuration are every part's.
Definition journal_source.hpp:57
const EventHeader * next() override
static bool is_market_data(EventType t) noexcept
Definition journal_source.hpp:79
const OwnOrderStripper * stripper() const noexcept
Null unless strip_own.
Definition journal_source.hpp:64
std::size_t dropped() const noexcept
remap: events dropped so far because the configuration lacks their symbol.
Definition journal_source.hpp:66
const std::vector< sim::SimAccountConfig > * balance_snapshots() const override
The first balance snapshot the journal recorded for each venue (the BalanceMsg rows from its first kS...
Definition journal_source.hpp:71
const std::vector< std::string > & paths() const noexcept
The files read, in order; the first is path.
Definition journal_source.hpp:59
std::string note() const override
std::size_t seq_gaps() const noexcept
Parts whose first sequence number did not follow the previous part's last.
Definition journal_source.hpp:61
Timestamp start_ts() const override
Definition journal_source.hpp:55
const sim::RecordedParams * recorded_params() const override
Its ParamUpdate records and the first part's parameter table.
Definition journal_source.hpp:77
std::size_t md_events() const noexcept
Definition journal_source.hpp:62
DataSource (8.4): a timestamp-ordered stream of normalized market-data events consumed by the simulat...
Instrument: the single definition of a tradable contract (5.3 / 5.15).
Definition backtest_config.hpp:39
std::uint64_t write_md_journal(MdSource &source, const std::string &path, const InstrumentTable &instruments, std::uint64_t seed, std::string_view strategy="data", std::uint64_t max_events=0)
Writes the events of source (all, or the first max_events when non-zero) to a fresh ....
EventType
Message discriminator carried in EventHeader::type.
Definition enums.hpp:300
@ OptionTicker
mark / implied vols / greeks of one option (OptionTickerMsg)
@ PerpState
mark, index and funding of one derivative (PerpStateMsg)
Definition messages.hpp:37
Definition time.hpp:45