1pub mod place;
3
4pub mod order;
6
7use std::{collections::BTreeMap, fmt, sync::Arc};
8
9use exc_service::{ExchangeError, Request};
10use futures::{future::BoxFuture, stream::BoxStream};
11use indicator::{Tick, TickValue, Tickable};
12pub use order::{Order, OrderId, OrderKind, OrderState, OrderStatus, OrderTrade, TimeInForce};
13pub use place::Place;
14use positions::Asset;
15use time::OffsetDateTime;
16
17use crate::Str;
18
19#[derive(Debug, Clone)]
21pub struct PlaceOrderOptions {
22 instrument: Str,
24 client_id: Option<Str>,
26 margin: Option<Asset>,
28 custom: BTreeMap<Str, Str>,
30}
31
32impl PlaceOrderOptions {
33 pub fn new(inst: impl AsRef<str>) -> Self {
35 Self {
36 instrument: Str::new(inst),
37 client_id: None,
38 margin: None,
39 custom: BTreeMap::default(),
40 }
41 }
42
43 pub fn with_client_id(&mut self, id: Option<impl AsRef<str>>) -> &mut Self {
45 self.client_id = id.map(Str::new);
46 self
47 }
48
49 pub fn with_margin(&mut self, currency: &Asset) -> &mut Self {
54 self.margin = Some(currency.clone());
55 self
56 }
57
58 pub fn insert<K, V>(&mut self, key: K, value: V) -> &mut Self
60 where
61 K: AsRef<str>,
62 V: AsRef<str>,
63 {
64 self.custom
65 .insert(Str::new(key.as_ref()), Str::new(value.as_ref()));
66 self
67 }
68
69 pub fn instrument(&self) -> &str {
71 &self.instrument
72 }
73
74 pub fn client_id(&self) -> Option<&str> {
76 self.client_id.as_deref()
77 }
78
79 pub fn margin(&self) -> Option<&str> {
81 self.margin.as_deref()
82 }
83
84 pub fn custom(&self) -> &BTreeMap<Str, Str> {
86 &self.custom
87 }
88}
89
90#[derive(Debug, Clone)]
92pub struct PlaceOrder {
93 pub place: Place,
95 pub opts: Arc<PlaceOrderOptions>,
97}
98
99impl PlaceOrder {
100 pub fn new(place: Place, opts: &PlaceOrderOptions) -> Self {
102 Self {
103 place,
104 opts: Arc::new(opts.clone()),
105 }
106 }
107}
108
109#[derive(Clone)]
111pub struct Placed {
112 pub id: OrderId,
114 pub order: Option<Order>,
116 pub ts: OffsetDateTime,
118}
119
120impl fmt::Debug for Placed {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_struct("Placed")
123 .field("ts", &self.ts.to_string())
124 .field("id", &self.id.as_str())
125 .field("order", &self.order)
126 .finish()
127 }
128}
129
130impl Request for PlaceOrder {
131 type Response = BoxFuture<'static, Result<Placed, ExchangeError>>;
132}
133
134#[derive(Debug, Clone)]
136pub struct CancelOrder {
137 pub instrument: Str,
139 pub id: OrderId,
141}
142
143impl CancelOrder {
144 pub fn new(inst: impl AsRef<str>, id: OrderId) -> Self {
146 Self {
147 instrument: Str::new(inst),
148 id,
149 }
150 }
151}
152
153#[derive(Clone)]
155pub struct Canceled {
156 pub order: Option<Order>,
158 pub ts: OffsetDateTime,
160}
161
162impl fmt::Debug for Canceled {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.debug_struct("Cancelled")
165 .field("ts", &self.ts.to_string())
166 .field("order", &self.order)
167 .finish()
168 }
169}
170
171impl Request for CancelOrder {
172 type Response = BoxFuture<'static, Result<Canceled, ExchangeError>>;
173}
174
175#[derive(Debug, Clone)]
177pub struct GetOrder {
178 pub instrument: Str,
180 pub id: OrderId,
182}
183
184impl GetOrder {
185 pub fn new(inst: impl AsRef<str>, id: OrderId) -> Self {
187 Self {
188 instrument: Str::new(inst),
189 id,
190 }
191 }
192}
193
194#[derive(Clone)]
196pub struct OrderUpdate {
197 pub ts: OffsetDateTime,
199 pub order: Order,
201}
202
203impl fmt::Debug for OrderUpdate {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 f.debug_struct("OrderUpdate")
206 .field("ts", &self.ts.to_string())
207 .field("order", &self.order)
208 .finish()
209 }
210}
211
212impl Tickable for OrderUpdate {
213 type Value = Order;
214
215 fn tick(&self) -> Tick {
216 Tick::new(self.ts)
217 }
218
219 fn value(&self) -> &Self::Value {
220 &self.order
221 }
222
223 fn into_tick_value(self) -> TickValue<Self::Value> {
224 TickValue::new(self.ts, self.order)
225 }
226}
227
228impl Request for GetOrder {
229 type Response = BoxFuture<'static, Result<OrderUpdate, ExchangeError>>;
230}
231
232pub type OrderStream = BoxStream<'static, Result<OrderUpdate, ExchangeError>>;
234
235#[derive(Debug, Clone)]
237pub struct SubscribeOrders {
238 pub instrument: Str,
240}
241
242impl SubscribeOrders {
243 pub fn new(inst: impl AsRef<str>) -> Self {
245 Self {
246 instrument: Str::new(inst),
247 }
248 }
249}
250
251impl Request for SubscribeOrders {
252 type Response = OrderStream;
253}