1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Order {
7 pub id: String,
9
10 pub symbol: String,
12
13 pub quantity: f64,
15
16 pub filled_quantity: f64,
18
19 pub price: Option<f64>,
21
22 pub stop_price: Option<f64>,
24
25 pub status: OrderStatus,
27
28 pub side: OrderSide,
30
31 pub order_type: OrderType,
33
34 pub time_in_force: TimeInForce,
36
37 pub extended_hours: bool,
39
40 pub created_at: DateTime<Utc>,
42
43 pub updated_at: DateTime<Utc>,
45
46 pub commission: f64,
48
49 pub rejected_reason: Option<String>,
51
52 pub average_fill_price: Option<f64>,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
58#[serde(rename_all = "UPPERCASE")]
59pub enum OrderStatus {
60 New,
62
63 PartiallyFilled,
65
66 Filled,
68
69 Canceled,
71
72 Rejected,
74
75 PendingCancel,
77
78 PendingNew,
80
81 PendingReplace,
83
84 Replaced,
86
87 Suspended,
89
90 Expired,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96#[serde(rename_all = "UPPERCASE")]
97pub enum OrderSide {
98 Buy,
100
101 Sell,
103
104 SellShort,
106
107 BuyToCover,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
113#[serde(rename_all = "UPPERCASE")]
114pub enum OrderType {
115 #[serde(rename = "MARKET")]
117 Market,
118
119 #[serde(rename = "LIMIT")]
121 Limit,
122
123 #[serde(rename = "STOP_LOSS")]
125 Stop,
126
127 #[serde(rename = "STOP_LOSS_LIMIT")]
129 StopLimit,
130
131 #[serde(rename = "TRAILING_STOP")]
133 TrailingStop,
134
135 #[serde(rename = "TRAILING_STOP_LIMIT")]
137 TrailingStopLimit,
138
139 #[serde(rename = "ENHANCED_LIMIT")]
141 EnhancedLimit,
142
143 #[serde(rename = "AT_AUCTION")]
145 AtAuction,
146
147 #[serde(rename = "AT_AUCTION_LIMIT")]
149 AtAuctionLimit,
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
154#[serde(rename_all = "UPPERCASE")]
155pub enum TimeInForce {
156 #[serde(rename = "DAY")]
158 Day,
159
160 #[serde(rename = "GTC")]
162 Gtc,
163
164 #[serde(rename = "GTD")]
166 Gtd,
167
168 #[serde(rename = "IOC")]
170 Ioc,
171
172 #[serde(rename = "FOK")]
174 Fok,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
179#[serde(rename_all = "UPPERCASE")]
180pub enum TrailingStopType {
181 #[serde(rename = "AMOUNT")]
183 Amount,
184
185 #[serde(rename = "PERCENT")]
187 Percent,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct OrderRequest {
193 pub symbol: String,
195
196 pub quantity: f64,
198
199 pub price: Option<f64>,
201
202 pub stop_price: Option<f64>,
204
205 pub side: OrderSide,
207
208 pub order_type: OrderType,
210
211 pub time_in_force: TimeInForce,
213
214 pub extended_hours: bool,
216
217 pub trailing_type: Option<TrailingStopType>,
219
220 pub trailing_stop_step: Option<f64>,
222
223 pub client_order_id: Option<String>,
225
226 pub instrument_id: Option<String>,
228}
229
230impl OrderRequest {
231 pub fn new() -> Self {
233 Self {
234 symbol: String::new(),
235 quantity: 0.0,
236 price: None,
237 stop_price: None,
238 side: OrderSide::Buy,
239 order_type: OrderType::Market,
240 time_in_force: TimeInForce::Day,
241 extended_hours: false,
242 trailing_type: None,
243 trailing_stop_step: None,
244 client_order_id: None,
245 instrument_id: None,
246 }
247 }
248
249 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
251 self.symbol = symbol.into();
252 self
253 }
254
255 pub fn quantity(mut self, quantity: f64) -> Self {
257 self.quantity = quantity;
258 self
259 }
260
261 pub fn price(mut self, price: f64) -> Self {
263 self.price = Some(price);
264 self
265 }
266
267 pub fn stop_price(mut self, stop_price: f64) -> Self {
269 self.stop_price = Some(stop_price);
270 self
271 }
272
273 pub fn side(mut self, side: OrderSide) -> Self {
275 self.side = side;
276 self
277 }
278
279 pub fn order_type(mut self, order_type: OrderType) -> Self {
281 self.order_type = order_type;
282 self
283 }
284
285 pub fn time_in_force(mut self, time_in_force: TimeInForce) -> Self {
287 self.time_in_force = time_in_force;
288 self
289 }
290
291 pub fn extended_hours(mut self, extended_hours: bool) -> Self {
293 self.extended_hours = extended_hours;
294 self
295 }
296
297 pub fn trailing_type(mut self, trailing_type: TrailingStopType) -> Self {
299 self.trailing_type = Some(trailing_type);
300 self
301 }
302
303 pub fn trailing_stop_step(mut self, trailing_stop_step: f64) -> Self {
305 self.trailing_stop_step = Some(trailing_stop_step);
306 self
307 }
308
309 pub fn client_order_id(mut self, client_order_id: impl Into<String>) -> Self {
311 self.client_order_id = Some(client_order_id.into());
312 self
313 }
314
315 pub fn instrument_id(mut self, instrument_id: impl Into<String>) -> Self {
317 self.instrument_id = Some(instrument_id.into());
318 self
319 }
320
321 pub fn market() -> Self {
323 Self::new().order_type(OrderType::Market)
324 }
325
326 pub fn limit() -> Self {
328 Self::new().order_type(OrderType::Limit)
329 }
330
331 pub fn stop() -> Self {
333 Self::new().order_type(OrderType::Stop)
334 }
335
336 pub fn stop_limit() -> Self {
338 Self::new().order_type(OrderType::StopLimit)
339 }
340
341 pub fn trailing_stop() -> Self {
343 Self::new().order_type(OrderType::TrailingStop)
344 }
345
346 pub fn trailing_stop_limit() -> Self {
348 Self::new().order_type(OrderType::TrailingStopLimit)
349 }
350}
351
352impl Default for OrderRequest {
353 fn default() -> Self {
354 Self::new()
355 }
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct OrderResponse {
361 pub id: String,
363
364 pub status: OrderStatus,
366
367 pub symbol: String,
369
370 pub quantity: f64,
372
373 pub price: Option<f64>,
375
376 pub stop_price: Option<f64>,
378
379 pub side: OrderSide,
381
382 pub order_type: OrderType,
384
385 pub time_in_force: TimeInForce,
387
388 pub extended_hours: bool,
390
391 pub created_at: DateTime<Utc>,
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize)]
397pub struct OrderQueryParams {
398 pub status: Option<OrderStatus>,
400
401 pub symbol: Option<String>,
403
404 pub start_date: Option<DateTime<Utc>>,
406
407 pub end_date: Option<DateTime<Utc>>,
409
410 pub limit: Option<u32>,
412}
413
414impl OrderQueryParams {
415 pub fn new() -> Self {
417 Self {
418 status: None,
419 symbol: None,
420 start_date: None,
421 end_date: None,
422 limit: None,
423 }
424 }
425
426 pub fn status(mut self, status: OrderStatus) -> Self {
428 self.status = Some(status);
429 self
430 }
431
432 pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
434 self.symbol = Some(symbol.into());
435 self
436 }
437
438 pub fn start_date(mut self, start_date: DateTime<Utc>) -> Self {
440 self.start_date = Some(start_date);
441 self
442 }
443
444 pub fn end_date(mut self, end_date: DateTime<Utc>) -> Self {
446 self.end_date = Some(end_date);
447 self
448 }
449
450 pub fn limit(mut self, limit: u32) -> Self {
452 self.limit = Some(limit);
453 self
454 }
455}
456
457impl Default for OrderQueryParams {
458 fn default() -> Self {
459 Self::new()
460 }
461}
462
463#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct OptionOrderRequest {
466 #[serde(rename = "client_order_id")]
468 pub client_order_id: String,
469
470 #[serde(rename = "contract_id")]
472 pub contract_id: String,
473
474 #[serde(rename = "qty")]
476 pub quantity: f64,
477
478 #[serde(rename = "side")]
480 pub side: OrderSide,
481
482 #[serde(rename = "order_type")]
484 pub order_type: OrderType,
485
486 #[serde(rename = "tif")]
488 pub time_in_force: TimeInForce,
489
490 #[serde(rename = "extended_hours_trading")]
492 pub extended_hours: bool,
493
494 #[serde(rename = "limit_price", skip_serializing_if = "Option::is_none")]
496 pub price: Option<f64>,
497
498 #[serde(rename = "stop_price", skip_serializing_if = "Option::is_none")]
500 pub stop_price: Option<f64>,
501}
502
503impl OptionOrderRequest {
504 pub fn new(
506 client_order_id: impl Into<String>,
507 contract_id: impl Into<String>,
508 quantity: f64,
509 ) -> Self {
510 Self {
511 client_order_id: client_order_id.into(),
512 contract_id: contract_id.into(),
513 quantity,
514 side: OrderSide::Buy,
515 order_type: OrderType::Limit,
516 time_in_force: TimeInForce::Day,
517 extended_hours: false,
518 price: None,
519 stop_price: None,
520 }
521 }
522
523 pub fn side(mut self, side: OrderSide) -> Self {
525 self.side = side;
526 self
527 }
528
529 pub fn order_type(mut self, order_type: OrderType) -> Self {
531 self.order_type = order_type;
532 self
533 }
534
535 pub fn time_in_force(mut self, time_in_force: TimeInForce) -> Self {
537 self.time_in_force = time_in_force;
538 self
539 }
540
541 pub fn extended_hours(mut self, extended_hours: bool) -> Self {
543 self.extended_hours = extended_hours;
544 self
545 }
546
547 pub fn price(mut self, price: f64) -> Self {
549 self.price = Some(price);
550 self
551 }
552
553 pub fn stop_price(mut self, stop_price: f64) -> Self {
555 self.stop_price = Some(stop_price);
556 self
557 }
558}
559
560#[derive(Debug, Clone, Serialize, Deserialize)]
562pub struct OptionOrderPreviewRequest {
563 #[serde(rename = "account_id")]
565 pub account_id: String,
566
567 #[serde(rename = "new_orders")]
569 pub new_orders: Vec<OptionOrderRequest>,
570}
571
572impl OptionOrderPreviewRequest {
573 pub fn new(account_id: impl Into<String>) -> Self {
575 Self {
576 account_id: account_id.into(),
577 new_orders: Vec::new(),
578 }
579 }
580
581 pub fn add_order(mut self, order: OptionOrderRequest) -> Self {
583 self.new_orders.push(order);
584 self
585 }
586}
587
588#[derive(Debug, Clone, Serialize, Deserialize)]
590pub struct OptionOrderPreviewResponse {
591 pub id: String,
593
594 pub commission: f64,
596
597 pub estimated_cost: f64,
599
600 pub estimated_proceeds: f64,
602
603 pub buying_power_effect: f64,
605
606 pub margin_requirement: f64,
608
609 pub error_message: Option<String>,
611
612 pub warning_message: Option<String>,
614}