1use crate::impl_json_display;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
11#[serde(rename_all = "UPPERCASE")]
12pub enum Direction {
13 #[default]
15 Buy,
16 Sell,
18}
19
20impl_json_display!(Direction);
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
24#[serde(rename_all = "UPPERCASE")]
25pub enum OrderType {
26 #[default]
28 Limit,
29 Market,
31 Quote,
33 Stop,
35 StopLimit,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
44#[serde(rename_all = "UPPERCASE")]
45pub enum Status {
46 Amended,
48 Deleted,
50 #[serde(rename = "FULLY_CLOSED")]
52 FullyClosed,
53 Opened,
55 #[serde(rename = "PARTIALLY_CLOSED")]
57 PartiallyClosed,
58 Closed,
60 #[default]
62 Open,
63 Updated,
65 Accepted,
67 Rejected,
69 Working,
71 Filled,
73 Cancelled,
75 Expired,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
81pub enum TimeInForce {
82 #[serde(rename = "GOOD_TILL_CANCELLED")]
84 #[default]
85 GoodTillCancelled,
86 #[serde(rename = "GOOD_TILL_DATE")]
88 GoodTillDate,
89 #[serde(rename = "IMMEDIATE_OR_CANCEL")]
91 ImmediateOrCancel,
92 #[serde(rename = "FILL_OR_KILL")]
94 FillOrKill,
95}
96
97#[derive(Debug, Clone, Serialize)]
99pub struct CreateOrderRequest {
100 pub epic: String,
102 pub direction: Direction,
104 pub size: f64,
106 #[serde(rename = "orderType")]
108 pub order_type: OrderType,
109 #[serde(rename = "timeInForce")]
111 pub time_in_force: TimeInForce,
112 #[serde(rename = "level", skip_serializing_if = "Option::is_none")]
114 pub level: Option<f64>,
115 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
117 pub guaranteed_stop: Option<bool>,
118 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
120 pub stop_level: Option<f64>,
121 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
123 pub stop_distance: Option<f64>,
124 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
126 pub limit_level: Option<f64>,
127 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
129 pub limit_distance: Option<f64>,
130 #[serde(rename = "expiry", skip_serializing_if = "Option::is_none")]
132 pub expiry: Option<String>,
133 #[serde(rename = "dealReference", skip_serializing_if = "Option::is_none")]
135 pub deal_reference: Option<String>,
136 #[serde(rename = "forceOpen", skip_serializing_if = "Option::is_none")]
138 pub force_open: Option<bool>,
139 #[serde(rename = "currencyCode", skip_serializing_if = "Option::is_none")]
141 pub currency_code: Option<String>,
142}
143
144impl CreateOrderRequest {
145 pub fn market(epic: String, direction: Direction, size: f64) -> Self {
147 Self {
148 epic,
149 direction,
150 size,
151 order_type: OrderType::Market,
152 time_in_force: TimeInForce::FillOrKill,
153 level: None,
154 guaranteed_stop: None,
155 stop_level: None,
156 stop_distance: None,
157 limit_level: None,
158 limit_distance: None,
159 expiry: None,
160 deal_reference: None,
161 force_open: Some(true),
162 currency_code: None,
163 }
164 }
165
166 pub fn limit(epic: String, direction: Direction, size: f64, level: f64) -> Self {
168 Self {
169 epic,
170 direction,
171 size,
172 order_type: OrderType::Limit,
173 time_in_force: TimeInForce::GoodTillCancelled,
174 level: Some(level),
175 guaranteed_stop: None,
176 stop_level: None,
177 stop_distance: None,
178 limit_level: None,
179 limit_distance: None,
180 expiry: None,
181 deal_reference: None,
182 force_open: Some(true),
183 currency_code: None,
184 }
185 }
186
187 pub fn with_stop_loss(mut self, stop_level: f64) -> Self {
189 self.stop_level = Some(stop_level);
190 self
191 }
192
193 pub fn with_take_profit(mut self, limit_level: f64) -> Self {
195 self.limit_level = Some(limit_level);
196 self
197 }
198
199 pub fn with_reference(mut self, reference: String) -> Self {
201 self.deal_reference = Some(reference);
202 self
203 }
204}
205
206#[derive(Debug, Clone, Deserialize)]
208pub struct CreateOrderResponse {
209 #[serde(rename = "dealReference")]
211 pub deal_reference: String,
212}
213
214#[derive(Debug, Clone, Deserialize)]
216pub struct OrderConfirmation {
217 pub date: String,
219 pub status: Status,
221 pub reason: Option<String>,
223 #[serde(rename = "dealId")]
225 pub deal_id: Option<String>,
226 #[serde(rename = "dealReference")]
228 pub deal_reference: String,
229 #[serde(rename = "dealStatus")]
231 pub deal_status: Option<String>,
232 pub epic: Option<String>,
234 #[serde(rename = "expiry")]
236 pub expiry: Option<String>,
237 #[serde(rename = "guaranteedStop")]
239 pub guaranteed_stop: Option<bool>,
240 #[serde(rename = "level")]
242 pub level: Option<f64>,
243 #[serde(rename = "limitDistance")]
245 pub limit_distance: Option<f64>,
246 #[serde(rename = "limitLevel")]
248 pub limit_level: Option<f64>,
249 pub size: Option<f64>,
251 #[serde(rename = "stopDistance")]
253 pub stop_distance: Option<f64>,
254 #[serde(rename = "stopLevel")]
256 pub stop_level: Option<f64>,
257 #[serde(rename = "trailingStop")]
259 pub trailing_stop: Option<bool>,
260 pub direction: Option<Direction>,
262}
263
264#[derive(Debug, Clone, Serialize)]
266pub struct UpdatePositionRequest {
267 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
269 pub stop_level: Option<f64>,
270 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
272 pub limit_level: Option<f64>,
273 #[serde(rename = "trailingStop", skip_serializing_if = "Option::is_none")]
275 pub trailing_stop: Option<bool>,
276 #[serde(
278 rename = "trailingStopDistance",
279 skip_serializing_if = "Option::is_none"
280 )]
281 pub trailing_stop_distance: Option<f64>,
282}
283
284#[derive(Debug, Clone, Serialize)]
286pub struct ClosePositionRequest {
287 #[serde(rename = "dealId")]
289 pub deal_id: String,
290 pub direction: Direction,
292 pub size: f64,
294 #[serde(rename = "orderType")]
296 pub order_type: OrderType,
297 #[serde(rename = "timeInForce")]
299 pub time_in_force: TimeInForce,
300 #[serde(rename = "level", skip_serializing_if = "Option::is_none")]
302 pub level: Option<f64>,
303 #[serde(rename = "forceOpen")]
305 pub force_open: bool,
306 #[serde(rename = "expiry")]
308 pub expiry: String,
309 pub epic: String,
311 #[serde(rename = "currencyCode")]
313 pub currency_code: String,
314 #[serde(rename = "guaranteedStop")]
316 pub guaranteed_stop: bool,
317}
318
319impl ClosePositionRequest {
320 pub fn market(deal_id: String, direction: Direction, size: f64, epic: String) -> Self {
322 Self {
323 deal_id,
324 direction,
325 size,
326 order_type: OrderType::Market,
327 time_in_force: TimeInForce::FillOrKill,
328 level: None,
329 force_open: false,
330 expiry: "JUL-25".to_string(), epic,
332 currency_code: "EUR".to_string(), guaranteed_stop: false, }
335 }
336
337 pub fn limit(
341 deal_id: String,
342 direction: Direction,
343 size: f64,
344 epic: String,
345 level: f64,
346 ) -> Self {
347 Self {
348 deal_id,
349 direction,
350 size,
351 order_type: OrderType::Limit,
352 time_in_force: TimeInForce::FillOrKill,
353 level: Some(level),
354 force_open: false,
355 expiry: "JUL-25".to_string(), epic,
357 currency_code: "EUR".to_string(), guaranteed_stop: false, }
360 }
361}
362
363#[derive(Debug, Clone, Deserialize)]
365pub struct ClosePositionResponse {
366 #[serde(rename = "dealReference")]
368 pub deal_reference: String,
369}
370
371#[derive(Debug, Clone, Deserialize)]
373pub struct UpdatePositionResponse {
374 #[serde(rename = "dealReference")]
376 pub deal_reference: String,
377}
378
379#[derive(Debug, Clone, Serialize)]
381pub struct CreateWorkingOrderRequest {
382 pub epic: String,
384 pub direction: Direction,
386 pub size: f64,
388 pub level: f64,
390 #[serde(rename = "type")]
392 pub order_type: OrderType,
393 #[serde(rename = "timeInForce")]
395 pub time_in_force: TimeInForce,
396 #[serde(rename = "guaranteedStop", skip_serializing_if = "Option::is_none")]
398 pub guaranteed_stop: Option<bool>,
399 #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
401 pub stop_level: Option<f64>,
402 #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
404 pub stop_distance: Option<f64>,
405 #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
407 pub limit_level: Option<f64>,
408 #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
410 pub limit_distance: Option<f64>,
411 #[serde(rename = "goodTillDate", skip_serializing_if = "Option::is_none")]
413 pub good_till_date: Option<String>,
414 #[serde(rename = "dealReference", skip_serializing_if = "Option::is_none")]
416 pub deal_reference: Option<String>,
417 #[serde(rename = "currencyCode", skip_serializing_if = "Option::is_none")]
419 pub currency_code: Option<String>,
420}
421
422impl CreateWorkingOrderRequest {
423 pub fn limit(epic: String, direction: Direction, size: f64, level: f64) -> Self {
425 Self {
426 epic,
427 direction,
428 size,
429 level,
430 order_type: OrderType::Limit,
431 time_in_force: TimeInForce::GoodTillCancelled,
432 guaranteed_stop: None,
433 stop_level: None,
434 stop_distance: None,
435 limit_level: None,
436 limit_distance: None,
437 good_till_date: None,
438 deal_reference: None,
439 currency_code: None,
440 }
441 }
442
443 pub fn stop(epic: String, direction: Direction, size: f64, level: f64) -> Self {
445 Self {
446 epic,
447 direction,
448 size,
449 level,
450 order_type: OrderType::Stop,
451 time_in_force: TimeInForce::GoodTillCancelled,
452 guaranteed_stop: None,
453 stop_level: None,
454 stop_distance: None,
455 limit_level: None,
456 limit_distance: None,
457 good_till_date: None,
458 deal_reference: None,
459 currency_code: None,
460 }
461 }
462
463 pub fn with_stop_loss(mut self, stop_level: f64) -> Self {
465 self.stop_level = Some(stop_level);
466 self
467 }
468
469 pub fn with_take_profit(mut self, limit_level: f64) -> Self {
471 self.limit_level = Some(limit_level);
472 self
473 }
474
475 pub fn with_reference(mut self, reference: String) -> Self {
477 self.deal_reference = Some(reference);
478 self
479 }
480
481 pub fn expires_at(mut self, date: String) -> Self {
483 self.time_in_force = TimeInForce::GoodTillDate;
484 self.good_till_date = Some(date);
485 self
486 }
487}
488
489#[derive(Debug, Clone, Deserialize)]
491pub struct CreateWorkingOrderResponse {
492 #[serde(rename = "dealReference")]
494 pub deal_reference: String,
495}