1use std::fmt::Display;
17
18use enum_dispatch::enum_dispatch;
19use serde::{Deserialize, Serialize};
20
21use super::{
22 Order, limit::LimitOrder, limit_if_touched::LimitIfTouchedOrder, market::MarketOrder,
23 market_if_touched::MarketIfTouchedOrder, market_to_limit::MarketToLimitOrder,
24 stop_limit::StopLimitOrder, stop_market::StopMarketOrder,
25 trailing_stop_limit::TrailingStopLimitOrder, trailing_stop_market::TrailingStopMarketOrder,
26};
27use crate::{events::OrderEventAny, types::Price};
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
30#[enum_dispatch(Order)]
31pub enum OrderAny {
32 Limit(LimitOrder),
33 LimitIfTouched(LimitIfTouchedOrder),
34 Market(MarketOrder),
35 MarketIfTouched(MarketIfTouchedOrder),
36 MarketToLimit(MarketToLimitOrder),
37 StopLimit(StopLimitOrder),
38 StopMarket(StopMarketOrder),
39 TrailingStopLimit(TrailingStopLimitOrder),
40 TrailingStopMarket(TrailingStopMarketOrder),
41}
42
43impl OrderAny {
44 pub fn from_events(events: Vec<OrderEventAny>) -> anyhow::Result<Self> {
45 if events.is_empty() {
46 anyhow::bail!("No order events provided to create OrderAny");
47 }
48
49 let init_event = events.first().unwrap();
51 match init_event {
52 OrderEventAny::Initialized(init) => {
53 let mut order = Self::from(init.clone());
54 for event in events.into_iter().skip(1) {
56 println!("Applying event: {event:?}"); order.apply(event).unwrap();
59 }
60 Ok(order)
61 }
62 _ => {
63 anyhow::bail!("First event must be `OrderInitialized`");
64 }
65 }
66 }
67}
68
69impl PartialEq for OrderAny {
70 fn eq(&self, other: &Self) -> bool {
71 self.client_order_id() == other.client_order_id()
72 }
73}
74
75impl Eq for OrderAny {}
77
78impl Display for OrderAny {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 write!(
81 f,
82 "{}",
83 match self {
84 Self::Limit(order) => order.to_string(),
85 Self::LimitIfTouched(order) => format!("{order:?}"), Self::Market(order) => order.to_string(),
87 Self::MarketIfTouched(order) => format!("{order:?}"), Self::MarketToLimit(order) => format!("{order:?}"), Self::StopLimit(order) => order.to_string(),
90 Self::StopMarket(order) => format!("{order:?}"), Self::TrailingStopLimit(order) => format!("{order:?}"), Self::TrailingStopMarket(order) => format!("{order:?}"), }
94 )
95 }
96}
97
98impl From<OrderAny> for PassiveOrderAny {
99 fn from(order: OrderAny) -> PassiveOrderAny {
100 match order {
101 OrderAny::Limit(_) => PassiveOrderAny::Limit(order.into()),
102 OrderAny::LimitIfTouched(_) => PassiveOrderAny::Stop(order.into()),
103 OrderAny::MarketIfTouched(_) => PassiveOrderAny::Stop(order.into()),
104 OrderAny::StopLimit(_) => PassiveOrderAny::Stop(order.into()),
105 OrderAny::StopMarket(_) => PassiveOrderAny::Stop(order.into()),
106 OrderAny::TrailingStopLimit(_) => PassiveOrderAny::Stop(order.into()),
107 OrderAny::TrailingStopMarket(_) => PassiveOrderAny::Stop(order.into()),
108 OrderAny::MarketToLimit(_) => PassiveOrderAny::Limit(order.into()),
109 _ => panic!("WIP: Implement trait bound to require `HasPrice`"),
110 }
111 }
112}
113
114impl From<PassiveOrderAny> for OrderAny {
115 fn from(order: PassiveOrderAny) -> OrderAny {
116 match order {
117 PassiveOrderAny::Limit(order) => order.into(),
118 PassiveOrderAny::Stop(order) => order.into(),
119 }
120 }
121}
122
123impl From<OrderAny> for StopOrderAny {
124 fn from(order: OrderAny) -> StopOrderAny {
125 match order {
126 OrderAny::LimitIfTouched(order) => StopOrderAny::LimitIfTouched(order),
127 OrderAny::MarketIfTouched(order) => StopOrderAny::MarketIfTouched(order),
128 OrderAny::StopLimit(order) => StopOrderAny::StopLimit(order),
129 OrderAny::StopMarket(order) => StopOrderAny::StopMarket(order),
130 OrderAny::TrailingStopLimit(order) => StopOrderAny::TrailingStopLimit(order),
131 OrderAny::TrailingStopMarket(order) => StopOrderAny::TrailingStopMarket(order),
132 _ => panic!("WIP: Implement trait bound to require `HasStopPrice`"),
133 }
134 }
135}
136
137impl From<StopOrderAny> for OrderAny {
138 fn from(order: StopOrderAny) -> OrderAny {
139 match order {
140 StopOrderAny::LimitIfTouched(order) => OrderAny::LimitIfTouched(order),
141 StopOrderAny::MarketIfTouched(order) => OrderAny::MarketIfTouched(order),
142 StopOrderAny::StopLimit(order) => OrderAny::StopLimit(order),
143 StopOrderAny::StopMarket(order) => OrderAny::StopMarket(order),
144 StopOrderAny::TrailingStopLimit(order) => OrderAny::TrailingStopLimit(order),
145 StopOrderAny::TrailingStopMarket(order) => OrderAny::TrailingStopMarket(order),
146 }
147 }
148}
149
150impl From<OrderAny> for LimitOrderAny {
151 fn from(order: OrderAny) -> LimitOrderAny {
152 match order {
153 OrderAny::Limit(order) => LimitOrderAny::Limit(order),
154 OrderAny::MarketToLimit(order) => LimitOrderAny::MarketToLimit(order),
155 OrderAny::StopLimit(order) => LimitOrderAny::StopLimit(order),
156 OrderAny::TrailingStopLimit(order) => LimitOrderAny::TrailingStopLimit(order),
157 _ => panic!("WIP: Implement trait bound to require `HasLimitPrice`"),
158 }
159 }
160}
161
162impl From<LimitOrderAny> for OrderAny {
163 fn from(order: LimitOrderAny) -> OrderAny {
164 match order {
165 LimitOrderAny::Limit(order) => OrderAny::Limit(order),
166 LimitOrderAny::MarketToLimit(order) => OrderAny::MarketToLimit(order),
167 LimitOrderAny::StopLimit(order) => OrderAny::StopLimit(order),
168 LimitOrderAny::TrailingStopLimit(order) => OrderAny::TrailingStopLimit(order),
169 }
170 }
171}
172
173#[derive(Clone, Debug)]
174#[enum_dispatch(Order)]
175pub enum PassiveOrderAny {
176 Limit(LimitOrderAny),
177 Stop(StopOrderAny),
178}
179
180impl PassiveOrderAny {
181 #[must_use]
182 pub fn to_any(&self) -> OrderAny {
183 match self {
184 Self::Limit(order) => order.clone().into(),
185 Self::Stop(order) => order.clone().into(),
186 }
187 }
188}
189
190impl PartialEq for PassiveOrderAny {
192 fn eq(&self, rhs: &Self) -> bool {
193 match self {
194 Self::Limit(order) => order.client_order_id() == rhs.client_order_id(),
195 Self::Stop(order) => order.client_order_id() == rhs.client_order_id(),
196 }
197 }
198}
199
200#[derive(Clone, Debug)]
201#[enum_dispatch(Order)]
202pub enum LimitOrderAny {
203 Limit(LimitOrder),
204 MarketToLimit(MarketToLimitOrder),
205 StopLimit(StopLimitOrder),
206 TrailingStopLimit(TrailingStopLimitOrder),
207}
208
209impl LimitOrderAny {
210 #[must_use]
211 pub fn limit_px(&self) -> Price {
212 match self {
213 Self::Limit(order) => order.price,
214 Self::MarketToLimit(order) => order.price.expect("No price for order"), Self::StopLimit(order) => order.price,
216 Self::TrailingStopLimit(order) => order.price,
217 }
218 }
219}
220
221impl PartialEq for LimitOrderAny {
222 fn eq(&self, rhs: &Self) -> bool {
223 match self {
224 Self::Limit(order) => order.client_order_id == rhs.client_order_id(),
225 Self::MarketToLimit(order) => order.client_order_id == rhs.client_order_id(),
226 Self::StopLimit(order) => order.client_order_id == rhs.client_order_id(),
227 Self::TrailingStopLimit(order) => order.client_order_id == rhs.client_order_id(),
228 }
229 }
230}
231
232#[derive(Clone, Debug)]
233#[enum_dispatch(Order)]
234pub enum StopOrderAny {
235 LimitIfTouched(LimitIfTouchedOrder),
236 MarketIfTouched(MarketIfTouchedOrder),
237 StopLimit(StopLimitOrder),
238 StopMarket(StopMarketOrder),
239 TrailingStopLimit(TrailingStopLimitOrder),
240 TrailingStopMarket(TrailingStopMarketOrder),
241}
242
243impl StopOrderAny {
244 #[must_use]
245 pub fn stop_px(&self) -> Price {
246 match self {
247 Self::LimitIfTouched(order) => order.trigger_price,
248 Self::MarketIfTouched(order) => order.trigger_price,
249 Self::StopLimit(order) => order.trigger_price,
250 Self::StopMarket(order) => order.trigger_price,
251 Self::TrailingStopLimit(order) => order.trigger_price,
252 Self::TrailingStopMarket(order) => order.trigger_price,
253 }
254 }
255}
256
257impl PartialEq for StopOrderAny {
259 fn eq(&self, rhs: &Self) -> bool {
260 match self {
261 Self::LimitIfTouched(order) => order.client_order_id == rhs.client_order_id(),
262 Self::StopLimit(order) => order.client_order_id == rhs.client_order_id(),
263 Self::StopMarket(order) => order.client_order_id == rhs.client_order_id(),
264 Self::MarketIfTouched(order) => order.client_order_id == rhs.client_order_id(),
265 Self::TrailingStopLimit(order) => order.client_order_id == rhs.client_order_id(),
266 Self::TrailingStopMarket(order) => order.client_order_id == rhs.client_order_id(),
267 }
268 }
269}