// file: kb_lib/src/db/dtos/pair_candle.rs //! Pair-candle DTO. /// Application-facing pair-candle DTO. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct KbPairCandleDto { /// Optional numeric primary key. pub id: std::option::Option, /// Related pair id. pub pair_id: i64, /// Candle timeframe in seconds. pub timeframe_seconds: i64, /// Inclusive bucket start in unix seconds. pub bucket_start_unix: i64, /// Exclusive bucket end in unix seconds. pub bucket_end_unix: i64, /// Open price in quote-per-base units. pub open_price_quote_per_base: f64, /// High price in quote-per-base units. pub high_price_quote_per_base: f64, /// Low price in quote-per-base units. pub low_price_quote_per_base: f64, /// Close price in quote-per-base units. pub close_price_quote_per_base: f64, /// Trade count inside the candle. pub trade_count: i64, /// Buy count inside the candle. pub buy_count: i64, /// Sell count inside the candle. pub sell_count: i64, /// Aggregated base volume as decimal text when available. pub base_volume_raw: std::option::Option, /// Aggregated quote volume as decimal text when available. pub quote_volume_raw: std::option::Option, /// Optional first trade signature inside the candle. pub first_trade_signature: std::option::Option, /// Optional last trade signature inside the candle. pub last_trade_signature: std::option::Option, /// Creation timestamp. pub created_at: chrono::DateTime, /// Update timestamp. pub updated_at: chrono::DateTime, } impl KbPairCandleDto { /// Creates a new pair-candle DTO. #[allow(clippy::too_many_arguments)] pub fn new( pair_id: i64, timeframe_seconds: i64, bucket_start_unix: i64, bucket_end_unix: i64, open_price_quote_per_base: f64, high_price_quote_per_base: f64, low_price_quote_per_base: f64, close_price_quote_per_base: f64, trade_count: i64, buy_count: i64, sell_count: i64, base_volume_raw: std::option::Option, quote_volume_raw: std::option::Option, first_trade_signature: std::option::Option, last_trade_signature: std::option::Option, ) -> Self { let now = chrono::Utc::now(); Self { id: None, pair_id, timeframe_seconds, bucket_start_unix, bucket_end_unix, open_price_quote_per_base, high_price_quote_per_base, low_price_quote_per_base, close_price_quote_per_base, trade_count, buy_count, sell_count, base_volume_raw, quote_volume_raw, first_trade_signature, last_trade_signature, created_at: now, updated_at: now, } } } impl TryFrom for KbPairCandleDto { type Error = crate::KbError; fn try_from(entity: crate::KbPairCandleEntity) -> Result { let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at); let created_at = match created_at_result { Ok(created_at) => created_at.with_timezone(&chrono::Utc), Err(error) => { return Err(crate::KbError::Db(format!( "cannot parse pair_candle created_at '{}': {}", entity.created_at, error ))); } }; let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at); let updated_at = match updated_at_result { Ok(updated_at) => updated_at.with_timezone(&chrono::Utc), Err(error) => { return Err(crate::KbError::Db(format!( "cannot parse pair_candle updated_at '{}': {}", entity.updated_at, error ))); } }; Ok(Self { id: Some(entity.id), pair_id: entity.pair_id, timeframe_seconds: entity.timeframe_seconds, bucket_start_unix: entity.bucket_start_unix, bucket_end_unix: entity.bucket_end_unix, open_price_quote_per_base: entity.open_price_quote_per_base, high_price_quote_per_base: entity.high_price_quote_per_base, low_price_quote_per_base: entity.low_price_quote_per_base, close_price_quote_per_base: entity.close_price_quote_per_base, trade_count: entity.trade_count, buy_count: entity.buy_count, sell_count: entity.sell_count, base_volume_raw: entity.base_volume_raw, quote_volume_raw: entity.quote_volume_raw, first_trade_signature: entity.first_trade_signature, last_trade_signature: entity.last_trade_signature, created_at, updated_at, }) } }