1use super::algo_builders::AlgoParams;
2use super::types::*;
3use super::validation;
4use crate::contracts::Contract;
5use crate::market_data::TradingHours;
6use crate::orders::{Action, Order, OrderComboLeg, OrderCondition, TagValue};
7
8#[cfg(test)]
9mod tests;
10
11pub struct OrderBuilder<'a, C> {
16 pub(crate) client: &'a C,
17 pub(crate) contract: &'a Contract,
18 action: Option<Action>,
19 quantity: Option<f64>, order_type: Option<OrderType>,
21 limit_price: Option<f64>, stop_price: Option<f64>, time_in_force: TimeInForce,
24 outside_rth: bool,
25 hidden: bool,
26 transmit: bool,
27 parent_id: Option<i32>,
28 oca_group: Option<String>,
29 oca_type: Option<i32>,
30 account: Option<String>,
31 good_after_time: Option<String>,
32 good_till_date: Option<String>,
33 conditions: Vec<OrderCondition>,
34 algo_strategy: Option<String>,
35 algo_params: Vec<TagValue>,
36 pub(crate) what_if: bool,
37
38 discretionary_amt: Option<f64>,
40 trailing_percent: Option<f64>,
41 trail_stop_price: Option<f64>,
42 limit_price_offset: Option<f64>,
43 volatility: Option<f64>,
44 volatility_type: Option<i32>,
45 delta: Option<f64>,
46 aux_price: Option<f64>,
47
48 sweep_to_fill: bool,
50 block_order: bool,
51 not_held: bool,
52 all_or_none: bool,
53
54 min_trade_qty: Option<i32>,
56 min_compete_size: Option<i32>,
57 compete_against_best_offset: Option<f64>,
58 mid_offset_at_whole: Option<f64>,
59 mid_offset_at_half: Option<f64>,
60
61 reference_contract_id: Option<i32>,
63 reference_exchange: Option<String>,
64 stock_ref_price: Option<f64>,
65 stock_range_lower: Option<f64>,
66 stock_range_upper: Option<f64>,
67 reference_change_amount: Option<f64>,
68 pegged_change_amount: Option<f64>,
69 is_pegged_change_amount_decrease: bool,
70
71 order_combo_legs: Vec<OrderComboLeg>,
73 smart_combo_routing_params: Vec<TagValue>,
74
75 cash_qty: Option<f64>,
77
78 manual_order_time: Option<String>,
80
81 auction_strategy: Option<i32>,
83
84 starting_price: Option<f64>,
86
87 hedge_type: Option<String>,
89}
90
91impl<'a, C> OrderBuilder<'a, C> {
92 pub fn new(client: &'a C, contract: &'a Contract) -> Self {
94 Self {
95 client,
96 contract,
97 action: None,
98 quantity: None,
99 order_type: None,
100 limit_price: None,
101 stop_price: None,
102 time_in_force: TimeInForce::Day,
103 outside_rth: false,
104 hidden: false,
105 transmit: true,
106 parent_id: None,
107 oca_group: None,
108 oca_type: None,
109 account: None,
110 good_after_time: None,
111 good_till_date: None,
112 conditions: Vec::new(),
113 algo_strategy: None,
114 algo_params: Vec::new(),
115 what_if: false,
116 discretionary_amt: None,
117 trailing_percent: None,
118 trail_stop_price: None,
119 limit_price_offset: None,
120 volatility: None,
121 volatility_type: None,
122 delta: None,
123 aux_price: None,
124 sweep_to_fill: false,
125 block_order: false,
126 not_held: false,
127 all_or_none: false,
128 min_trade_qty: None,
129 min_compete_size: None,
130 compete_against_best_offset: None,
131 mid_offset_at_whole: None,
132 mid_offset_at_half: None,
133 reference_contract_id: None,
134 reference_exchange: None,
135 stock_ref_price: None,
136 stock_range_lower: None,
137 stock_range_upper: None,
138 reference_change_amount: None,
139 pegged_change_amount: None,
140 is_pegged_change_amount_decrease: false,
141 order_combo_legs: Vec::new(),
142 smart_combo_routing_params: Vec::new(),
143 cash_qty: None,
144 manual_order_time: None,
145 auction_strategy: None,
146 starting_price: None,
147 hedge_type: None,
148 }
149 }
150
151 pub fn buy(mut self, quantity: impl Into<f64>) -> Self {
155 self.action = Some(Action::Buy);
156 self.quantity = Some(quantity.into());
157 self
158 }
159
160 pub fn sell(mut self, quantity: impl Into<f64>) -> Self {
162 self.action = Some(Action::Sell);
163 self.quantity = Some(quantity.into());
164 self
165 }
166
167 pub fn market(mut self) -> Self {
171 self.order_type = Some(OrderType::Market);
172 self
173 }
174
175 pub fn limit(mut self, price: impl Into<f64>) -> Self {
177 self.order_type = Some(OrderType::Limit);
178 self.limit_price = Some(price.into());
179 self
180 }
181
182 pub fn stop(mut self, stop_price: impl Into<f64>) -> Self {
184 self.order_type = Some(OrderType::Stop);
185 self.stop_price = Some(stop_price.into());
186 self
187 }
188
189 pub fn stop_limit(mut self, stop_price: impl Into<f64>, limit_price: impl Into<f64>) -> Self {
191 self.order_type = Some(OrderType::StopLimit);
192 self.stop_price = Some(stop_price.into());
193 self.limit_price = Some(limit_price.into());
194 self
195 }
196
197 pub fn trailing_stop(mut self, trailing_percent: f64, stop_price: impl Into<f64>) -> Self {
199 self.order_type = Some(OrderType::TrailingStop);
200 self.trailing_percent = Some(trailing_percent);
201 self.trail_stop_price = Some(stop_price.into());
202 self
203 }
204
205 pub fn order_type(mut self, order_type: OrderType) -> Self {
207 self.order_type = Some(order_type);
208 self
209 }
210
211 pub fn trailing_stop_limit(mut self, trailing_percent: f64, stop_price: impl Into<f64>, limit_offset: f64) -> Self {
213 self.order_type = Some(OrderType::TrailingStopLimit);
214 self.trailing_percent = Some(trailing_percent);
215 self.trail_stop_price = Some(stop_price.into());
216 self.limit_price_offset = Some(limit_offset);
217 self
218 }
219
220 pub fn market_if_touched(mut self, trigger_price: impl Into<f64>) -> Self {
222 self.order_type = Some(OrderType::MarketIfTouched);
223 self.aux_price = Some(trigger_price.into());
224 self
225 }
226
227 pub fn limit_if_touched(mut self, trigger_price: impl Into<f64>, limit_price: impl Into<f64>) -> Self {
229 self.order_type = Some(OrderType::LimitIfTouched);
230 self.aux_price = Some(trigger_price.into());
231 self.limit_price = Some(limit_price.into());
232 self
233 }
234
235 pub fn market_to_limit(mut self) -> Self {
237 self.order_type = Some(OrderType::MarketToLimit);
238 self
239 }
240
241 pub fn discretionary(mut self, limit_price: impl Into<f64>, discretionary_amt: f64) -> Self {
243 self.order_type = Some(OrderType::Limit);
244 self.limit_price = Some(limit_price.into());
245 self.discretionary_amt = Some(discretionary_amt);
246 self
247 }
248
249 pub fn sweep_to_fill(mut self, limit_price: impl Into<f64>) -> Self {
251 self.order_type = Some(OrderType::Limit);
252 self.limit_price = Some(limit_price.into());
253 self.sweep_to_fill = true;
254 self
255 }
256
257 pub fn block(mut self, limit_price: impl Into<f64>) -> Self {
259 self.order_type = Some(OrderType::Limit);
260 self.limit_price = Some(limit_price.into());
261 self.block_order = true;
262 self
263 }
264
265 pub fn midprice(mut self, price_cap: Option<f64>) -> Self {
267 self.order_type = Some(OrderType::Midprice);
268 self.limit_price = price_cap;
269 self
270 }
271
272 pub fn relative(mut self, offset: f64, price_cap: Option<f64>) -> Self {
274 self.order_type = Some(OrderType::Relative);
275 self.aux_price = Some(offset);
276 self.limit_price = price_cap;
277 self
278 }
279
280 pub fn passive_relative(mut self, offset: f64) -> Self {
282 self.order_type = Some(OrderType::PassiveRelative);
283 self.aux_price = Some(offset);
284 self
285 }
286
287 pub fn at_auction(mut self, price: impl Into<f64>) -> Self {
289 self.order_type = Some(OrderType::AtAuction);
290 self.limit_price = Some(price.into());
291 self.time_in_force = TimeInForce::Auction;
292 self
293 }
294
295 pub fn market_on_close(mut self) -> Self {
297 self.order_type = Some(OrderType::MarketOnClose);
298 self
299 }
300
301 pub fn limit_on_close(mut self, limit_price: impl Into<f64>) -> Self {
303 self.order_type = Some(OrderType::LimitOnClose);
304 self.limit_price = Some(limit_price.into());
305 self
306 }
307
308 pub fn market_on_open(mut self) -> Self {
310 self.order_type = Some(OrderType::Market);
311 self.time_in_force = TimeInForce::OpeningAuction;
312 self
313 }
314
315 pub fn limit_on_open(mut self, limit_price: impl Into<f64>) -> Self {
317 self.order_type = Some(OrderType::Limit);
318 self.limit_price = Some(limit_price.into());
319 self.time_in_force = TimeInForce::OpeningAuction;
320 self
321 }
322
323 pub fn market_with_protection(mut self) -> Self {
325 self.order_type = Some(OrderType::MarketWithProtection);
326 self
327 }
328
329 pub fn stop_with_protection(mut self, stop_price: impl Into<f64>) -> Self {
331 self.order_type = Some(OrderType::StopWithProtection);
332 self.stop_price = Some(stop_price.into());
333 self
334 }
335
336 pub fn time_in_force(mut self, tif: TimeInForce) -> Self {
340 self.time_in_force = tif;
341 self
342 }
343
344 pub fn day_order(mut self) -> Self {
346 self.time_in_force = TimeInForce::Day;
347 self
348 }
349
350 pub fn good_till_cancel(mut self) -> Self {
352 self.time_in_force = TimeInForce::GoodTillCancel;
353 self
354 }
355
356 pub fn good_till_date(mut self, date: impl Into<String>) -> Self {
358 let date_str = date.into();
359 self.time_in_force = TimeInForce::GoodTillDate { date: date_str.clone() };
360 self.good_till_date = Some(date_str);
361 self
362 }
363
364 pub fn fill_or_kill(mut self) -> Self {
366 self.time_in_force = TimeInForce::FillOrKill;
367 self
368 }
369
370 pub fn immediate_or_cancel(mut self) -> Self {
372 self.time_in_force = TimeInForce::ImmediateOrCancel;
373 self
374 }
375
376 pub fn outside_rth(mut self) -> Self {
380 self.outside_rth = true;
381 self
382 }
383
384 pub fn regular_hours_only(mut self) -> Self {
386 self.outside_rth = false;
387 self
388 }
389
390 pub fn trading_hours(mut self, hours: TradingHours) -> Self {
392 self.outside_rth = matches!(hours, TradingHours::Extended);
393 self
394 }
395
396 pub fn hidden(mut self) -> Self {
400 self.hidden = true;
401 self
402 }
403
404 pub fn account(mut self, account: impl Into<String>) -> Self {
406 self.account = Some(account.into());
407 self
408 }
409
410 pub fn parent(mut self, parent_id: i32) -> Self {
412 self.parent_id = Some(parent_id);
413 self
414 }
415
416 pub fn oca_group(mut self, group: impl Into<String>, oca_type: i32) -> Self {
418 self.oca_group = Some(group.into());
419 self.oca_type = Some(oca_type);
420 self
421 }
422
423 pub fn do_not_transmit(mut self) -> Self {
425 self.transmit = false;
426 self
427 }
428
429 pub fn bracket(self) -> BracketOrderBuilder<'a, C> {
431 BracketOrderBuilder::new(self)
432 }
433
434 pub fn condition(mut self, condition: impl Into<OrderCondition>) -> Self {
460 let mut cond = condition.into();
461 set_conjunction(&mut cond, true);
462 self.conditions.push(cond);
463 self
464 }
465
466 pub fn and_condition(mut self, condition: impl Into<OrderCondition>) -> Self {
488 if let Some(prev) = self.conditions.last_mut() {
489 set_conjunction(prev, true);
490 }
491 self.conditions.push(condition.into());
492 self
493 }
494
495 pub fn or_condition(mut self, condition: impl Into<OrderCondition>) -> Self {
517 if let Some(prev) = self.conditions.last_mut() {
518 set_conjunction(prev, false);
519 }
520 self.conditions.push(condition.into());
521 self
522 }
523
524 pub fn algo(mut self, algo: impl Into<AlgoParams>) -> Self {
571 let params = algo.into();
572 self.algo_strategy = Some(params.strategy);
573 self.algo_params.extend(params.params);
574 self
575 }
576
577 pub fn algo_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
582 self.algo_params.push(TagValue {
583 tag: key.into(),
584 value: value.into(),
585 });
586 self
587 }
588
589 pub fn what_if(mut self) -> Self {
593 self.what_if = true;
594 self
595 }
596
597 pub fn volatility(mut self, volatility: f64) -> Self {
601 self.volatility = Some(volatility);
602 self
603 }
604
605 pub fn not_held(mut self) -> Self {
607 self.not_held = true;
608 self
609 }
610
611 pub fn all_or_none(mut self) -> Self {
613 self.all_or_none = true;
614 self
615 }
616
617 pub fn good_after_time(mut self, time: impl Into<String>) -> Self {
619 self.good_after_time = Some(time.into());
620 self
621 }
622
623 pub fn good_till_time(mut self, time: impl Into<String>) -> Self {
625 self.good_till_date = Some(time.into());
626 self
627 }
628
629 pub fn min_trade_qty(mut self, qty: i32) -> Self {
633 self.min_trade_qty = Some(qty);
634 self
635 }
636
637 pub fn min_compete_size(mut self, size: i32) -> Self {
639 self.min_compete_size = Some(size);
640 self
641 }
642
643 pub fn compete_against_best_offset(mut self, offset: f64) -> Self {
645 self.compete_against_best_offset = Some(offset);
646 self
647 }
648
649 pub fn mid_offset_at_whole(mut self, offset: f64) -> Self {
651 self.mid_offset_at_whole = Some(offset);
652 self
653 }
654
655 pub fn mid_offset_at_half(mut self, offset: f64) -> Self {
657 self.mid_offset_at_half = Some(offset);
658 self
659 }
660
661 pub fn build(self) -> Result<Order, ValidationError> {
665 let action = self.action.ok_or(ValidationError::MissingRequiredField("action"))?;
667 let quantity_raw = self.quantity.ok_or(ValidationError::MissingRequiredField("quantity"))?;
668 let order_type = self.order_type.ok_or(ValidationError::MissingRequiredField("order_type"))?;
669
670 let quantity = Quantity::new(quantity_raw)?;
672
673 let limit_price = if order_type.requires_limit_price() {
675 let price_raw = self.limit_price.ok_or(ValidationError::MissingRequiredField("limit_price"))?;
676 Some(Price::new(price_raw)?)
677 } else if let Some(price_raw) = self.limit_price {
678 Some(Price::new(price_raw)?)
679 } else {
680 None
681 };
682
683 let stop_price = match order_type {
684 OrderType::Stop | OrderType::StopLimit => {
685 let price_raw = self.stop_price.ok_or(ValidationError::MissingRequiredField("stop_price"))?;
686 Some(Price::new(price_raw)?)
687 }
688 _ => {
689 if let Some(price_raw) = self.stop_price {
690 Some(Price::new(price_raw)?)
691 } else {
692 None
693 }
694 }
695 };
696
697 let trail_stop_price = match order_type {
698 OrderType::TrailingStop | OrderType::TrailingStopLimit => {
699 if self.trailing_percent.is_none() && self.trail_stop_price.is_none() {
700 return Err(ValidationError::MissingRequiredField("trailing amount or stop price"));
701 }
702 if let Some(price_raw) = self.trail_stop_price {
703 Some(Price::new(price_raw)?)
704 } else {
705 None
706 }
707 }
708 _ => None,
709 };
710
711 if order_type == OrderType::Volatility && self.volatility.is_none() {
713 return Err(ValidationError::MissingRequiredField("volatility"));
714 }
715
716 if let TimeInForce::GoodTillDate { .. } = &self.time_in_force {
718 if self.good_till_date.is_none() {
719 return Err(ValidationError::MissingRequiredField("good_till_date"));
720 }
721 }
722
723 let mut order = Order {
725 action,
726 total_quantity: quantity.value(),
727 order_type: order_type.as_str().to_string(),
728 ..Default::default()
729 };
730
731 if let Some(price) = limit_price {
733 order.limit_price = Some(price.value());
734 }
735
736 if let Some(price) = stop_price {
737 order.aux_price = Some(price.value());
738 }
739
740 if let Some(price) = trail_stop_price {
741 order.trail_stop_price = Some(price.value());
742 }
743
744 if let Some(percent) = self.trailing_percent {
745 order.trailing_percent = Some(percent);
746 }
747
748 if let Some(offset) = self.limit_price_offset {
749 order.limit_price_offset = Some(offset);
750 }
751
752 order.tif = crate::orders::TimeInForce::from(self.time_in_force.as_str());
754 if let TimeInForce::GoodTillDate { date } = &self.time_in_force {
755 order.good_till_date = date.clone();
756 }
757
758 order.outside_rth = self.outside_rth;
760 order.hidden = self.hidden;
761 order.transmit = self.transmit;
762
763 if let Some(parent_id) = self.parent_id {
764 order.parent_id = parent_id;
765 }
766
767 if let Some(group) = self.oca_group {
768 order.oca_group = group;
769 order.oca_type = self.oca_type.unwrap_or(0).into();
770 }
771
772 if let Some(account) = self.account {
773 order.account = account;
774 }
775
776 if let Some(time) = self.good_after_time {
777 order.good_after_time = time;
778 }
779
780 if let Some(date_time) = self.good_till_date {
782 if !matches!(self.time_in_force, TimeInForce::GoodTillDate { .. }) {
783 order.good_till_date = date_time;
785 }
786 }
787
788 if let Some(strategy) = self.algo_strategy {
789 order.algo_strategy = strategy;
790 order.algo_params = self.algo_params;
791 }
792
793 order.what_if = self.what_if;
794
795 if let Some(amt) = self.discretionary_amt {
797 order.discretionary_amt = amt;
798 }
799
800 if let Some(vol) = self.volatility {
801 order.volatility = Some(vol);
802 order.volatility_type = self.volatility_type.map(|v| v.into());
803 }
804
805 if let Some(delta) = self.delta {
806 order.delta = Some(delta);
807 }
808
809 if let Some(aux) = self.aux_price {
810 if order.aux_price.is_none() {
812 order.aux_price = Some(aux);
813 }
814 }
815
816 order.sweep_to_fill = self.sweep_to_fill;
818 order.block_order = self.block_order;
819 order.not_held = self.not_held;
820 order.all_or_none = self.all_or_none;
821
822 if let Some(qty) = self.min_trade_qty {
824 order.min_trade_qty = Some(qty);
825 }
826
827 if let Some(size) = self.min_compete_size {
828 order.min_compete_size = Some(size);
829 }
830
831 if let Some(offset) = self.compete_against_best_offset {
832 order.compete_against_best_offset = Some(offset);
833 }
834
835 if let Some(offset) = self.mid_offset_at_whole {
836 order.mid_offset_at_whole = Some(offset);
837 }
838
839 if let Some(offset) = self.mid_offset_at_half {
840 order.mid_offset_at_half = Some(offset);
841 }
842
843 if !self.conditions.is_empty() {
845 order.conditions = self.conditions;
846 }
847
848 if let Some(id) = self.reference_contract_id {
850 order.reference_contract_id = id;
851 }
852
853 if let Some(exchange) = self.reference_exchange {
854 order.reference_exchange = exchange;
855 }
856
857 if let Some(price) = self.stock_ref_price {
858 order.stock_ref_price = Some(price);
859 }
860
861 if let Some(lower) = self.stock_range_lower {
862 order.stock_range_lower = Some(lower);
863 }
864
865 if let Some(upper) = self.stock_range_upper {
866 order.stock_range_upper = Some(upper);
867 }
868
869 if let Some(amount) = self.reference_change_amount {
870 order.reference_change_amount = Some(amount);
871 }
872
873 if let Some(amount) = self.pegged_change_amount {
874 order.pegged_change_amount = Some(amount);
875 }
876
877 if self.is_pegged_change_amount_decrease {
878 order.is_pegged_change_amount_decrease = true;
879 }
880
881 if !self.order_combo_legs.is_empty() {
883 order.order_combo_legs = self.order_combo_legs;
884 }
885
886 if !self.smart_combo_routing_params.is_empty() {
887 order.smart_combo_routing_params = self.smart_combo_routing_params;
888 }
889
890 if let Some(qty) = self.cash_qty {
892 order.cash_qty = Some(qty);
893 }
894
895 if let Some(time) = self.manual_order_time {
897 order.manual_order_time = time;
898 }
899
900 if let Some(strategy) = self.auction_strategy {
902 order.auction_strategy = Some(strategy.into());
903 }
904
905 if let Some(price) = self.starting_price {
907 order.starting_price = Some(price);
908 }
909
910 if let Some(hedge_type) = self.hedge_type {
912 order.hedge_type = hedge_type;
913 }
914
915 Ok(order)
916 }
917}
918
919fn set_conjunction(condition: &mut OrderCondition, is_conjunction: bool) {
921 match condition {
922 OrderCondition::Price(c) => c.is_conjunction = is_conjunction,
923 OrderCondition::Time(c) => c.is_conjunction = is_conjunction,
924 OrderCondition::Margin(c) => c.is_conjunction = is_conjunction,
925 OrderCondition::Execution(c) => c.is_conjunction = is_conjunction,
926 OrderCondition::Volume(c) => c.is_conjunction = is_conjunction,
927 OrderCondition::PercentChange(c) => c.is_conjunction = is_conjunction,
928 }
929}
930
931#[derive(Default)]
933enum BracketEntryType {
934 #[default]
935 None,
936 Limit(f64),
937 Market,
938}
939
940pub struct BracketOrderBuilder<'a, C> {
942 pub(crate) parent_builder: OrderBuilder<'a, C>,
943 entry_type: BracketEntryType,
944 take_profit_price: Option<f64>,
945 stop_loss_price: Option<f64>,
946}
947
948impl<'a, C> BracketOrderBuilder<'a, C> {
949 fn new(parent_builder: OrderBuilder<'a, C>) -> Self {
950 Self {
951 parent_builder,
952 entry_type: BracketEntryType::None,
953 take_profit_price: None,
954 stop_loss_price: None,
955 }
956 }
957
958 pub fn entry_market(mut self) -> Self {
960 self.entry_type = BracketEntryType::Market;
961 self
962 }
963
964 pub fn entry_limit(mut self, price: impl Into<f64>) -> Self {
966 self.entry_type = BracketEntryType::Limit(price.into());
967 self
968 }
969
970 pub fn take_profit(mut self, price: impl Into<f64>) -> Self {
972 self.take_profit_price = Some(price.into());
973 self
974 }
975
976 pub fn stop_loss(mut self, price: impl Into<f64>) -> Self {
978 self.stop_loss_price = Some(price.into());
979 self
980 }
981
982 pub fn build(mut self) -> Result<Vec<Order>, ValidationError> {
984 let take_profit_raw = self.take_profit_price.ok_or(ValidationError::MissingRequiredField("take_profit"))?;
986 let stop_loss_raw = self.stop_loss_price.ok_or(ValidationError::MissingRequiredField("stop_loss"))?;
987
988 let take_profit = Price::new(take_profit_raw)?;
989 let stop_loss = Price::new(stop_loss_raw)?;
990
991 match self.entry_type {
993 BracketEntryType::None => {
994 return Err(ValidationError::MissingRequiredField("entry (use entry_limit() or entry_market())"));
995 }
996 BracketEntryType::Limit(price) => {
997 let entry_price = Price::new(price)?;
998 validation::validate_bracket_prices(
1000 self.parent_builder.action.as_ref(),
1001 entry_price.value(),
1002 take_profit.value(),
1003 stop_loss.value(),
1004 )?;
1005 self.parent_builder.order_type = Some(OrderType::Limit);
1006 self.parent_builder.limit_price = Some(entry_price.value());
1007 }
1008 BracketEntryType::Market => {
1009 self.parent_builder.order_type = Some(OrderType::Market);
1011 }
1012 }
1013
1014 let mut parent = self.parent_builder.build()?;
1016 parent.transmit = false;
1017
1018 let take_profit_order = Order {
1020 action: parent.action.reverse(),
1021 order_type: "LMT".to_string(),
1022 total_quantity: parent.total_quantity,
1023 limit_price: Some(take_profit.value()),
1024 parent_id: parent.order_id,
1025 transmit: false,
1026 outside_rth: parent.outside_rth,
1027 ..Default::default()
1028 };
1029
1030 let stop_loss_order = Order {
1032 action: parent.action.reverse(),
1033 order_type: "STP".to_string(),
1034 total_quantity: parent.total_quantity,
1035 aux_price: Some(stop_loss.value()),
1036 parent_id: parent.order_id,
1037 transmit: true,
1038 outside_rth: parent.outside_rth,
1039 ..Default::default()
1040 };
1041
1042 Ok(vec![parent, take_profit_order, stop_loss_order])
1043 }
1044}