1use crate::constants::{DEFAULT_ORDER_BUY_LEVEL, DEFAULT_ORDER_SELL_LEVEL};
7use crate::prelude::{Deserialize, Serialize, WorkingOrder};
8use crate::presentation::order::{Direction, OrderType, TimeInForce};
9use chrono::{Duration, Utc};
10use pretty_simple_display::{DebugPretty, DisplaySimple};
11use std::fmt;
12use std::fmt::{Debug, Display};
13
14#[derive(Clone, Default, Deserialize, Serialize)]
16pub struct RecentPricesRequest<'a> {
17 pub epic: &'a str,
19 pub resolution: Option<&'a str>,
21 pub from: Option<&'a str>,
23 pub to: Option<&'a str>,
25 pub max_points: Option<i32>,
27 pub page_size: Option<i32>,
29 pub page_number: Option<i32>,
31}
32
33impl<'a> RecentPricesRequest<'a> {
34 #[must_use]
36 pub fn new(epic: &'a str) -> Self {
37 Self {
38 epic,
39 ..Default::default()
40 }
41 }
42
43 #[must_use]
45 pub fn with_resolution(mut self, resolution: &'a str) -> Self {
46 self.resolution = Some(resolution);
47 self
48 }
49
50 #[must_use]
52 pub fn with_from(mut self, from: &'a str) -> Self {
53 self.from = Some(from);
54 self
55 }
56
57 #[must_use]
59 pub fn with_to(mut self, to: &'a str) -> Self {
60 self.to = Some(to);
61 self
62 }
63
64 #[must_use]
66 pub fn with_max_points(mut self, max_points: i32) -> Self {
67 self.max_points = Some(max_points);
68 self
69 }
70
71 #[must_use]
73 pub fn with_page_size(mut self, page_size: i32) -> Self {
74 self.page_size = Some(page_size);
75 self
76 }
77
78 #[must_use]
80 pub fn with_page_number(mut self, page_number: i32) -> Self {
81 self.page_number = Some(page_number);
82 self
83 }
84}
85
86impl Display for RecentPricesRequest<'_> {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 let json = serde_json::to_string(self).unwrap_or_else(|_| "Invalid JSON".to_string());
89 write!(f, "{}", json)
90 }
91}
92
93impl Debug for RecentPricesRequest<'_> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 let json =
96 serde_json::to_string_pretty(self).unwrap_or_else(|_| "Invalid JSON".to_string());
97 write!(f, "{}", json)
98 }
99}
100
101#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
103pub struct CreateOrderRequest {
104 pub epic: String,
106 pub direction: Direction,
108 pub size: f64,
110 #[serde(rename = "orderType")]
112 pub order_type: OrderType,
113 #[serde(rename = "timeInForce")]
115 pub time_in_force: TimeInForce,
116 #[serde(skip_serializing_if = "Option::is_none")]
118 pub level: Option<f64>,
119 #[serde(rename = "guaranteedStop")]
121 pub guaranteed_stop: bool,
122 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
124 pub stop_level: Option<f64>,
125 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
127 pub stop_distance: Option<f64>,
128 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
130 pub limit_level: Option<f64>,
131 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
133 pub limit_distance: Option<f64>,
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub expiry: Option<String>,
137 #[serde(rename = "dealReference", skip_serializing_if = "Option::is_none")]
139 pub deal_reference: Option<String>,
140 #[serde(rename = "forceOpen")]
142 pub force_open: bool,
143 #[serde(rename = "currencyCode")]
145 pub currency_code: String,
146 #[serde(rename = "quoteId", skip_serializing_if = "Option::is_none")]
148 pub quote_id: Option<String>,
149 #[serde(rename = "trailingStop", skip_serializing_if = "Option::is_none")]
151 pub trailing_stop: Option<bool>,
152 #[serde(
154 rename = "trailingStopIncrement",
155 skip_serializing_if = "Option::is_none"
156 )]
157 pub trailing_stop_increment: Option<f64>,
158}
159
160impl CreateOrderRequest {
161 #[must_use]
163 pub fn market(
164 epic: String,
165 direction: Direction,
166 size: f64,
167 currency_code: Option<String>,
168 deal_reference: Option<String>,
169 ) -> Self {
170 let rounded_size = (size * 100.0).floor() / 100.0;
171
172 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
173
174 Self {
175 epic,
176 direction,
177 size: rounded_size,
178 order_type: OrderType::Market,
179 time_in_force: TimeInForce::FillOrKill,
180 level: None,
181 guaranteed_stop: false,
182 stop_level: None,
183 stop_distance: None,
184 limit_level: None,
185 limit_distance: None,
186 expiry: Some("-".to_string()),
187 deal_reference,
188 force_open: true,
189 currency_code,
190 quote_id: None,
191 trailing_stop: Some(false),
192 trailing_stop_increment: None,
193 }
194 }
195
196 #[must_use]
198 pub fn limit(
199 epic: String,
200 direction: Direction,
201 size: f64,
202 level: f64,
203 currency_code: Option<String>,
204 deal_reference: Option<String>,
205 ) -> Self {
206 let rounded_size = (size * 100.0).floor() / 100.0;
207
208 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
209
210 Self {
211 epic,
212 direction,
213 size: rounded_size,
214 order_type: OrderType::Limit,
215 time_in_force: TimeInForce::GoodTillCancelled,
216 level: Some(level),
217 guaranteed_stop: false,
218 stop_level: None,
219 stop_distance: None,
220 limit_level: None,
221 limit_distance: None,
222 expiry: None,
223 deal_reference,
224 force_open: true,
225 currency_code,
226 quote_id: None,
227 trailing_stop: Some(false),
228 trailing_stop_increment: None,
229 }
230 }
231
232 #[must_use]
265 pub fn sell_option_to_market(
266 epic: String,
267 size: f64,
268 expiry: Option<String>,
269 deal_reference: Option<String>,
270 currency_code: Option<String>,
271 ) -> Self {
272 let rounded_size = (size * 100.0).floor() / 100.0;
273
274 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
275
276 let deal_reference =
277 deal_reference.or_else(|| Some(nanoid::nanoid!(30, &nanoid::alphabet::SAFE)));
278
279 Self {
280 epic,
281 direction: Direction::Sell,
282 size: rounded_size,
283 order_type: OrderType::Limit,
284 time_in_force: TimeInForce::FillOrKill,
285 level: Some(DEFAULT_ORDER_SELL_LEVEL),
286 guaranteed_stop: false,
287 stop_level: None,
288 stop_distance: None,
289 limit_level: None,
290 limit_distance: None,
291 expiry: expiry.clone(),
292 deal_reference: deal_reference.clone(),
293 force_open: true,
294 currency_code,
295 quote_id: None,
296 trailing_stop: Some(false),
297 trailing_stop_increment: None,
298 }
299 }
300
301 #[must_use]
334 pub fn sell_option_to_market_w_force(
335 epic: String,
336 size: f64,
337 expiry: Option<String>,
338 deal_reference: Option<String>,
339 currency_code: Option<String>,
340 force_open: bool, ) -> Self {
342 let rounded_size = (size * 100.0).floor() / 100.0;
343
344 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
345
346 let deal_reference =
347 deal_reference.or_else(|| Some(nanoid::nanoid!(30, &nanoid::alphabet::SAFE)));
348
349 Self {
350 epic,
351 direction: Direction::Sell,
352 size: rounded_size,
353 order_type: OrderType::Limit,
354 time_in_force: TimeInForce::FillOrKill,
355 level: Some(DEFAULT_ORDER_SELL_LEVEL),
356 guaranteed_stop: false,
357 stop_level: None,
358 stop_distance: None,
359 limit_level: None,
360 limit_distance: None,
361 expiry: expiry.clone(),
362 deal_reference: deal_reference.clone(),
363 force_open,
364 currency_code,
365 quote_id: None,
366 trailing_stop: Some(false),
367 trailing_stop_increment: None,
368 }
369 }
370
371 #[must_use]
391 pub fn buy_option_to_market(
392 epic: String,
393 size: f64,
394 expiry: Option<String>,
395 deal_reference: Option<String>,
396 currency_code: Option<String>,
397 ) -> Self {
398 let rounded_size = (size * 100.0).floor() / 100.0;
399
400 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
401
402 let deal_reference =
403 deal_reference.or_else(|| Some(nanoid::nanoid!(30, &nanoid::alphabet::SAFE)));
404
405 Self {
406 epic,
407 direction: Direction::Buy,
408 size: rounded_size,
409 order_type: OrderType::Limit,
410 time_in_force: TimeInForce::FillOrKill,
411 level: Some(DEFAULT_ORDER_BUY_LEVEL),
412 guaranteed_stop: false,
413 stop_level: None,
414 stop_distance: None,
415 limit_level: None,
416 limit_distance: None,
417 expiry: expiry.clone(),
418 deal_reference: deal_reference.clone(),
419 force_open: true,
420 currency_code: currency_code.clone(),
421 quote_id: None,
422 trailing_stop: Some(false),
423 trailing_stop_increment: None,
424 }
425 }
426
427 #[must_use]
455 pub fn buy_option_to_market_w_force(
456 epic: String,
457 size: f64,
458 expiry: Option<String>,
459 deal_reference: Option<String>,
460 currency_code: Option<String>,
461 force_open: bool,
462 ) -> Self {
463 let rounded_size = (size * 100.0).floor() / 100.0;
464
465 let currency_code = currency_code.unwrap_or_else(|| "EUR".to_string());
466
467 let deal_reference =
468 deal_reference.or_else(|| Some(nanoid::nanoid!(30, &nanoid::alphabet::SAFE)));
469
470 Self {
471 epic,
472 direction: Direction::Buy,
473 size: rounded_size,
474 order_type: OrderType::Limit,
475 time_in_force: TimeInForce::FillOrKill,
476 level: Some(DEFAULT_ORDER_BUY_LEVEL),
477 guaranteed_stop: false,
478 stop_level: None,
479 stop_distance: None,
480 limit_level: None,
481 limit_distance: None,
482 expiry: expiry.clone(),
483 deal_reference: deal_reference.clone(),
484 force_open,
485 currency_code: currency_code.clone(),
486 quote_id: None,
487 trailing_stop: Some(false),
488 trailing_stop_increment: None,
489 }
490 }
491
492 #[must_use]
494 pub fn with_stop_loss(mut self, stop_level: f64) -> Self {
495 self.stop_level = Some(stop_level);
496 self
497 }
498
499 #[must_use]
501 pub fn with_take_profit(mut self, limit_level: f64) -> Self {
502 self.limit_level = Some(limit_level);
503 self
504 }
505
506 #[must_use]
508 pub fn with_trailing_stop_loss(mut self, trailing_stop_increment: f64) -> Self {
509 self.trailing_stop = Some(true);
510 self.trailing_stop_increment = Some(trailing_stop_increment);
511 self
512 }
513
514 #[must_use]
516 pub fn with_reference(mut self, reference: String) -> Self {
517 self.deal_reference = Some(reference);
518 self
519 }
520
521 #[must_use]
523 pub fn with_stop_distance(mut self, stop_distance: f64) -> Self {
524 self.stop_distance = Some(stop_distance);
525 self
526 }
527
528 #[must_use]
530 pub fn with_limit_distance(mut self, limit_distance: f64) -> Self {
531 self.limit_distance = Some(limit_distance);
532 self
533 }
534
535 #[must_use]
537 pub fn with_guaranteed_stop(mut self, guaranteed: bool) -> Self {
538 self.guaranteed_stop = guaranteed;
539 self
540 }
541}
542
543#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
552pub struct UpdatePositionRequest {
553 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
555 pub guaranteed_stop: Option<bool>,
556 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
558 pub limit_level: Option<f64>,
559 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
561 pub stop_level: Option<f64>,
562 #[serde(rename = "trailingStop", skip_serializing_if = "Option::is_none")]
564 pub trailing_stop: Option<bool>,
565 #[serde(
567 rename = "trailingStopDistance",
568 skip_serializing_if = "Option::is_none"
569 )]
570 pub trailing_stop_distance: Option<f64>,
571 #[serde(
573 rename = "trailingStopIncrement",
574 skip_serializing_if = "Option::is_none"
575 )]
576 pub trailing_stop_increment: Option<f64>,
577}
578
579#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
581pub struct ClosePositionRequest {
582 #[serde(rename = "dealId", skip_serializing_if = "Option::is_none")]
584 pub deal_id: Option<String>,
585 pub direction: Direction,
587 #[serde(skip_serializing_if = "Option::is_none")]
589 pub epic: Option<String>,
590 #[serde(rename = "expiry", skip_serializing_if = "Option::is_none")]
592 pub expiry: Option<String>,
593 #[serde(rename = "level", skip_serializing_if = "Option::is_none")]
595 pub level: Option<f64>,
596 #[serde(rename = "orderType")]
598 pub order_type: OrderType,
599 #[serde(rename = "quoteId", skip_serializing_if = "Option::is_none")]
601 pub quote_id: Option<String>,
602 pub size: f64,
604 #[serde(rename = "timeInForce")]
606 pub time_in_force: TimeInForce,
607}
608
609impl ClosePositionRequest {
610 #[must_use]
612 pub fn market(deal_id: String, direction: Direction, size: f64) -> Self {
613 Self {
614 deal_id: Some(deal_id),
615 direction,
616 size,
617 order_type: OrderType::Market,
618 time_in_force: TimeInForce::FillOrKill,
619 level: None,
620 expiry: None,
621 epic: None,
622 quote_id: None,
623 }
624 }
625
626 #[must_use]
630 pub fn limit(deal_id: String, direction: Direction, size: f64, level: f64) -> Self {
631 Self {
632 deal_id: Some(deal_id),
633 direction,
634 size,
635 order_type: OrderType::Limit,
636 time_in_force: TimeInForce::FillOrKill,
637 level: Some(level),
638 expiry: None,
639 epic: None,
640 quote_id: None,
641 }
642 }
643
644 #[must_use]
654 pub fn close_option_to_market_by_id(deal_id: String, direction: Direction, size: f64) -> Self {
655 let level = match direction {
658 Direction::Buy => Some(DEFAULT_ORDER_BUY_LEVEL),
659 Direction::Sell => Some(DEFAULT_ORDER_SELL_LEVEL),
660 };
661
662 Self {
663 deal_id: Some(deal_id),
664 direction,
665 size,
666 order_type: OrderType::Limit,
667 time_in_force: TimeInForce::FillOrKill,
668 level,
669 expiry: None,
670 epic: None,
671 quote_id: None,
672 }
673 }
674
675 #[must_use]
687 pub fn close_option_to_market_by_epic(
688 epic: String,
689 expiry: String,
690 direction: Direction,
691 size: f64,
692 ) -> Self {
693 let level = match direction {
696 Direction::Buy => Some(DEFAULT_ORDER_BUY_LEVEL),
697 Direction::Sell => Some(DEFAULT_ORDER_SELL_LEVEL),
698 };
699
700 Self {
701 deal_id: None,
702 direction,
703 size,
704 order_type: OrderType::Limit,
705 time_in_force: TimeInForce::FillOrKill,
706 level,
707 expiry: Some(expiry),
708 epic: Some(epic),
709 quote_id: None,
710 }
711 }
712}
713
714#[derive(DebugPretty, DisplaySimple, Clone, Deserialize, Serialize, Default)]
716pub struct CreateWorkingOrderRequest {
717 pub epic: String,
719 pub direction: Direction,
721 pub size: f64,
723 pub level: f64,
725 #[serde(rename = "type")]
727 pub order_type: OrderType,
728 #[serde(rename = "timeInForce")]
730 pub time_in_force: TimeInForce,
731 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
733 pub guaranteed_stop: Option<bool>,
734 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
736 pub stop_level: Option<f64>,
737 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
739 pub stop_distance: Option<f64>,
740 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
742 pub limit_level: Option<f64>,
743 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
745 pub limit_distance: Option<f64>,
746 #[serde(rename = "goodTillDate", skip_serializing_if = "Option::is_none")]
748 pub good_till_date: Option<String>,
749 #[serde(rename = "dealReference", skip_serializing_if = "Option::is_none")]
751 pub deal_reference: Option<String>,
752 #[serde(rename = "currencyCode")]
754 pub currency_code: String,
755 pub expiry: String,
757}
758
759impl From<WorkingOrder> for CreateWorkingOrderRequest {
760 fn from(value: WorkingOrder) -> Self {
761 let data = value.working_order_data;
762 Self {
763 epic: data.epic,
764 direction: data.direction,
765 size: data.order_size,
766 level: data.order_level,
767 order_type: data.order_type,
768 time_in_force: data.time_in_force,
769 guaranteed_stop: Some(data.guaranteed_stop),
770 stop_level: data.stop_level,
771 stop_distance: data.stop_distance,
772 limit_level: data.limit_level,
773 limit_distance: data.limit_distance,
774 good_till_date: data.good_till_date,
775 deal_reference: data.deal_reference,
776 currency_code: data.currency_code,
777 expiry: value.market_data.expiry,
778 }
779 }
780}
781
782impl CreateWorkingOrderRequest {
783 #[must_use]
785 pub fn limit(
786 epic: String,
787 direction: Direction,
788 size: f64,
789 level: f64,
790 currency_code: String,
791 expiry: String,
792 ) -> Self {
793 Self {
794 epic,
795 direction,
796 size,
797 level,
798 order_type: OrderType::Limit,
799 time_in_force: TimeInForce::GoodTillCancelled,
800 guaranteed_stop: Some(false),
801 stop_level: None,
802 stop_distance: None,
803 limit_level: None,
804 limit_distance: None,
805 good_till_date: None,
806 deal_reference: None,
807 currency_code,
808 expiry,
809 }
810 }
811
812 #[must_use]
814 pub fn stop(
815 epic: String,
816 direction: Direction,
817 size: f64,
818 level: f64,
819 currency_code: String,
820 expiry: String,
821 ) -> Self {
822 Self {
823 epic,
824 direction,
825 size,
826 level,
827 order_type: OrderType::Stop,
828 time_in_force: TimeInForce::GoodTillCancelled,
829 guaranteed_stop: Some(false),
830 stop_level: None,
831 stop_distance: None,
832 limit_level: None,
833 limit_distance: None,
834 good_till_date: None,
835 deal_reference: None,
836 currency_code,
837 expiry,
838 }
839 }
840
841 #[must_use]
843 pub fn with_stop_loss(mut self, stop_level: f64) -> Self {
844 self.stop_level = Some(stop_level);
845 self
846 }
847
848 #[must_use]
850 pub fn with_take_profit(mut self, limit_level: f64) -> Self {
851 self.limit_level = Some(limit_level);
852 self
853 }
854
855 #[must_use]
857 pub fn with_reference(mut self, reference: String) -> Self {
858 self.deal_reference = Some(reference);
859 self
860 }
861
862 #[must_use]
877 pub fn expires_at(mut self, date: String) -> Self {
878 self.time_in_force = TimeInForce::GoodTillDate;
879 self.good_till_date = Some(date);
880 self
881 }
882
883 #[must_use]
900 pub fn expires_tomorrow(mut self) -> Self {
901 self.time_in_force = TimeInForce::GoodTillDate;
902 let tomorrow = Utc::now() + Duration::days(1);
903 self.good_till_date = Some(tomorrow.format("%Y/%m/%d %H:%M:%S").to_string());
904 self
905 }
906
907 #[must_use]
924 pub fn expires_in(mut self, duration: Duration) -> Self {
925 self.time_in_force = TimeInForce::GoodTillDate;
926 let tomorrow = Utc::now() + duration;
927 self.good_till_date = Some(tomorrow.format("%Y/%m/%d %H:%M:%S").to_string());
928 self
929 }
930}
931
932#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
938pub struct CreateWatchlistRequest {
939 pub name: String,
941 #[serde(skip_serializing_if = "Option::is_none")]
943 pub epics: Option<Vec<String>>,
944}
945
946impl CreateWatchlistRequest {
947 #[must_use]
949 pub fn new(name: &str) -> Self {
950 Self {
951 name: name.to_string(),
952 epics: None,
953 }
954 }
955
956 #[must_use]
958 pub fn with_epics(name: &str, epics: Vec<String>) -> Self {
959 Self {
960 name: name.to_string(),
961 epics: Some(epics),
962 }
963 }
964}
965
966#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
968pub struct AddToWatchlistRequest {
969 pub epic: String,
971}
972
973#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
979pub struct UpdateWorkingOrderRequest {
980 #[serde(rename = "goodTillDate", skip_serializing_if = "Option::is_none")]
982 pub good_till_date: Option<String>,
983 pub level: f64,
985 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
987 pub limit_distance: Option<f64>,
988 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
990 pub limit_level: Option<f64>,
991 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
993 pub stop_distance: Option<f64>,
994 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
996 pub stop_level: Option<f64>,
997 #[serde(rename = "guaranteedStop")]
999 pub guaranteed_stop: bool,
1000 #[serde(rename = "timeInForce")]
1002 pub time_in_force: TimeInForce,
1003 #[serde(rename = "type")]
1005 pub order_type: OrderType,
1006}
1007
1008impl UpdateWorkingOrderRequest {
1009 #[must_use]
1011 pub fn new(level: f64, order_type: OrderType, time_in_force: TimeInForce) -> Self {
1012 Self {
1013 level,
1014 order_type,
1015 time_in_force,
1016 guaranteed_stop: false,
1017 good_till_date: None,
1018 limit_distance: None,
1019 limit_level: None,
1020 stop_distance: None,
1021 stop_level: None,
1022 }
1023 }
1024
1025 #[must_use]
1027 pub fn with_stop_level(mut self, stop_level: f64) -> Self {
1028 self.stop_level = Some(stop_level);
1029 self
1030 }
1031
1032 #[must_use]
1034 pub fn with_limit_level(mut self, limit_level: f64) -> Self {
1035 self.limit_level = Some(limit_level);
1036 self
1037 }
1038
1039 #[must_use]
1041 pub fn with_guaranteed_stop(mut self, guaranteed: bool) -> Self {
1042 self.guaranteed_stop = guaranteed;
1043 self
1044 }
1045}
1046
1047#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
1053pub struct OpenCostsRequest {
1054 pub epic: String,
1056 pub direction: Direction,
1058 pub size: f64,
1060 #[serde(rename = "orderType")]
1062 pub order_type: OrderType,
1063 #[serde(rename = "currencyCode")]
1065 pub currency_code: String,
1066 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
1068 pub guaranteed_stop: Option<bool>,
1069 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
1071 pub stop_distance: Option<f64>,
1072 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
1074 pub limit_distance: Option<f64>,
1075}
1076
1077impl OpenCostsRequest {
1078 #[must_use]
1080 pub fn new(epic: &str, direction: Direction, size: f64, currency_code: &str) -> Self {
1081 Self {
1082 epic: epic.to_string(),
1083 direction,
1084 size,
1085 order_type: OrderType::Market,
1086 currency_code: currency_code.to_string(),
1087 guaranteed_stop: None,
1088 stop_distance: None,
1089 limit_distance: None,
1090 }
1091 }
1092}
1093
1094#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
1096pub struct CloseCostsRequest {
1097 #[serde(rename = "dealId")]
1099 pub deal_id: String,
1100 pub direction: Direction,
1102 pub size: f64,
1104 #[serde(rename = "orderType")]
1106 pub order_type: OrderType,
1107}
1108
1109impl CloseCostsRequest {
1110 #[must_use]
1112 pub fn new(deal_id: &str, direction: Direction, size: f64) -> Self {
1113 Self {
1114 deal_id: deal_id.to_string(),
1115 direction,
1116 size,
1117 order_type: OrderType::Market,
1118 }
1119 }
1120}
1121
1122#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
1124pub struct EditCostsRequest {
1125 #[serde(rename = "dealId")]
1127 pub deal_id: String,
1128 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
1130 pub stop_level: Option<f64>,
1131 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
1133 pub limit_level: Option<f64>,
1134 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
1136 pub guaranteed_stop: Option<bool>,
1137}
1138
1139impl EditCostsRequest {
1140 #[must_use]
1142 pub fn new(deal_id: &str) -> Self {
1143 Self {
1144 deal_id: deal_id.to_string(),
1145 stop_level: None,
1146 limit_level: None,
1147 guaranteed_stop: None,
1148 }
1149 }
1150
1151 #[must_use]
1153 pub fn with_stop_level(mut self, stop_level: f64) -> Self {
1154 self.stop_level = Some(stop_level);
1155 self
1156 }
1157
1158 #[must_use]
1160 pub fn with_limit_level(mut self, limit_level: f64) -> Self {
1161 self.limit_level = Some(limit_level);
1162 self
1163 }
1164}
1165
1166#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
1172pub struct UpdatePreferencesRequest {
1173 #[serde(rename = "trailingStopsEnabled")]
1175 pub trailing_stops_enabled: bool,
1176}