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
13mod 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#[derive(Debug, Clone, Serialize, Deserialize)]
37pub enum ExchangeMessage {
38 Order(OrderRequest),
40
41 Auth(AuthRequest),
43
44 Subscribe(Box<SubscriptionRequest>),
46
47 Heartbeat,
49
50 Ping,
52
53 Pong,
55
56 Custom(simd_json::OwnedValue),
58
59 Fix(FixMessage),
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct FixMessage {
66 #[serde(with = "serde_bytes")]
68 pub raw_message: Vec<u8>,
69 pub version: SmartString,
71 pub msg_type: Option<SmartString>,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct OrderRequest {
78 pub request_id: SmartString,
80
81 pub operation: OrderOperation,
83
84 pub order_details: Option<OrderDetails>,
86
87 pub order_id: Option<SmartString>,
89
90 pub instrument_id: Option<InstrumentId>,
92
93 pub timestamp: u64,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99pub enum OrderOperation {
100 New,
102
103 Modify,
105
106 Cancel,
108
109 CancelAll,
111
112 Query,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct OrderDetails {
119 pub client_order_id: SmartString,
121
122 pub instrument_id: InstrumentId,
124
125 pub side: OrderSide,
127
128 pub order_type: OrderType,
130
131 pub quantity: Decimal,
133
134 pub price: Option<Decimal>,
136
137 pub time_in_force: Option<TimeInForce>,
139
140 pub post_only: bool,
142
143 pub reduce_only: bool,
145
146 pub exchange_specific: Option<simd_json::OwnedValue>,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct AuthRequest {
153 pub api_key: SmartString,
155
156 pub timestamp: u64,
158
159 pub signature: SmartString,
161
162 pub additional_params: Option<simd_json::OwnedValue>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct SubscriptionRequest {
169 pub channels: SmallVec<[SmartString; 8]>,
171
172 pub instruments: Option<SmallVec<[InstrumentId; 8]>>,
174
175 pub auth: Option<AuthRequest>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct ExchangeConfig {
182 pub venue: Venue,
184
185 pub rest_url: SmartString,
187
188 pub ws_url: SmartString,
190
191 pub api_key: SmartString,
193
194 pub api_secret: SmartString,
196
197 #[serde(with = "serde_duration_millis")]
199 pub timeout: Duration,
200
201 pub rate_limits: SmallVec<[RateLimit; 8]>,
203
204 pub reconnect_settings: ReconnectSettings,
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct RateLimit {
211 pub category: SmartString,
213
214 pub max_requests: usize,
216
217 pub window_ms: u64,
219
220 pub is_weight_based: bool,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct ReconnectSettings {
227 pub max_attempts: usize,
229
230 pub initial_delay_ms: u64,
232
233 pub max_delay_ms: u64,
235
236 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#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct ExchangeDetails {
254 pub venue: Venue,
256
257 pub supported_order_types: SmallVec<[OrderType; 4]>,
259
260 pub supported_time_in_force: SmallVec<[TimeInForce; 4]>,
262
263 pub supports_modify: bool,
265
266 pub supports_post_only: bool,
268
269 pub supports_reduce_only: bool,
271
272 pub max_open_orders: Option<usize>,
274
275 pub decimal_precision: DecimalPrecision,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct DecimalPrecision {
282 pub price_precision: u8,
284
285 pub quantity_precision: u8,
287
288 pub min_quantity: Decimal,
290
291 pub min_notional: Decimal,
293}