583 lines
20 KiB
C++
583 lines
20 KiB
C++
#include "Security.h"
|
|
#include "lib/config/config.h"
|
|
#include "lib/config/protos/orders_fills_cleanup.pb.h"
|
|
#include "lib/domain_model/Security.pb.h"
|
|
#include "lib/io/JsonMacros.h"
|
|
#include "lib/md/common.h"
|
|
#include "lib/utils/pb_json_macros.h"
|
|
|
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
#include <google/protobuf/text_format.h>
|
|
#include <nlohmann/json.hpp>
|
|
|
|
namespace bts {
|
|
namespace securities {
|
|
|
|
using bts::api::Security;
|
|
using std::optional;
|
|
|
|
api::SecurityType security_type(api::Security const &security) {
|
|
return security_type(security.Contract_case());
|
|
}
|
|
|
|
api::SecurityType security_type(api::Security::ContractCase contract_case) {
|
|
switch (contract_case) {
|
|
case api::Security::ContractCase::kFuture:
|
|
return api::SecurityType::SECURITYTYPE_FUTURE;
|
|
case api::Security::ContractCase::kOption:
|
|
return api::SecurityType::SECURITYTYPE_OPTION;
|
|
case api::Security::ContractCase::kSpot:
|
|
return api::SecurityType::SECURITYTYPE_SPOT;
|
|
case api::Security::ContractCase::kSpread:
|
|
return api::SecurityType::SECURITYTYPE_SPREAD;
|
|
case api::Security::ContractCase::kSynthetic:
|
|
return api::SecurityType::SECURITYTYPE_SYNTHETIC;
|
|
case api::Security::ContractCase::CONTRACT_NOT_SET:
|
|
return api::SecurityType::SECURITYTYPE_UNSET;
|
|
}
|
|
return api::SecurityType::SECURITYTYPE_UNSET;
|
|
}
|
|
|
|
std::optional<core::TimeStamp> smallest_leg(
|
|
::google::protobuf::RepeatedPtrField<::bts::api::ContractLeg> const &l) {
|
|
bts_assert(l.size());
|
|
auto smallest = expiration(l[0].security());
|
|
for (const auto &leg : l) {
|
|
auto this_date = expiration(leg.security());
|
|
if (this_date < smallest) {
|
|
smallest = this_date;
|
|
}
|
|
}
|
|
return smallest;
|
|
}
|
|
|
|
std::optional<core::TimeStamp> expiration(api::Security const &security) {
|
|
switch (security.Contract_case()) {
|
|
case api::Security::kFuture: {
|
|
const auto &fut = security.future();
|
|
core::TimeStamp exp;
|
|
if (core::TimeStamp::from_ymd(
|
|
fut.expiration_year(), fut.expiration_month(),
|
|
fut.expiration_day(), &exp)) {
|
|
return exp;
|
|
}
|
|
break;
|
|
}
|
|
case api::Security::kOption: {
|
|
const auto &opt = security.option();
|
|
core::TimeStamp exp;
|
|
if (core::TimeStamp::from_ymd(
|
|
opt.expiration_year(), opt.expiration_month(),
|
|
opt.expiration_day(), &exp)) {
|
|
return exp;
|
|
}
|
|
break;
|
|
}
|
|
case api::Security::kSpread:
|
|
return smallest_leg(security.spread().legs());
|
|
case api::Security::kSynthetic:
|
|
return smallest_leg(security.synthetic().legs());
|
|
default:
|
|
break;
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
bool is_expired(
|
|
api::Security const &security,
|
|
core::TimeStamp now,
|
|
uint32_t sod_hh,
|
|
uint32_t sod_mm) {
|
|
auto maybe_exp = expiration(security);
|
|
if (!maybe_exp) {
|
|
return false;
|
|
}
|
|
const auto exp = *maybe_exp;
|
|
return exp < now && (exp.date() + core::TimeSpan::from_hours(sod_hh) +
|
|
core::TimeSpan::from_minutes(sod_mm)) < now;
|
|
}
|
|
|
|
bool is_expired(api::Security const &security, core::TimeStamp now) {
|
|
const auto &sod = config::get<config::SODTime>();
|
|
return is_expired(security, now, sod.sod_hh(), sod.sod_mm());
|
|
}
|
|
|
|
bool is_expired(api::Security const &security) {
|
|
return is_expired(security, core::TimeStamp::now());
|
|
}
|
|
|
|
void write_date_string(
|
|
uint32_t year, uint32_t month, uint32_t day, std::ostringstream &result) {
|
|
result << std::setw(2) << std::setfill('0') << month << "/" << std::setw(2)
|
|
<< std::setfill('0') << day << "/" << year - 2000;
|
|
}
|
|
|
|
std::ostringstream &write_leg_descriptor(
|
|
std::ostringstream &result, char separator, const api::ContractLeg &leg) {
|
|
bts_assert(leg.security().id() != md::invalid_security_key);
|
|
// Keep the string small, yet readable for diagnostic purposes.
|
|
result << (leg.side() == api::SIDE_BUY ? '+' : '-') << separator
|
|
<< leg.quantity() << "*(i=" << leg.security().id()
|
|
<< ",m=" << leg.price_multiplier() << ",d=" << leg.leg_delta() << ")";
|
|
return result;
|
|
}
|
|
|
|
std::ostringstream &write_future_descriptor(
|
|
std::ostringstream &result, const api::FutureContract &future) {
|
|
write_date_string(
|
|
future.expiration_year(), future.expiration_month(),
|
|
future.expiration_day(), result);
|
|
return result;
|
|
}
|
|
|
|
std::ostringstream &write_option_descriptor(
|
|
std::ostringstream &result,
|
|
char separator,
|
|
const api::OptionContract &option) {
|
|
write_date_string(
|
|
option.expiration_year(), option.expiration_month(),
|
|
option.expiration_day(), result);
|
|
result << separator << option.strike()
|
|
<< (option.call_put() == api::PUTORCALL_CALL ? 'C' : 'P');
|
|
return result;
|
|
}
|
|
|
|
std::ostringstream &write_legs_descriptor(
|
|
std::ostringstream &result,
|
|
char separator,
|
|
const google::protobuf::RepeatedPtrField<api::ContractLeg> &legs) {
|
|
bts_assert(legs.size() > 0);
|
|
auto it = legs.begin();
|
|
write_leg_descriptor(result, separator, *it);
|
|
while (++it != legs.end()) {
|
|
result << separator;
|
|
write_leg_descriptor(result, separator, *it);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string unique_descriptor(const api::Security &security) {
|
|
const char separator = ' ';
|
|
std::ostringstream result;
|
|
result << api::Venue_Name(security.exchange()).substr(6) << separator
|
|
<< api::SecurityType_Name(security_type(security)).substr(12)
|
|
<< descriptor(security);
|
|
switch (security.Contract_case()) {
|
|
case Security::ContractCase::kOption:
|
|
result << separator;
|
|
write_option_descriptor(result, separator, security.option());
|
|
break;
|
|
case Security::ContractCase::kFuture:
|
|
result << separator;
|
|
write_future_descriptor(result, security.future());
|
|
break;
|
|
case Security::ContractCase::kSpot:
|
|
break;
|
|
case Security::ContractCase::kSpread:
|
|
result << separator;
|
|
write_legs_descriptor(result, separator, security.spread().legs());
|
|
break;
|
|
case Security::ContractCase::kSynthetic: {
|
|
result << "pc="
|
|
<< api::SyntheticContract::PriceCalc_Name(
|
|
security.synthetic().price_calc());
|
|
write_legs_descriptor(result, separator, security.synthetic().legs());
|
|
break;
|
|
}
|
|
default:
|
|
bts_assert_msg(
|
|
false, "unique_descriptor failed due to invalid contract case");
|
|
break;
|
|
}
|
|
return result.str();
|
|
}
|
|
|
|
} // namespace securities
|
|
} // namespace bts
|
|
|
|
namespace bts::api {
|
|
|
|
using nlohmann::json;
|
|
using std::uint32_t;
|
|
|
|
void to_json(json &j, const api::ContractQuantityInfo &cqi) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, min_value);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, max_value);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, tick_unit);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, tick_base);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, multiplier);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, cqi, max_price);
|
|
}
|
|
|
|
void from_json(const json &j, api::ContractQuantityInfo &cqi) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, cqi, min_value, it);
|
|
PB_JSON_READ_VALUE(j, cqi, max_value, it);
|
|
PB_JSON_READ_VALUE(j, cqi, max_value, it);
|
|
PB_JSON_READ_VALUE(j, cqi, tick_unit, it);
|
|
PB_JSON_READ_VALUE(j, cqi, tick_base, it);
|
|
PB_JSON_READ_VALUE(j, cqi, max_price, it);
|
|
}
|
|
|
|
void to_json(json &j, const api::ContractSpecification &spec) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, low_tick);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, price_break);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, high_tick);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, cash_per_point);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, price_multiplier);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, main_fraction);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, sub_fraction);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, spec, price_display_format);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, spec, quantity_infos);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, spec, notional_quantity_infos);
|
|
}
|
|
|
|
void from_json(const json &j, api::ContractSpecification &spec) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, spec, low_tick, it);
|
|
PB_JSON_READ_VALUE(j, spec, price_break, it);
|
|
PB_JSON_READ_VALUE(j, spec, high_tick, it);
|
|
PB_JSON_READ_VALUE(j, spec, cash_per_point, it);
|
|
PB_JSON_READ_VALUE(j, spec, price_multiplier, it);
|
|
PB_JSON_READ_VALUE(j, spec, main_fraction, it);
|
|
PB_JSON_READ_VALUE(j, spec, sub_fraction, it);
|
|
PB_JSON_READ_VALUE(j, spec, price_display_format, it);
|
|
PB_JSON_READ_ARRAY(j, spec, quantity_infos, it);
|
|
PB_JSON_READ_ARRAY(j, spec, notional_quantity_infos, it);
|
|
}
|
|
|
|
void to_json(json &, const SpotContract &) {}
|
|
void from_json(const json &, SpotContract &) {}
|
|
|
|
template <class ExpContract>
|
|
static void exp_to_json(json &j, const ExpContract &ec) {
|
|
j = bts::core::TimeStamp::from_ymd(
|
|
ec.expiration_year(), ec.expiration_month(), ec.expiration_day())
|
|
.to_iso_string();
|
|
}
|
|
|
|
template <class ExpContract>
|
|
static void exp_from_json(const json &j, ExpContract &ec) {
|
|
const auto dt = bts::core::TimeStamp::from_iso_string(j.get<std::string>());
|
|
uint32_t y, m, d;
|
|
dt.to_date(y, m, d);
|
|
ec.set_expiration_year(y);
|
|
ec.set_expiration_month(m);
|
|
ec.set_expiration_day(d);
|
|
}
|
|
|
|
void to_json(json &j, const FutureContract &f) {
|
|
exp_to_json(j["expiration"], f);
|
|
}
|
|
|
|
void from_json(const json &j, FutureContract &f) {
|
|
const auto it = j.find("expiration");
|
|
if (it != j.end()) {
|
|
exp_from_json(*it, f);
|
|
}
|
|
}
|
|
|
|
void to_json(json &j, const OptionContract &opt) {
|
|
exp_to_json(j["expiration"], opt);
|
|
PB_JSON_WRITE_VALUE(j, opt, strike);
|
|
PB_JSON_WRITE_VALUE(j, opt, call_put);
|
|
}
|
|
|
|
void from_json(const json &j, OptionContract &opt) {
|
|
json::const_iterator it;
|
|
it = j.find("expiration");
|
|
if (it != j.end()) {
|
|
exp_from_json(*it, opt);
|
|
}
|
|
PB_JSON_READ_VALUE(j, opt, strike, it);
|
|
PB_JSON_READ_VALUE(j, opt, call_put, it);
|
|
}
|
|
|
|
void to_json(json &j, const ContractLeg &leg) {
|
|
PB_JSON_WRITE_STRUCT(j, leg, security);
|
|
PB_JSON_WRITE_VALUE(j, leg, quantity);
|
|
PB_JSON_WRITE_VALUE(j, leg, side);
|
|
PB_JSON_WRITE_VALUE(j, leg, price_multiplier);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, leg, leg_delta);
|
|
PB_JSON_WRITE_VALUE(j, leg, price_calc);
|
|
}
|
|
|
|
void from_json(const json &j, ContractLeg &leg) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_STRUCT(j, leg, security, it);
|
|
PB_JSON_READ_VALUE(j, leg, quantity, it);
|
|
PB_JSON_READ_VALUE(j, leg, side, it);
|
|
PB_JSON_READ_VALUE(j, leg, price_multiplier, it);
|
|
PB_JSON_READ_VALUE(j, leg, leg_delta, it);
|
|
PB_JSON_READ_VALUE(j, leg, price_calc, it);
|
|
}
|
|
|
|
void to_json(json &j, const SpreadContract &spd) {
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, spd, legs);
|
|
}
|
|
|
|
void from_json(const json &j, SpreadContract &spd) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_ARRAY(j, spd, legs, it);
|
|
}
|
|
|
|
void to_json(json &j, const SyntheticContract &syn) {
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, syn, name);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, syn, user_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, syn, legs);
|
|
PB_JSON_WRITE_VALUE(j, syn, price_calc);
|
|
}
|
|
|
|
void from_json(const json &j, SyntheticContract &syn) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_STRING(j, syn, name, it);
|
|
PB_JSON_READ_VALUE(j, syn, user_id, it);
|
|
PB_JSON_READ_ARRAY(j, syn, legs, it);
|
|
PB_JSON_READ_VALUE(j, syn, price_calc, it);
|
|
}
|
|
|
|
void to_json(json &j, const GLBXExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, cfi_code);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, cme_symbol);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, market_segment_id);
|
|
}
|
|
|
|
void from_json(const json &j, GLBXExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
PB_JSON_READ_STRING(j, data, cfi_code, it);
|
|
PB_JSON_READ_STRING(j, data, cme_symbol, it);
|
|
PB_JSON_READ_VALUE(j, data, market_segment_id, it);
|
|
}
|
|
|
|
void to_json(json &j, const CBOEExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, class_key);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, source);
|
|
}
|
|
|
|
void from_json(const json &j, CBOEExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
PB_JSON_READ_VALUE(j, data, class_key, it);
|
|
PB_JSON_READ_STRING(j, data, source, it);
|
|
}
|
|
|
|
void to_json(json &j, const CBOECFEExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, class_key);
|
|
}
|
|
|
|
void from_json(const json &j, CBOECFEExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
PB_JSON_READ_VALUE(j, data, class_key, it);
|
|
}
|
|
|
|
void to_json(json &j, const ICEExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, price_denominator);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, deal_denominator);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, settle_denominator);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, market_description);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, cleared_alias);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, product_name);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, hub_alias);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, strip_name);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, mic_code);
|
|
PB_JSON_WRITE_IF_TRUE(j, data, is_strip);
|
|
}
|
|
|
|
void from_json(const json &j, ICEExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
PB_JSON_READ_VALUE(j, data, price_denominator, it);
|
|
PB_JSON_READ_VALUE(j, data, deal_denominator, it);
|
|
PB_JSON_READ_VALUE(j, data, settle_denominator, it);
|
|
PB_JSON_READ_STRING(j, data, market_description, it);
|
|
PB_JSON_READ_STRING(j, data, cleared_alias, it);
|
|
PB_JSON_READ_STRING(j, data, product_name, it);
|
|
PB_JSON_READ_STRING(j, data, hub_alias, it);
|
|
PB_JSON_READ_STRING(j, data, strip_name, it);
|
|
PB_JSON_READ_STRING(j, data, mic_code, it);
|
|
PB_JSON_READ_VALUE(j, data, is_strip, it);
|
|
}
|
|
|
|
void to_json(json &j, const TAIFEXExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, class_key);
|
|
}
|
|
|
|
void from_json(const json &j, TAIFEXExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
PB_JSON_READ_VALUE(j, data, class_key, it);
|
|
}
|
|
|
|
void to_json(json &j, const DeribitExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, DeribitExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const FTXExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, FTXExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const BinanceExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, BinanceExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const BinanceUsdsFuturesExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, BinanceUsdsFuturesExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const BinanceCoinFuturesExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, BinanceCoinFuturesExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const BinanceUsExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, BinanceUsExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const OkxExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, OkxExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const CoinbaseExchangeData &data) {
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, data, exchange_id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, data, security_desc);
|
|
}
|
|
|
|
void from_json(const json &j, CoinbaseExchangeData &data) {
|
|
json::const_iterator it;
|
|
PB_JSON_READ_VALUE(j, data, exchange_id, it);
|
|
PB_JSON_READ_STRING(j, data, security_desc, it);
|
|
}
|
|
|
|
void to_json(json &j, const Security &s) {
|
|
// clang-format off
|
|
#define CONTRACT_ONEOF(oneof) \
|
|
oneof(j, s, Spot, spot) \
|
|
oneof(j, s, Future, future) \
|
|
oneof(j, s, Option, option) \
|
|
oneof(j, s, Spread, spread) \
|
|
oneof(j, s, Synthetic, synthetic)
|
|
|
|
#define EXCHANGE_DATA_ONEOF(oneof) \
|
|
oneof(j, s, Glbx, glbx) \
|
|
oneof(j, s, Cboe, cboe) \
|
|
oneof(j, s, Cfe, cfe) \
|
|
oneof(j, s, Ice, ice) \
|
|
oneof(j, s, Deribit, deribit) \
|
|
oneof(j, s, Ftx, ftx) \
|
|
oneof(j, s, Binance, binance) \
|
|
oneof(j, s, BinanceCoinFutures, binance_coin_futures) \
|
|
oneof(j, s, BinanceUsdsFutures, binance_usds_futures) \
|
|
oneof(j, s, BinanceUs, binance_us) \
|
|
oneof(j, s, Coinbase, coinbase) \
|
|
oneof(j, s, Okx, okx) \
|
|
oneof(j, s, Taifex, taifex)
|
|
// clang-format on
|
|
|
|
PB_JSON_WRITE_IF_NOT_ZERO(j, s, id);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, s, symbol);
|
|
PB_JSON_WRITE_VALUE(j, s, exchange);
|
|
PB_JSON_WRITE_STRUCT(j, s, contract_spec);
|
|
PB_JSON_WRITE_IF_NOT_EMPTY(j, s, currency);
|
|
PB_JSON_WRITE_ONEOF(j, s, Contract, CONTRACT_ONEOF);
|
|
PB_JSON_WRITE_ONEOF(j, s, ExchangeData, EXCHANGE_DATA_ONEOF);
|
|
}
|
|
|
|
void from_json(const json &j, Security &s) {
|
|
json::const_iterator it;
|
|
|
|
#define SEC_TYPE_ONEOF(oneof) \
|
|
oneof(j, s, future, it); \
|
|
oneof(j, s, option, it); \
|
|
oneof(j, s, spread, it); \
|
|
oneof(j, s, synthetic, it)
|
|
|
|
#define CONTRACT_CASE_ONEOF(oneof) \
|
|
oneof(j, s, glbx, it); \
|
|
oneof(j, s, cboe, it); \
|
|
oneof(j, s, cfe, it); \
|
|
oneof(j, s, ice, it); \
|
|
oneof(j, s, deribit, it); \
|
|
oneof(j, s, ftx, it); \
|
|
oneof(j, s, binance, it); \
|
|
oneof(j, s, binance_usds_futures, it); \
|
|
oneof(j, s, binance_coin_futures, it); \
|
|
oneof(j, s, binance_us, it); \
|
|
oneof(j, s, coinbase, it); \
|
|
oneof(j, s, okx, it); \
|
|
oneof(j, s, taifex, it);
|
|
|
|
PB_JSON_READ_VALUE(j, s, id, it);
|
|
PB_JSON_READ_STRING(j, s, symbol, it);
|
|
PB_JSON_READ_STRING(j, s, currency, it);
|
|
PB_JSON_READ_STRUCT(j, s, contract_spec, it);
|
|
PB_JSON_READ_ONEOFS(SEC_TYPE_ONEOF);
|
|
PB_JSON_READ_ONEOFS(CONTRACT_CASE_ONEOF);
|
|
}
|
|
|
|
} // namespace bts::api
|