Skip to content

Commit 3440981

Browse files
committed
ADD: Support formatting params for pretty fmting
1 parent 07193d9 commit 3440981

File tree

11 files changed

+283
-97
lines changed

11 files changed

+283
-97
lines changed

cmake/SourcesAndHeaders.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ set(headers
2828
include/databento/live_threaded.hpp
2929
include/databento/log.hpp
3030
include/databento/metadata.hpp
31+
include/databento/pretty.hpp
3132
include/databento/publishers.hpp
3233
include/databento/record.hpp
3334
include/databento/symbol_map.hpp
@@ -58,14 +59,14 @@ set(sources
5859
src/enums.cpp
5960
src/exceptions.cpp
6061
src/file_stream.cpp
61-
src/fixed_price.cpp
6262
src/flag_set.cpp
6363
src/historical.cpp
6464
src/live.cpp
6565
src/live_blocking.cpp
6666
src/live_threaded.cpp
6767
src/log.cpp
6868
src/metadata.cpp
69+
src/pretty.cpp
6970
src/publishers.cpp
7071
src/record.cpp
7172
src/symbol_map.cpp

include/databento/fixed_price.hpp

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

33
#include <cstdint>
4-
#include <sstream>
54
#include <string>
65

7-
#include "databento/constants.hpp"
6+
#include "databento/pretty.hpp"
87

98
namespace databento {
10-
// A fixed-precision price.
11-
struct FixPx {
12-
bool IsUndefined() const { return val == databento::kUndefPrice; }
9+
// Has been renamed to pretty::Px
10+
using FixPx [[deprecated]] = pretty::Px;
1311

14-
std::int64_t val;
15-
};
16-
17-
std::ostream& operator<<(std::ostream& stream, FixPx fix_px);
18-
19-
// Convert a fixed-precision price to a formatted string.
20-
inline std::string PxToString(std::int64_t px) {
21-
std::ostringstream ss;
22-
ss << FixPx{px};
23-
return ss.str();
12+
// Has been moved to the pretty namespace
13+
[[deprecated]] inline std::string PxToString(std::int64_t px) {
14+
return pretty::PxToString(px);
2415
}
2516
} // namespace databento

include/databento/pretty.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <sstream>
5+
#include <string>
6+
7+
#include "databento/constants.hpp"
8+
#include "databento/datetime.hpp"
9+
10+
namespace databento::pretty {
11+
// A helper type for formatting the fixed-precision prices used in DBN.
12+
//
13+
// Supports configurable fill, width, and precision [0, 6). By default
14+
// will print all 9 decimal places of precision.
15+
struct Px {
16+
bool IsUndefined() const { return val == databento::kUndefPrice; }
17+
18+
std::int64_t val;
19+
};
20+
21+
std::ostream& operator<<(std::ostream& stream, Px px);
22+
23+
// A helper type for formatting the nanosecond UNIX timestamps used in DBN to
24+
// the canonical ISO 8601 format used by Databento.
25+
//
26+
// Supports configurable fill and width.
27+
struct Ts {
28+
bool IsUndefined() const {
29+
return val.time_since_epoch().count() == databento::kUndefTimestamp;
30+
}
31+
32+
UnixNanos val;
33+
};
34+
35+
std::ostream& operator<<(std::ostream& stream, Ts ts);
36+
37+
// Convert a fixed-precision price to a formatted string.
38+
inline std::string PxToString(std::int64_t px) {
39+
std::ostringstream ss;
40+
ss << Px{px};
41+
return ss.str();
42+
}
43+
} // namespace databento::pretty

src/fixed_price.cpp

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/pretty.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "databento/pretty.hpp"
2+
3+
#include <array>
4+
#include <cstdint>
5+
#include <iomanip>
6+
#include <sstream>
7+
8+
#include "databento/datetime.hpp"
9+
10+
namespace databento::pretty {
11+
std::ostream& operator<<(std::ostream& stream, Px px) {
12+
constexpr std::array<std::int64_t, 6> kDivisors = {
13+
0, 100'000'000, 10'000'000, 1'000'000, 100'000, 10'000};
14+
if (px.IsUndefined()) {
15+
stream << "UNDEF_PRICE";
16+
return stream;
17+
}
18+
const bool is_negative = (px.val < 0);
19+
const int64_t px_abs = is_negative ? -px.val : px.val;
20+
const int64_t price_integer = px_abs / kFixedPriceScale;
21+
const int64_t price_fraction = px_abs % kFixedPriceScale;
22+
std::ostringstream ss;
23+
if (is_negative) {
24+
ss << '-';
25+
}
26+
const auto orig_precision = static_cast<int>(stream.precision());
27+
if (orig_precision == 0) {
28+
ss << price_integer;
29+
} else {
30+
// Don't support precision 6-8 (inclusive). 6 is the default and there's no
31+
// way to disambiguate between explicitly set 6 and the default value,
32+
// however by default we want to print all 9 digits
33+
const auto precision = orig_precision < 6 ? orig_precision : 9;
34+
ss << price_integer << '.' << std::setw(precision) << std::setfill('0')
35+
<< (precision == 9 ? price_fraction
36+
: price_fraction /
37+
kDivisors[static_cast<std::size_t>(precision)]);
38+
}
39+
stream << ss.str();
40+
return stream;
41+
}
42+
43+
std::ostream& operator<<(std::ostream& stream, Ts ts) {
44+
stream << ToIso8601(ts.val);
45+
return stream;
46+
}
47+
} // namespace databento::pretty

src/record.cpp

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include "databento/enums.hpp"
66
#include "databento/exceptions.hpp" // InvalidArgumentError
7-
#include "databento/fixed_price.hpp"
7+
#include "databento/pretty.hpp" // Px
88
#include "stream_op_helper.hpp"
99

1010
using databento::Record;
@@ -229,7 +229,7 @@ std::ostream& operator<<(std::ostream& stream, const MboMsg& mbo_msg) {
229229
.Build()
230230
.AddField("hd", mbo_msg.hd)
231231
.AddField("order_id", mbo_msg.order_id)
232-
.AddField("price", FixPx{mbo_msg.price})
232+
.AddField("price", pretty::Px{mbo_msg.price})
233233
.AddField("size", mbo_msg.size)
234234
.AddField("flags", mbo_msg.flags)
235235
.AddField("channel_id", mbo_msg.channel_id)
@@ -246,8 +246,8 @@ std::ostream& operator<<(std::ostream& stream, const BidAskPair& ba_pair) {
246246
.SetSpacer(" ")
247247
.SetTypeName("BidAskPair")
248248
.Build()
249-
.AddField("bid_px", FixPx{ba_pair.bid_px})
250-
.AddField("ask_px", FixPx{ba_pair.ask_px})
249+
.AddField("bid_px", pretty::Px{ba_pair.bid_px})
250+
.AddField("ask_px", pretty::Px{ba_pair.ask_px})
251251
.AddField("bid_sz", ba_pair.bid_sz)
252252
.AddField("ask_sz", ba_pair.ask_sz)
253253
.AddField("bid_ct", ba_pair.bid_ct)
@@ -263,8 +263,8 @@ std::ostream& operator<<(std::ostream& stream,
263263
.SetSpacer(" ")
264264
.SetTypeName("ConsolidatedBidAskPair")
265265
.Build()
266-
.AddField("bid_px", FixPx{ba_pair.bid_px})
267-
.AddField("ask_px", FixPx{ba_pair.ask_px})
266+
.AddField("bid_px", pretty::Px{ba_pair.bid_px})
267+
.AddField("ask_px", pretty::Px{ba_pair.ask_px})
268268
.AddField("bid_sz", ba_pair.bid_sz)
269269
.AddField("ask_sz", ba_pair.ask_sz)
270270
.AddField("bid_pb", ba_pair.bid_pb)
@@ -278,7 +278,7 @@ std::ostream& operator<<(std::ostream& stream, const Mbp1Msg& mbp_msg) {
278278
.SetSpacer("\n ")
279279
.Build()
280280
.AddField("hd", mbp_msg.hd)
281-
.AddField("price", FixPx{mbp_msg.price})
281+
.AddField("price", pretty::Px{mbp_msg.price})
282282
.AddField("size", mbp_msg.size)
283283
.AddField("action", mbp_msg.action)
284284
.AddField("side", mbp_msg.side)
@@ -303,7 +303,7 @@ std::ostream& operator<<(std::ostream& stream, const Mbp10Msg& mbp_msg) {
303303
.SetSpacer("\n ")
304304
.Build()
305305
.AddField("hd", mbp_msg.hd)
306-
.AddField("price", FixPx{mbp_msg.price})
306+
.AddField("price", pretty::Px{mbp_msg.price})
307307
.AddField("size", mbp_msg.size)
308308
.AddField("action", mbp_msg.action)
309309
.AddField("side", mbp_msg.side)
@@ -323,7 +323,7 @@ std::ostream& operator<<(std::ostream& stream, const BboMsg& bbo_msg) {
323323
.SetSpacer("\n ")
324324
.Build()
325325
.AddField("hd", bbo_msg.hd)
326-
.AddField("price", FixPx{bbo_msg.price})
326+
.AddField("price", pretty::Px{bbo_msg.price})
327327
.AddField("size", bbo_msg.size)
328328
.AddField("side", bbo_msg.side)
329329
.AddField("flags", bbo_msg.flags)
@@ -339,7 +339,7 @@ std::ostream& operator<<(std::ostream& stream, const Cmbp1Msg& cmbp1_msg) {
339339
.SetSpacer("\n ")
340340
.Build()
341341
.AddField("hd", cmbp1_msg.hd)
342-
.AddField("price", FixPx{cmbp1_msg.price})
342+
.AddField("price", pretty::Px{cmbp1_msg.price})
343343
.AddField("size", cmbp1_msg.size)
344344
.AddField("action", cmbp1_msg.action)
345345
.AddField("side", cmbp1_msg.side)
@@ -356,7 +356,7 @@ std::ostream& operator<<(std::ostream& stream, const CbboMsg& cbbo_msg) {
356356
.SetSpacer("\n ")
357357
.Build()
358358
.AddField("hd", cbbo_msg.hd)
359-
.AddField("price", FixPx{cbbo_msg.price})
359+
.AddField("price", pretty::Px{cbbo_msg.price})
360360
.AddField("size", cbbo_msg.size)
361361
.AddField("side", cbbo_msg.side)
362362
.AddField("flags", cbbo_msg.flags)
@@ -373,7 +373,7 @@ std::ostream& operator<<(std::ostream& stream, const TradeMsg& trade_msg) {
373373
.SetTypeName("TradeMsg")
374374
.Build()
375375
.AddField("hd", trade_msg.hd)
376-
.AddField("price", FixPx{trade_msg.price})
376+
.AddField("price", pretty::Px{trade_msg.price})
377377
.AddField("size", trade_msg.size)
378378
.AddField("action", trade_msg.action)
379379
.AddField("side", trade_msg.side)
@@ -393,10 +393,10 @@ std::ostream& operator<<(std::ostream& stream, const OhlcvMsg& ohlcv_msg) {
393393
.SetTypeName("OhlcvMsg")
394394
.Build()
395395
.AddField("hd", ohlcv_msg.hd)
396-
.AddField("open", FixPx{ohlcv_msg.open})
397-
.AddField("high", FixPx{ohlcv_msg.high})
398-
.AddField("low", FixPx{ohlcv_msg.low})
399-
.AddField("close", FixPx{ohlcv_msg.close})
396+
.AddField("open", pretty::Px{ohlcv_msg.open})
397+
.AddField("high", pretty::Px{ohlcv_msg.high})
398+
.AddField("low", pretty::Px{ohlcv_msg.low})
399+
.AddField("close", pretty::Px{ohlcv_msg.close})
400400
.AddField("volume", ohlcv_msg.volume)
401401
.Finish();
402402
}
@@ -429,21 +429,24 @@ std::ostream& operator<<(std::ostream& stream,
429429
.Build()
430430
.AddField("hd", instr_def_msg.hd)
431431
.AddField("ts_recv", instr_def_msg.ts_recv)
432-
.AddField("min_price_increment", FixPx{instr_def_msg.min_price_increment})
433-
.AddField("display_factor", FixPx{instr_def_msg.display_factor})
432+
.AddField("min_price_increment",
433+
pretty::Px{instr_def_msg.min_price_increment})
434+
.AddField("display_factor", pretty::Px{instr_def_msg.display_factor})
434435
.AddField("expiration", instr_def_msg.expiration)
435436
.AddField("activation", instr_def_msg.activation)
436-
.AddField("high_limit_price", FixPx{instr_def_msg.high_limit_price})
437-
.AddField("low_limit_price", FixPx{instr_def_msg.low_limit_price})
438-
.AddField("max_price_variation", FixPx{instr_def_msg.max_price_variation})
439-
.AddField("unit_of_measure_qty", FixPx{instr_def_msg.unit_of_measure_qty})
437+
.AddField("high_limit_price", pretty::Px{instr_def_msg.high_limit_price})
438+
.AddField("low_limit_price", pretty::Px{instr_def_msg.low_limit_price})
439+
.AddField("max_price_variation",
440+
pretty::Px{instr_def_msg.max_price_variation})
441+
.AddField("unit_of_measure_qty",
442+
pretty::Px{instr_def_msg.unit_of_measure_qty})
440443
.AddField("min_price_increment_amount",
441-
FixPx{instr_def_msg.min_price_increment_amount})
442-
.AddField("price_ratio", FixPx{instr_def_msg.price_ratio})
443-
.AddField("strike_price", FixPx{instr_def_msg.strike_price})
444+
pretty::Px{instr_def_msg.min_price_increment_amount})
445+
.AddField("price_ratio", pretty::Px{instr_def_msg.price_ratio})
446+
.AddField("strike_price", pretty::Px{instr_def_msg.strike_price})
444447
.AddField("raw_instrument_id", instr_def_msg.raw_instrument_id)
445-
.AddField("leg_price", FixPx{instr_def_msg.leg_price})
446-
.AddField("leg_delta", FixPx{instr_def_msg.leg_delta})
448+
.AddField("leg_price", pretty::Px{instr_def_msg.leg_price})
449+
.AddField("leg_delta", pretty::Px{instr_def_msg.leg_delta})
447450
.AddField("inst_attrib_value", instr_def_msg.inst_attrib_value)
448451
.AddField("underlying_id", instr_def_msg.underlying_id)
449452
.AddField("market_depth_implied", instr_def_msg.market_depth_implied)
@@ -518,15 +521,17 @@ std::ostream& operator<<(std::ostream& stream,
518521
.Build()
519522
.AddField("hd", imbalance_msg.hd)
520523
.AddField("ts_recv", imbalance_msg.ts_recv)
521-
.AddField("ref_price", FixPx{imbalance_msg.ref_price})
524+
.AddField("ref_price", pretty::Px{imbalance_msg.ref_price})
522525
.AddField("auction_time", imbalance_msg.auction_time)
523-
.AddField("cont_book_clr_price", FixPx{imbalance_msg.cont_book_clr_price})
526+
.AddField("cont_book_clr_price",
527+
pretty::Px{imbalance_msg.cont_book_clr_price})
524528
.AddField("auct_interest_clr_price",
525-
FixPx{imbalance_msg.auct_interest_clr_price})
526-
.AddField("ssr_filling_price", FixPx{imbalance_msg.ssr_filling_price})
527-
.AddField("ind_match_price", FixPx{imbalance_msg.ind_match_price})
528-
.AddField("upper_collar", FixPx{imbalance_msg.upper_collar})
529-
.AddField("lower_collar", FixPx{imbalance_msg.lower_collar})
529+
pretty::Px{imbalance_msg.auct_interest_clr_price})
530+
.AddField("ssr_filling_price",
531+
pretty::Px{imbalance_msg.ssr_filling_price})
532+
.AddField("ind_match_price", pretty::Px{imbalance_msg.ind_match_price})
533+
.AddField("upper_collar", pretty::Px{imbalance_msg.upper_collar})
534+
.AddField("lower_collar", pretty::Px{imbalance_msg.lower_collar})
530535
.AddField("paired_qty", imbalance_msg.paired_qty)
531536
.AddField("total_imbalance_qty", imbalance_msg.total_imbalance_qty)
532537
.AddField("market_imbalance_qty", imbalance_msg.market_imbalance_qty)
@@ -550,7 +555,7 @@ std::ostream& operator<<(std::ostream& stream, const StatMsg& stat_msg) {
550555
.AddField("hd", stat_msg.hd)
551556
.AddField("ts_recv", stat_msg.ts_recv)
552557
.AddField("ts_ref", stat_msg.ts_ref)
553-
.AddField("price", FixPx{stat_msg.price})
558+
.AddField("price", pretty::Px{stat_msg.price})
554559
.AddField("quantity", stat_msg.quantity)
555560
.AddField("sequence", stat_msg.sequence)
556561
.AddField("ts_in_delta", stat_msg.ts_in_delta)

0 commit comments

Comments
 (0)