use std::ffi::c_char;
use databento::dbn;
use nautilus_core::UnixNanos;
use nautilus_model::{enums::FromU8, identifiers::InstrumentId, types::Quantity};
use super::primitives::{
decode_optional_price, decode_optional_quantity, decode_price_or_undef, parse_order_side,
};
use crate::{
enums::{DatabentoStatisticType, DatabentoStatisticUpdateAction},
types::{DatabentoImbalance, DatabentoStatistics},
};
pub fn decode_imbalance_msg(
msg: &dbn::ImbalanceMsg,
instrument_id: InstrumentId,
price_precision: u8,
ts_init: Option<UnixNanos>,
) -> anyhow::Result<DatabentoImbalance> {
let ts_event = msg.ts_recv.into();
let ts_init = ts_init.unwrap_or(ts_event);
Ok(DatabentoImbalance::new(
instrument_id,
decode_price_or_undef(msg.ref_price, price_precision),
decode_price_or_undef(msg.cont_book_clr_price, price_precision),
decode_price_or_undef(msg.auct_interest_clr_price, price_precision),
Quantity::new(f64::from(msg.paired_qty), 0),
Quantity::new(f64::from(msg.total_imbalance_qty), 0),
parse_order_side(msg.side),
msg.significant_imbalance as c_char,
msg.hd.ts_event.into(),
ts_event,
ts_init,
))
}
pub fn decode_statistics_msg(
msg: &dbn::StatMsg,
instrument_id: InstrumentId,
price_precision: u8,
ts_init: Option<UnixNanos>,
) -> anyhow::Result<Option<DatabentoStatistics>> {
let Some(stat_type) = u8::try_from(msg.stat_type)
.ok()
.and_then(DatabentoStatisticType::from_u8)
else {
log::warn!(
"Skipping unsupported `stat_type` {} for {instrument_id}",
msg.stat_type,
);
return Ok(None);
};
let update_action =
DatabentoStatisticUpdateAction::from_u8(msg.update_action).ok_or_else(|| {
anyhow::anyhow!("Invalid value for `update_action`: {}", msg.update_action)
})?;
let ts_event = msg.ts_recv.into();
let ts_init = ts_init.unwrap_or(ts_event);
Ok(Some(DatabentoStatistics::new(
instrument_id,
stat_type,
update_action,
decode_optional_price(msg.price, price_precision),
decode_optional_quantity(msg.quantity),
msg.channel_id,
msg.stat_flags,
msg.sequence,
msg.ts_ref.into(),
msg.ts_in_delta,
msg.hd.ts_event.into(),
ts_event,
ts_init,
)))
}
#[must_use]
pub fn is_supported_stat_type(stat_type: u16) -> bool {
u8::try_from(stat_type)
.ok()
.and_then(DatabentoStatisticType::from_u8)
.is_some()
}