Skip to main content

rangebar_core/
trade.rs

1//! Trade and data source types
2//!
3//! Extracted from types.rs (Phase 2c refactoring)
4
5use crate::fixed_point::FixedPoint;
6use serde::{Deserialize, Serialize};
7
8/// Data source for market data (future-proofing for multi-exchange support)
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
10#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
11pub enum DataSource {
12    /// Binance Spot Market (8 fields including is_best_match)
13    BinanceSpot,
14    /// Binance USD-Margined Futures (7 fields without is_best_match)
15    #[default]
16    BinanceFuturesUM,
17    /// Binance Coin-Margined Futures
18    BinanceFuturesCM,
19}
20
21/// Aggregate trade data from Binance markets
22///
23/// Represents a single AggTrade record which aggregates multiple individual
24/// exchange trades that occurred at the same price within ~100ms timeframe.
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
27pub struct AggTrade {
28    /// Aggregate trade ID (unique per AggTrade record)
29    pub agg_trade_id: i64,
30
31    /// Price as fixed-point integer
32    pub price: FixedPoint,
33
34    /// Volume as fixed-point integer (total quantity across all individual trades)
35    pub volume: FixedPoint,
36
37    /// First individual trade ID in this aggregation
38    pub first_trade_id: i64,
39
40    /// Last individual trade ID in this aggregation
41    pub last_trade_id: i64,
42
43    /// Timestamp in microseconds (preserves maximum precision)
44    pub timestamp: i64,
45
46    /// Whether buyer is market maker (true = sell pressure, false = buy pressure)
47    /// Critical for order flow analysis and market microstructure
48    pub is_buyer_maker: bool,
49
50    /// Whether trade was best price match (Spot market only)
51    /// None for futures markets, Some(bool) for spot markets
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub is_best_match: Option<bool>,
54}
55
56impl AggTrade {
57    /// Number of individual exchange trades in this aggregated record
58    ///
59    /// Each AggTrade record represents multiple individual trades that occurred
60    /// at the same price within the same ~100ms window on the exchange.
61    pub fn individual_trade_count(&self) -> i64 {
62        self.last_trade_id - self.first_trade_id + 1
63    }
64
65    /// Turnover (price * volume) as i128 to prevent overflow
66    pub fn turnover(&self) -> i128 {
67        (self.price.0 as i128) * (self.volume.0 as i128)
68    }
69}