ig_client/application/models/
working_order.rs

1use crate::application::models::order::{Direction, OrderType, TimeInForce};
2use serde::{Deserialize, Serialize};
3
4/// Model for creating a new working order
5#[derive(Debug, Clone, Serialize)]
6pub struct CreateWorkingOrderRequest {
7    /// Instrument EPIC identifier
8    pub epic: String,
9    /// Order direction (buy or sell)
10    pub direction: Direction,
11    /// Order size/quantity
12    pub size: f64,
13    /// Price level for the order
14    pub level: f64,
15    /// Type of working order (LIMIT or STOP)
16    #[serde(rename = "type")]
17    pub order_type: OrderType,
18    /// Order duration (how long the order remains valid)
19    #[serde(rename = "timeInForce")]
20    pub time_in_force: TimeInForce,
21    /// Whether to use a guaranteed stop
22    #[serde(rename = "guaranteedStop")]
23    pub guaranteed_stop: bool,
24    /// Price level for stop loss
25    #[serde(rename = "stopLevel", skip_serializing_if = "Option::is_none")]
26    pub stop_level: Option<f64>,
27    /// Distance for stop loss
28    #[serde(rename = "stopDistance", skip_serializing_if = "Option::is_none")]
29    pub stop_distance: Option<f64>,
30    /// Price level for take profit
31    #[serde(rename = "limitLevel", skip_serializing_if = "Option::is_none")]
32    pub limit_level: Option<f64>,
33    /// Distance for take profit
34    #[serde(rename = "limitDistance", skip_serializing_if = "Option::is_none")]
35    pub limit_distance: Option<f64>,
36    /// Expiry date for GTD orders
37    #[serde(rename = "goodTillDate", skip_serializing_if = "Option::is_none")]
38    pub good_till_date: Option<String>,
39    /// Client-generated reference for the deal
40    #[serde(rename = "dealReference", skip_serializing_if = "Option::is_none")]
41    pub deal_reference: Option<String>,
42    /// Currency code for the order (e.g., "USD", "EUR")
43    #[serde(rename = "currencyCode", skip_serializing_if = "Option::is_none")]
44    pub currency_code: Option<String>,
45    /// Expiry date for the order (required by the API)
46    #[serde(rename = "expiry")]
47    pub expiry: String,
48}
49
50impl CreateWorkingOrderRequest {
51    /// Creates a new limit working order
52    pub fn limit(epic: String, direction: Direction, size: f64, level: f64) -> Self {
53        Self {
54            epic,
55            direction,
56            size,
57            level,
58            order_type: OrderType::Limit,
59            time_in_force: TimeInForce::GoodTillCancelled,
60            guaranteed_stop: false,
61            stop_level: None,
62            stop_distance: None,
63            limit_level: None,
64            limit_distance: None,
65            good_till_date: None,
66            deal_reference: None,
67            currency_code: None,
68            expiry: "DFB".to_string(), // Default expiry for Daily Forward Bet
69        }
70    }
71
72    /// Creates a new stop working order
73    pub fn stop(epic: String, direction: Direction, size: f64, level: f64) -> Self {
74        Self {
75            epic,
76            direction,
77            size,
78            level,
79            order_type: OrderType::Stop,
80            time_in_force: TimeInForce::GoodTillCancelled,
81            guaranteed_stop: false,
82            stop_level: None,
83            stop_distance: None,
84            limit_level: None,
85            limit_distance: None,
86            good_till_date: None,
87            deal_reference: None,
88            currency_code: None,
89            expiry: "DFB".to_string(), // Default expiry for Daily Forward Bet
90        }
91    }
92
93    /// Adds a stop loss to the working order
94    pub fn with_stop_loss(mut self, stop_level: f64) -> Self {
95        self.stop_level = Some(stop_level);
96        self
97    }
98
99    /// Adds a take profit to the working order
100    pub fn with_take_profit(mut self, limit_level: f64) -> Self {
101        self.limit_level = Some(limit_level);
102        self
103    }
104
105    /// Adds a reference to the working order
106    pub fn with_reference(mut self, reference: String) -> Self {
107        self.deal_reference = Some(reference);
108        self
109    }
110
111    /// Sets the order to expire at a specific date
112    pub fn expires_at(mut self, date: String) -> Self {
113        self.time_in_force = TimeInForce::GoodTillDate;
114        self.good_till_date = Some(date);
115        self
116    }
117
118    /// Sets the expiry for the order
119    pub fn with_expiry(mut self, expiry: String) -> Self {
120        self.expiry = expiry;
121        self
122    }
123}
124
125/// Response to working order creation
126#[derive(Debug, Clone, Deserialize)]
127pub struct CreateWorkingOrderResponse {
128    /// Client-generated reference for the deal
129    #[serde(rename = "dealReference")]
130    pub deal_reference: String,
131}