Skip to content

Commit 1d25b83

Browse files
committed
ADD: Add instrument definitions to C++ client lib
1 parent 3406d1c commit 1d25b83

File tree

7 files changed

+453
-6
lines changed

7 files changed

+453
-6
lines changed

include/databento/record.hpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static_assert(sizeof(TradeMsg) == 48, "TradeMsg size must match C");
127127
static_assert(sizeof(Mbp1Msg) == sizeof(TradeMsg) + sizeof(BidAskPair),
128128
"Mbp1Msg size must match C");
129129

130+
// Aggregate of open, high, low, and close prices with volume.
130131
struct OhlcvMsg {
131132
static constexpr std::uint8_t kTypeId = 0x11;
132133

@@ -140,11 +141,86 @@ struct OhlcvMsg {
140141

141142
static_assert(sizeof(OhlcvMsg) == 56, "OhlcvMsg size must match C");
142143

144+
// Instrument definition.
145+
struct InstrumentDefMsg {
146+
static constexpr std::uint8_t kTypeId = 0x13;
147+
148+
RecordHeader hd;
149+
UnixNanos ts_recv;
150+
std::int64_t min_price_increment;
151+
std::int64_t display_factor;
152+
std::uint64_t expiration;
153+
std::uint64_t activation;
154+
std::int64_t high_limit_price;
155+
std::int64_t low_limit_price;
156+
std::int64_t max_price_variation;
157+
std::int64_t trading_reference_price;
158+
std::int64_t unit_of_measure_qty;
159+
std::int64_t min_price_increment_amount;
160+
std::int64_t price_ratio;
161+
std::int32_t inst_attrib_value;
162+
std::uint32_t underlying_id;
163+
std::int32_t cleared_volume;
164+
std::int32_t market_depth_implied;
165+
std::int32_t market_depth;
166+
std::uint32_t market_segment_id;
167+
std::uint32_t max_trade_vol;
168+
std::int32_t min_lot_size;
169+
std::int32_t min_lot_size_block;
170+
std::int32_t min_lot_size_round_lot;
171+
std::uint32_t min_trade_vol;
172+
std::int32_t open_interest_qty;
173+
std::int32_t contract_multiplier;
174+
std::int32_t decay_quantity;
175+
std::int32_t original_contract_size;
176+
std::uint32_t related_security_id;
177+
std::uint16_t trading_reference_date;
178+
std::int16_t appl_id;
179+
std::uint16_t maturity_year;
180+
std::uint16_t decay_start_date;
181+
std::uint16_t channel_id;
182+
std::array<char, 4> currency;
183+
std::array<char, 4> settl_currency;
184+
std::array<char, 6> secsubtype;
185+
std::array<char, 22> symbol;
186+
std::array<char, 21> group;
187+
std::array<char, 5> exchange;
188+
std::array<char, 7> asset;
189+
std::array<char, 7> cfi;
190+
std::array<char, 7> security_type;
191+
std::array<char, 31> unit_of_measure;
192+
std::array<char, 21> underlying;
193+
std::array<char, 21> related;
194+
char match_algorithm;
195+
std::uint8_t md_security_trading_status;
196+
std::uint8_t main_fraction;
197+
std::uint8_t price_display_format;
198+
std::uint8_t settl_price_type;
199+
std::uint8_t sub_fraction;
200+
std::uint8_t underlying_product;
201+
char security_update_action;
202+
std::uint8_t maturity_month;
203+
std::uint8_t maturity_day;
204+
std::uint8_t maturity_week;
205+
char user_defined_instrument;
206+
std::int8_t contract_multiplier_unit;
207+
std::int8_t flow_schedule_type;
208+
std::uint8_t tick_rule;
209+
// padding for alignment
210+
std::array<char, 3> dummy;
211+
};
212+
213+
static_assert(sizeof(InstrumentDefMsg) == 360,
214+
"InstrumentDefMsg size must match C");
215+
143216
inline bool operator==(const RecordHeader& lhs, const RecordHeader& rhs) {
144217
return lhs.length == rhs.length && lhs.rtype == rhs.rtype &&
145218
lhs.publisher_id == rhs.publisher_id &&
146219
lhs.product_id == rhs.product_id && lhs.ts_event == rhs.ts_event;
147220
}
221+
inline bool operator!=(const RecordHeader& lhs, const RecordHeader& rhs) {
222+
return !(lhs == rhs);
223+
}
148224

149225
inline bool operator==(const MboMsg& lhs, const MboMsg& rhs) {
150226
return lhs.hd == rhs.hd && lhs.order_id == rhs.order_id &&
@@ -154,12 +230,18 @@ inline bool operator==(const MboMsg& lhs, const MboMsg& rhs) {
154230
lhs.ts_recv == rhs.ts_recv && lhs.ts_in_delta == rhs.ts_in_delta &&
155231
lhs.sequence == rhs.sequence;
156232
}
233+
inline bool operator!=(const TickMsg& lhs, const TickMsg& rhs) {
234+
return !(lhs == rhs);
235+
}
157236

158237
inline bool operator==(const BidAskPair& lhs, const BidAskPair& rhs) {
159238
return lhs.bid_px == rhs.bid_px && lhs.ask_px == rhs.ask_px &&
160239
lhs.bid_sz == rhs.bid_sz && lhs.ask_sz == rhs.ask_sz &&
161240
lhs.bid_ct == rhs.bid_ct && lhs.ask_ct == rhs.ask_ct;
162241
}
242+
inline bool operator!=(const BidAskPair& lhs, const BidAskPair& rhs) {
243+
return !(lhs == rhs);
244+
}
163245

164246
namespace detail {
165247
template <std::size_t N>
@@ -170,6 +252,10 @@ bool operator==(const MbpMsg<N>& lhs, const MbpMsg<N>& rhs) {
170252
lhs.ts_recv == rhs.ts_recv && lhs.ts_in_delta == rhs.ts_in_delta &&
171253
lhs.sequence == rhs.sequence && lhs.booklevel == rhs.booklevel;
172254
}
255+
template <std::size_t N>
256+
bool operator!=(const MbpMsg<N>& lhs, const MbpMsg<N>& rhs) {
257+
return !(lhs == rhs);
258+
}
173259

174260
template <std::size_t N>
175261
std::string ToString(const MbpMsg<N>& mbp_msg);
@@ -193,12 +279,24 @@ inline bool operator==(const TradeMsg& lhs, const TradeMsg& rhs) {
193279
lhs.ts_recv == rhs.ts_recv && lhs.ts_in_delta == rhs.ts_in_delta &&
194280
lhs.sequence == rhs.sequence;
195281
}
282+
inline bool operator!=(const TradeMsg& lhs, const TradeMsg& rhs) {
283+
return !(lhs == rhs);
284+
}
196285

197286
inline bool operator==(const OhlcvMsg& lhs, const OhlcvMsg& rhs) {
198287
return lhs.hd == rhs.hd && lhs.open == rhs.open && lhs.high == rhs.high &&
199288
lhs.low == rhs.low && lhs.close == rhs.close &&
200289
lhs.volume == rhs.volume;
201290
}
291+
inline bool operator!=(const OhlcvMsg& lhs, const OhlcvMsg& rhs) {
292+
return !(lhs == rhs);
293+
}
294+
295+
bool operator==(const InstrumentDefMsg& lhs, const InstrumentDefMsg& rhs);
296+
inline bool operator!=(const InstrumentDefMsg& lhs,
297+
const InstrumentDefMsg& rhs) {
298+
return !(lhs == rhs);
299+
}
202300

203301
std::string ToString(const RecordHeader& header);
204302
std::ostream& operator<<(std::ostream& stream, const RecordHeader& header);
@@ -210,4 +308,7 @@ std::string ToString(const TradeMsg& trade_msg);
210308
std::ostream& operator<<(std::ostream& stream, const TradeMsg& trade_msg);
211309
std::string ToString(const OhlcvMsg& ohlcv_msg);
212310
std::ostream& operator<<(std::ostream& stream, const OhlcvMsg& ohlcv_msg);
311+
std::string ToString(const InstrumentDefMsg& instr_def_msg);
312+
std::ostream& operator<<(std::ostream& stream,
313+
const InstrumentDefMsg& instr_def_msg);
213314
} // namespace databento

src/record.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ std::size_t Record::SizeOfType(const std::uint8_t rtype) {
2727
case OhlcvMsg::kTypeId: {
2828
return sizeof(OhlcvMsg);
2929
}
30+
case InstrumentDefMsg::kTypeId: {
31+
return sizeof(InstrumentDefMsg);
32+
}
3033
default: {
3134
throw InvalidArgumentError{
3235
"Record::SizeOfType", "rtype",
@@ -58,6 +61,9 @@ std::uint8_t Record::TypeIdFromSchema(const Schema schema) {
5861
case Schema::Ohlcv1S: {
5962
return OhlcvMsg::kTypeId;
6063
}
64+
case Schema::Definition: {
65+
return InstrumentDefMsg::kTypeId;
66+
}
6167
default: {
6268
throw InvalidArgumentError{
6369
"Record::TypeIdFromSchema", "schema",
@@ -67,6 +73,65 @@ std::uint8_t Record::TypeIdFromSchema(const Schema schema) {
6773
}
6874
}
6975

76+
using databento::InstrumentDefMsg;
77+
78+
bool databento::operator==(const InstrumentDefMsg& lhs,
79+
const InstrumentDefMsg& rhs) {
80+
return lhs.hd == rhs.hd && lhs.ts_recv == rhs.ts_recv &&
81+
lhs.min_price_increment == rhs.min_price_increment &&
82+
lhs.display_factor == rhs.display_factor &&
83+
lhs.expiration == rhs.expiration && lhs.activation == rhs.activation &&
84+
lhs.high_limit_price == rhs.high_limit_price &&
85+
lhs.low_limit_price == rhs.low_limit_price &&
86+
lhs.max_price_variation == rhs.max_price_variation &&
87+
lhs.trading_reference_price == rhs.trading_reference_price &&
88+
lhs.unit_of_measure_qty == rhs.unit_of_measure_qty &&
89+
lhs.min_price_increment_amount == rhs.min_price_increment_amount &&
90+
lhs.price_ratio == rhs.price_ratio &&
91+
lhs.inst_attrib_value == rhs.inst_attrib_value &&
92+
lhs.underlying_id == rhs.underlying_id &&
93+
lhs.cleared_volume == rhs.cleared_volume &&
94+
lhs.market_depth_implied == rhs.market_depth_implied &&
95+
lhs.market_depth == rhs.market_depth &&
96+
lhs.market_segment_id == rhs.market_segment_id &&
97+
lhs.max_trade_vol == rhs.max_trade_vol &&
98+
lhs.min_lot_size == rhs.min_lot_size &&
99+
lhs.min_lot_size_block == rhs.min_lot_size_block &&
100+
lhs.min_lot_size_round_lot == rhs.min_lot_size_round_lot &&
101+
lhs.min_trade_vol == rhs.min_trade_vol &&
102+
lhs.open_interest_qty == rhs.open_interest_qty &&
103+
lhs.contract_multiplier == rhs.contract_multiplier &&
104+
lhs.decay_quantity == rhs.decay_quantity &&
105+
lhs.original_contract_size == rhs.original_contract_size &&
106+
lhs.related_security_id == rhs.related_security_id &&
107+
lhs.trading_reference_date == rhs.trading_reference_date &&
108+
lhs.appl_id == rhs.appl_id && lhs.maturity_year == rhs.maturity_year &&
109+
lhs.decay_start_date == rhs.decay_start_date &&
110+
lhs.channel_id == rhs.channel_id && lhs.currency == rhs.currency &&
111+
lhs.settl_currency == rhs.settl_currency &&
112+
lhs.secsubtype == rhs.secsubtype && lhs.symbol == rhs.symbol &&
113+
lhs.group == rhs.group && lhs.exchange == rhs.exchange &&
114+
lhs.asset == rhs.asset && lhs.cfi == rhs.cfi &&
115+
lhs.security_type == rhs.security_type &&
116+
lhs.unit_of_measure == rhs.unit_of_measure &&
117+
lhs.underlying == rhs.underlying && lhs.related == rhs.related &&
118+
lhs.match_algorithm == rhs.match_algorithm &&
119+
lhs.md_security_trading_status == rhs.md_security_trading_status &&
120+
lhs.main_fraction == rhs.main_fraction &&
121+
lhs.price_display_format == rhs.price_display_format &&
122+
lhs.settl_price_type == rhs.settl_price_type &&
123+
lhs.sub_fraction == rhs.sub_fraction &&
124+
lhs.underlying_product == rhs.underlying_product &&
125+
lhs.security_update_action == rhs.security_update_action &&
126+
lhs.maturity_month == rhs.maturity_month &&
127+
lhs.maturity_day == rhs.maturity_day &&
128+
lhs.maturity_week == rhs.maturity_week &&
129+
lhs.user_defined_instrument == rhs.user_defined_instrument &&
130+
lhs.contract_multiplier_unit == rhs.contract_multiplier_unit &&
131+
lhs.flow_schedule_type == rhs.flow_schedule_type &&
132+
lhs.tick_rule == rhs.tick_rule;
133+
}
134+
70135
namespace databento {
71136
namespace detail {
72137
template <>
@@ -206,4 +271,81 @@ std::ostream& operator<<(std::ostream& stream, const OhlcvMsg& ohlcv_msg) {
206271
.AddField("volume", ohlcv_msg.volume)
207272
.Finish();
208273
}
274+
std::string ToString(const InstrumentDefMsg& instr_def_msg) {
275+
return MakeString(instr_def_msg);
276+
}
277+
std::ostream& operator<<(std::ostream& stream,
278+
const InstrumentDefMsg& instr_def_msg) {
279+
return StreamOpBuilder{stream}
280+
.SetSpacer("\n ")
281+
.SetTypeName("InstrumentDefMsg")
282+
.Build()
283+
.AddField("hd", instr_def_msg.hd)
284+
.AddField("ts_recv", instr_def_msg.ts_recv)
285+
.AddField("min_price_increment", instr_def_msg.min_price_increment)
286+
.AddField("display_factor", instr_def_msg.display_factor)
287+
.AddField("expiration", instr_def_msg.expiration)
288+
.AddField("activation", instr_def_msg.activation)
289+
.AddField("high_limit_price", instr_def_msg.high_limit_price)
290+
.AddField("low_limit_price", instr_def_msg.low_limit_price)
291+
.AddField("max_price_variation", instr_def_msg.max_price_variation)
292+
.AddField("trading_reference_price",
293+
instr_def_msg.trading_reference_price)
294+
.AddField("unit_of_measure_qty", instr_def_msg.unit_of_measure_qty)
295+
.AddField("min_price_increment_amount",
296+
instr_def_msg.min_price_increment_amount)
297+
.AddField("price_ratio", instr_def_msg.price_ratio)
298+
.AddField("inst_attrib_value", instr_def_msg.inst_attrib_value)
299+
.AddField("underlying_id", instr_def_msg.underlying_id)
300+
.AddField("cleared_volume", instr_def_msg.cleared_volume)
301+
.AddField("market_depth_implied", instr_def_msg.market_depth_implied)
302+
.AddField("market_depth", instr_def_msg.market_depth)
303+
.AddField("market_segment_id", instr_def_msg.market_segment_id)
304+
.AddField("max_trade_vol", instr_def_msg.max_trade_vol)
305+
.AddField("min_lot_size", instr_def_msg.min_lot_size)
306+
.AddField("min_lot_size_block", instr_def_msg.min_lot_size_block)
307+
.AddField("min_lot_size_round_lot", instr_def_msg.min_lot_size_round_lot)
308+
.AddField("min_trade_vol", instr_def_msg.min_trade_vol)
309+
.AddField("open_interest_qty", instr_def_msg.open_interest_qty)
310+
.AddField("contract_multiplier", instr_def_msg.contract_multiplier)
311+
.AddField("decay_quantity", instr_def_msg.decay_quantity)
312+
.AddField("original_contract_size", instr_def_msg.original_contract_size)
313+
.AddField("related_security_id", instr_def_msg.related_security_id)
314+
.AddField("trading_reference_date", instr_def_msg.trading_reference_date)
315+
.AddField("appl_id", instr_def_msg.appl_id)
316+
.AddField("maturity_year", instr_def_msg.maturity_year)
317+
.AddField("decay_start_date", instr_def_msg.decay_start_date)
318+
.AddField("channel_id", instr_def_msg.channel_id)
319+
.AddField("currency", instr_def_msg.currency)
320+
.AddField("settl_currency", instr_def_msg.settl_currency)
321+
.AddField("secsubtype", instr_def_msg.secsubtype)
322+
.AddField("symbol", instr_def_msg.symbol)
323+
.AddField("group", instr_def_msg.group)
324+
.AddField("exchange", instr_def_msg.exchange)
325+
.AddField("asset", instr_def_msg.asset)
326+
.AddField("cfi", instr_def_msg.cfi)
327+
.AddField("security_type", instr_def_msg.security_type)
328+
.AddField("unit_of_measure", instr_def_msg.unit_of_measure)
329+
.AddField("underlying", instr_def_msg.underlying)
330+
.AddField("related", instr_def_msg.related)
331+
.AddField("match_algorithm", instr_def_msg.match_algorithm)
332+
.AddField("md_security_trading_status",
333+
instr_def_msg.md_security_trading_status)
334+
.AddField("main_fraction", instr_def_msg.main_fraction)
335+
.AddField("price_display_format", instr_def_msg.price_display_format)
336+
.AddField("settl_price_type", instr_def_msg.settl_price_type)
337+
.AddField("sub_fraction", instr_def_msg.sub_fraction)
338+
.AddField("underlying_product", instr_def_msg.underlying_product)
339+
.AddField("security_update_action", instr_def_msg.security_update_action)
340+
.AddField("maturity_month", instr_def_msg.maturity_month)
341+
.AddField("maturity_day", instr_def_msg.maturity_day)
342+
.AddField("maturity_week", instr_def_msg.maturity_week)
343+
.AddField("user_defined_instrument",
344+
instr_def_msg.user_defined_instrument)
345+
.AddField("contract_multiplier_unit",
346+
instr_def_msg.contract_multiplier_unit)
347+
.AddField("flow_schedule_type", instr_def_msg.flow_schedule_type)
348+
.AddField("tick_rule", instr_def_msg.tick_rule)
349+
.Finish();
350+
}
209351
} // namespace databento

src/stream_op_helper.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#pragma once
22

3+
#include <array>
34
#include <cstdint>
4-
#include <ios>
5-
#include <ostream>
6-
#include <sstream>
5+
#include <cstring> // strlen
6+
#include <ios> // boolalpha
7+
#include <ostream> // ostream
8+
#include <sstream> // stringstream
79
#include <string>
8-
#include <utility>
10+
#include <utility> // move
911

10-
#include "databento/datetime.hpp"
12+
#include "databento/datetime.hpp" // TimeDeltaNanos, UnixNanos
1113

1214
namespace databento {
1315
template <typename T>
@@ -53,6 +55,14 @@ class StreamOpHelper {
5355

5456
void FmtToStream(const std::ostringstream& val) { stream_ << val.str(); }
5557

58+
template <std::size_t N>
59+
void FmtToStream(const std::array<char, N>& val) {
60+
stream_ << '"';
61+
stream_.write(val.data(),
62+
static_cast<std::streamsize>(::strlen(val.data())));
63+
stream_ << '"';
64+
}
65+
5666
public:
5767
StreamOpHelper(std::ostream& stream, const std::string& type_name,
5868
std::string spacer, std::string indent)

test/data/test_data.definition.dbz

472 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)