algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
event.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algotradelib/core>
4
5#include <array>
6#include <chrono>
7#include <cstdint>
8#include <optional>
9#include <ratio>
10#include <string>
11#include <vector>
12
13namespace algotradelib {
14namespace strategy {
15
23
30enum class MarketPhase {
32 UNKNOWN,
34 CLOSED,
38 OPEN,
41};
42
51
57inline constexpr std::string_view market_phase_name(MarketPhase phase) noexcept {
58 switch (phase) {
60 return "unknown";
62 return "closed";
64 return "pre_open";
66 return "open";
68 return "post_close";
69 }
70 return "";
71}
72
79inline constexpr bool market_phase_session_ended(MarketPhase phase) noexcept {
80 switch (phase) {
83 return true;
87 return false;
88 }
89 return false;
90}
91
92static_assert(
93 lists_every_value(all_market_phases, [](MarketPhase phase) { return !market_phase_name(phase).empty(); }),
94 "all_market_phases must list every MarketPhase"
95);
96
108 std::chrono::minutes open_{std::chrono::hours(9)};
110 std::chrono::minutes close_{std::chrono::hours(15) + std::chrono::minutes(30)};
112 std::chrono::minutes utc_offset_{std::chrono::hours(9)};
114 std::string source_{"KRX regular session, 09:00-15:30 KST (library default)"};
115
120 static SessionWindow krx() { return SessionWindow{}; }
121
132 std::chrono::system_clock::time_point now,
133 std::optional<bool> trading_day
134 ) const {
135 if (!trading_day) {
137 }
138 if (!*trading_day) {
139 return MarketPhase::CLOSED;
140 }
141 const auto local = now + utc_offset_;
142 const auto since_midnight =
143 std::chrono::duration_cast<std::chrono::minutes>(local - local_midnight(now));
144 if (since_midnight < open_) {
146 }
147 if (close_ <= since_midnight) {
149 }
150 return MarketPhase::OPEN;
151 }
152
162 Date local_date(std::chrono::system_clock::time_point now) const {
163 using Days = std::chrono::duration<std::int64_t, std::ratio<86400>>;
165 std::chrono::duration_cast<Days>(local_midnight(now).time_since_epoch()).count()
166 );
167 }
168
175 std::chrono::system_clock::time_point opens_at(
176 std::chrono::system_clock::time_point now
177 ) const {
178 return local_midnight(now) - utc_offset_ + open_;
179 }
180
181private:
182 // The market's local midnight before `now`, as a UTC-shifted instant. floor rounds toward
183 // negative infinity, so instants before the epoch work too. phase() and local_date() share it so
184 // they always agree on the day.
185 std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> local_midnight(
186 std::chrono::system_clock::time_point now
187 ) const {
188 using Days = std::chrono::duration<std::int64_t, std::ratio<86400>>;
189 return std::chrono::time_point_cast<std::chrono::seconds>(
190 std::chrono::floor<Days>(now + utc_offset_)
191 );
192 }
193};
194
202struct BarEvent {
206 BarInterval interval_{BarInterval::ONE_DAY};
218 std::chrono::system_clock::time_point period_end_{};
219};
220
232inline std::chrono::system_clock::time_point bar_period_end(
233 const Bar& bar,
234 BarInterval interval,
235 BarStamp stamp
236) {
237 if (stamp == BarStamp::CLOSE) {
238 return bar.timestamp_;
239 }
240 switch (interval) {
241 case BarInterval::ONE_MINUTE:
242 return bar.timestamp_ + std::chrono::minutes(1);
244 return bar.timestamp_ + std::chrono::minutes(5);
246 return bar.timestamp_ + std::chrono::minutes(15);
248 return bar.timestamp_ + std::chrono::minutes(30);
250 return bar.timestamp_ + std::chrono::hours(1);
251 case BarInterval::ONE_DAY:
252 return bar.timestamp_ + std::chrono::hours(24);
253 case BarInterval::ONE_WEEK:
254 return bar.timestamp_ + std::chrono::hours(24 * 7);
255 case BarInterval::ONE_MONTH:
256 // Nominal: a month has no fixed length. Documented on the function.
257 return bar.timestamp_ + std::chrono::hours(24 * 31);
258 case BarInterval::ONE_YEAR:
259 return bar.timestamp_ + std::chrono::hours(24 * 366);
260 }
261 return bar.timestamp_;
262}
263
274 InstrumentId instrument,
275 BarInterval interval,
276 BarStamp stamp,
277 Bar bar
278) {
279 BarEvent event;
280 event.instrument_ = std::move(instrument);
281 event.interval_ = interval;
282 event.stamp_ = stamp;
283 event.period_end_ = bar_period_end(bar, interval, stamp);
284 event.bar_ = std::move(bar);
285 return event;
286}
287
298struct BarSlice {
300 std::chrono::system_clock::time_point period_end_{};
302 BarInterval interval_{BarInterval::ONE_DAY};
304 std::vector<BarEvent> bars_;
305
311 const BarEvent* find(const InstrumentId& id) const noexcept {
312 for (const auto& event : bars_) {
313 if (event.instrument_ == id) {
314 return &event;
315 }
316 }
317 return nullptr;
318 }
319};
320
322namespace slice_detail {
323
328class Bucket {
329public:
331 bool empty() const noexcept { return slices_.empty(); }
332
334 std::chrono::system_clock::time_point period_end() const noexcept { return period_end_; }
335
337 bool holds(const BarEvent& event) const noexcept {
338 for (const auto& slice : slices_) {
339 if (slice.interval_ == event.interval_) {
340 return slice.find(event.instrument_) != nullptr;
341 }
342 }
343 return false;
344 }
345
347 void add(const BarEvent& event) {
348 if (slices_.empty()) {
349 period_end_ = event.period_end_;
350 }
351 for (auto& slice : slices_) {
352 if (slice.interval_ == event.interval_) {
353 slice.bars_.push_back(event);
354 return;
355 }
356 }
357 BarSlice slice;
358 slice.period_end_ = event.period_end_;
359 slice.interval_ = event.interval_;
360 slice.bars_.push_back(event);
361 slices_.push_back(std::move(slice));
362 }
363
365 BarSlice take_first() {
366 BarSlice slice = std::move(slices_.front());
367 slices_.erase(slices_.begin());
368 return slice;
369 }
370
372 std::vector<BarSlice> take() {
373 std::vector<BarSlice> slices = std::move(slices_);
374 slices_.clear();
375 return slices;
376 }
377
379 void clear() noexcept { slices_.clear(); }
380
381private:
382 std::chrono::system_clock::time_point period_end_{};
383 std::vector<BarSlice> slices_;
384};
385
386} // namespace slice_detail
388
394
407struct Fill {
409 std::string order_id_;
413 OrderSide side_{OrderSide::BUY};
419 std::string tag_;
421 std::chrono::system_clock::time_point at_{};
422};
423
424} // namespace strategy
425} // namespace algotradelib
An exact signed decimal: an int64 coefficient times 10^-scale.
Definition types.hpp:297
What a strategy sees and emits: events, intents, the portfolio, reconciliation and risk limits.
Definition concept.hpp:16
BarEvent make_bar_event(InstrumentId instrument, BarInterval interval, BarStamp stamp, Bar bar)
Makes a bar event, computing its period_end_ with bar_period_end.
Definition event.hpp:273
MarketPhase
Where the clock stands relative to the trading session.
Definition event.hpp:30
@ CLOSED
A date the market does not trade.
Definition event.hpp:34
@ PRE_OPEN
A trading day, before the session opens.
Definition event.hpp:36
@ UNKNOWN
The calendar does not cover this date; nothing is known about it.
Definition event.hpp:32
@ POST_CLOSE
A trading day, after the session closed.
Definition event.hpp:40
@ OPEN
Inside the session.
Definition event.hpp:38
constexpr std::array< MarketPhase, 5 > all_market_phases
Every MarketPhase, in declaration order.
Definition event.hpp:44
constexpr std::string_view market_phase_name(MarketPhase phase) noexcept
Returns a lowercase name for a phase, such as "pre_open", for logs and display.
Definition event.hpp:57
std::chrono::system_clock::time_point bar_period_end(const Bar &bar, BarInterval interval, BarStamp stamp)
Computes the instant a bar's period ended.
Definition event.hpp:232
constexpr bool market_phase_session_ended(MarketPhase phase) noexcept
Tests whether a phase means the day's session is over (or never opened), so a day order no longer wor...
Definition event.hpp:79
The library: broker-neutral types (core), and the modules below.
BarStamp
Which edge of its period a bar's timestamp marks.
@ CLOSE
The timestamp is the instant the period ended.
constexpr bool lists_every_value(const std::array< Enum, N > &values, IsEnumerator is_enumerator) noexcept
Tests whether a list holds every value of an enum exactly once, in any order.
Date date_from_epoch_days(std::int64_t days)
Converts a day count since 1970-01-01 to a Gregorian date.
Definition types.hpp:1186
BarInterval
The period one bar covers.
@ FIVE_MINUTES
Five minutes.
@ THIRTY_MINUTES
Thirty minutes.
@ FIFTEEN_MINUTES
Fifteen minutes.
OrderSide
The side of an order: its economic direction, buy or sell.
Definition types.hpp:1683
One bar: the prices and volume of one period, as exact decimals.
A calendar date with no time of day or time zone.
Definition types.hpp:1142
Identifies an instrument: its country, venue and symbol.
Definition types.hpp:78
A quote: the last traded price of an instrument at a point in time.
Definition types.hpp:870
One bar, delivered to on_bar.
Definition event.hpp:202
BarStamp stamp_
Whether bar_.timestamp_ marks the period's open or close.
Definition event.hpp:208
std::chrono::system_clock::time_point period_end_
When the bar's period ended: the earliest moment the bar could be known.
Definition event.hpp:218
InstrumentId instrument_
The instrument the bar is for.
Definition event.hpp:204
BarInterval interval_
The period length the bar covers.
Definition event.hpp:206
Every instrument's bar of one interval for one period end, delivered to on_bars.
Definition event.hpp:298
std::chrono::system_clock::time_point period_end_
When the period ended, shared by every bar in bars_.
Definition event.hpp:300
const BarEvent * find(const InstrumentId &id) const noexcept
Finds an instrument's bar.
Definition event.hpp:311
std::vector< BarEvent > bars_
The bars, one per instrument, in the order they were fed.
Definition event.hpp:304
BarInterval interval_
The period length every bar in bars_ covers.
Definition event.hpp:302
One execution of an order the strategy placed, delivered to on_fill.
Definition event.hpp:407
std::chrono::system_clock::time_point at_
When the execution happened.
Definition event.hpp:421
InstrumentId instrument_
The instrument traded.
Definition event.hpp:411
std::string tag_
The tag of the intent that produced the order.
Definition event.hpp:419
OrderSide side_
The side of the order.
Definition event.hpp:413
std::string order_id_
The broker's order id.
Definition event.hpp:409
Decimal64 price_
The execution price.
Definition event.hpp:417
Decimal64 quantity_
The quantity of this execution, not the order's running total.
Definition event.hpp:415
A quote the runner has just read, delivered to on_quote.
Definition event.hpp:390
QuoteSnapshot quote_
The quote, as the broker reported it.
Definition event.hpp:392
The intraday session of a market, as the operator states it.
Definition event.hpp:106
std::chrono::minutes open_
The session open, in minutes from local midnight.
Definition event.hpp:108
std::string source_
A description of where the window came from, for reports.
Definition event.hpp:114
std::chrono::minutes utc_offset_
The market's offset from UTC.
Definition event.hpp:112
MarketPhase phase(std::chrono::system_clock::time_point now, std::optional< bool > trading_day) const
Returns the market phase at an instant.
Definition event.hpp:131
std::chrono::system_clock::time_point opens_at(std::chrono::system_clock::time_point now) const
Returns the instant the session opens on the local date of an instant.
Definition event.hpp:175
std::chrono::minutes close_
The session close, in minutes from local midnight.
Definition event.hpp:110
Date local_date(std::chrono::system_clock::time_point now) const
Returns the market's local date at an instant.
Definition event.hpp:162
static SessionWindow krx()
Returns the KRX regular session, 09:00-15:30 KST.
Definition event.hpp:120