algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
types.hpp
1#pragma once
2
3#include <array>
4#include <chrono>
5#include <cstddef>
6#include <functional>
7#include <cstdint>
8#include <cstdio>
9#include <cstdlib>
10#include <ctime>
11#include <limits>
12#include <optional>
13#include <stdexcept>
14#include <string>
15#include <string_view>
16#include <utility>
17#include <variant>
18#include <vector>
19
20#include "./enum_values.hpp"
21
22namespace algotradelib {
23
30enum class Country {
31 KR,
32 US,
33};
34
36inline constexpr std::array<Country, 2> all_countries{Country::KR, Country::US};
37
43enum class Venue {
44 UNSPECIFIED,
45 KRX,
46 NXT,
47 COMBINED,
48};
49
51inline constexpr std::array<Venue, 4> all_venues{Venue::UNSPECIFIED, Venue::KRX, Venue::NXT, Venue::COMBINED};
52
58inline constexpr std::string_view venue_name(Venue venue) noexcept {
59 switch (venue) {
60 case Venue::UNSPECIFIED:
61 return "unspecified";
62 case Venue::KRX:
63 return "KRX";
64 case Venue::NXT:
65 return "NXT";
66 case Venue::COMBINED:
67 return "COMBINED";
68 }
69 return "";
70}
71
72static_assert(
73 lists_every_value(all_venues, [](Venue venue) { return !venue_name(venue).empty(); }),
74 "all_venues must list every Venue"
75);
76
80 Country country_{Country::KR};
86 Venue venue_{Venue::COMBINED};
88 std::string symbol_;
89
96 friend bool operator==(const InstrumentId& lhs, const InstrumentId& rhs) {
97 return lhs.country_ == rhs.country_ && lhs.venue_ == rhs.venue_ && lhs.symbol_ == rhs.symbol_;
98 }
99
109 friend bool operator<(const InstrumentId& lhs, const InstrumentId& rhs) {
110 if (lhs.country_ != rhs.country_) {
111 return lhs.country_ < rhs.country_;
112 }
113 if (lhs.venue_ != rhs.venue_) {
114 return lhs.venue_ < rhs.venue_;
115 }
116 return lhs.symbol_ < rhs.symbol_;
117 }
118};
119
130template <std::size_t N>
131class Code {
132public:
134 Code() = default;
135
142 explicit Code(std::string_view text) {
143 if (text.size() > N) {
144 throw std::invalid_argument("code is longer than its capacity");
145 }
146 for (std::size_t i = 0; i < text.size(); ++i) {
147 const char ch = text[i];
148 const bool valid = (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_';
149 if (!valid) {
150 throw std::invalid_argument("code must use uppercase ASCII, digits, or underscore");
151 }
152 characters_[i] = ch;
153 }
154 size_ = static_cast<std::uint8_t>(text.size());
155 }
156
163 static std::optional<Code> try_make(std::string_view text) {
164 if (text.size() > N) {
165 return std::nullopt;
166 }
167 Code code;
168 for (std::size_t i = 0; i < text.size(); ++i) {
169 const char ch = text[i];
170 const bool valid = (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_';
171 if (!valid) {
172 return std::nullopt;
173 }
174 code.characters_[i] = ch;
175 }
176 code.size_ = static_cast<std::uint8_t>(text.size());
177 return code;
178 }
179
184 std::string_view view() const noexcept {
185 return std::string_view(characters_.data(), size_);
186 }
187
192 std::string str() const { return std::string(view()); }
193
198 bool empty() const noexcept { return size_ == 0; }
199
204 std::size_t size() const noexcept { return size_; }
205
210 static constexpr std::size_t capacity() noexcept { return N; }
211
218 friend bool operator==(const Code& lhs, const Code& rhs) { return lhs.view() == rhs.view(); }
219
226 friend bool operator!=(const Code& lhs, const Code& rhs) { return !(lhs == rhs); }
227
228private:
229 std::array<char, N> characters_{};
230 std::uint8_t size_{0};
231};
232
234class Currency {
235public:
237 Currency() : code_{'K', 'R', 'W'} {}
238
245 explicit Currency(std::string_view code) {
246 if (code.size() != code_.size()) {
247 throw std::invalid_argument("currency code must contain three characters");
248 }
249 for (std::size_t i = 0; i < code_.size(); ++i) {
250 const char ch = code[i];
251 if (ch < 'A' || ch > 'Z') {
252 throw std::invalid_argument("currency code must use uppercase ASCII characters");
253 }
254 code_[i] = ch;
255 }
256 }
257
262 static Currency krw() { return Currency("KRW"); }
263
268 static Currency usd() { return Currency("USD"); }
269
274 std::string str() const { return std::string(code_.begin(), code_.end()); }
275
282 friend bool operator==(const Currency& lhs, const Currency& rhs) {
283 return lhs.code_ == rhs.code_;
284 }
285
286private:
287 std::array<char, 3> code_{};
288};
289
298public:
300 Decimal64() = default;
301
307 Decimal64(std::int64_t coefficient, std::uint8_t scale)
308 : coefficient_(coefficient), scale_(scale) {}
309
323 static Decimal64 parse(std::string_view input) {
324 if (input.empty()) {
325 throw std::invalid_argument("decimal value is empty");
326 }
327
328 bool negative = false;
329 std::size_t index = 0;
330 if (input.front() == '+' || input.front() == '-') {
331 negative = input.front() == '-';
332 index = 1;
333 }
334 if (index == input.size()) {
335 throw std::invalid_argument("decimal value has no digits");
336 }
337
338 std::uint64_t magnitude = 0;
339 std::uint8_t scale = 0;
340 bool decimal_point = false;
341 bool has_digit = false;
342 const std::uint64_t limit = negative ?
343 static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max()) + 1ULL :
344 static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max());
345
346 for (; index < input.size(); ++index) {
347 const char ch = input[index];
348 if (ch == '.') {
349 if (decimal_point) {
350 throw std::invalid_argument("decimal value contains multiple points");
351 }
352 decimal_point = true;
353 continue;
354 }
355 if (ch < '0' || ch > '9') {
356 throw std::invalid_argument("decimal value contains an invalid character");
357 }
358 has_digit = true;
359 const auto digit = static_cast<std::uint64_t>(ch - '0');
360 if (magnitude > (limit - digit) / 10ULL) {
361 throw std::out_of_range("decimal value exceeds Decimal64 range");
362 }
363 magnitude = magnitude * 10ULL + digit;
364 if (decimal_point) {
365 if (scale == std::numeric_limits<std::uint8_t>::max()) {
366 throw std::out_of_range("decimal scale exceeds Decimal64 range");
367 }
368 ++scale;
369 }
370 }
371 if (!has_digit) {
372 throw std::invalid_argument("decimal value has no digits");
373 }
374
375 while (scale > 0 && magnitude % 10ULL == 0) {
376 magnitude /= 10ULL;
377 --scale;
378 }
379
380 std::int64_t coefficient;
381 if (
382 negative &&
383 magnitude == static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max()) + 1ULL
384 ) {
385 coefficient = std::numeric_limits<std::int64_t>::min();
386 } else {
387 coefficient = static_cast<std::int64_t>(magnitude);
388 if (negative) {
390 }
391 }
392 return Decimal64(coefficient, scale);
393 }
394
399 std::int64_t coefficient() const noexcept { return coefficient_; }
400
405 std::uint8_t scale() const noexcept { return scale_; }
406
411 std::string str() const {
412 const bool negative = coefficient_ < 0;
413 std::uint64_t magnitude = negative ?
414 static_cast<std::uint64_t>(-(coefficient_ + 1)) + 1ULL :
415 static_cast<std::uint64_t>(coefficient_);
416 std::string digits = std::to_string(magnitude);
417 if (scale_ > 0) {
418 if (digits.size() <= scale_) {
419 digits.insert(0, static_cast<std::size_t>(scale_) - digits.size() + 1, '0');
420 }
421 digits.insert(digits.size() - scale_, 1, '.');
422 }
423 if (negative) {
424 digits.insert(digits.begin(), '-');
425 }
426 return digits;
427 }
428
441 friend bool operator==(const Decimal64& lhs, const Decimal64& rhs) {
442 return lhs.coefficient_ == rhs.coefficient_ && lhs.scale_ == rhs.scale_;
443 }
444
445private:
446 std::int64_t coefficient_{0};
447 std::uint8_t scale_{0};
448};
449
456 auto coefficient = value.coefficient();
457 auto scale = value.scale();
458 while (scale > 0 && coefficient % 10 == 0) {
459 coefficient /= 10;
460 --scale;
461 }
462 return Decimal64(coefficient, scale);
463}
464
465namespace decimal_detail {
466
473inline bool align(
474 const Decimal64& lhs,
475 const Decimal64& rhs,
476 std::int64_t& left,
477 std::int64_t& right,
478 std::uint8_t& scale
479) {
480 scale = lhs.scale() > rhs.scale() ? lhs.scale() : rhs.scale();
481 left = lhs.coefficient();
482 right = rhs.coefficient();
483 for (std::uint8_t step = lhs.scale(); step < scale; ++step) {
484 if (left > std::numeric_limits<std::int64_t>::max() / 10 ||
485 left < std::numeric_limits<std::int64_t>::min() / 10) {
486 return false;
487 }
488 left *= 10;
489 }
490 for (std::uint8_t step = rhs.scale(); step < scale; ++step) {
491 if (right > std::numeric_limits<std::int64_t>::max() / 10 ||
492 right < std::numeric_limits<std::int64_t>::min() / 10) {
493 return false;
494 }
495 right *= 10;
496 }
497 return true;
498}
499
500} // namespace decimal_detail
501
509inline std::optional<Decimal64> decimal_add(const Decimal64& lhs, const Decimal64& rhs) {
510 std::int64_t left = 0;
511 std::int64_t right = 0;
512 std::uint8_t scale = 0;
513 if (!decimal_detail::align(lhs, rhs, left, right, scale)) {
514 return std::nullopt;
515 }
516 if ((right > 0 && left > std::numeric_limits<std::int64_t>::max() - right) ||
517 (right < 0 && left < std::numeric_limits<std::int64_t>::min() - right)) {
518 return std::nullopt;
519 }
520 return decimal_normalized(Decimal64(left + right, scale));
521}
522
530inline std::optional<Decimal64> decimal_subtract(const Decimal64& lhs, const Decimal64& rhs) {
531 std::int64_t left = 0;
532 std::int64_t right = 0;
533 std::uint8_t scale = 0;
534 if (!decimal_detail::align(lhs, rhs, left, right, scale)) {
535 return std::nullopt;
536 }
537 if ((right < 0 && left > std::numeric_limits<std::int64_t>::max() + right) ||
538 (right > 0 && left < std::numeric_limits<std::int64_t>::min() + right)) {
539 return std::nullopt;
540 }
541 return decimal_normalized(Decimal64(left - right, scale));
542}
543
549inline std::optional<Decimal64> decimal_halve(const Decimal64& value) {
550 const auto coefficient = value.coefficient();
551 if (coefficient % 2 == 0) {
552 return decimal_normalized(Decimal64(coefficient / 2, value.scale()));
553 }
554 if (value.scale() == std::numeric_limits<std::uint8_t>::max() ||
555 coefficient > std::numeric_limits<std::int64_t>::max() / 5 ||
556 coefficient < std::numeric_limits<std::int64_t>::min() / 5) {
557 return std::nullopt;
558 }
559 return decimal_normalized(
560 Decimal64(coefficient * 5, static_cast<std::uint8_t>(value.scale() + 1))
561 );
562}
563
571inline std::optional<Decimal64> decimal_multiply(const Decimal64& lhs, const Decimal64& rhs) {
572 const auto left = lhs.coefficient();
573 const auto right = rhs.coefficient();
574 const int scale = static_cast<int>(lhs.scale()) + static_cast<int>(rhs.scale());
575 if (scale > std::numeric_limits<std::uint8_t>::max()) {
576 return std::nullopt;
577 }
578 if (left != 0 && right != 0) {
579 // Checked before multiplying rather than after, because signed overflow is undefined and a
580 // wrapped price is exactly the failure this type exists to prevent.
581 if (left > 0 ? (right > 0 ? left > std::numeric_limits<std::int64_t>::max() / right
582 : right < std::numeric_limits<std::int64_t>::min() / left)
583 : (right > 0 ? left < std::numeric_limits<std::int64_t>::min() / right
584 : left < std::numeric_limits<std::int64_t>::max() / right)) {
585 return std::nullopt;
586 }
587 }
588 return decimal_normalized(Decimal64(left * right, static_cast<std::uint8_t>(scale)));
589}
590
602inline std::optional<Decimal64> decimal_divide(
603 const Decimal64& lhs,
604 const Decimal64& rhs,
605 std::uint8_t scale
606) {
607 std::int64_t left = 0;
608 std::int64_t right = 0;
609 std::uint8_t common = 0;
610 if (!decimal_detail::align(lhs, rhs, left, right, common) || right == 0) {
611 return std::nullopt;
612 }
613 // Aligning cancels the scales, so `left / right` is the plain ratio. Each requested decimal
614 // place is one more factor of ten taken before the division.
615 for (std::uint8_t step = 0; step < scale; ++step) {
616 if (left > std::numeric_limits<std::int64_t>::max() / 10 ||
617 left < std::numeric_limits<std::int64_t>::min() / 10) {
618 return std::nullopt;
619 }
620 left *= 10;
621 }
622 if (left == std::numeric_limits<std::int64_t>::min() && right == -1) {
623 return std::nullopt;
624 }
625 return decimal_normalized(Decimal64(left / right, scale));
626}
627
639inline std::optional<Decimal64> decimal_floor_to_multiple(
640 const Decimal64& value,
641 const Decimal64& step
642) {
643 std::int64_t left = 0;
644 std::int64_t right = 0;
645 std::uint8_t scale = 0;
646 if (!decimal_detail::align(value, step, left, right, scale) || right <= 0) {
647 return std::nullopt;
648 }
649 auto rest = left % right;
650 if (rest < 0) {
651 rest += right;
652 }
653 if (left < std::numeric_limits<std::int64_t>::min() + rest) {
654 return std::nullopt;
655 }
656 return decimal_normalized(Decimal64(left - rest, scale));
657}
658
665inline bool decimal_less(const Decimal64& lhs, const Decimal64& rhs) {
666 std::int64_t left = 0;
667 std::int64_t right = 0;
668 std::uint8_t scale = 0;
669 if (decimal_detail::align(lhs, rhs, left, right, scale)) {
670 return left < right;
671 }
672 // Rescaling overflowed, so the values differ by more than any shared scale can
673 // express: the one with the smaller scale has the larger magnitude. Between two
674 // negatives the larger magnitude is the smaller value.
675 const bool left_negative = lhs.coefficient() < 0;
676 if (left_negative != (rhs.coefficient() < 0)) {
677 return left_negative;
678 }
679 return left_negative ? lhs.scale() < rhs.scale() : lhs.scale() > rhs.scale();
680}
681
715
722inline constexpr bool error_category_is_rate_limit(ErrorCategory category) noexcept {
723 switch (category) {
725 return true;
732 return false;
733 }
734 return false;
735}
736
753 bool reached_broker_{true};
761 std::string broker_code_;
763 std::string request_id_;
772 std::string message_;
779 std::optional<std::chrono::seconds> retry_after_;
785 std::optional<int> rate_limit_;
786};
787
796template <typename T>
797class Result {
798public:
803 Result(T value) : value_(std::move(value)) {}
804
809 Result(BrokerError error) : value_(std::move(error)) {}
810
815 bool has_value() const noexcept { return std::holds_alternative<T>(value_); }
816
821 explicit operator bool() const noexcept { return has_value(); }
822
828 T& value() { return std::get<T>(value_); }
829
835 const T& value() const { return std::get<T>(value_); }
836
842 BrokerError& error() { return std::get<BrokerError>(value_); }
843
849 const BrokerError& error() const { return std::get<BrokerError>(value_); }
850
851private:
852 std::variant<T, BrokerError> value_;
853};
854
858struct TopOfBook {
860 std::optional<Decimal64> bid_price_;
862 std::optional<Decimal64> bid_quantity_;
864 std::optional<Decimal64> ask_price_;
866 std::optional<Decimal64> ask_quantity_;
867};
868
878 std::optional<std::chrono::system_clock::time_point> exchange_time_;
880 std::chrono::system_clock::time_point received_at_;
881
889 std::optional<TopOfBook> top_of_book_;
891 std::optional<Decimal64> volume_;
892};
893
895struct Money {
900
907 friend bool operator==(const Money& lhs, const Money& rhs) {
908 return lhs.amount_ == rhs.amount_ && lhs.currency_ == rhs.currency_;
909 }
910};
911
920 enum class Coverage {
922 UNESTABLISHED,
924 WHOLE_HOLDING,
929 PARTIAL,
930 };
931
933 enum class RestingTreatment {
935 UNESTABLISHED,
942 DEDUCT,
943 };
944
954 bool verified_ = false;
955
960 constexpr bool is_enforceable() const noexcept {
961 bool covers = false;
962 switch (coverage_) {
964 covers = true;
965 break;
968 break;
969 }
970 bool treated = false;
971 switch (resting_) {
973 treated = true;
974 break;
976 break;
977 }
978 return covers && treated;
979 }
980};
981
987inline constexpr std::string_view sellable_coverage_name(SellableBasis::Coverage coverage
988) noexcept {
989 switch (coverage) {
991 return "unestablished";
993 return "whole_holding";
995 return "partial";
996 }
997 return "unestablished";
998}
999
1005inline constexpr std::string_view sellable_resting_name(SellableBasis::RestingTreatment treatment
1006) noexcept {
1007 switch (treatment) {
1009 return "unestablished";
1011 return "deduct";
1012 }
1013 return "unestablished";
1014}
1015
1055
1072
1073
1077 std::vector<HoldingPosition> positions_;
1079 std::vector<HoldingsTotals> totals_;
1081 std::chrono::system_clock::time_point received_at_;
1089};
1090
1100
1106inline constexpr std::string_view sellable_source_name(SellableSource source) noexcept {
1107 switch (source) {
1109 return "holdings";
1111 return "inquiry";
1113 return "none";
1114 }
1115 return "none";
1116}
1117
1134 std::chrono::system_clock::time_point received_at_{};
1135};
1136
1142struct Date {
1144 int year_{0};
1146 unsigned month_{0};
1148 unsigned day_{0};
1149
1156 friend bool operator==(const Date& lhs, const Date& rhs) {
1157 return lhs.year_ == rhs.year_ && lhs.month_ == rhs.month_ && lhs.day_ == rhs.day_;
1158 }
1159
1166 friend bool operator<(const Date& lhs, const Date& rhs) {
1167 if (lhs.year_ != rhs.year_) {
1168 return lhs.year_ < rhs.year_;
1169 }
1170 if (lhs.month_ != rhs.month_) {
1171 return lhs.month_ < rhs.month_;
1172 }
1173 return lhs.day_ < rhs.day_;
1174 }
1175};
1176
1186inline Date date_from_epoch_days(std::int64_t days) {
1187 // Shifts the era so that the year starts in March, which is what removes the leap-day special
1188 // case from everything below: 1970-01-01 is 719468 days after 0000-03-01.
1189 const std::int64_t shifted = days + 719468;
1190 const std::int64_t era = (shifted >= 0 ? shifted : shifted - 146096) / 146097;
1191 const std::int64_t day_of_era = shifted - era * 146097;
1192 const std::int64_t year_of_era =
1193 (day_of_era - day_of_era / 1460 + day_of_era / 36524 - day_of_era / 146096) / 365;
1194 const std::int64_t year = year_of_era + era * 400;
1195 const std::int64_t day_of_year =
1196 day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100);
1197 const std::int64_t shifted_month = (5 * day_of_year + 2) / 153;
1198 const std::int64_t day = day_of_year - (153 * shifted_month + 2) / 5 + 1;
1199 const std::int64_t month = shifted_month + (shifted_month < 10 ? 3 : -9);
1200 return Date{
1201 static_cast<int>(year + (month <= 2 ? 1 : 0)),
1202 static_cast<unsigned>(month),
1203 static_cast<unsigned>(day),
1204 };
1205}
1206
1212inline bool is_valid_date(const Date& date) {
1213 if (date.year_ < 1 || date.year_ > 9999 || date.month_ < 1 || date.month_ > 12) {
1214 return false;
1215 }
1216 static constexpr unsigned days_per_month[] = {
1217 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
1218 };
1219 unsigned days = days_per_month[date.month_ - 1];
1220 const bool leap = date.year_ % 4 == 0 && (date.year_ % 100 != 0 || date.year_ % 400 == 0);
1221 if (date.month_ == 2 && leap) {
1222 ++days;
1223 }
1224 return date.day_ >= 1 && date.day_ <= days;
1225}
1226
1236
1245public:
1247 VenueKey() = default;
1248
1253 static VenueKey any() noexcept { return VenueKey(); }
1254
1260 static std::optional<VenueKey> normalized(Venue venue) {
1261 if (venue == Venue::UNSPECIFIED) {
1262 return std::nullopt;
1263 }
1264 VenueKey key;
1265 key.kind_ = VenueKeyKind::NORMALIZED;
1266 key.venue_ = venue;
1267 return key;
1268 }
1269
1275 static std::optional<VenueKey> raw(std::string_view code) {
1276 auto stored = Code<8>::try_make(code);
1277 if (!stored || stored->empty()) {
1278 return std::nullopt;
1279 }
1280 VenueKey key;
1281 key.kind_ = VenueKeyKind::RAW;
1282 key.raw_ = *stored;
1283 return key;
1284 }
1285
1290 VenueKeyKind kind() const noexcept { return kind_; }
1291
1296 bool is_any() const noexcept { return kind_ == VenueKeyKind::ANY; }
1297
1302 Venue venue() const noexcept { return venue_; }
1303
1308 const Code<8>& raw_code() const noexcept { return raw_; }
1309
1319 bool matches(const VenueKey& asserted) const noexcept {
1320 if (kind_ != asserted.kind_) {
1321 return false;
1322 }
1323 switch (kind_) {
1324 case VenueKeyKind::ANY:
1325 return true;
1327 return venue_ == asserted.venue_;
1328 case VenueKeyKind::RAW:
1329 return raw_ == asserted.raw_;
1330 }
1331 return false;
1332 }
1333
1340 friend bool operator==(const VenueKey& lhs, const VenueKey& rhs) noexcept { return lhs.matches(rhs); }
1341
1348 friend bool operator!=(const VenueKey& lhs, const VenueKey& rhs) noexcept { return !(lhs == rhs); }
1349
1350private:
1352 Venue venue_{Venue::UNSPECIFIED};
1353 Code<8> raw_;
1354};
1355
1361inline constexpr std::string_view venue_key_kind_name(VenueKeyKind kind) noexcept {
1362 switch (kind) {
1363 case VenueKeyKind::ANY:
1364 return "any";
1366 return "normalized";
1367 case VenueKeyKind::RAW:
1368 return "raw";
1369 }
1370 return "unknown";
1371}
1372
1380
1386inline constexpr bool commission_origin_is_broker(CommissionOrigin origin) noexcept {
1387 switch (origin) {
1389 return true;
1391 return false;
1392 }
1393 return false;
1394}
1395
1401inline constexpr bool commission_origin_names_tariff(CommissionOrigin origin) noexcept {
1402 switch (origin) {
1404 return true;
1406 return false;
1407 }
1408 return true;
1409}
1410
1416inline constexpr std::string_view commission_origin_name(CommissionOrigin origin) noexcept {
1417 switch (origin) {
1419 return "broker_published";
1421 return "caller_stated";
1422 }
1423 return "unknown";
1424}
1425
1439
1451 Country country_{Country::KR};
1475 std::optional<Decimal64> institution_rate_;
1479 std::optional<Date> from_;
1481 std::optional<Date> until_;
1488 bool from_unreadable_{false};
1496
1501 bool normalized() const noexcept { return other_.empty(); }
1502
1510 RateApplicability applies_on(const Date& date) const {
1511 if (excluded_on(date)) {
1512 return RateApplicability::NO;
1513 }
1516 }
1518 }
1519
1525 bool excluded_on(const Date& date) const {
1526 return (from_ && date < *from_) || (until_ && *until_ < date);
1527 }
1528};
1529
1537 std::vector<CommissionRate> rates_;
1539 std::chrono::system_clock::time_point received_at_{};
1549 std::string tariff_;
1550
1556 std::size_t dropped_{0};
1557
1564 std::size_t unreadable_bounds_{0};
1565
1569 std::optional<CommissionRate> rate_;
1577 };
1578
1593 Country country,
1594 const VenueKey& asserted,
1595 const Date& date
1596 ) const {
1597 // A row for a market this library does not normalize can never be the answer to a question asked
1598 // in terms of `Country`, and it is kept so a caller can see that the broker sent it.
1599 const auto in_market = [&](const CommissionRate& rate) {
1600 return rate.normalized() && rate.country_ == country;
1601 };
1602 // **Each pass stops at the first row that decides it, and an unreadable row decides it too.**
1603 // Within a pass the first match has always won, so a damaged row *after* a definite match could
1604 // never have been the answer and is not a reason to refuse -- scanning the whole pass first would
1605 // throw away an answer this library knows. A damaged row reached *before* any match is the
1606 // opposite case: it may have been the match, so nothing later in the pass can be trusted to be
1607 // the winner.
1608 const auto pass = [&](bool venue_specific) -> std::optional<RateSelection> {
1609 for (const auto& rate : rates_) {
1610 if (!in_market(rate)) {
1611 continue;
1612 }
1613 if (!(venue_specific ? rate.venue_.matches(asserted) : rate.venue_.is_any())) {
1614 continue;
1615 }
1616 switch (rate.applies_on(date)) {
1618 continue;
1620 RateSelection found;
1621 found.rate_ = rate;
1622 return found;
1623 }
1625 RateSelection refused;
1626 refused.bounds_unreadable_ = true;
1627 return refused;
1628 }
1629 }
1630 }
1631 return std::nullopt;
1632 };
1633 // An undecided pass one falls through; a *refused* pass one does not. Pass two's precondition is
1634 // "no row for the asserted venue applies", and that is precisely what stopped being known.
1635 if (const auto venue_row = pass(true)) {
1636 return *venue_row;
1637 }
1638 if (const auto neutral_row = pass(false)) {
1639 return *neutral_row;
1640 }
1641 return RateSelection{};
1642 }
1643
1649 bool any_dated_rate_for(Country country) const {
1650 for (const auto& rate : rates_) {
1651 // A bound that could not be read is still a bound the source stated. Asking only whether the
1652 // optionals are filled would read a row dated *solely* by damage as undated, and hand the
1653 // caller the very "every candidate is the same whichever calendar named the day" assurance
1654 // that the damage makes impossible.
1655 const bool dated = rate.from_ || rate.until_ || rate.from_unreadable_ || rate.until_unreadable_;
1656 if (rate.normalized() && rate.country_ == country && dated) {
1657 return true;
1658 }
1659 }
1660 return false;
1661 }
1662
1672 RateSelection rate_for(Country country, const Date& date) const {
1673 return rate_for(country, VenueKey::any(), date);
1674 }
1675};
1676
1683enum class OrderSide {
1684 BUY,
1685 SELL,
1686};
1687
1689inline constexpr std::array<OrderSide, 2> all_order_sides{OrderSide::BUY, OrderSide::SELL};
1690
1691// The direction is closed: about forty sites in the ledger, fills, costs, risk and reconciliation read
1692// "not BUY" as SELL. A short-sale or short-exempt mark, or a cover-only constraint, is a separate fact that
1693// would travel in its own field through the intent, the request, the journal and recovery.
1694static_assert(
1695 all_order_sides.size() == 2,
1696 "OrderSide is buy or sell: a short-sale mark or a cover belongs in its own field, not in OrderSide"
1697);
1698
1726
1728inline constexpr std::array<OrderType, 9> all_order_types{
1729 OrderType::UNKNOWN,
1738};
1739
1748inline constexpr bool carries_caller_price(OrderType type) noexcept {
1749 switch (type) {
1750 case OrderType::LIMIT:
1753 return true;
1754 case OrderType::UNKNOWN:
1755 case OrderType::MARKET:
1760 return false;
1761 }
1762 return false;
1763}
1764
1774inline constexpr bool carries_trigger_price(OrderType type) noexcept {
1775 switch (type) {
1777 return true;
1778 case OrderType::UNKNOWN:
1779 case OrderType::LIMIT:
1780 case OrderType::MARKET:
1786 return false;
1787 }
1788 return false;
1789}
1790
1806
1808inline constexpr std::array<TimeInForce, 4> all_times_in_force{
1809 TimeInForce::UNKNOWN,
1813};
1814
1822inline constexpr bool time_in_force_expires_at_close(TimeInForce condition) noexcept {
1823 switch (condition) {
1824 case TimeInForce::DAY:
1825 return true;
1826 case TimeInForce::UNKNOWN:
1829 return false;
1830 }
1831 return false;
1832}
1833
1858
1871
1879enum class OrderStatus {
1880 UNKNOWN,
1881 PENDING,
1882 PENDING_CANCEL,
1883 PENDING_REPLACE,
1884 PARTIAL_FILLED,
1885 FILLED,
1886 CANCELED,
1887 REJECTED,
1888 CANCEL_REJECTED,
1889 REPLACE_REJECTED,
1890 REPLACED,
1891};
1892
1899inline constexpr bool order_status_cancel_pending(OrderStatus status) noexcept {
1900 switch (status) {
1901 case OrderStatus::PENDING_CANCEL:
1902 return true;
1903 case OrderStatus::UNKNOWN:
1904 case OrderStatus::PENDING:
1905 case OrderStatus::PENDING_REPLACE:
1906 case OrderStatus::PARTIAL_FILLED:
1907 case OrderStatus::FILLED:
1908 case OrderStatus::CANCELED:
1909 case OrderStatus::REJECTED:
1910 case OrderStatus::CANCEL_REJECTED:
1911 case OrderStatus::REPLACE_REJECTED:
1912 case OrderStatus::REPLACED:
1913 return false;
1914 }
1915 return false;
1916}
1917
1970
1990 std::optional<Decimal64> average_filled_price_;
1996 std::optional<Money> filled_amount_;
1998 std::optional<Money> commission_;
2000 std::optional<Money> tax_;
2002 std::optional<std::chrono::system_clock::time_point> filled_at_;
2004 std::optional<Date> settlement_date_;
2005};
2006
2010 std::string order_id_;
2014 std::string name_;
2016 OrderSide side_{OrderSide::BUY};
2018 OrderType type_{OrderType::UNKNOWN};
2020 TimeInForce time_in_force_{TimeInForce::UNKNOWN};
2022 OrderSession session_{OrderSession::UNKNOWN};
2029 Venue venue_{Venue::UNSPECIFIED};
2038 OrderStatus status_{OrderStatus::UNKNOWN};
2040 std::optional<Decimal64> price_;
2048 std::optional<Decimal64> trigger_price_;
2058 std::optional<Decimal64> order_amount_;
2065 std::optional<std::chrono::system_clock::time_point> ordered_at_;
2072 std::optional<std::chrono::system_clock::time_point> canceled_at_;
2075};
2076
2080 std::vector<OrderSnapshot> orders_;
2082 std::optional<std::string> next_cursor_;
2084 std::chrono::system_clock::time_point received_at_;
2085};
2086
2092struct OrderAck {
2094 std::string order_id_;
2096 std::optional<std::string> client_order_id_;
2098 std::chrono::system_clock::time_point accepted_at_;
2099};
2100
2110template <typename Broker>
2111struct OrderRef {
2113 std::string primary_;
2115 std::string secondary_;
2116
2121 static constexpr std::string_view broker() noexcept { return Broker::name; }
2122
2127 std::string str() const {
2128 std::string text(broker());
2129 text += ':';
2130 text += primary_;
2131 if (!secondary_.empty()) {
2132 text += ':';
2133 text += secondary_;
2134 }
2135 return text;
2136 }
2137
2144 friend bool operator==(const OrderRef& lhs, const OrderRef& rhs) {
2145 return lhs.primary_ == rhs.primary_ && lhs.secondary_ == rhs.secondary_;
2146 }
2147
2154 friend bool operator!=(const OrderRef& lhs, const OrderRef& rhs) { return !(lhs == rhs); }
2155};
2156
2164template <typename Broker>
2171
2181 OrderShape() = default;
2192 OrderType type,
2193 std::optional<Decimal64> price,
2194 std::optional<TimeInForce> time_in_force = std::nullopt,
2195 std::optional<OrderSession> session = std::nullopt,
2196 std::optional<Decimal64> trigger_price = std::nullopt
2197 )
2198 : type_(type),
2199 price_(std::move(price)),
2200 trigger_price_(std::move(trigger_price)),
2201 time_in_force_(time_in_force),
2202 session_(session) {}
2203
2207 std::optional<Decimal64> price_;
2216 std::optional<Decimal64> trigger_price_;
2223 std::optional<TimeInForce> time_in_force_;
2230 std::optional<OrderSession> session_;
2231};
2232
2248 Venue venue_{Venue::UNSPECIFIED};
2250 std::optional<Decimal64> quantity_;
2252 bool all_remaining_{false};
2261 std::optional<OrderShape> resting_;
2262};
2263
2271inline std::optional<Decimal64> amended_trigger_price(const AmendInstruction& instruction) {
2272 if (instruction.shape_.trigger_price_) {
2273 return instruction.shape_.trigger_price_;
2274 }
2275 if (
2276 carries_trigger_price(instruction.shape_.type_) && instruction.resting_ &&
2277 carries_trigger_price(instruction.resting_->type_)
2278 ) {
2279 return instruction.resting_->trigger_price_;
2280 }
2281 return std::nullopt;
2282}
2283
2289template <typename Broker>
2306
2311template <typename Broker>
2314 std::vector<WorkingOrder<Broker>> orders_;
2316 std::chrono::system_clock::time_point received_at_;
2317};
2318
2327 std::optional<Date> from_;
2329 std::optional<Date> to_;
2331 std::optional<std::string> symbol_;
2333 std::optional<std::string> cursor_;
2335 std::optional<int> limit_;
2336};
2337
2344template <typename Broker>
2346 OrderShape shape;
2347 shape.type_ = order.order_.type_;
2348 shape.price_ = order.order_.price_;
2349 shape.trigger_price_ = order.order_.trigger_price_;
2350 shape.time_in_force_ = order.order_.time_in_force_;
2351 shape.session_ = order.order_.session_;
2352 return shape;
2353}
2354
2361template <typename Broker>
2363 AmendInstruction instruction;
2364 // A cancellation copies the whole shape, so a broker that re-reads it sees the same order.
2365 instruction.shape_.type_ = order.order_.type_;
2366 instruction.shape_.time_in_force_ = order.order_.time_in_force_;
2367 instruction.shape_.session_ = order.order_.session_;
2368 instruction.shape_.price_ = order.order_.price_;
2369 instruction.shape_.trigger_price_ = order.order_.trigger_price_;
2370 instruction.resting_ = instruction.shape_;
2371 instruction.venue_ = order.order_.venue_;
2372 instruction.quantity_ = order.amendable_quantity_;
2373 instruction.all_remaining_ = true;
2374 return instruction;
2375}
2376
2384template <typename Broker>
2386 AmendInstruction instruction;
2387 instruction.shape_.type_ = order.order_.type_;
2388 instruction.shape_.time_in_force_ = order.order_.time_in_force_;
2389 instruction.shape_.session_ = order.order_.session_;
2390 instruction.shape_.price_ = order.order_.price_;
2391 instruction.shape_.trigger_price_ = order.order_.trigger_price_;
2392 instruction.resting_ = instruction.shape_;
2393 instruction.venue_ = order.order_.venue_;
2394 instruction.quantity_ = quantity;
2395 instruction.all_remaining_ = false;
2396 return instruction;
2397}
2398
2413template <typename Broker>
2415 const WorkingOrder<Broker>& order,
2416 OrderShape shape,
2417 std::optional<Decimal64> quantity = std::nullopt
2418) {
2419 AmendInstruction instruction;
2420 instruction.shape_ = std::move(shape);
2421 instruction.resting_ = resting_shape(order);
2422 // The caller's shape is kept as written; `resting_` lets each adapter tell a change from a keep.
2423 instruction.venue_ = order.order_.venue_;
2424 instruction.all_remaining_ = !quantity.has_value();
2425 instruction.quantity_ = quantity ? quantity : order.amendable_quantity_;
2426 return instruction;
2427}
2428
2437template <typename Broker>
2439 const WorkingOrder<Broker>& order,
2440 Decimal64 price,
2441 std::optional<Decimal64> quantity = std::nullopt
2442) {
2443 auto shape = resting_shape(order);
2444 shape.price_ = std::move(price);
2445 return replace_with(order, std::move(shape), std::move(quantity));
2446}
2447
2453inline std::string format_iso8601_utc(std::chrono::system_clock::time_point value) {
2454 const auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(value);
2455 const std::time_t raw = std::chrono::system_clock::to_time_t(seconds);
2456 std::tm utc{};
2457#ifdef _WIN32
2458 gmtime_s(&utc, &raw);
2459#else
2460 gmtime_r(&raw, &utc);
2461#endif
2462 char buffer[32];
2463 const auto written = std::strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", &utc);
2464 return std::string(buffer, written);
2465}
2466
2478inline std::optional<std::chrono::system_clock::time_point> parse_iso8601_timestamp(
2479 std::string_view value
2480) {
2481 // The fixed layout first: `sscanf`'s `%d` would accept signs, spaces and short fields.
2482 const auto digits = [value](std::size_t from, std::size_t count) {
2483 for (std::size_t index = from; index < from + count; ++index) {
2484 if (value[index] < '0' || value[index] > '9') {
2485 return false;
2486 }
2487 }
2488 return true;
2489 };
2490 if (value.size() < 20 || !digits(0, 4) || value[4] != '-' || !digits(5, 2) || value[7] != '-' ||
2491 !digits(8, 2) || value[10] != 'T' || !digits(11, 2) || value[13] != ':' || !digits(14, 2) ||
2492 value[16] != ':' || !digits(17, 2)) {
2493 return std::nullopt;
2494 }
2495 int year, month, day, hour, minute, second;
2496 if (
2497 std::sscanf(
2498 std::string(value).c_str(), "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, &second
2499 ) != 6
2500 ) {
2501 return std::nullopt;
2502 }
2503 if (!is_valid_date(Date{year, static_cast<unsigned>(month), static_cast<unsigned>(day)}) ||
2504 hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 60) {
2505 return std::nullopt;
2506 }
2507
2508 // An optional fraction of digits only, then the zone, then nothing.
2509 std::size_t timezone_position = 19;
2510 if (value[19] == '.') {
2511 timezone_position = 20;
2512 while (timezone_position < value.size() && value[timezone_position] >= '0' &&
2513 value[timezone_position] <= '9') {
2514 ++timezone_position;
2515 }
2516 if (timezone_position == 20) {
2517 return std::nullopt;
2518 }
2519 }
2520 if (timezone_position >= value.size()) {
2521 return std::nullopt;
2522 }
2523 const char zone = value[timezone_position];
2524 if (zone == 'Z') {
2525 if (timezone_position + 1 != value.size()) {
2526 return std::nullopt;
2527 }
2528 } else if (zone == '+' || zone == '-') {
2529 if (value.size() != timezone_position + 6 || !digits(timezone_position + 1, 2) ||
2530 value[timezone_position + 3] != ':' || !digits(timezone_position + 4, 2)) {
2531 return std::nullopt;
2532 }
2533 } else {
2534 return std::nullopt;
2535 }
2536
2537 std::tm time{};
2538 time.tm_year = year - 1900;
2539 time.tm_mon = month - 1;
2540 time.tm_mday = day;
2541 time.tm_hour = hour;
2542 time.tm_min = minute;
2543 time.tm_sec = second;
2544 time.tm_isdst = 0;
2545#ifdef _WIN32
2546 std::time_t utc = _mkgmtime(&time);
2547#else
2548 std::time_t utc = timegm(&time);
2549#endif
2550 if (utc == static_cast<std::time_t>(-1)) {
2551 return std::nullopt;
2552 }
2553
2554 if (value[timezone_position] != 'Z') {
2555 int offset_hour, offset_minute;
2556 if (
2557 std::sscanf(
2558 std::string(value.substr(timezone_position + 1)).c_str(),
2559 "%d:%d",
2560 &offset_hour,
2561 &offset_minute
2562 ) != 2
2563 ) {
2564 return std::nullopt;
2565 }
2566 if (offset_hour > 23 || offset_minute > 59) {
2567 return std::nullopt;
2568 }
2569 const int offset = offset_hour * 3600 + offset_minute * 60;
2570 utc += value[timezone_position] == '+' ? -offset : offset;
2571 }
2572
2573 auto result = std::chrono::system_clock::from_time_t(utc);
2574 const auto dot = value.find('.', 19);
2575 if (dot != std::string_view::npos && dot < timezone_position) {
2576 std::uint32_t milliseconds = 0;
2577 std::uint32_t factor = 100;
2578 for (std::size_t index = dot + 1; index < timezone_position && factor > 0; ++index) {
2579 if (value[index] < '0' || value[index] > '9') {
2580 return std::nullopt;
2581 }
2582 milliseconds += static_cast<std::uint32_t>(value[index] - '0') * factor;
2583 factor /= 10;
2584 }
2585 result += std::chrono::milliseconds(milliseconds);
2586 }
2587 return result;
2588}
2589
2590} // namespace algotradelib
2591
2592namespace std {
2593
2598template <typename Broker>
2599struct hash<algotradelib::OrderRef<Broker>> {
2605 std::size_t operator()(const algotradelib::OrderRef<Broker>& ref) const noexcept {
2606 std::size_t seed = hash<std::string>{}(ref.primary_);
2607 seed ^= hash<std::string>{}(ref.secondary_) + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);
2608 return seed;
2609 }
2610};
2611
2612} // namespace std
A short uppercase code (letters, digits, _), stored inline without allocation.
Definition types.hpp:131
bool empty() const noexcept
Tests whether the code is empty.
Definition types.hpp:198
friend bool operator!=(const Code &lhs, const Code &rhs)
Compares two codes for inequality.
Definition types.hpp:226
Code()=default
Constructs an empty code.
static std::optional< Code > try_make(std::string_view text)
Makes a code without throwing.
Definition types.hpp:163
friend bool operator==(const Code &lhs, const Code &rhs)
Compares two codes' characters.
Definition types.hpp:218
std::size_t size() const noexcept
Returns the number of characters.
Definition types.hpp:204
static constexpr std::size_t capacity() noexcept
Returns the maximum number of characters.
Definition types.hpp:210
std::string str() const
Returns the code as a string.
Definition types.hpp:192
Code(std::string_view text)
Constructs a code.
Definition types.hpp:142
std::string_view view() const noexcept
Returns the code's characters.
Definition types.hpp:184
A three-letter currency code, such as KRW or USD (ISO 4217 style).
Definition types.hpp:234
static Currency usd()
Returns United States dollars.
Definition types.hpp:268
Currency()
Constructs Korean won.
Definition types.hpp:237
static Currency krw()
Returns Korean won.
Definition types.hpp:262
friend bool operator==(const Currency &lhs, const Currency &rhs)
Compares two currencies.
Definition types.hpp:282
Currency(std::string_view code)
Constructs a currency from its code.
Definition types.hpp:245
std::string str() const
Returns the code.
Definition types.hpp:274
An exact signed decimal: an int64 coefficient times 10^-scale.
Definition types.hpp:297
std::uint8_t scale() const noexcept
Returns the scale.
Definition types.hpp:405
friend bool operator==(const Decimal64 &lhs, const Decimal64 &rhs)
Compares the coefficient and the scale.
Definition types.hpp:441
std::int64_t coefficient() const noexcept
Returns the coefficient.
Definition types.hpp:399
Decimal64(std::int64_t coefficient, std::uint8_t scale)
Constructs coefficient * 10^-scale, keeping the scale as given.
Definition types.hpp:307
std::string str() const
Formats the value as a decimal string.
Definition types.hpp:411
Decimal64()=default
Constructs zero.
static Decimal64 parse(std::string_view input)
Parses a decimal string exactly (no binary floating point).
Definition types.hpp:323
Result(T value)
Constructs a successful result.
Definition types.hpp:803
const BrokerError & error() const
Returns the error.
Definition types.hpp:849
BrokerError & error()
Returns the error.
Definition types.hpp:842
const T & value() const
Returns the value.
Definition types.hpp:835
bool has_value() const noexcept
Tests whether the result holds a value.
Definition types.hpp:815
T & value()
Returns the value.
Definition types.hpp:828
Result(BrokerError error)
Constructs a failed result.
Definition types.hpp:809
Which venue a commission rate applies to: any venue, a normalized Venue, or a raw code.
Definition types.hpp:1244
friend bool operator!=(const VenueKey &lhs, const VenueKey &rhs) noexcept
Compares two keys for inequality.
Definition types.hpp:1348
static VenueKey any() noexcept
Returns the key for any venue.
Definition types.hpp:1253
bool matches(const VenueKey &asserted) const noexcept
Tests whether two keys name the same venue, exactly in kind and value.
Definition types.hpp:1319
static std::optional< VenueKey > raw(std::string_view code)
Makes a key for a venue code the library does not normalize.
Definition types.hpp:1275
friend bool operator==(const VenueKey &lhs, const VenueKey &rhs) noexcept
Compares kind and value; same as matches.
Definition types.hpp:1340
static std::optional< VenueKey > normalized(Venue venue)
Makes a key for a normalized venue.
Definition types.hpp:1260
bool is_any() const noexcept
Tests whether the key is for any venue.
Definition types.hpp:1296
const Code< 8 > & raw_code() const noexcept
Returns the raw venue code.
Definition types.hpp:1308
VenueKey()=default
Constructs the key for any venue.
VenueKeyKind kind() const noexcept
Returns the key's kind.
Definition types.hpp:1290
Venue venue() const noexcept
Returns the normalized venue.
Definition types.hpp:1302
A compile-time check that a list names every value of an enum, and a parser over the list.
The library: broker-neutral types (core), and the modules below.
OrderStatus
Where an order stands in its lifecycle.
Definition types.hpp:1879
std::optional< Decimal64 > decimal_floor_to_multiple(const Decimal64 &value, const Decimal64 &step)
Rounds down to a multiple of a step (toward negative infinity).
Definition types.hpp:639
SellableSource
Where the library gets a broker's sellable quantity.
Definition types.hpp:1092
@ HOLDINGS
On the holdings snapshot, at no extra request.
Definition types.hpp:1094
@ INQUIRY
From a per-instrument inquiry, made only where the snapshot has no figure.
Definition types.hpp:1096
@ NONE
No per-instrument inquiry: any figure comes on the holdings rows (Kiwoom), or there is none.
Definition types.hpp:1098
AmendInstruction reprice(const WorkingOrder< Broker > &order, Decimal64 price, std::optional< Decimal64 > quantity=std::nullopt)
Makes an instruction changing only a working order's price.
Definition types.hpp:2438
VenueKeyKind
Which kind of venue a VenueKey names.
Definition types.hpp:1228
@ NORMALIZED
A Venue the library normalizes.
Definition types.hpp:1232
@ RAW
A broker venue code the library does not normalize, kept verbatim.
Definition types.hpp:1234
@ ANY
Any venue (a venue-neutral rate).
Definition types.hpp:1230
constexpr std::array< Venue, 4 > all_venues
Every Venue, in declaration order.
Definition types.hpp:51
CommissionOrigin
Where a commission schedule's numbers came from.
Definition types.hpp:1374
@ CALLER_STATED
The caller stated them, from a fee page or their own agreement.
Definition types.hpp:1378
@ BROKER_PUBLISHED
The broker published them, through an inquiry the library made.
Definition types.hpp:1376
std::optional< std::chrono::system_clock::time_point > parse_iso8601_timestamp(std::string_view value)
Parses an ISO 8601 timestamp, YYYY-MM-DDTHH:MM:SS[.fraction] followed by Z or a +hh:mm/-hh:mm offset.
Definition types.hpp:2478
constexpr bool commission_origin_names_tariff(CommissionOrigin origin) noexcept
Tests whether a schedule of this origin must name the tariff it was read from.
Definition types.hpp:1401
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.
std::optional< Decimal64 > decimal_add(const Decimal64 &lhs, const Decimal64 &rhs)
Adds two decimals exactly.
Definition types.hpp:509
constexpr std::string_view commission_origin_name(CommissionOrigin origin) noexcept
Returns a lowercase name for an origin, such as "caller_stated", for reports.
Definition types.hpp:1416
ErrorCategory
The kind of failure a BrokerError reports.
Definition types.hpp:687
@ RATE_LIMIT
The broker refused the request for its rate limit.
Definition types.hpp:697
@ HTTP
The broker answered with an HTTP error status (http_status_).
Definition types.hpp:693
@ PROTOCOL
The reply could not be read, or the broker declared a failure this client does not classify further: ...
Definition types.hpp:704
@ CANCELLED
The operation was cancelled, such as by closing the client or a local deadline.
Definition types.hpp:689
@ AUTHENTICATION
The credentials or token were refused.
Definition types.hpp:695
@ TRANSPORT
The connection failed (DNS, connect, TLS, write or read).
Definition types.hpp:691
@ INVALID_ARGUMENT
The request was invalid, refused by the client before sending or by the broker.
Definition types.hpp:713
OrderType
How an order's price is decided (its price basis).
Definition types.hpp:1707
@ LIMIT
지정가: fills at the stated price or better.
Definition types.hpp:1710
@ BEST_LIMIT
최유리지정가: priced at the best quote on the opposite side.
Definition types.hpp:1716
@ PRIMARY_LIMIT
최우선지정가: priced at the best quote on the order's own side.
Definition types.hpp:1718
@ CONDITIONAL_LIMIT
조건부지정가: a limit that becomes a market order at the close.
Definition types.hpp:1714
@ MID_PRICE
중간가: priced at the midpoint of the spread.
Definition types.hpp:1720
@ STOP_LIMIT
스톱지정가: a limit released when a trigger price is reached.
Definition types.hpp:1722
@ CLOSING_PRICE
시간외종가: priced at a session's closing price.
Definition types.hpp:1724
@ MARKET
시장가: fills at whatever the book offers.
Definition types.hpp:1712
constexpr bool carries_trigger_price(OrderType type) noexcept
Tests whether an order type takes a trigger price.
Definition types.hpp:1774
RateApplicability
Whether a commission rate applies on a date.
Definition types.hpp:1427
@ UNREADABLE
Unknown: no readable bound excludes the date, but a bound could not be read.
Definition types.hpp:1437
@ YES
Every bound was readable, and they cover the date.
Definition types.hpp:1431
@ NO
A readable date bound puts the date outside the rate's window.
Definition types.hpp:1429
constexpr bool carries_caller_price(OrderType type) noexcept
Tests whether an order type takes a price from the caller.
Definition types.hpp:1748
std::optional< Decimal64 > decimal_halve(const Decimal64 &value)
Halves a decimal exactly, adding a decimal place when needed.
Definition types.hpp:549
AmendInstruction cancel_all(const WorkingOrder< Broker > &order)
Makes an instruction cancelling all that remains of an order.
Definition types.hpp:2362
constexpr std::array< OrderType, 9 > all_order_types
Every OrderType, in declaration order.
Definition types.hpp:1728
constexpr std::string_view sellable_coverage_name(SellableBasis::Coverage coverage) noexcept
Returns a lowercase name for a coverage, such as "whole_holding", for logs.
Definition types.hpp:987
constexpr bool order_status_cancel_pending(OrderStatus status) noexcept
Tests whether a cancellation of an order in this status is already on its way, so asking again can on...
Definition types.hpp:1899
AmendInstruction cancel_quantity(const WorkingOrder< Broker > &order, Decimal64 quantity)
Makes an instruction cancelling part of an order.
Definition types.hpp:2385
constexpr bool error_category_is_rate_limit(ErrorCategory category) noexcept
Tests whether an error of this category is a broker asking the caller to slow down,...
Definition types.hpp:722
@ UNREADABLE
No readable date rules it out, but an unreadable date might.
constexpr std::string_view sellable_resting_name(SellableBasis::RestingTreatment treatment) noexcept
Returns a lowercase name for a treatment, such as "deduct", for logs.
Definition types.hpp:1005
Country
A country (market) the library supports.
Definition types.hpp:30
Decimal64 decimal_normalized(const Decimal64 &value)
Removes trailing fractional zeros, so equal numbers compare equal with ==.
Definition types.hpp:455
OrderSession
The trading session an order is submitted into.
Definition types.hpp:1839
@ OPENING_AUCTION
The opening single-price auction (시가단일가; Toss OPG).
Definition types.hpp:1844
@ AFTER_HOURS
After the close, at that session's close (장후 시간외).
Definition types.hpp:1850
@ CLOSING_AUCTION
The closing auction (Toss CLS, a US limit-on-close).
Definition types.hpp:1846
@ REGULAR
The continuous regular session.
Definition types.hpp:1842
@ AFTER_MARKET
KRX's after-market session (애프터마켓).
Definition types.hpp:1854
@ AFTER_HOURS_AUCTION
The after-hours single-price auction (시간외 단일가).
Definition types.hpp:1852
@ PRE_MARKET
Before the open, at the previous session's close (장전 시간외).
Definition types.hpp:1848
@ GTP
NXT's GTP session.
Definition types.hpp:1856
constexpr bool commission_origin_is_broker(CommissionOrigin origin) noexcept
Tests whether commission rates of this origin came from the broker.
Definition types.hpp:1386
constexpr std::string_view venue_name(Venue venue) noexcept
Returns a display name for a venue, such as "KRX".
Definition types.hpp:58
constexpr std::array< OrderSide, 2 > all_order_sides
Every OrderSide, in declaration order.
Definition types.hpp:1689
AmendInstruction replace_with(const WorkingOrder< Broker > &order, OrderShape shape, std::optional< Decimal64 > quantity=std::nullopt)
Makes an instruction changing a working order to a new shape.
Definition types.hpp:2414
std::optional< Decimal64 > decimal_subtract(const Decimal64 &lhs, const Decimal64 &rhs)
Subtracts two decimals exactly.
Definition types.hpp:530
std::optional< Decimal64 > decimal_divide(const Decimal64 &lhs, const Decimal64 &rhs, std::uint8_t scale)
Divides two decimals, truncating toward zero at a given scale.
Definition types.hpp:602
constexpr std::array< OrderSession, 9 > all_order_sessions
Every OrderSession, in declaration order.
Definition types.hpp:1860
constexpr bool time_in_force_expires_at_close(TimeInForce condition) noexcept
Tests whether an order with this condition expires at the session's close, so its filled quantity is ...
Definition types.hpp:1822
Venue
A trading venue: an exchange, or the combined view across exchanges.
Definition types.hpp:43
constexpr std::array< TimeInForce, 4 > all_times_in_force
Every TimeInForce, in declaration order.
Definition types.hpp:1808
constexpr std::string_view venue_key_kind_name(VenueKeyKind kind) noexcept
Returns a lowercase name for a key kind, such as "raw", for reports.
Definition types.hpp:1361
bool decimal_less(const Decimal64 &lhs, const Decimal64 &rhs)
Compares two decimals numerically, whatever their scales.
Definition types.hpp:665
std::optional< Decimal64 > decimal_multiply(const Decimal64 &lhs, const Decimal64 &rhs)
Multiplies two decimals exactly; the scales add.
Definition types.hpp:571
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
constexpr std::string_view sellable_source_name(SellableSource source) noexcept
Returns a lowercase name for a source, such as "inquiry", for logs.
Definition types.hpp:1106
bool is_valid_date(const Date &date)
Tests whether a date exists in the Gregorian calendar, in years 1 to 9999.
Definition types.hpp:1212
TimeInForce
How long an order stays valid and what happens to an unfilled remainder.
Definition types.hpp:1797
@ FILL_OR_KILL
Fills entirely and immediately, or not at all.
Definition types.hpp:1804
@ DAY
Rests until the session ends; an unfilled remainder is cancelled then.
Definition types.hpp:1800
@ IMMEDIATE_OR_CANCEL
Fills what it can immediately and cancels the remainder.
Definition types.hpp:1802
OrderSide
The side of an order: its economic direction, buy or sell.
Definition types.hpp:1683
std::optional< Decimal64 > amended_trigger_price(const AmendInstruction &instruction)
Returns the trigger price an amendment leaves the order with.
Definition types.hpp:2271
std::string format_iso8601_utc(std::chrono::system_clock::time_point value)
Formats an instant as an ISO 8601 timestamp in UTC, such as 2026-10-06T00:30:00Z.
Definition types.hpp:2453
constexpr std::array< Country, 2 > all_countries
Every Country, in declaration order.
Definition types.hpp:36
OrderShape resting_shape(const WorkingOrder< Broker > &order)
Returns a working order's current shape.
Definition types.hpp:2345
A modification or cancellation of a working order.
Definition types.hpp:2240
Venue venue_
The venue the order rests at, for a broker whose amendment needs it (KIS).
Definition types.hpp:2248
bool confirm_high_value_
Confirms a high-value amendment, where the broker asks for that confirmation.
Definition types.hpp:2254
std::optional< OrderShape > resting_
The shape the order has now, or unset if unknown.
Definition types.hpp:2261
std::optional< Decimal64 > quantity_
The quantity affected; never substituted if a broker needs one and it is missing.
Definition types.hpp:2250
OrderShape shape_
The shape the order should have afterwards.
Definition types.hpp:2242
bool all_remaining_
Whether the whole remaining quantity is affected, rather than quantity_.
Definition types.hpp:2252
The error a broker or transport operation returns.
Definition types.hpp:742
std::string request_id_
The broker's request id for this call, if it gave one.
Definition types.hpp:763
int http_status_
The HTTP status of the reply: set for an HTTP error and for a reply whose body is not a JSON object....
Definition types.hpp:759
std::string message_
A human-readable description, for logs; do not parse it.
Definition types.hpp:772
ErrorCategory category_
The kind of failure; the field to branch on.
Definition types.hpp:744
std::string broker_code_
The broker's own error code, verbatim (for example KIS's EGW00201).
Definition types.hpp:761
std::optional< int > rate_limit_
The rate limit the broker says it enforces, in requests per second, for a rate-limit error.
Definition types.hpp:785
std::optional< std::chrono::seconds > retry_after_
How long the broker asked the caller to wait (Retry-After), for a rate-limit error.
Definition types.hpp:779
bool reached_broker_
Whether a request was sent before this error.
Definition types.hpp:753
What the broker says may be spent, in one currency.
Definition types.hpp:1126
Money cash_
The amount that may be spent.
Definition types.hpp:1128
std::chrono::system_clock::time_point received_at_
When the figure was received, on this machine's clock (brokers do not timestamp it).
Definition types.hpp:1134
One commission rate, the market and venue it applies to, and the dates it applies on.
Definition types.hpp:1449
bool until_unreadable_
Whether the source stated an end date that could not be read (so until_ is empty).
Definition types.hpp:1495
bool normalized() const noexcept
Tests whether the rate's market is a normalized Country.
Definition types.hpp:1501
Country country_
The market the rate applies to; meaningless when other_ is set.
Definition types.hpp:1451
RateApplicability applies_on(const Date &date) const
Tests whether the rate applies on a date.
Definition types.hpp:1510
std::optional< Date > from_
The first date the rate applies on; empty is open-ended unless from_unreadable_ is set.
Definition types.hpp:1479
VenueKey venue_
The venue the rate applies to.
Definition types.hpp:1465
std::optional< Date > until_
The last date the rate applies on; empty is open-ended unless until_unreadable_ is set.
Definition types.hpp:1481
bool excluded_on(const Date &date) const
Tests whether a readable bound puts a date outside the rate's window.
Definition types.hpp:1525
Decimal64 rate_
The broker's commission, as a fraction of traded value (0.00015, not 0.015).
Definition types.hpp:1467
std::optional< Decimal64 > institution_rate_
The institution fee (유관기관제비용), as a fraction of traded value, if stated separately.
Definition types.hpp:1475
bool from_unreadable_
Whether the source stated a start date that could not be read (so from_ is empty).
Definition types.hpp:1488
Code< 16 > other_
The broker's market code, when the library does not normalize that market.
Definition types.hpp:1458
The result of rate_for: a rate, or why there is none.
Definition types.hpp:1567
bool bounds_unreadable_
Whether an unreadable date window is why no rate was returned.
Definition types.hpp:1576
std::optional< CommissionRate > rate_
The rate in force, if one definitely is.
Definition types.hpp:1569
The commission rates a broker published for an account, or a caller stated.
Definition types.hpp:1535
RateSelection rate_for(Country country, const VenueKey &asserted, const Date &date) const
Finds the rate in force for a market and venue on a date.
Definition types.hpp:1592
RateSelection rate_for(Country country, const Date &date) const
Finds the venue-neutral rate in force for a market on a date.
Definition types.hpp:1672
std::vector< CommissionRate > rates_
The rate rows.
Definition types.hpp:1537
CommissionOrigin origin_
Whether a broker published the rates or a caller stated them.
Definition types.hpp:1541
std::chrono::system_clock::time_point received_at_
When the schedule was received, on this machine's clock.
Definition types.hpp:1539
std::size_t unreadable_bounds_
How many rows have a date bound that could not be read.
Definition types.hpp:1564
std::size_t dropped_
How many broker rows were skipped because their market code could not be stored.
Definition types.hpp:1556
bool any_dated_rate_for(Country country) const
Tests whether any rate for a market has a date bound, readable or not.
Definition types.hpp:1649
std::string tariff_
Which tariff the rates are, in the source's own words.
Definition types.hpp:1549
A calendar date with no time of day or time zone.
Definition types.hpp:1142
friend bool operator==(const Date &lhs, const Date &rhs)
Compares two dates.
Definition types.hpp:1156
friend bool operator<(const Date &lhs, const Date &rhs)
Orders dates chronologically.
Definition types.hpp:1166
unsigned month_
The month, 1-12; zero means unset.
Definition types.hpp:1146
int year_
The year.
Definition types.hpp:1144
unsigned day_
The day of the month, 1-31; zero means unset.
Definition types.hpp:1148
One position row in a holdings snapshot.
Definition types.hpp:1017
std::string name_
The instrument's name as the broker spells it.
Definition types.hpp:1021
Money unrealized_profit_loss_
The unrealized profit or loss, as the broker reported it.
Definition types.hpp:1051
Money purchase_value_
The cost basis, as the broker computed it.
Definition types.hpp:1047
Decimal64 average_purchase_price_
The broker's average purchase price.
Definition types.hpp:1043
std::optional< Decimal64 > sellable_quantity_
How much the broker says may be sold now.
Definition types.hpp:1034
Decimal64 unrealized_return_
The broker's return figure, as a fraction (0.05 is 5%).
Definition types.hpp:1053
Decimal64 quantity_
The quantity in this row.
Definition types.hpp:1027
InstrumentId instrument_
The instrument held (brokers report holdings without a trading venue).
Definition types.hpp:1019
Money market_value_
The market value, as the broker computed it.
Definition types.hpp:1049
Decimal64 last_price_
The price the broker valued the position at.
Definition types.hpp:1045
std::optional< SellableBasis > sellable_basis_
What this row's sellable_quantity_ covers, when the figure came from a per-instrument inquiry rather ...
Definition types.hpp:1041
An account's positions and per-currency totals at one point in time.
Definition types.hpp:1075
std::chrono::system_clock::time_point received_at_
When this process received the snapshot (brokers do not timestamp holdings).
Definition types.hpp:1081
std::vector< HoldingsTotals > totals_
One totals row per currency held.
Definition types.hpp:1079
SellableBasis sellable_basis_
What the rows' sellable_quantity_ figures cover (unless a row carries its own).
Definition types.hpp:1088
std::vector< HoldingPosition > positions_
Every position row; one instrument may appear in more than one.
Definition types.hpp:1077
The broker's holdings totals for one currency.
Definition types.hpp:1057
Decimal64 unrealized_profit_loss_
The broker's total unrealized profit or loss in currency_, from its summary.
Definition types.hpp:1070
Decimal64 market_value_
The broker's total market value in currency_, from its summary.
Definition types.hpp:1068
Decimal64 purchase_value_
The broker's total cost basis in currency_.
Definition types.hpp:1066
Currency currency_
The currency; there is one totals row per currency, never converted.
Definition types.hpp:1059
Identifies an instrument: its country, venue and symbol.
Definition types.hpp:78
Country country_
The listing country, which selects the symbol convention and the price grid.
Definition types.hpp:80
friend bool operator==(const InstrumentId &lhs, const InstrumentId &rhs)
Compares country, venue and symbol.
Definition types.hpp:96
Venue venue_
The venue that is part of the identity (two venues are two instruments).
Definition types.hpp:86
std::string symbol_
The symbol as the venue spells it, such as "005930".
Definition types.hpp:88
friend bool operator<(const InstrumentId &lhs, const InstrumentId &rhs)
Orders identities by country, venue, then symbol, so they can key a map.
Definition types.hpp:109
An exact amount of money in one currency.
Definition types.hpp:895
Currency currency_
The currency; the library never adds amounts in different currencies.
Definition types.hpp:899
friend bool operator==(const Money &lhs, const Money &rhs)
Compares amount (with Decimal64::operator==) and currency.
Definition types.hpp:907
Decimal64 amount_
The amount.
Definition types.hpp:897
The broker's acknowledgement that it accepted an instruction.
Definition types.hpp:2092
std::optional< std::string > client_order_id_
The idempotency key, if the broker echoed one.
Definition types.hpp:2096
std::chrono::system_clock::time_point accepted_at_
When the acknowledgement was received.
Definition types.hpp:2098
std::string order_id_
The order number the broker assigned.
Definition types.hpp:2094
What has filled on one order, and what it cost.
Definition types.hpp:1981
std::optional< Money > commission_
Commission charged so far, if the broker reports it per order.
Definition types.hpp:1998
Decimal64 filled_quantity_
The quantity filled so far; zero if nothing has filled. Always present.
Definition types.hpp:1983
std::optional< Decimal64 > average_filled_price_
The average fill price, only where the broker supplies it.
Definition types.hpp:1990
std::optional< std::chrono::system_clock::time_point > filled_at_
When the most recent fill happened, if the broker timestamps it.
Definition types.hpp:2002
std::optional< Money > filled_amount_
The value of the fills, as the broker computed it.
Definition types.hpp:1996
std::optional< Money > tax_
Transaction tax charged so far, if the broker reports it per order.
Definition types.hpp:2000
std::optional< Date > settlement_date_
The settlement date the broker stated.
Definition types.hpp:2004
The filter for an order-history inquiry.
Definition types.hpp:2325
std::optional< std::string > symbol_
Only this symbol, where the broker supports the filter.
Definition types.hpp:2331
std::optional< int > limit_
The most rows to return, where the broker supports a limit.
Definition types.hpp:2335
std::optional< std::string > cursor_
A previous page's next_cursor_, passed back unchanged.
Definition types.hpp:2333
std::optional< Date > from_
The first date to include; required where BrokerCaps::history_requires_range.
Definition types.hpp:2327
std::optional< Date > to_
The last date to include.
Definition types.hpp:2329
One page of an order listing.
Definition types.hpp:2078
std::vector< OrderSnapshot > orders_
The rows, in the broker's order.
Definition types.hpp:2080
std::optional< std::string > next_cursor_
The cursor for the next page, to pass back unchanged; empty if there is none.
Definition types.hpp:2082
std::chrono::system_clock::time_point received_at_
When the page was received, on this machine's clock.
Definition types.hpp:2084
A broker's reference to one order, used to amend or cancel it.
Definition types.hpp:2111
friend bool operator==(const OrderRef &lhs, const OrderRef &rhs)
Compares two references.
Definition types.hpp:2144
friend bool operator!=(const OrderRef &lhs, const OrderRef &rhs)
Compares two references for inequality.
Definition types.hpp:2154
std::string str() const
Formats the reference for logs, as broker:primary[:secondary].
Definition types.hpp:2127
static constexpr std::string_view broker() noexcept
Returns the issuing broker's name.
Definition types.hpp:2121
An order to place, in broker-neutral form.
Definition types.hpp:1925
std::optional< std::string > client_order_id_
An idempotency key, if the broker offers one; never generated by the library.
Definition types.hpp:1966
Decimal64 quantity_
The quantity, in the instrument's units (shares).
Definition types.hpp:1950
OrderType type_
The price basis: limit, market, best-limit, and so on.
Definition types.hpp:1931
InstrumentId instrument_
The instrument; its venue_ is identity, and routing is this struct's venue_.
Definition types.hpp:1927
Venue venue_
Where to route the order, if the broker offers a choice.
Definition types.hpp:1948
std::optional< Decimal64 > price_
The price; required when carries_caller_price(type_), refused otherwise.
Definition types.hpp:1952
OrderSide side_
Buy or sell.
Definition types.hpp:1929
OrderSession session_
The trading session.
Definition types.hpp:1935
TimeInForce time_in_force_
How long the order stays valid.
Definition types.hpp:1933
bool confirm_high_value_
Confirms a high-value order, where the broker asks for that confirmation.
Definition types.hpp:1968
std::optional< Decimal64 > trigger_price_
The trigger price; required for STOP_LIMIT, refused otherwise.
Definition types.hpp:1959
An order's type, price, trigger, time in force and session, as an amendment states them.
Definition types.hpp:2179
std::optional< TimeInForce > time_in_force_
The time in force; unset means "keep the resting order's".
Definition types.hpp:2223
std::optional< Decimal64 > price_
The price, for a basis that takes one.
Definition types.hpp:2207
std::optional< OrderSession > session_
The session; unset means "keep the resting order's".
Definition types.hpp:2230
OrderShape()=default
Constructs a limit shape with nothing else stated.
OrderShape(OrderType type, std::optional< Decimal64 > price, std::optional< TimeInForce > time_in_force=std::nullopt, std::optional< OrderSession > session=std::nullopt, std::optional< Decimal64 > trigger_price=std::nullopt)
Constructs a shape, stating only what the caller means to set.
Definition types.hpp:2191
std::optional< Decimal64 > trigger_price_
The trigger price, for STOP_LIMIT.
Definition types.hpp:2216
OrderType type_
The price basis.
Definition types.hpp:2205
The state of one order, as a broker listing reported it.
Definition types.hpp:2008
Venue venue_
Where the broker says the order was routed; UNSPECIFIED if it does not say.
Definition types.hpp:2029
OrderSide side_
Buy or sell.
Definition types.hpp:2016
OrderStatus status_
The status; UNKNOWN where the broker publishes none.
Definition types.hpp:2038
OrderSession session_
The session; UNKNOWN if the broker's code was not recognized.
Definition types.hpp:2022
std::optional< std::chrono::system_clock::time_point > canceled_at_
When the order was cancelled, if the broker reports it.
Definition types.hpp:2072
OrderType type_
The price basis; UNKNOWN if the broker's code was not recognized.
Definition types.hpp:2018
OrderExecution execution_
What has filled and what it cost; see OrderExecution before testing a fill.
Definition types.hpp:2074
std::string name_
The instrument's name as the broker spells it.
Definition types.hpp:2014
std::optional< Decimal64 > trigger_price_
The trigger price, whenever the broker reports a positive one.
Definition types.hpp:2048
bool ordered_date_assumed_
Whether the broker stated only the time of day, and the date in ordered_at_ is the day the adapter re...
Definition types.hpp:2070
Currency currency_
The currency of the row's prices and amounts.
Definition types.hpp:2060
Decimal64 quantity_
The quantity ordered; the remainder is this minus execution_.filled_quantity_.
Definition types.hpp:2050
std::string order_id_
The broker's order number.
Definition types.hpp:2010
std::optional< std::chrono::system_clock::time_point > ordered_at_
When the broker recorded the order, if it gives a time. KIS's real-server working orders have none; o...
Definition types.hpp:2065
std::optional< Decimal64 > order_amount_
The money an amount-based order committed (Toss US market orders), if any.
Definition types.hpp:2058
InstrumentId instrument_
The instrument (identity venue; the routing venue is venue_).
Definition types.hpp:2012
TimeInForce time_in_force_
The time in force; UNKNOWN if the broker's code was not recognized.
Definition types.hpp:2020
Code< 8 > shape_code_
The broker's own order-type code, verbatim (KIS two digits, Toss three letters).
Definition types.hpp:2036
std::optional< Decimal64 > price_
The limit price, if the order has one.
Definition types.hpp:2040
An accepted order: the acknowledgement and the reference to address it with.
Definition types.hpp:2165
A quote: the last traded price of an instrument at a point in time.
Definition types.hpp:870
Currency currency_
The currency of last_price_.
Definition types.hpp:876
Decimal64 last_price_
The last traded price, as the broker reported it.
Definition types.hpp:874
std::chrono::system_clock::time_point received_at_
When this process received the quote, on this machine's clock.
Definition types.hpp:880
std::optional< TopOfBook > top_of_book_
The best bid and offer.
Definition types.hpp:889
std::optional< std::chrono::system_clock::time_point > exchange_time_
When the exchange says the quote was true, if the broker gave a timestamp.
Definition types.hpp:878
InstrumentId instrument_
The instrument.
Definition types.hpp:872
std::optional< Decimal64 > volume_
The session's cumulative traded volume, if the broker gave it.
Definition types.hpp:891
What a sellable quantity covers, and how RiskGuard must treat resting sells against it.
Definition types.hpp:918
bool verified_
Whether the basis was confirmed from a real broker response, rather than stated as a policy.
Definition types.hpp:954
constexpr bool is_enforceable() const noexcept
Tests whether RiskGuard may check a sell against a figure with this basis.
Definition types.hpp:960
RestingTreatment resting_
How resting sells are treated; unestablished by default.
Definition types.hpp:948
Coverage
Whether the figure covers the whole holding.
Definition types.hpp:920
@ WHOLE_HOLDING
Every share held of the instrument, whatever venue or lot.
Definition types.hpp:924
@ UNESTABLISHED
Not established; RiskGuard refuses.
Definition types.hpp:922
@ PARTIAL
Only part of the holding, such as one venue's shares; RiskGuard refuses, reporting SELLABLE_BASIS_UNE...
Definition types.hpp:929
Coverage coverage_
What the figure covers; unestablished by default.
Definition types.hpp:946
RestingTreatment
How RiskGuard treats resting sell orders against the figure.
Definition types.hpp:933
@ DEDUCT
Subtract every resting sell from the figure.
Definition types.hpp:942
@ UNESTABLISHED
Not stated; RiskGuard refuses.
Definition types.hpp:935
The best bid and offer, with the size at each. An absent field was not stated, never zero.
Definition types.hpp:858
std::optional< Decimal64 > bid_price_
The best bid price.
Definition types.hpp:860
std::optional< Decimal64 > ask_price_
The best offer price.
Definition types.hpp:864
std::optional< Decimal64 > bid_quantity_
The size at the best bid.
Definition types.hpp:862
std::optional< Decimal64 > ask_quantity_
The size at the best offer.
Definition types.hpp:866
An order still open to modification or cancellation.
Definition types.hpp:2290
std::optional< Decimal64 > amendable_quantity_
Definition types.hpp:2296
The orders open to modification or cancellation at one point in time.
Definition types.hpp:2312
std::vector< WorkingOrder< BrokerTag > > orders_
Definition types.hpp:2314
std::chrono::system_clock::time_point received_at_
Definition types.hpp:2316
std::size_t operator()(const algotradelib::OrderRef< Broker > &ref) const noexcept
Hashes both parts of the reference.
Definition types.hpp:2605