Skip to content

VER: Release 0.40.0 #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
BasedOnStyle: Google
ColumnLimit: 88
IncludeCategories:
- Regex: '^<(httplib|nlohmann)'
Priority: 1
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## 0.40.0 - 2025-07-29

### Enhancements
- Added `OhlcvEod` variant to `RType`
- Added documentation to more enums and record structs
- Aligned string representation of `RType` with Rust

### Breaking changes
- Switched to `std::byte` for most padding fields in record structs. These fields are
now initialized by default
- Hidden padding fields now begin with `_`

### Bug fixes
- Added missing `IndexTs()` method to `v1::InstrumentDefMsg`, `v2::InstrumentDefMsg`,
and `v1::SymbolMappingMsg`
- Fixed error in templated overload of `DbnDecoder::EncodeRecord()`
- Removed unused `Disk` and `S3` variants from `Delivery` enum

## 0.39.1 - 2025-07-22

### Bug fixes
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24..4.0)

project(
databento
VERSION 0.39.1
VERSION 0.40.0
LANGUAGES CXX
DESCRIPTION "Official Databento client library"
)
Expand Down
6 changes: 3 additions & 3 deletions examples/historical/batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
int main() {
auto client = databento::HistoricalBuilder{}.SetKeyFromEnv().Build();

const auto job = client.BatchSubmitJob(databento::dataset::kGlbxMdp3,
{"GEZ2"}, databento::Schema::Trades,
{"2022-08-26", "2022-09-27"});
const auto job =
client.BatchSubmitJob(databento::dataset::kGlbxMdp3, {"GEZ2"},
databento::Schema::Trades, {"2022-08-26", "2022-09-27"});
const auto all_jobs = client.BatchListJobs();

const auto all_job_it = std::find_if(
Expand Down
24 changes: 10 additions & 14 deletions examples/historical/metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ int main() {
}
std::cout << '\n';

const auto fields = client.MetadataListFields(databento::Encoding::Dbn,
databento::Schema::Trades);
const auto fields =
client.MetadataListFields(databento::Encoding::Dbn, databento::Schema::Trades);
std::cout << "Fields:\n";
for (const auto& field_detail : fields) {
std::cout << "- " << field_detail << '\n';
}
std::cout << '\n';

const auto dataset_conditions = client.MetadataGetDatasetCondition(
"GLBX.MDP3", {"2019-06-01", "2019-08-01"});
const auto dataset_conditions =
client.MetadataGetDatasetCondition("GLBX.MDP3", {"2019-06-01", "2019-08-01"});
std::cout << "Conditions:\n";
for (const auto& dataset_condition : dataset_conditions) {
std::cout << "- " << dataset_condition << "\n";
Expand All @@ -52,26 +52,22 @@ int main() {
for (const auto& [mode, unit_prices] : all_unit_prices) {
const auto* mode_str = ToString(mode);
for (const auto [schema, price] : unit_prices) {
std::cout << "- (" << mode_str << ", " << schema << "): " << price
<< '\n';
std::cout << "- (" << mode_str << ", " << schema << "): " << price << '\n';
}
}
std::cout << '\n';

const auto record_count =
client.MetadataGetRecordCount(kGlbxMdp3, {"2020-12-28", "2020-12-29"},
{"ESH1"}, databento::Schema::Mbo);
const auto record_count = client.MetadataGetRecordCount(
kGlbxMdp3, {"2020-12-28", "2020-12-29"}, {"ESH1"}, databento::Schema::Mbo);
std::cout << "Record count: " << record_count << "\n\n";

const std::size_t billable_size = client.MetadataGetBillableSize(
kGlbxMdp3, {"2020-12-28", "2020-12-29"}, {"ESH1"}, databento::Schema::Mbo,
databento::SType::RawSymbol, {});
std::cout << "Billable size (uncompressed binary bytes): " << billable_size
<< "\n\n";
std::cout << "Billable size (uncompressed binary bytes): " << billable_size << "\n\n";

const auto cost =
client.MetadataGetCost(kGlbxMdp3, {"2020-12-28", "2020-12-29"}, {"ESH1"},
databento::Schema::Mbo);
const auto cost = client.MetadataGetCost(kGlbxMdp3, {"2020-12-28", "2020-12-29"},
{"ESH1"}, databento::Schema::Mbo);
std::cout << "Cost (in cents): " << cost << '\n';

return 0;
Expand Down
11 changes: 5 additions & 6 deletions examples/historical/readme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ int main() {
};
auto print_trades = [&symbol_map](const Record& record) {
const auto& trade_msg = record.Get<TradeMsg>();
std::cout << "Received trade for " << symbol_map.At(trade_msg) << ": "
<< trade_msg << '\n';
std::cout << "Received trade for " << symbol_map.At(trade_msg) << ": " << trade_msg
<< '\n';
return KeepGoing::Continue;
};
client.TimeseriesGetRange(
"GLBX.MDP3", {"2022-06-10T14:30", "2022-06-10T14:40"}, {"ESM2", "NQZ2"},
Schema::Trades, SType::RawSymbol, SType::InstrumentId, {}, decode_symbols,
print_trades);
client.TimeseriesGetRange("GLBX.MDP3", {"2022-06-10T14:30", "2022-06-10T14:40"},
{"ESM2", "NQZ2"}, Schema::Trades, SType::RawSymbol,
SType::InstrumentId, {}, decode_symbols, print_trades);
}
// NOLINTEND(google-build-using-namespace)
7 changes: 3 additions & 4 deletions examples/historical/timeseries_get_range_to_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ int main() {
auto client = databento::HistoricalBuilder{}.SetKeyFromEnv().Build();
const auto limit = 1000;
databento::DbnFileStore dbn_file_store = client.TimeseriesGetRangeToFile(
databento::dataset::kGlbxMdp3, {"2022-10-03T00:00", "2022-10-04T00:00"},
{"ESZ2"}, databento::Schema::Ohlcv1M, databento::SType::RawSymbol,
databento::SType::InstrumentId, limit,
"ESZ2-ohlcv1m-20201003-20201004.dbn.zst");
databento::dataset::kGlbxMdp3, {"2022-10-03T00:00", "2022-10-04T00:00"}, {"ESZ2"},
databento::Schema::Ohlcv1M, databento::SType::RawSymbol,
databento::SType::InstrumentId, limit, "ESZ2-ohlcv1m-20201003-20201004.dbn.zst");
dbn_file_store.Replay([](const databento::Record record) {
const auto& ohlcv_bar = record.Get<databento::OhlcvMsg>();
std::cout << ohlcv_bar << '\n';
Expand Down
21 changes: 10 additions & 11 deletions examples/live/live_smoke_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ std::pair<bool, UnixNanos> TryConvertToUnixNanos(const char* start) {
return std::make_pair(true, UnixNanos{std::chrono::nanoseconds(result)});
}

void ProcessRecords(LiveBlocking& client, Schema schema,
bool start_from_epoch) {
void ProcessRecords(LiveBlocking& client, Schema schema, bool start_from_epoch) {
client.Start();

std::cout << "Starting client...\n";
Expand All @@ -46,7 +45,7 @@ void ProcessRecords(LiveBlocking& client, Schema schema,
// outside trading hours
auto expected_rtype = Record::RTypeFromSchema(schema);
if (!start_from_epoch) {
expected_rtype = databento::rtype::SymbolMapping;
expected_rtype = databento::RType::SymbolMapping;
}

constexpr auto timeout = std::chrono::seconds{30};
Expand Down Expand Up @@ -112,9 +111,9 @@ class ArgParser {
void Parse(int argc, char* argv[]) {
for (auto i = 1; i < argc;) {
const auto cur_arg = argv[i];
auto it = std::find_if(
args.begin(), args.end(),
[&cur_arg](const auto& arg) { return cur_arg == arg.arg; });
auto it = std::find_if(args.begin(), args.end(), [&cur_arg](const auto& arg) {
return cur_arg == arg.arg;
});
if (it != args.end()) {
it->value = argv[i + 1];
}
Expand All @@ -123,9 +122,9 @@ class ArgParser {
}

const char* Get(const std::string& arg_name) const {
auto it = std::find_if(
args.begin(), args.end(),
[&arg_name](const auto& arg) { return arg_name == arg.name; });
auto it = std::find_if(args.begin(), args.end(), [&arg_name](const auto& arg) {
return arg_name == arg.name;
});

if (it == args.end()) {
return nullptr;
Expand All @@ -144,8 +143,8 @@ ArgParser ParseArgs(int argc, char* argv[]
ArgParser parser;
parser.Add(ArgParser::Arg{"gateway", "--gateway"});
parser.Add(ArgParser::Arg{"port", "--port", "13000"});
parser.Add(ArgParser::Arg{"api_key_env_var", "--api-key-env-var",
"DATABENTO_API_KEY"});
parser.Add(
ArgParser::Arg{"api_key_env_var", "--api-key-env-var", "DATABENTO_API_KEY"});
parser.Add(ArgParser::Arg{"dataset", "--dataset"});
parser.Add(ArgParser::Arg{"schema", "--schema"});
parser.Add(ArgParser::Arg{"stype", "--stype"});
Expand Down
11 changes: 4 additions & 7 deletions examples/live/readme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ using namespace databento;
int main() {
PitSymbolMap symbol_mappings;

auto client = LiveBuilder{}
.SetKeyFromEnv()
.SetDataset(Dataset::GlbxMdp3)
.BuildThreaded();
auto client =
LiveBuilder{}.SetKeyFromEnv().SetDataset(Dataset::GlbxMdp3).BuildThreaded();

auto handler = [&symbol_mappings](const Record& rec) {
symbol_mappings.OnRecord(rec);
if (const auto* trade = rec.GetIf<TradeMsg>()) {
std::cout << "Received trade for "
<< symbol_mappings[trade->hd.instrument_id] << ':' << *trade
<< '\n';
std::cout << "Received trade for " << symbol_mappings[trade->hd.instrument_id]
<< ':' << *trade << '\n';
}
return KeepGoing::Continue;
};
Expand Down
21 changes: 9 additions & 12 deletions examples/live/simple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ static std::sig_atomic_t volatile gSignal;

int main() {
databento::PitSymbolMap symbol_mappings;
auto log_receiver = std::make_unique<databento::ConsoleLogReceiver>(
databento::LogLevel::Debug);
auto log_receiver =
std::make_unique<databento::ConsoleLogReceiver>(databento::LogLevel::Debug);

auto client = databento::LiveBuilder{}
.SetLogReceiver(log_receiver.get())
Expand All @@ -30,10 +30,8 @@ int main() {
std::signal(SIGINT, [](int signal) { gSignal = signal; });

std::vector<std::string> symbols{"ESZ5", "ESZ5 C6200", "ESZ5 P5500"};
client.Subscribe(symbols, databento::Schema::Definition,
databento::SType::RawSymbol);
client.Subscribe(symbols, databento::Schema::Mbo,
databento::SType::RawSymbol);
client.Subscribe(symbols, databento::Schema::Definition, databento::SType::RawSymbol);
client.Subscribe(symbols, databento::Schema::Mbo, databento::SType::RawSymbol);

auto metadata_callback = [](databento::Metadata&& metadata) {
std::cout << metadata << '\n';
Expand All @@ -43,15 +41,14 @@ int main() {
switch (rec.RType()) {
case RType::Mbo: {
auto ohlcv = rec.Get<databento::WithTsOut<databento::MboMsg>>();
std::cout << "Received tick for "
<< symbol_mappings[ohlcv.rec.hd.instrument_id]
<< " with ts_out " << ohlcv.ts_out.time_since_epoch().count()
<< ": " << ohlcv.rec << '\n';
std::cout << "Received tick for " << symbol_mappings[ohlcv.rec.hd.instrument_id]
<< " with ts_out " << ohlcv.ts_out.time_since_epoch().count() << ": "
<< ohlcv.rec << '\n';
break;
}
case RType::InstrumentDef: {
std::cout << "Received definition: "
<< rec.Get<databento::InstrumentDefMsg>() << '\n';
std::cout << "Received definition: " << rec.Get<databento::InstrumentDefMsg>()
<< '\n';
break;
}
case RType::SymbolMapping: {
Expand Down
11 changes: 4 additions & 7 deletions include/databento/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <cstdint>
#include <limits>

#include "databento/system.hpp" // DATABENTO_CXX_COMPILER_*, DATABENTO_SYSTEM_*
#include "databento/system.hpp" // DATABENTO_CXX_COMPILER_*, DATABENTO_SYSTEM_*
#include "databento/version.hpp" // DATABENTO_VERSION

namespace databento {
Expand All @@ -15,14 +15,11 @@ static constexpr std::int64_t kFixedPriceScale = 1000000000;
// The sentinel value for an unset or null price.
static constexpr auto kUndefPrice = std::numeric_limits<std::int64_t>::max();
// The sentinel value for an unset or null order size.
static constexpr auto kUndefOrderSize =
std::numeric_limits<std::uint32_t>::max();
static constexpr auto kUndefOrderSize = std::numeric_limits<std::uint32_t>::max();
// The sentinel value for an unset statistic quantity.
static constexpr auto kUndefStatQuantity =
std::numeric_limits<std::int64_t>::max();
static constexpr auto kUndefStatQuantity = std::numeric_limits<std::int64_t>::max();
// The sentinel value for an unset or null timestamp.
static constexpr auto kUndefTimestamp =
std::numeric_limits<std::uint64_t>::max();
static constexpr auto kUndefTimestamp = std::numeric_limits<std::uint64_t>::max();
// The current version of the DBN encoding.
static constexpr auto kDbnVersion = 3;
// The length of fixed-length symbol strings.
Expand Down
14 changes: 5 additions & 9 deletions include/databento/datetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@

namespace databento {
// Nanoseconds since the UNIX epoch.
using UnixNanos =
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<uint64_t, std::nano>>;
using UnixNanos = std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<uint64_t, std::nano>>;
// A representation of the difference between two timestamps.
using TimeDeltaNanos = std::chrono::duration<int32_t, std::nano>;
std::string ToString(UnixNanos unix_nanos);
Expand All @@ -25,22 +24,19 @@ template <typename T>
struct DateTimeRange {
explicit DateTimeRange(T start_) : DateTimeRange{std::move(start_), {}} {}
// underscore to prevent shadowing
DateTimeRange(T start_, T end_)
: start{std::move(start_)}, end{std::move(end_)} {}
DateTimeRange(T start_, T end_) : start{std::move(start_)}, end{std::move(end_)} {}

T start;
T end;
};
using DateRange = DateTimeRange<std::string>;

template <typename T>
inline bool operator==(const DateTimeRange<T>& lhs,
const DateTimeRange<T>& rhs) {
inline bool operator==(const DateTimeRange<T>& lhs, const DateTimeRange<T>& rhs) {
return lhs.start == rhs.start && lhs.end == rhs.end;
}
template <typename T>
inline bool operator!=(const DateTimeRange<T>& lhs,
const DateTimeRange<T>& rhs) {
inline bool operator!=(const DateTimeRange<T>& lhs, const DateTimeRange<T>& rhs) {
return !(lhs == rhs);
}

Expand Down
13 changes: 6 additions & 7 deletions include/databento/dbn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,12 @@ inline bool operator!=(const SymbolMapping& lhs, const SymbolMapping& rhs) {

inline bool operator==(const Metadata& lhs, const Metadata& rhs) {
return lhs.version == rhs.version && lhs.dataset == rhs.dataset &&
lhs.schema == rhs.schema && lhs.start == rhs.start &&
lhs.end == rhs.end && lhs.limit == rhs.limit &&
lhs.stype_in == rhs.stype_in && lhs.stype_out == rhs.stype_out &&
lhs.ts_out == rhs.ts_out &&
lhs.symbol_cstr_len == rhs.symbol_cstr_len &&
lhs.symbols == rhs.symbols && lhs.partial == rhs.partial &&
lhs.not_found == rhs.not_found && lhs.mappings == rhs.mappings;
lhs.schema == rhs.schema && lhs.start == rhs.start && lhs.end == rhs.end &&
lhs.limit == rhs.limit && lhs.stype_in == rhs.stype_in &&
lhs.stype_out == rhs.stype_out && lhs.ts_out == rhs.ts_out &&
lhs.symbol_cstr_len == rhs.symbol_cstr_len && lhs.symbols == rhs.symbols &&
lhs.partial == rhs.partial && lhs.not_found == rhs.not_found &&
lhs.mappings == rhs.mappings;
}
inline bool operator!=(const Metadata& lhs, const Metadata& rhs) {
return !(lhs == rhs);
Expand Down
22 changes: 11 additions & 11 deletions include/databento/dbn_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ class DbnDecoder {

static std::pair<std::uint8_t, std::size_t> DecodeMetadataVersionAndSize(
const std::byte* buffer, std::size_t size);
static Metadata DecodeMetadataFields(std::uint8_t version,
const std::byte* buffer,
static Metadata DecodeMetadataFields(std::uint8_t version, const std::byte* buffer,
const std::byte* buffer_end);
// Decodes a record possibly applying upgrading the data according to the
// given version and upgrade policy. If an upgrade is applied,
// compat_buffer is modified.
static Record DecodeRecordCompat(
std::uint8_t version, VersionUpgradePolicy upgrade_policy, bool ts_out,
std::array<std::byte, kMaxRecordLen>* compat_buffer, Record rec);
static Record DecodeRecordCompat(std::uint8_t version,
VersionUpgradePolicy upgrade_policy, bool ts_out,
std::array<std::byte, kMaxRecordLen>* compat_buffer,
Record rec);

// Should be called exactly once.
Metadata DecodeMetadata();
Expand All @@ -45,12 +45,12 @@ class DbnDecoder {
private:
static std::string DecodeSymbol(std::size_t symbol_cstr_len,
const std::byte*& buffer);
static std::vector<std::string> DecodeRepeatedSymbol(
std::size_t symbol_cstr_len, const std::byte*& buffer,
const std::byte* buffer_end);
static std::vector<SymbolMapping> DecodeSymbolMappings(
std::size_t symbol_cstr_len, const std::byte*& buffer,
const std::byte* buffer_end);
static std::vector<std::string> DecodeRepeatedSymbol(std::size_t symbol_cstr_len,
const std::byte*& buffer,
const std::byte* buffer_end);
static std::vector<SymbolMapping> DecodeSymbolMappings(std::size_t symbol_cstr_len,
const std::byte*& buffer,
const std::byte* buffer_end);
static SymbolMapping DecodeSymbolMapping(std::size_t symbol_cstr_len,
const std::byte*& buffer,
const std::byte* buffer_end);
Expand Down
Loading
Loading