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}