rusty_ems/
protocol.rs

1use rust_decimal::Decimal;
2use rusty_common::SmartString;
3use rusty_model::{
4    enums::{OrderSide, OrderType, TimeInForce},
5    instruments::InstrumentId,
6    venues::Venue,
7};
8use serde::{Deserialize, Serialize};
9use serde_bytes;
10use smallvec::SmallVec;
11use std::time::Duration;
12
13/// Serialization helper for Duration in milliseconds
14mod serde_duration_millis {
15    use serde::{Deserialize, Deserializer, Serializer};
16    use std::time::Duration;
17
18    pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
19    where
20        S: Serializer,
21    {
22        let millis = duration.as_millis() as u64;
23        serializer.serialize_u64(millis)
24    }
25
26    pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
27    where
28        D: Deserializer<'de>,
29    {
30        let millis = u64::deserialize(deserializer)?;
31        Ok(Duration::from_millis(millis))
32    }
33}
34
35/// Message types for exchange communication
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub enum ExchangeMessage {
38    /// Order requests
39    Order(OrderRequest),
40
41    /// Authentication messages
42    Auth(AuthRequest),
43
44    /// Subscription requests
45    Subscribe(Box<SubscriptionRequest>),
46
47    /// Heartbeat messages
48    Heartbeat,
49
50    /// Ping messages
51    Ping,
52
53    /// Pong responses
54    Pong,
55
56    /// Custom exchange-specific messages
57    Custom(simd_json::OwnedValue),
58
59    /// FIX messages
60    Fix(FixMessage),
61}
62
63/// Represents a raw FIX message
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct FixMessage {
66    /// Raw FIX message bytes
67    #[serde(with = "serde_bytes")]
68    pub raw_message: Vec<u8>,
69    /// FIX version (e.g., FIX.4.4, FIX.5.0SP2)
70    pub version: SmartString,
71    /// Optional message type (e.g., `NewOrderSingle`, `ExecutionReport`)
72    pub msg_type: Option<SmartString>,
73}
74
75/// A request to place, modify, or cancel an order
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct OrderRequest {
78    /// Unique request ID
79    pub request_id: SmartString,
80
81    /// Order operation type
82    pub operation: OrderOperation,
83
84    /// Order details (for New and Modify operations)
85    pub order_details: Option<OrderDetails>,
86
87    /// Order ID (for Cancel and Query operations)
88    pub order_id: Option<SmartString>,
89
90    /// Instrument ID (for canceling all orders for an instrument)
91    pub instrument_id: Option<InstrumentId>,
92
93    /// Request timestamp (nanoseconds)
94    pub timestamp: u64,
95}
96
97/// Types of order operations
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub enum OrderOperation {
100    /// Place a new order
101    New,
102
103    /// Modify an existing order
104    Modify,
105
106    /// Cancel an existing order
107    Cancel,
108
109    /// Cancel all orders for an instrument
110    CancelAll,
111
112    /// Query order status
113    Query,
114}
115
116/// Details for a new or modified order
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct OrderDetails {
119    /// Client-generated order ID
120    pub client_order_id: SmartString,
121
122    /// Instrument to trade
123    pub instrument_id: InstrumentId,
124
125    /// Order side (buy/sell)
126    pub side: OrderSide,
127
128    /// Order type
129    pub order_type: OrderType,
130
131    /// Order quantity
132    pub quantity: Decimal,
133
134    /// Order price (for limit orders)
135    pub price: Option<Decimal>,
136
137    /// Time in force
138    pub time_in_force: Option<TimeInForce>,
139
140    /// Whether the order is a post-only order
141    pub post_only: bool,
142
143    /// Whether the order is a reduce-only order
144    pub reduce_only: bool,
145
146    /// Additional exchange-specific parameters
147    pub exchange_specific: Option<simd_json::OwnedValue>,
148}
149
150/// Authentication request
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct AuthRequest {
153    /// API key
154    pub api_key: SmartString,
155
156    /// Authentication timestamp
157    pub timestamp: u64,
158
159    /// Signature (generated with secret key)
160    pub signature: SmartString,
161
162    /// Additional authentication parameters
163    pub additional_params: Option<simd_json::OwnedValue>,
164}
165
166/// Subscription request for user data streams
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct SubscriptionRequest {
169    /// Channels to subscribe to
170    pub channels: SmallVec<[SmartString; 8]>,
171
172    /// Instruments to subscribe for (if channel-specific)
173    pub instruments: Option<SmallVec<[InstrumentId; 8]>>,
174
175    /// Authentication for private channels
176    pub auth: Option<AuthRequest>,
177}
178
179/// Exchange configuration for connection management
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct ExchangeConfig {
182    /// Exchange venue
183    pub venue: Venue,
184
185    /// REST API base URL
186    pub rest_url: SmartString,
187
188    /// WebSocket API base URL
189    pub ws_url: SmartString,
190
191    /// API key
192    pub api_key: SmartString,
193
194    /// API secret
195    pub api_secret: SmartString,
196
197    /// Connection timeout
198    #[serde(with = "serde_duration_millis")]
199    pub timeout: Duration,
200
201    /// Request rate limits per endpoint category
202    pub rate_limits: SmallVec<[RateLimit; 8]>,
203
204    /// Reconnection parameters
205    pub reconnect_settings: ReconnectSettings,
206}
207
208/// Rate limit configuration
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct RateLimit {
211    /// Endpoint category (e.g., "order", "`market_data`")
212    pub category: SmartString,
213
214    /// Maximum requests per window
215    pub max_requests: usize,
216
217    /// Time window in milliseconds
218    pub window_ms: u64,
219
220    /// Whether the limit is weight-based
221    pub is_weight_based: bool,
222}
223
224/// Reconnection settings
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct ReconnectSettings {
227    /// Maximum number of reconnection attempts
228    pub max_attempts: usize,
229
230    /// Initial delay between reconnection attempts (ms)
231    pub initial_delay_ms: u64,
232
233    /// Maximum delay between reconnection attempts (ms)
234    pub max_delay_ms: u64,
235
236    /// Whether to use exponential backoff
237    pub use_exponential_backoff: bool,
238}
239
240impl Default for ReconnectSettings {
241    fn default() -> Self {
242        Self {
243            max_attempts: 10,
244            initial_delay_ms: 1000,
245            max_delay_ms: 30000,
246            use_exponential_backoff: true,
247        }
248    }
249}
250
251/// Exchange-specific details for normalization and interoperability
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct ExchangeDetails {
254    /// Exchange venue
255    pub venue: Venue,
256
257    /// Supported order types
258    pub supported_order_types: SmallVec<[OrderType; 4]>,
259
260    /// Supported time in force options
261    pub supported_time_in_force: SmallVec<[TimeInForce; 4]>,
262
263    /// Whether the exchange supports modifying orders
264    pub supports_modify: bool,
265
266    /// Whether the exchange supports post-only orders
267    pub supports_post_only: bool,
268
269    /// Whether the exchange supports reduce-only orders
270    pub supports_reduce_only: bool,
271
272    /// Maximum number of open orders allowed per account
273    pub max_open_orders: Option<usize>,
274
275    /// Precision requirements for quantity and price
276    pub decimal_precision: DecimalPrecision,
277}
278
279/// Precision requirements for decimal values
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct DecimalPrecision {
282    /// Price precision (decimal places)
283    pub price_precision: u8,
284
285    /// Quantity precision (decimal places)
286    pub quantity_precision: u8,
287
288    /// Minimum order quantity
289    pub min_quantity: Decimal,
290
291    /// Minimum order value (price * quantity)
292    pub min_notional: Decimal,
293}