Skip to main content

oanda_client/models/
order.rs

1//! OANDA v20 order definitions.
2use super::{
3    ClientExtensions, GuaranteedStopLossDetails, GuaranteedStopLossOrderLevelRestriction,
4    MarketOrderDelayedTradeClose, MarketOrderMarginCloseout, MarketOrderPositionCloseout,
5    MarketOrderTradeClose, StopLossDetails, TakeProfitDetails, TradeState, TrailingStopLossDetails,
6};
7use crate::ids::{ClientID, InstrumentName, OrderID, TradeID, TransactionID};
8use crate::timestamp::Timestamp;
9use rust_decimal::Decimal;
10use serde::{Deserialize, Serialize};
11
12/// A `MarketOrder` is an order that is filled immediately upon creation using the current market price.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct MarketOrder {
16    /// The Order’s identifier, unique within the Order’s Account.
17    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
18    pub id: Option<OrderID>,
19    /// The time when the Order was created.
20    #[serde(
21        rename = "createTime",
22        default,
23        skip_serializing_if = "Option::is_none"
24    )]
25    pub create_time: Option<Timestamp>,
26    /// The current state of the Order.
27    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
28    pub state: Option<OrderState>,
29    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
30    /// associated with MT4.
31    #[serde(
32        rename = "clientExtensions",
33        default,
34        skip_serializing_if = "Option::is_none"
35    )]
36    pub client_extensions: Option<ClientExtensions>,
37    /// The type of the Order. Always set to “MARKET” for Market Orders.
38    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
39    #[serde(serialize_with = "serialize_market_order_type")]
40    pub r#type: Option<OrderType>,
41    /// The Market Order’s Instrument.
42    #[serde(rename = "instrument")]
43    pub instrument: InstrumentName,
44    /// The quantity requested to be filled by the Market Order. A positive number of units results in a long
45    /// Order, and a negative number of units results in a short Order.
46    #[serde(rename = "units")]
47    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
48    pub units: Decimal,
49    /// The time-in-force requested for the Market Order. Restricted to FOK or IOC for a `MarketOrder`.
50    #[serde(rename = "timeInForce")]
51    pub time_in_force: TimeInForce,
52    /// The worst price that the client is willing to have the Market Order filled at.
53    #[serde(
54        rename = "priceBound",
55        default,
56        skip_serializing_if = "Option::is_none"
57    )]
58    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
59    pub price_bound: Option<Decimal>,
60    /// Specification of how Positions in the Account are modified when the Order is filled.
61    #[serde(rename = "positionFill")]
62    pub position_fill: OrderPositionFill,
63    /// Details of the Trade requested to be closed, only provided when the Market Order is being used to
64    /// explicitly close a Trade.
65    #[serde(
66        rename = "tradeClose",
67        default,
68        skip_serializing_if = "Option::is_none"
69    )]
70    pub trade_close: Option<MarketOrderTradeClose>,
71    /// Details of the long Position requested to be closed out, only provided when a Market Order is being used
72    /// to explicitly closeout a long Position.
73    #[serde(
74        rename = "longPositionCloseout",
75        default,
76        skip_serializing_if = "Option::is_none"
77    )]
78    pub long_position_closeout: Option<MarketOrderPositionCloseout>,
79    /// Details of the short Position requested to be closed out, only provided when a Market Order is being
80    /// used to explicitly closeout a short Position.
81    #[serde(
82        rename = "shortPositionCloseout",
83        default,
84        skip_serializing_if = "Option::is_none"
85    )]
86    pub short_position_closeout: Option<MarketOrderPositionCloseout>,
87    /// Details of the Margin Closeout that this Market Order was created for
88    #[serde(
89        rename = "marginCloseout",
90        default,
91        skip_serializing_if = "Option::is_none"
92    )]
93    pub margin_closeout: Option<MarketOrderMarginCloseout>,
94    /// Details of the delayed Trade close that this Market Order was created for
95    #[serde(
96        rename = "delayedTradeClose",
97        default,
98        skip_serializing_if = "Option::is_none"
99    )]
100    pub delayed_trade_close: Option<MarketOrderDelayedTradeClose>,
101    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
102    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
103    /// dependent Take Profit Order is modified directly through the Trade.
104    #[serde(
105        rename = "takeProfitOnFill",
106        default,
107        skip_serializing_if = "Option::is_none"
108    )]
109    pub take_profit_on_fill: Option<TakeProfitDetails>,
110    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
111    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
112    /// Stop Loss Order is modified directly through the Trade.
113    #[serde(
114        rename = "stopLossOnFill",
115        default,
116        skip_serializing_if = "Option::is_none"
117    )]
118    pub stop_loss_on_fill: Option<StopLossDetails>,
119    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
120    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
121    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
122    #[serde(
123        rename = "guaranteedStopLossOnFill",
124        default,
125        skip_serializing_if = "Option::is_none"
126    )]
127    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
128    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
129    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
130    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
131    #[serde(
132        rename = "trailingStopLossOnFill",
133        default,
134        skip_serializing_if = "Option::is_none"
135    )]
136    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
137    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
138    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
139    #[serde(
140        rename = "tradeClientExtensions",
141        default,
142        skip_serializing_if = "Option::is_none"
143    )]
144    pub trade_client_extensions: Option<ClientExtensions>,
145    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
146    #[serde(
147        rename = "fillingTransactionID",
148        default,
149        skip_serializing_if = "Option::is_none"
150    )]
151    pub filling_transaction_id: Option<TransactionID>,
152    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
153    #[serde(
154        rename = "filledTime",
155        default,
156        skip_serializing_if = "Option::is_none"
157    )]
158    pub filled_time: Option<Timestamp>,
159    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
160    /// Trade was opened as a result of the fill)
161    #[serde(
162        rename = "tradeOpenedID",
163        default,
164        skip_serializing_if = "Option::is_none"
165    )]
166    pub trade_opened_id: Option<TradeID>,
167    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
168    /// a Trade was reduced as a result of the fill)
169    #[serde(
170        rename = "tradeReducedID",
171        default,
172        skip_serializing_if = "Option::is_none"
173    )]
174    pub trade_reduced_id: Option<TradeID>,
175    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
176    /// one or more Trades were closed as a result of the fill)
177    #[serde(
178        rename = "tradeClosedIDs",
179        default,
180        skip_serializing_if = "Option::is_none"
181    )]
182    pub trade_closed_ids: Option<Vec<TradeID>>,
183    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
184    #[serde(
185        rename = "cancellingTransactionID",
186        default,
187        skip_serializing_if = "Option::is_none"
188    )]
189    pub cancelling_transaction_id: Option<TransactionID>,
190    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
191    #[serde(
192        rename = "cancelledTime",
193        default,
194        skip_serializing_if = "Option::is_none"
195    )]
196    pub cancelled_time: Option<Timestamp>,
197}
198
199/// A `FixedPriceOrder` is an order that is filled immediately upon creation using a fixed price.
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
201#[serde(rename_all = "camelCase")]
202pub struct FixedPriceOrder {
203    /// The Order’s identifier, unique within the Order’s Account.
204    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
205    pub id: Option<OrderID>,
206    /// The time when the Order was created.
207    #[serde(
208        rename = "createTime",
209        default,
210        skip_serializing_if = "Option::is_none"
211    )]
212    pub create_time: Option<Timestamp>,
213    /// The current state of the Order.
214    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
215    pub state: Option<OrderState>,
216    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
217    /// associated with MT4.
218    #[serde(
219        rename = "clientExtensions",
220        default,
221        skip_serializing_if = "Option::is_none"
222    )]
223    pub client_extensions: Option<ClientExtensions>,
224    /// The type of the Order. Always set to “`FIXED_PRICE`” for Fixed Price Orders.
225    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
226    #[serde(serialize_with = "serialize_fixed_price_order_type")]
227    pub r#type: Option<OrderType>,
228    /// The Fixed Price Order’s Instrument.
229    #[serde(rename = "instrument")]
230    pub instrument: InstrumentName,
231    /// The quantity requested to be filled by the Fixed Price Order. A positive number of units results in a
232    /// long Order, and a negative number of units results in a short Order.
233    #[serde(rename = "units")]
234    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
235    pub units: Decimal,
236    /// The price specified for the Fixed Price Order. This price is the exact price that the Fixed Price Order
237    /// will be filled at.
238    #[serde(rename = "price")]
239    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
240    pub price: Decimal,
241    /// Specification of how Positions in the Account are modified when the Order is filled.
242    #[serde(rename = "positionFill")]
243    pub position_fill: OrderPositionFill,
244    /// The state that the trade resulting from the Fixed Price Order should be set to.
245    #[serde(rename = "tradeState")]
246    pub trade_state: TradeState,
247    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
248    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
249    /// dependent Take Profit Order is modified directly through the Trade.
250    #[serde(
251        rename = "takeProfitOnFill",
252        default,
253        skip_serializing_if = "Option::is_none"
254    )]
255    pub take_profit_on_fill: Option<TakeProfitDetails>,
256    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
257    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
258    /// Stop Loss Order is modified directly through the Trade.
259    #[serde(
260        rename = "stopLossOnFill",
261        default,
262        skip_serializing_if = "Option::is_none"
263    )]
264    pub stop_loss_on_fill: Option<StopLossDetails>,
265    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
266    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
267    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
268    #[serde(
269        rename = "guaranteedStopLossOnFill",
270        default,
271        skip_serializing_if = "Option::is_none"
272    )]
273    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
274    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
275    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
276    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
277    #[serde(
278        rename = "trailingStopLossOnFill",
279        default,
280        skip_serializing_if = "Option::is_none"
281    )]
282    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
283    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
284    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
285    #[serde(
286        rename = "tradeClientExtensions",
287        default,
288        skip_serializing_if = "Option::is_none"
289    )]
290    pub trade_client_extensions: Option<ClientExtensions>,
291    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
292    #[serde(
293        rename = "fillingTransactionID",
294        default,
295        skip_serializing_if = "Option::is_none"
296    )]
297    pub filling_transaction_id: Option<TransactionID>,
298    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
299    #[serde(
300        rename = "filledTime",
301        default,
302        skip_serializing_if = "Option::is_none"
303    )]
304    pub filled_time: Option<Timestamp>,
305    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
306    /// Trade was opened as a result of the fill)
307    #[serde(
308        rename = "tradeOpenedID",
309        default,
310        skip_serializing_if = "Option::is_none"
311    )]
312    pub trade_opened_id: Option<TradeID>,
313    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
314    /// a Trade was reduced as a result of the fill)
315    #[serde(
316        rename = "tradeReducedID",
317        default,
318        skip_serializing_if = "Option::is_none"
319    )]
320    pub trade_reduced_id: Option<TradeID>,
321    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
322    /// one or more Trades were closed as a result of the fill)
323    #[serde(
324        rename = "tradeClosedIDs",
325        default,
326        skip_serializing_if = "Option::is_none"
327    )]
328    pub trade_closed_ids: Option<Vec<TradeID>>,
329    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
330    #[serde(
331        rename = "cancellingTransactionID",
332        default,
333        skip_serializing_if = "Option::is_none"
334    )]
335    pub cancelling_transaction_id: Option<TransactionID>,
336    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
337    #[serde(
338        rename = "cancelledTime",
339        default,
340        skip_serializing_if = "Option::is_none"
341    )]
342    pub cancelled_time: Option<Timestamp>,
343}
344
345/// A `LimitOrder` is an order that is created with a price threshold, and will only be filled by a price that
346/// is equal to or better than the threshold.
347#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
348#[serde(rename_all = "camelCase")]
349pub struct LimitOrder {
350    /// The Order’s identifier, unique within the Order’s Account.
351    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
352    pub id: Option<OrderID>,
353    /// The time when the Order was created.
354    #[serde(
355        rename = "createTime",
356        default,
357        skip_serializing_if = "Option::is_none"
358    )]
359    pub create_time: Option<Timestamp>,
360    /// The current state of the Order.
361    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
362    pub state: Option<OrderState>,
363    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
364    /// associated with MT4.
365    #[serde(
366        rename = "clientExtensions",
367        default,
368        skip_serializing_if = "Option::is_none"
369    )]
370    pub client_extensions: Option<ClientExtensions>,
371    /// The type of the Order. Always set to “LIMIT” for Limit Orders.
372    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
373    #[serde(serialize_with = "serialize_limit_order_type")]
374    pub r#type: Option<OrderType>,
375    /// The Limit Order’s Instrument.
376    #[serde(rename = "instrument")]
377    pub instrument: InstrumentName,
378    /// The quantity requested to be filled by the Limit Order. A positive number of units results in a long
379    /// Order, and a negative number of units results in a short Order.
380    #[serde(rename = "units")]
381    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
382    pub units: Decimal,
383    /// The price threshold specified for the Limit Order. The Limit Order will only be filled by a market price
384    /// that is equal to or better than this price.
385    #[serde(rename = "price")]
386    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
387    pub price: Decimal,
388    /// The time-in-force requested for the Limit Order.
389    #[serde(rename = "timeInForce")]
390    pub time_in_force: TimeInForce,
391    /// The date/time when the Limit Order will be cancelled if its timeInForce is “GTD”.
392    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
393    pub gtd_time: Option<Timestamp>,
394    /// Specification of how Positions in the Account are modified when the Order is filled.
395    #[serde(rename = "positionFill")]
396    pub position_fill: OrderPositionFill,
397    /// Specification of which price component should be used when determining if an Order should be triggered
398    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
399    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
400    /// filled using their default price component. This feature is only provided through the REST API. Clients
401    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
402    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
403    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
404    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
405    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
406    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
407    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
408    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
409    #[serde(rename = "triggerCondition")]
410    pub trigger_condition: OrderTriggerCondition,
411    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
412    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
413    /// dependent Take Profit Order is modified directly through the Trade.
414    #[serde(
415        rename = "takeProfitOnFill",
416        default,
417        skip_serializing_if = "Option::is_none"
418    )]
419    pub take_profit_on_fill: Option<TakeProfitDetails>,
420    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
421    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
422    /// Stop Loss Order is modified directly through the Trade.
423    #[serde(
424        rename = "stopLossOnFill",
425        default,
426        skip_serializing_if = "Option::is_none"
427    )]
428    pub stop_loss_on_fill: Option<StopLossDetails>,
429    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
430    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
431    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
432    #[serde(
433        rename = "guaranteedStopLossOnFill",
434        default,
435        skip_serializing_if = "Option::is_none"
436    )]
437    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
438    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
439    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
440    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
441    #[serde(
442        rename = "trailingStopLossOnFill",
443        default,
444        skip_serializing_if = "Option::is_none"
445    )]
446    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
447    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
448    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
449    #[serde(
450        rename = "tradeClientExtensions",
451        default,
452        skip_serializing_if = "Option::is_none"
453    )]
454    pub trade_client_extensions: Option<ClientExtensions>,
455    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
456    #[serde(
457        rename = "fillingTransactionID",
458        default,
459        skip_serializing_if = "Option::is_none"
460    )]
461    pub filling_transaction_id: Option<TransactionID>,
462    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
463    #[serde(
464        rename = "filledTime",
465        default,
466        skip_serializing_if = "Option::is_none"
467    )]
468    pub filled_time: Option<Timestamp>,
469    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
470    /// Trade was opened as a result of the fill)
471    #[serde(
472        rename = "tradeOpenedID",
473        default,
474        skip_serializing_if = "Option::is_none"
475    )]
476    pub trade_opened_id: Option<TradeID>,
477    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
478    /// a Trade was reduced as a result of the fill)
479    #[serde(
480        rename = "tradeReducedID",
481        default,
482        skip_serializing_if = "Option::is_none"
483    )]
484    pub trade_reduced_id: Option<TradeID>,
485    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
486    /// one or more Trades were closed as a result of the fill)
487    #[serde(
488        rename = "tradeClosedIDs",
489        default,
490        skip_serializing_if = "Option::is_none"
491    )]
492    pub trade_closed_ids: Option<Vec<TradeID>>,
493    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
494    #[serde(
495        rename = "cancellingTransactionID",
496        default,
497        skip_serializing_if = "Option::is_none"
498    )]
499    pub cancelling_transaction_id: Option<TransactionID>,
500    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
501    #[serde(
502        rename = "cancelledTime",
503        default,
504        skip_serializing_if = "Option::is_none"
505    )]
506    pub cancelled_time: Option<Timestamp>,
507    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
508    /// a cancel/replace).
509    #[serde(
510        rename = "replacesOrderID",
511        default,
512        skip_serializing_if = "Option::is_none"
513    )]
514    pub replaces_order_id: Option<OrderID>,
515    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
516    /// cancel/replace).
517    #[serde(
518        rename = "replacedByOrderID",
519        default,
520        skip_serializing_if = "Option::is_none"
521    )]
522    pub replaced_by_order_id: Option<OrderID>,
523}
524
525/// A `StopOrder` is an order that is created with a price threshold, and will only be filled by a price that
526/// is equal to or worse than the threshold.
527#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
528#[serde(rename_all = "camelCase")]
529pub struct StopOrder {
530    /// The Order’s identifier, unique within the Order’s Account.
531    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
532    pub id: Option<OrderID>,
533    /// The time when the Order was created.
534    #[serde(
535        rename = "createTime",
536        default,
537        skip_serializing_if = "Option::is_none"
538    )]
539    pub create_time: Option<Timestamp>,
540    /// The current state of the Order.
541    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
542    pub state: Option<OrderState>,
543    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
544    /// associated with MT4.
545    #[serde(
546        rename = "clientExtensions",
547        default,
548        skip_serializing_if = "Option::is_none"
549    )]
550    pub client_extensions: Option<ClientExtensions>,
551    /// The type of the Order. Always set to “STOP” for Stop Orders.
552    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
553    #[serde(serialize_with = "serialize_stop_order_type")]
554    pub r#type: Option<OrderType>,
555    /// The Stop Order’s Instrument.
556    #[serde(rename = "instrument")]
557    pub instrument: InstrumentName,
558    /// The quantity requested to be filled by the Stop Order. A positive number of units results in a long
559    /// Order, and a negative number of units results in a short Order.
560    #[serde(rename = "units")]
561    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
562    pub units: Decimal,
563    /// The price threshold specified for the Stop Order. The Stop Order will only be filled by a market price
564    /// that is equal to or worse than this price.
565    #[serde(rename = "price")]
566    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
567    pub price: Decimal,
568    /// The worst market price that may be used to fill this Stop Order. If the market gaps and crosses through
569    /// both the price and the priceBound, the Stop Order will be cancelled instead of being filled.
570    #[serde(
571        rename = "priceBound",
572        default,
573        skip_serializing_if = "Option::is_none"
574    )]
575    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
576    pub price_bound: Option<Decimal>,
577    /// The time-in-force requested for the Stop Order.
578    #[serde(rename = "timeInForce")]
579    pub time_in_force: TimeInForce,
580    /// The date/time when the Stop Order will be cancelled if its timeInForce is “GTD”.
581    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
582    pub gtd_time: Option<Timestamp>,
583    /// Specification of how Positions in the Account are modified when the Order is filled.
584    #[serde(rename = "positionFill")]
585    pub position_fill: OrderPositionFill,
586    /// Specification of which price component should be used when determining if an Order should be triggered
587    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
588    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
589    /// filled using their default price component. This feature is only provided through the REST API. Clients
590    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
591    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
592    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
593    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
594    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
595    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
596    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
597    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
598    #[serde(rename = "triggerCondition")]
599    pub trigger_condition: OrderTriggerCondition,
600    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
601    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
602    /// dependent Take Profit Order is modified directly through the Trade.
603    #[serde(
604        rename = "takeProfitOnFill",
605        default,
606        skip_serializing_if = "Option::is_none"
607    )]
608    pub take_profit_on_fill: Option<TakeProfitDetails>,
609    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
610    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
611    /// Stop Loss Order is modified directly through the Trade.
612    #[serde(
613        rename = "stopLossOnFill",
614        default,
615        skip_serializing_if = "Option::is_none"
616    )]
617    pub stop_loss_on_fill: Option<StopLossDetails>,
618    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
619    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
620    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
621    #[serde(
622        rename = "guaranteedStopLossOnFill",
623        default,
624        skip_serializing_if = "Option::is_none"
625    )]
626    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
627    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
628    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
629    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
630    #[serde(
631        rename = "trailingStopLossOnFill",
632        default,
633        skip_serializing_if = "Option::is_none"
634    )]
635    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
636    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
637    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
638    #[serde(
639        rename = "tradeClientExtensions",
640        default,
641        skip_serializing_if = "Option::is_none"
642    )]
643    pub trade_client_extensions: Option<ClientExtensions>,
644    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
645    #[serde(
646        rename = "fillingTransactionID",
647        default,
648        skip_serializing_if = "Option::is_none"
649    )]
650    pub filling_transaction_id: Option<TransactionID>,
651    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
652    #[serde(
653        rename = "filledTime",
654        default,
655        skip_serializing_if = "Option::is_none"
656    )]
657    pub filled_time: Option<Timestamp>,
658    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
659    /// Trade was opened as a result of the fill)
660    #[serde(
661        rename = "tradeOpenedID",
662        default,
663        skip_serializing_if = "Option::is_none"
664    )]
665    pub trade_opened_id: Option<TradeID>,
666    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
667    /// a Trade was reduced as a result of the fill)
668    #[serde(
669        rename = "tradeReducedID",
670        default,
671        skip_serializing_if = "Option::is_none"
672    )]
673    pub trade_reduced_id: Option<TradeID>,
674    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
675    /// one or more Trades were closed as a result of the fill)
676    #[serde(
677        rename = "tradeClosedIDs",
678        default,
679        skip_serializing_if = "Option::is_none"
680    )]
681    pub trade_closed_ids: Option<Vec<TradeID>>,
682    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
683    #[serde(
684        rename = "cancellingTransactionID",
685        default,
686        skip_serializing_if = "Option::is_none"
687    )]
688    pub cancelling_transaction_id: Option<TransactionID>,
689    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
690    #[serde(
691        rename = "cancelledTime",
692        default,
693        skip_serializing_if = "Option::is_none"
694    )]
695    pub cancelled_time: Option<Timestamp>,
696    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
697    /// a cancel/replace).
698    #[serde(
699        rename = "replacesOrderID",
700        default,
701        skip_serializing_if = "Option::is_none"
702    )]
703    pub replaces_order_id: Option<OrderID>,
704    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
705    /// cancel/replace).
706    #[serde(
707        rename = "replacedByOrderID",
708        default,
709        skip_serializing_if = "Option::is_none"
710    )]
711    pub replaced_by_order_id: Option<OrderID>,
712}
713
714/// A `MarketIfTouchedOrder` is an order that is created with a price threshold, and will only be filled by a
715/// market price that touches or crosses the threshold.
716#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
717#[serde(rename_all = "camelCase")]
718pub struct MarketIfTouchedOrder {
719    /// The Order’s identifier, unique within the Order’s Account.
720    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
721    pub id: Option<OrderID>,
722    /// The time when the Order was created.
723    #[serde(
724        rename = "createTime",
725        default,
726        skip_serializing_if = "Option::is_none"
727    )]
728    pub create_time: Option<Timestamp>,
729    /// The current state of the Order.
730    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
731    pub state: Option<OrderState>,
732    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
733    /// associated with MT4.
734    #[serde(
735        rename = "clientExtensions",
736        default,
737        skip_serializing_if = "Option::is_none"
738    )]
739    pub client_extensions: Option<ClientExtensions>,
740    /// The type of the Order. Always set to “`MARKET_IF_TOUCHED`” for Market If Touched Orders.
741    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
742    #[serde(serialize_with = "serialize_market_if_touched_order_type")]
743    pub r#type: Option<OrderType>,
744    /// The `MarketIfTouched` Order’s Instrument.
745    #[serde(rename = "instrument")]
746    pub instrument: InstrumentName,
747    /// The quantity requested to be filled by the `MarketIfTouched` Order. A positive number of units results in
748    /// a long Order, and a negative number of units results in a short Order.
749    #[serde(rename = "units")]
750    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
751    pub units: Decimal,
752    /// The price threshold specified for the `MarketIfTouched` Order. The `MarketIfTouched` Order will only be
753    /// filled by a market price that crosses this price from the direction of the market price at the time when
754    /// the Order was created (the initialMarketPrice). Depending on the value of the Order’s price and
755    /// initialMarketPrice, the `MarketIfTouchedOrder` will behave like a Limit or a Stop Order.
756    #[serde(rename = "price")]
757    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
758    pub price: Decimal,
759    /// The worst market price that may be used to fill this `MarketIfTouched` Order.
760    #[serde(
761        rename = "priceBound",
762        default,
763        skip_serializing_if = "Option::is_none"
764    )]
765    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
766    pub price_bound: Option<Decimal>,
767    /// The time-in-force requested for the `MarketIfTouched` Order. Restricted to “GTC”, “GFD” and “GTD” for
768    /// `MarketIfTouched` Orders.
769    #[serde(rename = "timeInForce")]
770    pub time_in_force: TimeInForce,
771    /// The date/time when the `MarketIfTouched` Order will be cancelled if its timeInForce is “GTD”.
772    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
773    pub gtd_time: Option<Timestamp>,
774    /// Specification of how Positions in the Account are modified when the Order is filled.
775    #[serde(rename = "positionFill")]
776    pub position_fill: OrderPositionFill,
777    /// Specification of which price component should be used when determining if an Order should be triggered
778    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
779    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
780    /// filled using their default price component. This feature is only provided through the REST API. Clients
781    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
782    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
783    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
784    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
785    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
786    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
787    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
788    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
789    #[serde(rename = "triggerCondition")]
790    pub trigger_condition: OrderTriggerCondition,
791    /// The Market price at the time when the `MarketIfTouched` Order was created.
792    #[serde(
793        rename = "initialMarketPrice",
794        default,
795        skip_serializing_if = "Option::is_none"
796    )]
797    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
798    pub initial_market_price: Option<Decimal>,
799    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
800    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
801    /// dependent Take Profit Order is modified directly through the Trade.
802    #[serde(
803        rename = "takeProfitOnFill",
804        default,
805        skip_serializing_if = "Option::is_none"
806    )]
807    pub take_profit_on_fill: Option<TakeProfitDetails>,
808    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
809    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
810    /// Stop Loss Order is modified directly through the Trade.
811    #[serde(
812        rename = "stopLossOnFill",
813        default,
814        skip_serializing_if = "Option::is_none"
815    )]
816    pub stop_loss_on_fill: Option<StopLossDetails>,
817    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
818    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
819    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
820    #[serde(
821        rename = "guaranteedStopLossOnFill",
822        default,
823        skip_serializing_if = "Option::is_none"
824    )]
825    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
826    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
827    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
828    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
829    #[serde(
830        rename = "trailingStopLossOnFill",
831        default,
832        skip_serializing_if = "Option::is_none"
833    )]
834    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
835    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
836    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
837    #[serde(
838        rename = "tradeClientExtensions",
839        default,
840        skip_serializing_if = "Option::is_none"
841    )]
842    pub trade_client_extensions: Option<ClientExtensions>,
843    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
844    #[serde(
845        rename = "fillingTransactionID",
846        default,
847        skip_serializing_if = "Option::is_none"
848    )]
849    pub filling_transaction_id: Option<TransactionID>,
850    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
851    #[serde(
852        rename = "filledTime",
853        default,
854        skip_serializing_if = "Option::is_none"
855    )]
856    pub filled_time: Option<Timestamp>,
857    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
858    /// Trade was opened as a result of the fill)
859    #[serde(
860        rename = "tradeOpenedID",
861        default,
862        skip_serializing_if = "Option::is_none"
863    )]
864    pub trade_opened_id: Option<TradeID>,
865    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
866    /// a Trade was reduced as a result of the fill)
867    #[serde(
868        rename = "tradeReducedID",
869        default,
870        skip_serializing_if = "Option::is_none"
871    )]
872    pub trade_reduced_id: Option<TradeID>,
873    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
874    /// one or more Trades were closed as a result of the fill)
875    #[serde(
876        rename = "tradeClosedIDs",
877        default,
878        skip_serializing_if = "Option::is_none"
879    )]
880    pub trade_closed_ids: Option<Vec<TradeID>>,
881    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
882    #[serde(
883        rename = "cancellingTransactionID",
884        default,
885        skip_serializing_if = "Option::is_none"
886    )]
887    pub cancelling_transaction_id: Option<TransactionID>,
888    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
889    #[serde(
890        rename = "cancelledTime",
891        default,
892        skip_serializing_if = "Option::is_none"
893    )]
894    pub cancelled_time: Option<Timestamp>,
895    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
896    /// a cancel/replace).
897    #[serde(
898        rename = "replacesOrderID",
899        default,
900        skip_serializing_if = "Option::is_none"
901    )]
902    pub replaces_order_id: Option<OrderID>,
903    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
904    /// cancel/replace).
905    #[serde(
906        rename = "replacedByOrderID",
907        default,
908        skip_serializing_if = "Option::is_none"
909    )]
910    pub replaced_by_order_id: Option<OrderID>,
911}
912
913/// A `TakeProfitOrder` is an order that is linked to an open Trade and created with a price threshold. The
914/// Order will be filled (closing the Trade) by the first price that is equal to or better than the
915/// threshold. A `TakeProfitOrder` cannot be used to open a new Position.
916#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
917#[serde(rename_all = "camelCase")]
918pub struct TakeProfitOrder {
919    /// The Order’s identifier, unique within the Order’s Account.
920    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
921    pub id: Option<OrderID>,
922    /// The time when the Order was created.
923    #[serde(
924        rename = "createTime",
925        default,
926        skip_serializing_if = "Option::is_none"
927    )]
928    pub create_time: Option<Timestamp>,
929    /// The current state of the Order.
930    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
931    pub state: Option<OrderState>,
932    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
933    /// associated with MT4.
934    #[serde(
935        rename = "clientExtensions",
936        default,
937        skip_serializing_if = "Option::is_none"
938    )]
939    pub client_extensions: Option<ClientExtensions>,
940    /// The type of the Order. Always set to “`TAKE_PROFIT`” for Take Profit Orders.
941    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
942    #[serde(serialize_with = "serialize_take_profit_order_type")]
943    pub r#type: Option<OrderType>,
944    /// The ID of the Trade to close when the price threshold is breached.
945    #[serde(rename = "tradeID")]
946    pub trade_id: TradeID,
947    /// The client ID of the Trade to be closed when the price threshold is breached.
948    #[serde(
949        rename = "clientTradeID",
950        default,
951        skip_serializing_if = "Option::is_none"
952    )]
953    pub client_trade_id: Option<ClientID>,
954    /// The price threshold specified for the `TakeProfit` Order. The associated Trade will be closed by a market
955    /// price that is equal to or better than this threshold.
956    #[serde(rename = "price")]
957    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
958    pub price: Decimal,
959    /// The time-in-force requested for the `TakeProfit` Order. Restricted to “GTC”, “GFD” and “GTD” for
960    /// `TakeProfit` Orders.
961    #[serde(rename = "timeInForce")]
962    pub time_in_force: TimeInForce,
963    /// The date/time when the `TakeProfit` Order will be cancelled if its timeInForce is “GTD”.
964    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
965    pub gtd_time: Option<Timestamp>,
966    /// Specification of which price component should be used when determining if an Order should be triggered
967    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
968    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
969    /// filled using their default price component. This feature is only provided through the REST API. Clients
970    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
971    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
972    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
973    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
974    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
975    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
976    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
977    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
978    #[serde(rename = "triggerCondition")]
979    pub trigger_condition: OrderTriggerCondition,
980    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
981    #[serde(
982        rename = "fillingTransactionID",
983        default,
984        skip_serializing_if = "Option::is_none"
985    )]
986    pub filling_transaction_id: Option<TransactionID>,
987    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
988    #[serde(
989        rename = "filledTime",
990        default,
991        skip_serializing_if = "Option::is_none"
992    )]
993    pub filled_time: Option<Timestamp>,
994    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
995    /// Trade was opened as a result of the fill)
996    #[serde(
997        rename = "tradeOpenedID",
998        default,
999        skip_serializing_if = "Option::is_none"
1000    )]
1001    pub trade_opened_id: Option<TradeID>,
1002    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
1003    /// a Trade was reduced as a result of the fill)
1004    #[serde(
1005        rename = "tradeReducedID",
1006        default,
1007        skip_serializing_if = "Option::is_none"
1008    )]
1009    pub trade_reduced_id: Option<TradeID>,
1010    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
1011    /// one or more Trades were closed as a result of the fill)
1012    #[serde(
1013        rename = "tradeClosedIDs",
1014        default,
1015        skip_serializing_if = "Option::is_none"
1016    )]
1017    pub trade_closed_ids: Option<Vec<TradeID>>,
1018    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
1019    #[serde(
1020        rename = "cancellingTransactionID",
1021        default,
1022        skip_serializing_if = "Option::is_none"
1023    )]
1024    pub cancelling_transaction_id: Option<TransactionID>,
1025    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
1026    #[serde(
1027        rename = "cancelledTime",
1028        default,
1029        skip_serializing_if = "Option::is_none"
1030    )]
1031    pub cancelled_time: Option<Timestamp>,
1032    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
1033    /// a cancel/replace).
1034    #[serde(
1035        rename = "replacesOrderID",
1036        default,
1037        skip_serializing_if = "Option::is_none"
1038    )]
1039    pub replaces_order_id: Option<OrderID>,
1040    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
1041    /// cancel/replace).
1042    #[serde(
1043        rename = "replacedByOrderID",
1044        default,
1045        skip_serializing_if = "Option::is_none"
1046    )]
1047    pub replaced_by_order_id: Option<OrderID>,
1048}
1049
1050/// A `StopLossOrder` is an order that is linked to an open Trade and created with a price threshold. The
1051/// Order will be filled (closing the Trade) by the first price that is equal to or worse than the
1052/// threshold. A `StopLossOrder` cannot be used to open a new Position.
1053#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1054#[serde(rename_all = "camelCase")]
1055pub struct StopLossOrder {
1056    /// The Order’s identifier, unique within the Order’s Account.
1057    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
1058    pub id: Option<OrderID>,
1059    /// The time when the Order was created.
1060    #[serde(
1061        rename = "createTime",
1062        default,
1063        skip_serializing_if = "Option::is_none"
1064    )]
1065    pub create_time: Option<Timestamp>,
1066    /// The current state of the Order.
1067    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
1068    pub state: Option<OrderState>,
1069    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
1070    /// associated with MT4.
1071    #[serde(
1072        rename = "clientExtensions",
1073        default,
1074        skip_serializing_if = "Option::is_none"
1075    )]
1076    pub client_extensions: Option<ClientExtensions>,
1077    /// The type of the Order. Always set to “`STOP_LOSS`” for Stop Loss Orders.
1078    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1079    #[serde(serialize_with = "serialize_stop_loss_order_type")]
1080    pub r#type: Option<OrderType>,
1081    /// The premium that will be charged if the Stop Loss Order is guaranteed and the Order is filled at the
1082    /// guaranteed price. It is in price units and is charged for each unit of the Trade. Deprecated: Will be
1083    /// removed in a future API update.
1084    #[serde(
1085        rename = "guaranteedExecutionPremium",
1086        default,
1087        skip_serializing_if = "Option::is_none"
1088    )]
1089    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1090    pub guaranteed_execution_premium: Option<Decimal>,
1091    /// The ID of the Trade to close when the price threshold is breached.
1092    #[serde(rename = "tradeID")]
1093    pub trade_id: TradeID,
1094    /// The client ID of the Trade to be closed when the price threshold is breached.
1095    #[serde(
1096        rename = "clientTradeID",
1097        default,
1098        skip_serializing_if = "Option::is_none"
1099    )]
1100    pub client_trade_id: Option<ClientID>,
1101    /// The price threshold specified for the Stop Loss Order. The associated Trade will be closed by a market
1102    /// price that is equal to or worse than this threshold.
1103    #[serde(rename = "price")]
1104    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1105    pub price: Decimal,
1106    /// Specifies the distance (in price units) from the Account’s current price to use as the Stop Loss Order
1107    /// price. If the Trade is short the Instrument’s bid price is used, and for long Trades the ask is used.
1108    #[serde(rename = "distance", default, skip_serializing_if = "Option::is_none")]
1109    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1110    pub distance: Option<Decimal>,
1111    /// The time-in-force requested for the `StopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for `StopLoss`
1112    /// Orders.
1113    #[serde(rename = "timeInForce")]
1114    pub time_in_force: TimeInForce,
1115    /// The date/time when the `StopLoss` Order will be cancelled if its timeInForce is “GTD”.
1116    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1117    pub gtd_time: Option<Timestamp>,
1118    /// Specification of which price component should be used when determining if an Order should be triggered
1119    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1120    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1121    /// filled using their default price component. This feature is only provided through the REST API. Clients
1122    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1123    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1124    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1125    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1126    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1127    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1128    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1129    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1130    #[serde(rename = "triggerCondition")]
1131    pub trigger_condition: OrderTriggerCondition,
1132    /// Flag indicating that the Stop Loss Order is guaranteed. The default value depends on the
1133    /// `GuaranteedStopLossOrderMode` of the account, if it is REQUIRED, the default will be true, for DISABLED or
1134    /// ENABLED the default is false. Deprecated: Will be removed in a future API update.
1135    #[serde(
1136        rename = "guaranteed",
1137        default,
1138        skip_serializing_if = "Option::is_none"
1139    )]
1140    pub guaranteed: Option<bool>,
1141    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
1142    #[serde(
1143        rename = "fillingTransactionID",
1144        default,
1145        skip_serializing_if = "Option::is_none"
1146    )]
1147    pub filling_transaction_id: Option<TransactionID>,
1148    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
1149    #[serde(
1150        rename = "filledTime",
1151        default,
1152        skip_serializing_if = "Option::is_none"
1153    )]
1154    pub filled_time: Option<Timestamp>,
1155    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
1156    /// Trade was opened as a result of the fill)
1157    #[serde(
1158        rename = "tradeOpenedID",
1159        default,
1160        skip_serializing_if = "Option::is_none"
1161    )]
1162    pub trade_opened_id: Option<TradeID>,
1163    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
1164    /// a Trade was reduced as a result of the fill)
1165    #[serde(
1166        rename = "tradeReducedID",
1167        default,
1168        skip_serializing_if = "Option::is_none"
1169    )]
1170    pub trade_reduced_id: Option<TradeID>,
1171    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
1172    /// one or more Trades were closed as a result of the fill)
1173    #[serde(
1174        rename = "tradeClosedIDs",
1175        default,
1176        skip_serializing_if = "Option::is_none"
1177    )]
1178    pub trade_closed_ids: Option<Vec<TradeID>>,
1179    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
1180    #[serde(
1181        rename = "cancellingTransactionID",
1182        default,
1183        skip_serializing_if = "Option::is_none"
1184    )]
1185    pub cancelling_transaction_id: Option<TransactionID>,
1186    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
1187    #[serde(
1188        rename = "cancelledTime",
1189        default,
1190        skip_serializing_if = "Option::is_none"
1191    )]
1192    pub cancelled_time: Option<Timestamp>,
1193    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
1194    /// a cancel/replace).
1195    #[serde(
1196        rename = "replacesOrderID",
1197        default,
1198        skip_serializing_if = "Option::is_none"
1199    )]
1200    pub replaces_order_id: Option<OrderID>,
1201    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
1202    /// cancel/replace).
1203    #[serde(
1204        rename = "replacedByOrderID",
1205        default,
1206        skip_serializing_if = "Option::is_none"
1207    )]
1208    pub replaced_by_order_id: Option<OrderID>,
1209}
1210
1211/// A `GuaranteedStopLossOrder` is an order that is linked to an open Trade and created with a price threshold
1212/// which is guaranteed against slippage that may occur as the market crosses the price set for that order.
1213/// The Order will be filled (closing the Trade) by the first price that is equal to or worse than the
1214/// threshold. The price level specified for the `GuaranteedStopLossOrder` must be at least the configured
1215/// minimum distance (in price units) away from the entry price for the traded instrument. A
1216/// `GuaranteedStopLossOrder` cannot be used to open a new Position.
1217#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1218#[serde(rename_all = "camelCase")]
1219pub struct GuaranteedStopLossOrder {
1220    /// The Order’s identifier, unique within the Order’s Account.
1221    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
1222    pub id: Option<OrderID>,
1223    /// The time when the Order was created.
1224    #[serde(
1225        rename = "createTime",
1226        default,
1227        skip_serializing_if = "Option::is_none"
1228    )]
1229    pub create_time: Option<Timestamp>,
1230    /// The current state of the Order.
1231    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
1232    pub state: Option<OrderState>,
1233    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
1234    /// associated with MT4.
1235    #[serde(
1236        rename = "clientExtensions",
1237        default,
1238        skip_serializing_if = "Option::is_none"
1239    )]
1240    pub client_extensions: Option<ClientExtensions>,
1241    /// The type of the Order. Always set to “`GUARANTEED_STOP_LOSS`” for Guaranteed Stop Loss Orders.
1242    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1243    #[serde(serialize_with = "serialize_guaranteed_stop_loss_order_type")]
1244    pub r#type: Option<OrderType>,
1245    /// The premium that will be charged if the Guaranteed Stop Loss Order is filled at the guaranteed price. It
1246    /// is in price units and is charged for each unit of the Trade.
1247    #[serde(
1248        rename = "guaranteedExecutionPremium",
1249        default,
1250        skip_serializing_if = "Option::is_none"
1251    )]
1252    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1253    pub guaranteed_execution_premium: Option<Decimal>,
1254    /// The ID of the Trade to close when the price threshold is breached.
1255    #[serde(rename = "tradeID")]
1256    pub trade_id: TradeID,
1257    /// The client ID of the Trade to be closed when the price threshold is breached.
1258    #[serde(
1259        rename = "clientTradeID",
1260        default,
1261        skip_serializing_if = "Option::is_none"
1262    )]
1263    pub client_trade_id: Option<ClientID>,
1264    /// The price threshold specified for the Guaranteed Stop Loss Order. The associated Trade will be closed at
1265    /// this price.
1266    #[serde(rename = "price")]
1267    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1268    pub price: Decimal,
1269    /// Specifies the distance (in price units) from the Account’s current price to use as the Guaranteed Stop
1270    /// Loss Order price. If the Trade is short the Instrument’s bid price is used, and for long Trades the ask
1271    /// is used.
1272    #[serde(rename = "distance", default, skip_serializing_if = "Option::is_none")]
1273    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1274    pub distance: Option<Decimal>,
1275    /// The time-in-force requested for the `GuaranteedStopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for
1276    /// `GuaranteedStopLoss` Orders.
1277    #[serde(rename = "timeInForce")]
1278    pub time_in_force: TimeInForce,
1279    /// The date/time when the `GuaranteedStopLoss` Order will be cancelled if its timeInForce is “GTD”.
1280    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1281    pub gtd_time: Option<Timestamp>,
1282    /// Specification of which price component should be used when determining if an Order should be triggered
1283    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1284    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1285    /// filled using their default price component. This feature is only provided through the REST API. Clients
1286    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1287    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1288    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1289    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1290    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1291    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1292    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1293    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1294    #[serde(rename = "triggerCondition")]
1295    pub trigger_condition: OrderTriggerCondition,
1296    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
1297    #[serde(
1298        rename = "fillingTransactionID",
1299        default,
1300        skip_serializing_if = "Option::is_none"
1301    )]
1302    pub filling_transaction_id: Option<TransactionID>,
1303    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
1304    #[serde(
1305        rename = "filledTime",
1306        default,
1307        skip_serializing_if = "Option::is_none"
1308    )]
1309    pub filled_time: Option<Timestamp>,
1310    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
1311    /// Trade was opened as a result of the fill)
1312    #[serde(
1313        rename = "tradeOpenedID",
1314        default,
1315        skip_serializing_if = "Option::is_none"
1316    )]
1317    pub trade_opened_id: Option<TradeID>,
1318    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
1319    /// a Trade was reduced as a result of the fill)
1320    #[serde(
1321        rename = "tradeReducedID",
1322        default,
1323        skip_serializing_if = "Option::is_none"
1324    )]
1325    pub trade_reduced_id: Option<TradeID>,
1326    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
1327    /// one or more Trades were closed as a result of the fill)
1328    #[serde(
1329        rename = "tradeClosedIDs",
1330        default,
1331        skip_serializing_if = "Option::is_none"
1332    )]
1333    pub trade_closed_ids: Option<Vec<TradeID>>,
1334    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
1335    #[serde(
1336        rename = "cancellingTransactionID",
1337        default,
1338        skip_serializing_if = "Option::is_none"
1339    )]
1340    pub cancelling_transaction_id: Option<TransactionID>,
1341    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
1342    #[serde(
1343        rename = "cancelledTime",
1344        default,
1345        skip_serializing_if = "Option::is_none"
1346    )]
1347    pub cancelled_time: Option<Timestamp>,
1348    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
1349    /// a cancel/replace).
1350    #[serde(
1351        rename = "replacesOrderID",
1352        default,
1353        skip_serializing_if = "Option::is_none"
1354    )]
1355    pub replaces_order_id: Option<OrderID>,
1356    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
1357    /// cancel/replace).
1358    #[serde(
1359        rename = "replacedByOrderID",
1360        default,
1361        skip_serializing_if = "Option::is_none"
1362    )]
1363    pub replaced_by_order_id: Option<OrderID>,
1364}
1365
1366/// A `TrailingStopLossOrder` is an order that is linked to an open Trade and created with a price distance.
1367/// The price distance is used to calculate a trailing stop value for the order that is in the losing
1368/// direction from the market price at the time of the order’s creation. The trailing stop value will follow
1369/// the market price as it moves in the winning direction, and the order will be filled (closing the Trade)
1370/// by the first price that is equal to or worse than the trailing stop value. A `TrailingStopLossOrder`
1371/// cannot be used to open a new Position.
1372#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1373#[serde(rename_all = "camelCase")]
1374pub struct TrailingStopLossOrder {
1375    /// The Order’s identifier, unique within the Order’s Account.
1376    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
1377    pub id: Option<OrderID>,
1378    /// The time when the Order was created.
1379    #[serde(
1380        rename = "createTime",
1381        default,
1382        skip_serializing_if = "Option::is_none"
1383    )]
1384    pub create_time: Option<Timestamp>,
1385    /// The current state of the Order.
1386    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
1387    pub state: Option<OrderState>,
1388    /// The client extensions of the Order. Do not set, modify, or delete clientExtensions if your account is
1389    /// associated with MT4.
1390    #[serde(
1391        rename = "clientExtensions",
1392        default,
1393        skip_serializing_if = "Option::is_none"
1394    )]
1395    pub client_extensions: Option<ClientExtensions>,
1396    /// The type of the Order. Always set to “`TRAILING_STOP_LOSS`” for Trailing Stop Loss Orders.
1397    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1398    #[serde(serialize_with = "serialize_trailing_stop_loss_order_type")]
1399    pub r#type: Option<OrderType>,
1400    /// The ID of the Trade to close when the price threshold is breached.
1401    #[serde(rename = "tradeID")]
1402    pub trade_id: TradeID,
1403    /// The client ID of the Trade to be closed when the price threshold is breached.
1404    #[serde(
1405        rename = "clientTradeID",
1406        default,
1407        skip_serializing_if = "Option::is_none"
1408    )]
1409    pub client_trade_id: Option<ClientID>,
1410    /// The price distance (in price units) specified for the `TrailingStopLoss` Order.
1411    #[serde(rename = "distance")]
1412    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1413    pub distance: Decimal,
1414    /// The time-in-force requested for the `TrailingStopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for
1415    /// `TrailingStopLoss` Orders.
1416    #[serde(rename = "timeInForce")]
1417    pub time_in_force: TimeInForce,
1418    /// The date/time when the `StopLoss` Order will be cancelled if its timeInForce is “GTD”.
1419    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1420    pub gtd_time: Option<Timestamp>,
1421    /// Specification of which price component should be used when determining if an Order should be triggered
1422    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1423    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1424    /// filled using their default price component. This feature is only provided through the REST API. Clients
1425    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1426    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1427    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1428    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1429    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1430    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1431    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1432    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1433    #[serde(rename = "triggerCondition")]
1434    pub trigger_condition: OrderTriggerCondition,
1435    /// The trigger price for the Trailing Stop Loss Order. The trailing stop value will trail (follow) the
1436    /// market price by the TSL order’s configured “distance” as the market price moves in the winning
1437    /// direction. If the market price moves to a level that is equal to or worse than the trailing stop value,
1438    /// the order will be filled and the Trade will be closed.
1439    #[serde(
1440        rename = "trailingStopValue",
1441        default,
1442        skip_serializing_if = "Option::is_none"
1443    )]
1444    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1445    pub trailing_stop_value: Option<Decimal>,
1446    /// ID of the Transaction that filled this Order (only provided when the Order’s state is FILLED)
1447    #[serde(
1448        rename = "fillingTransactionID",
1449        default,
1450        skip_serializing_if = "Option::is_none"
1451    )]
1452    pub filling_transaction_id: Option<TransactionID>,
1453    /// Date/time when the Order was filled (only provided when the Order’s state is FILLED)
1454    #[serde(
1455        rename = "filledTime",
1456        default,
1457        skip_serializing_if = "Option::is_none"
1458    )]
1459    pub filled_time: Option<Timestamp>,
1460    /// Trade ID of Trade opened when the Order was filled (only provided when the Order’s state is FILLED and a
1461    /// Trade was opened as a result of the fill)
1462    #[serde(
1463        rename = "tradeOpenedID",
1464        default,
1465        skip_serializing_if = "Option::is_none"
1466    )]
1467    pub trade_opened_id: Option<TradeID>,
1468    /// Trade ID of Trade reduced when the Order was filled (only provided when the Order’s state is FILLED and
1469    /// a Trade was reduced as a result of the fill)
1470    #[serde(
1471        rename = "tradeReducedID",
1472        default,
1473        skip_serializing_if = "Option::is_none"
1474    )]
1475    pub trade_reduced_id: Option<TradeID>,
1476    /// Trade IDs of Trades closed when the Order was filled (only provided when the Order’s state is FILLED and
1477    /// one or more Trades were closed as a result of the fill)
1478    #[serde(
1479        rename = "tradeClosedIDs",
1480        default,
1481        skip_serializing_if = "Option::is_none"
1482    )]
1483    pub trade_closed_ids: Option<Vec<TradeID>>,
1484    /// ID of the Transaction that cancelled the Order (only provided when the Order’s state is CANCELLED)
1485    #[serde(
1486        rename = "cancellingTransactionID",
1487        default,
1488        skip_serializing_if = "Option::is_none"
1489    )]
1490    pub cancelling_transaction_id: Option<TransactionID>,
1491    /// Date/time when the Order was cancelled (only provided when the state of the Order is CANCELLED)
1492    #[serde(
1493        rename = "cancelledTime",
1494        default,
1495        skip_serializing_if = "Option::is_none"
1496    )]
1497    pub cancelled_time: Option<Timestamp>,
1498    /// The ID of the Order that was replaced by this Order (only provided if this Order was created as part of
1499    /// a cancel/replace).
1500    #[serde(
1501        rename = "replacesOrderID",
1502        default,
1503        skip_serializing_if = "Option::is_none"
1504    )]
1505    pub replaces_order_id: Option<OrderID>,
1506    /// The ID of the Order that replaced this Order (only provided if this Order was cancelled as part of a
1507    /// cancel/replace).
1508    #[serde(
1509        rename = "replacedByOrderID",
1510        default,
1511        skip_serializing_if = "Option::is_none"
1512    )]
1513    pub replaced_by_order_id: Option<OrderID>,
1514}
1515
1516/// A `MarketOrderRequest` specifies the parameters that may be set when creating a Market Order.
1517#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1518#[serde(rename_all = "camelCase")]
1519pub struct MarketOrderRequest {
1520    /// The type of the Order to Create. Must be set to “MARKET” when creating a Market Order.
1521    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1522    #[serde(serialize_with = "serialize_market_order_request_type")]
1523    pub r#type: Option<OrderType>,
1524    /// The Market Order’s Instrument.
1525    #[serde(rename = "instrument")]
1526    pub instrument: InstrumentName,
1527    /// The quantity requested to be filled by the Market Order. A positive number of units results in a long
1528    /// Order, and a negative number of units results in a short Order.
1529    #[serde(rename = "units")]
1530    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1531    pub units: Decimal,
1532    /// The time-in-force requested for the Market Order. Restricted to FOK or IOC for a `MarketOrder`.
1533    #[serde(rename = "timeInForce")]
1534    pub time_in_force: TimeInForce,
1535    /// The worst price that the client is willing to have the Market Order filled at.
1536    #[serde(
1537        rename = "priceBound",
1538        default,
1539        skip_serializing_if = "Option::is_none"
1540    )]
1541    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1542    pub price_bound: Option<Decimal>,
1543    /// Specification of how Positions in the Account are modified when the Order is filled.
1544    #[serde(rename = "positionFill")]
1545    pub position_fill: OrderPositionFill,
1546    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
1547    /// account is associated with MT4.
1548    #[serde(
1549        rename = "clientExtensions",
1550        default,
1551        skip_serializing_if = "Option::is_none"
1552    )]
1553    pub client_extensions: Option<ClientExtensions>,
1554    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
1555    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
1556    /// dependent Take Profit Order is modified directly through the Trade.
1557    #[serde(
1558        rename = "takeProfitOnFill",
1559        default,
1560        skip_serializing_if = "Option::is_none"
1561    )]
1562    pub take_profit_on_fill: Option<TakeProfitDetails>,
1563    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
1564    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
1565    /// Stop Loss Order is modified directly through the Trade.
1566    #[serde(
1567        rename = "stopLossOnFill",
1568        default,
1569        skip_serializing_if = "Option::is_none"
1570    )]
1571    pub stop_loss_on_fill: Option<StopLossDetails>,
1572    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
1573    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
1574    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
1575    #[serde(
1576        rename = "guaranteedStopLossOnFill",
1577        default,
1578        skip_serializing_if = "Option::is_none"
1579    )]
1580    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
1581    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
1582    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
1583    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
1584    #[serde(
1585        rename = "trailingStopLossOnFill",
1586        default,
1587        skip_serializing_if = "Option::is_none"
1588    )]
1589    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
1590    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
1591    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
1592    #[serde(
1593        rename = "tradeClientExtensions",
1594        default,
1595        skip_serializing_if = "Option::is_none"
1596    )]
1597    pub trade_client_extensions: Option<ClientExtensions>,
1598}
1599
1600/// A `LimitOrderRequest` specifies the parameters that may be set when creating a Limit Order.
1601#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1602#[serde(rename_all = "camelCase")]
1603pub struct LimitOrderRequest {
1604    /// The type of the Order to Create. Must be set to “LIMIT” when creating a Market Order.
1605    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1606    #[serde(serialize_with = "serialize_limit_order_request_type")]
1607    pub r#type: Option<OrderType>,
1608    /// The Limit Order’s Instrument.
1609    #[serde(rename = "instrument")]
1610    pub instrument: InstrumentName,
1611    /// The quantity requested to be filled by the Limit Order. A positive number of units results in a long
1612    /// Order, and a negative number of units results in a short Order.
1613    #[serde(rename = "units")]
1614    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1615    pub units: Decimal,
1616    /// The price threshold specified for the Limit Order. The Limit Order will only be filled by a market price
1617    /// that is equal to or better than this price.
1618    #[serde(rename = "price")]
1619    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1620    pub price: Decimal,
1621    /// The time-in-force requested for the Limit Order.
1622    #[serde(rename = "timeInForce")]
1623    pub time_in_force: TimeInForce,
1624    /// The date/time when the Limit Order will be cancelled if its timeInForce is “GTD”.
1625    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1626    pub gtd_time: Option<Timestamp>,
1627    /// Specification of how Positions in the Account are modified when the Order is filled.
1628    #[serde(rename = "positionFill")]
1629    pub position_fill: OrderPositionFill,
1630    /// Specification of which price component should be used when determining if an Order should be triggered
1631    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1632    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1633    /// filled using their default price component. This feature is only provided through the REST API. Clients
1634    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1635    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1636    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1637    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1638    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1639    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1640    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1641    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1642    #[serde(rename = "triggerCondition")]
1643    pub trigger_condition: OrderTriggerCondition,
1644    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
1645    /// account is associated with MT4.
1646    #[serde(
1647        rename = "clientExtensions",
1648        default,
1649        skip_serializing_if = "Option::is_none"
1650    )]
1651    pub client_extensions: Option<ClientExtensions>,
1652    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
1653    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
1654    /// dependent Take Profit Order is modified directly through the Trade.
1655    #[serde(
1656        rename = "takeProfitOnFill",
1657        default,
1658        skip_serializing_if = "Option::is_none"
1659    )]
1660    pub take_profit_on_fill: Option<TakeProfitDetails>,
1661    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
1662    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
1663    /// Stop Loss Order is modified directly through the Trade.
1664    #[serde(
1665        rename = "stopLossOnFill",
1666        default,
1667        skip_serializing_if = "Option::is_none"
1668    )]
1669    pub stop_loss_on_fill: Option<StopLossDetails>,
1670    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
1671    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
1672    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
1673    #[serde(
1674        rename = "guaranteedStopLossOnFill",
1675        default,
1676        skip_serializing_if = "Option::is_none"
1677    )]
1678    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
1679    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
1680    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
1681    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
1682    #[serde(
1683        rename = "trailingStopLossOnFill",
1684        default,
1685        skip_serializing_if = "Option::is_none"
1686    )]
1687    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
1688    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
1689    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
1690    #[serde(
1691        rename = "tradeClientExtensions",
1692        default,
1693        skip_serializing_if = "Option::is_none"
1694    )]
1695    pub trade_client_extensions: Option<ClientExtensions>,
1696}
1697
1698/// A `StopOrderRequest` specifies the parameters that may be set when creating a Stop Order.
1699#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1700#[serde(rename_all = "camelCase")]
1701pub struct StopOrderRequest {
1702    /// The type of the Order to Create. Must be set to “STOP” when creating a Stop Order.
1703    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1704    #[serde(serialize_with = "serialize_stop_order_request_type")]
1705    pub r#type: Option<OrderType>,
1706    /// The Stop Order’s Instrument.
1707    #[serde(rename = "instrument")]
1708    pub instrument: InstrumentName,
1709    /// The quantity requested to be filled by the Stop Order. A positive number of units results in a long
1710    /// Order, and a negative number of units results in a short Order.
1711    #[serde(rename = "units")]
1712    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1713    pub units: Decimal,
1714    /// The price threshold specified for the Stop Order. The Stop Order will only be filled by a market price
1715    /// that is equal to or worse than this price.
1716    #[serde(rename = "price")]
1717    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1718    pub price: Decimal,
1719    /// The worst market price that may be used to fill this Stop Order. If the market gaps and crosses through
1720    /// both the price and the priceBound, the Stop Order will be cancelled instead of being filled.
1721    #[serde(
1722        rename = "priceBound",
1723        default,
1724        skip_serializing_if = "Option::is_none"
1725    )]
1726    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1727    pub price_bound: Option<Decimal>,
1728    /// The time-in-force requested for the Stop Order.
1729    #[serde(rename = "timeInForce")]
1730    pub time_in_force: TimeInForce,
1731    /// The date/time when the Stop Order will be cancelled if its timeInForce is “GTD”.
1732    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1733    pub gtd_time: Option<Timestamp>,
1734    /// Specification of how Positions in the Account are modified when the Order is filled.
1735    #[serde(rename = "positionFill")]
1736    pub position_fill: OrderPositionFill,
1737    /// Specification of which price component should be used when determining if an Order should be triggered
1738    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1739    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1740    /// filled using their default price component. This feature is only provided through the REST API. Clients
1741    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1742    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1743    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1744    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1745    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1746    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1747    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1748    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1749    #[serde(rename = "triggerCondition")]
1750    pub trigger_condition: OrderTriggerCondition,
1751    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
1752    /// account is associated with MT4.
1753    #[serde(
1754        rename = "clientExtensions",
1755        default,
1756        skip_serializing_if = "Option::is_none"
1757    )]
1758    pub client_extensions: Option<ClientExtensions>,
1759    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
1760    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
1761    /// dependent Take Profit Order is modified directly through the Trade.
1762    #[serde(
1763        rename = "takeProfitOnFill",
1764        default,
1765        skip_serializing_if = "Option::is_none"
1766    )]
1767    pub take_profit_on_fill: Option<TakeProfitDetails>,
1768    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
1769    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
1770    /// Stop Loss Order is modified directly through the Trade.
1771    #[serde(
1772        rename = "stopLossOnFill",
1773        default,
1774        skip_serializing_if = "Option::is_none"
1775    )]
1776    pub stop_loss_on_fill: Option<StopLossDetails>,
1777    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
1778    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
1779    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
1780    #[serde(
1781        rename = "guaranteedStopLossOnFill",
1782        default,
1783        skip_serializing_if = "Option::is_none"
1784    )]
1785    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
1786    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
1787    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
1788    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
1789    #[serde(
1790        rename = "trailingStopLossOnFill",
1791        default,
1792        skip_serializing_if = "Option::is_none"
1793    )]
1794    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
1795    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
1796    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
1797    #[serde(
1798        rename = "tradeClientExtensions",
1799        default,
1800        skip_serializing_if = "Option::is_none"
1801    )]
1802    pub trade_client_extensions: Option<ClientExtensions>,
1803}
1804
1805/// A `MarketIfTouchedOrderRequest` specifies the parameters that may be set when creating a Market-if-Touched
1806/// Order.
1807#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1808#[serde(rename_all = "camelCase")]
1809pub struct MarketIfTouchedOrderRequest {
1810    /// The type of the Order to Create. Must be set to “`MARKET_IF_TOUCHED`” when creating a Market If Touched
1811    /// Order.
1812    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1813    #[serde(serialize_with = "serialize_market_if_touched_order_request_type")]
1814    pub r#type: Option<OrderType>,
1815    /// The `MarketIfTouched` Order’s Instrument.
1816    #[serde(rename = "instrument")]
1817    pub instrument: InstrumentName,
1818    /// The quantity requested to be filled by the `MarketIfTouched` Order. A positive number of units results in
1819    /// a long Order, and a negative number of units results in a short Order.
1820    #[serde(rename = "units")]
1821    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1822    pub units: Decimal,
1823    /// The price threshold specified for the `MarketIfTouched` Order. The `MarketIfTouched` Order will only be
1824    /// filled by a market price that crosses this price from the direction of the market price at the time when
1825    /// the Order was created (the initialMarketPrice). Depending on the value of the Order’s price and
1826    /// initialMarketPrice, the `MarketIfTouchedOrder` will behave like a Limit or a Stop Order.
1827    #[serde(rename = "price")]
1828    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1829    pub price: Decimal,
1830    /// The worst market price that may be used to fill this `MarketIfTouched` Order.
1831    #[serde(
1832        rename = "priceBound",
1833        default,
1834        skip_serializing_if = "Option::is_none"
1835    )]
1836    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1837    pub price_bound: Option<Decimal>,
1838    /// The time-in-force requested for the `MarketIfTouched` Order. Restricted to “GTC”, “GFD” and “GTD” for
1839    /// `MarketIfTouched` Orders.
1840    #[serde(rename = "timeInForce")]
1841    pub time_in_force: TimeInForce,
1842    /// The date/time when the `MarketIfTouched` Order will be cancelled if its timeInForce is “GTD”.
1843    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1844    pub gtd_time: Option<Timestamp>,
1845    /// Specification of how Positions in the Account are modified when the Order is filled.
1846    #[serde(rename = "positionFill")]
1847    pub position_fill: OrderPositionFill,
1848    /// Specification of which price component should be used when determining if an Order should be triggered
1849    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1850    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1851    /// filled using their default price component. This feature is only provided through the REST API. Clients
1852    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1853    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1854    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1855    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1856    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1857    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1858    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1859    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1860    #[serde(rename = "triggerCondition")]
1861    pub trigger_condition: OrderTriggerCondition,
1862    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
1863    /// account is associated with MT4.
1864    #[serde(
1865        rename = "clientExtensions",
1866        default,
1867        skip_serializing_if = "Option::is_none"
1868    )]
1869    pub client_extensions: Option<ClientExtensions>,
1870    /// `TakeProfitDetails` specifies the details of a Take Profit Order to be created on behalf of a client. This
1871    /// may happen when an Order is filled that opens a Trade requiring a Take Profit, or when a Trade’s
1872    /// dependent Take Profit Order is modified directly through the Trade.
1873    #[serde(
1874        rename = "takeProfitOnFill",
1875        default,
1876        skip_serializing_if = "Option::is_none"
1877    )]
1878    pub take_profit_on_fill: Option<TakeProfitDetails>,
1879    /// `StopLossDetails` specifies the details of a Stop Loss Order to be created on behalf of a client. This may
1880    /// happen when an Order is filled that opens a Trade requiring a Stop Loss, or when a Trade’s dependent
1881    /// Stop Loss Order is modified directly through the Trade.
1882    #[serde(
1883        rename = "stopLossOnFill",
1884        default,
1885        skip_serializing_if = "Option::is_none"
1886    )]
1887    pub stop_loss_on_fill: Option<StopLossDetails>,
1888    /// `GuaranteedStopLossDetails` specifies the details of a Guaranteed Stop Loss Order to be created on behalf
1889    /// of a client. This may happen when an Order is filled that opens a Trade requiring a Guaranteed Stop
1890    /// Loss, or when a Trade’s dependent Guaranteed Stop Loss Order is modified directly through the Trade.
1891    #[serde(
1892        rename = "guaranteedStopLossOnFill",
1893        default,
1894        skip_serializing_if = "Option::is_none"
1895    )]
1896    pub guaranteed_stop_loss_on_fill: Option<GuaranteedStopLossDetails>,
1897    /// `TrailingStopLossDetails` specifies the details of a Trailing Stop Loss Order to be created on behalf of a
1898    /// client. This may happen when an Order is filled that opens a Trade requiring a Trailing Stop Loss, or
1899    /// when a Trade’s dependent Trailing Stop Loss Order is modified directly through the Trade.
1900    #[serde(
1901        rename = "trailingStopLossOnFill",
1902        default,
1903        skip_serializing_if = "Option::is_none"
1904    )]
1905    pub trailing_stop_loss_on_fill: Option<TrailingStopLossDetails>,
1906    /// Client Extensions to add to the Trade created when the Order is filled (if such a Trade is created). Do
1907    /// not set, modify, or delete tradeClientExtensions if your account is associated with MT4.
1908    #[serde(
1909        rename = "tradeClientExtensions",
1910        default,
1911        skip_serializing_if = "Option::is_none"
1912    )]
1913    pub trade_client_extensions: Option<ClientExtensions>,
1914}
1915
1916/// A `TakeProfitOrderRequest` specifies the parameters that may be set when creating a Take Profit Order.
1917#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1918#[serde(rename_all = "camelCase")]
1919pub struct TakeProfitOrderRequest {
1920    /// The type of the Order to Create. Must be set to “`TAKE_PROFIT`” when creating a Take Profit Order.
1921    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1922    #[serde(serialize_with = "serialize_take_profit_order_request_type")]
1923    pub r#type: Option<OrderType>,
1924    /// The ID of the Trade to close when the price threshold is breached.
1925    #[serde(rename = "tradeID")]
1926    pub trade_id: TradeID,
1927    /// The client ID of the Trade to be closed when the price threshold is breached.
1928    #[serde(
1929        rename = "clientTradeID",
1930        default,
1931        skip_serializing_if = "Option::is_none"
1932    )]
1933    pub client_trade_id: Option<ClientID>,
1934    /// The price threshold specified for the `TakeProfit` Order. The associated Trade will be closed by a market
1935    /// price that is equal to or better than this threshold.
1936    #[serde(rename = "price")]
1937    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1938    pub price: Decimal,
1939    /// The time-in-force requested for the `TakeProfit` Order. Restricted to “GTC”, “GFD” and “GTD” for
1940    /// `TakeProfit` Orders.
1941    #[serde(rename = "timeInForce")]
1942    pub time_in_force: TimeInForce,
1943    /// The date/time when the `TakeProfit` Order will be cancelled if its timeInForce is “GTD”.
1944    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
1945    pub gtd_time: Option<Timestamp>,
1946    /// Specification of which price component should be used when determining if an Order should be triggered
1947    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
1948    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
1949    /// filled using their default price component. This feature is only provided through the REST API. Clients
1950    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
1951    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
1952    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
1953    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
1954    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
1955    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
1956    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
1957    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
1958    #[serde(rename = "triggerCondition")]
1959    pub trigger_condition: OrderTriggerCondition,
1960    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
1961    /// account is associated with MT4.
1962    #[serde(
1963        rename = "clientExtensions",
1964        default,
1965        skip_serializing_if = "Option::is_none"
1966    )]
1967    pub client_extensions: Option<ClientExtensions>,
1968}
1969
1970/// A `StopLossOrderRequest` specifies the parameters that may be set when creating a Stop Loss Order. Only
1971/// one of the price and distance fields may be specified.
1972///
1973/// The published definition requires `price` while allowing `distance` only in
1974/// its absence. This DTO follows that requiredness: outbound admission rejects
1975/// an explicit distance alongside the required price. Distance-only creation is
1976/// unavailable under this published contract; received fields remain inspectable.
1977#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1978#[serde(rename_all = "camelCase")]
1979pub struct StopLossOrderRequest {
1980    /// The type of the Order to Create. Must be set to “`STOP_LOSS`” when creating a Stop Loss Order.
1981    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
1982    #[serde(serialize_with = "serialize_stop_loss_order_request_type")]
1983    pub r#type: Option<OrderType>,
1984    /// The ID of the Trade to close when the price threshold is breached.
1985    #[serde(rename = "tradeID")]
1986    pub trade_id: TradeID,
1987    /// The client ID of the Trade to be closed when the price threshold is breached.
1988    #[serde(
1989        rename = "clientTradeID",
1990        default,
1991        skip_serializing_if = "Option::is_none"
1992    )]
1993    pub client_trade_id: Option<ClientID>,
1994    /// The price threshold specified for the Stop Loss Order. The associated Trade will be closed by a market
1995    /// price that is equal to or worse than this threshold.
1996    #[serde(rename = "price")]
1997    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
1998    pub price: Decimal,
1999    /// Specifies the distance (in price units) from the Account’s current price to use as the Stop Loss Order
2000    /// price. If the Trade is short the Instrument’s bid price is used, and for long Trades the ask is used.
2001    #[serde(rename = "distance", default, skip_serializing_if = "Option::is_none")]
2002    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2003    pub distance: Option<Decimal>,
2004    /// The time-in-force requested for the `StopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for `StopLoss`
2005    /// Orders.
2006    #[serde(rename = "timeInForce")]
2007    pub time_in_force: TimeInForce,
2008    /// The date/time when the `StopLoss` Order will be cancelled if its timeInForce is “GTD”.
2009    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
2010    pub gtd_time: Option<Timestamp>,
2011    /// Specification of which price component should be used when determining if an Order should be triggered
2012    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
2013    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
2014    /// filled using their default price component. This feature is only provided through the REST API. Clients
2015    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
2016    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
2017    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
2018    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
2019    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
2020    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
2021    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
2022    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
2023    #[serde(rename = "triggerCondition")]
2024    pub trigger_condition: OrderTriggerCondition,
2025    /// Flag indicating that the Stop Loss Order is guaranteed. The default value depends on the
2026    /// `GuaranteedStopLossOrderMode` of the account, if it is REQUIRED, the default will be true, for DISABLED or
2027    /// ENABLED the default is false. Deprecated: Will be removed in a future API update.
2028    #[serde(
2029        rename = "guaranteed",
2030        default,
2031        skip_serializing_if = "Option::is_none"
2032    )]
2033    pub guaranteed: Option<bool>,
2034    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
2035    /// account is associated with MT4.
2036    #[serde(
2037        rename = "clientExtensions",
2038        default,
2039        skip_serializing_if = "Option::is_none"
2040    )]
2041    pub client_extensions: Option<ClientExtensions>,
2042}
2043
2044/// A `GuaranteedStopLossOrderRequest` specifies the parameters that may be set when creating a Guaranteed
2045/// Stop Loss Order. Only one of the price and distance fields may be specified.
2046///
2047/// The published definition requires `price` while allowing `distance` only in
2048/// its absence. This DTO follows that requiredness: outbound admission rejects
2049/// an explicit distance alongside the required price. Distance-only creation is
2050/// unavailable under this published contract; received fields remain inspectable.
2051#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2052#[serde(rename_all = "camelCase")]
2053pub struct GuaranteedStopLossOrderRequest {
2054    /// The type of the Order to Create. Must be set to “`GUARANTEED_STOP_LOSS`” when creating a Guaranteed Stop
2055    /// Loss Order.
2056    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
2057    #[serde(serialize_with = "serialize_guaranteed_stop_loss_order_request_type")]
2058    pub r#type: Option<OrderType>,
2059    /// The ID of the Trade to close when the price threshold is breached.
2060    #[serde(rename = "tradeID")]
2061    pub trade_id: TradeID,
2062    /// The client ID of the Trade to be closed when the price threshold is breached.
2063    #[serde(
2064        rename = "clientTradeID",
2065        default,
2066        skip_serializing_if = "Option::is_none"
2067    )]
2068    pub client_trade_id: Option<ClientID>,
2069    /// The price threshold specified for the Guaranteed Stop Loss Order. The associated Trade will be closed at
2070    /// this price.
2071    #[serde(rename = "price")]
2072    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
2073    pub price: Decimal,
2074    /// Specifies the distance (in price units) from the Account’s current price to use as the Guaranteed Stop
2075    /// Loss Order price. If the Trade is short the Instrument’s bid price is used, and for long Trades the ask
2076    /// is used.
2077    #[serde(rename = "distance", default, skip_serializing_if = "Option::is_none")]
2078    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2079    pub distance: Option<Decimal>,
2080    /// The time-in-force requested for the `GuaranteedStopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for
2081    /// `GuaranteedStopLoss` Orders.
2082    #[serde(rename = "timeInForce")]
2083    pub time_in_force: TimeInForce,
2084    /// The date/time when the `GuaranteedStopLoss` Order will be cancelled if its timeInForce is “GTD”.
2085    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
2086    pub gtd_time: Option<Timestamp>,
2087    /// Specification of which price component should be used when determining if an Order should be triggered
2088    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
2089    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
2090    /// filled using their default price component. This feature is only provided through the REST API. Clients
2091    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
2092    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
2093    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
2094    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
2095    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
2096    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
2097    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
2098    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
2099    #[serde(rename = "triggerCondition")]
2100    pub trigger_condition: OrderTriggerCondition,
2101    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
2102    /// account is associated with MT4.
2103    #[serde(
2104        rename = "clientExtensions",
2105        default,
2106        skip_serializing_if = "Option::is_none"
2107    )]
2108    pub client_extensions: Option<ClientExtensions>,
2109}
2110
2111/// A `TrailingStopLossOrderRequest` specifies the parameters that may be set when creating a Trailing Stop
2112/// Loss Order.
2113#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2114#[serde(rename_all = "camelCase")]
2115pub struct TrailingStopLossOrderRequest {
2116    /// The type of the Order to Create. Must be set to “`TRAILING_STOP_LOSS`” when creating a Trailing Stop Loss
2117    /// Order.
2118    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
2119    #[serde(serialize_with = "serialize_trailing_stop_loss_order_request_type")]
2120    pub r#type: Option<OrderType>,
2121    /// The ID of the Trade to close when the price threshold is breached.
2122    #[serde(rename = "tradeID")]
2123    pub trade_id: TradeID,
2124    /// The client ID of the Trade to be closed when the price threshold is breached.
2125    #[serde(
2126        rename = "clientTradeID",
2127        default,
2128        skip_serializing_if = "Option::is_none"
2129    )]
2130    pub client_trade_id: Option<ClientID>,
2131    /// The price distance (in price units) specified for the `TrailingStopLoss` Order.
2132    #[serde(rename = "distance")]
2133    #[serde(deserialize_with = "crate::decimal_wire::number_or_string")]
2134    pub distance: Decimal,
2135    /// The time-in-force requested for the `TrailingStopLoss` Order. Restricted to “GTC”, “GFD” and “GTD” for
2136    /// `TrailingStopLoss` Orders.
2137    #[serde(rename = "timeInForce")]
2138    pub time_in_force: TimeInForce,
2139    /// The date/time when the `StopLoss` Order will be cancelled if its timeInForce is “GTD”.
2140    #[serde(rename = "gtdTime", default, skip_serializing_if = "Option::is_none")]
2141    pub gtd_time: Option<Timestamp>,
2142    /// Specification of which price component should be used when determining if an Order should be triggered
2143    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
2144    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
2145    /// filled using their default price component. This feature is only provided through the REST API. Clients
2146    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
2147    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
2148    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
2149    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
2150    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
2151    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
2152    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
2153    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
2154    #[serde(rename = "triggerCondition")]
2155    pub trigger_condition: OrderTriggerCondition,
2156    /// The client extensions to add to the Order. Do not set, modify, or delete clientExtensions if your
2157    /// account is associated with MT4.
2158    #[serde(
2159        rename = "clientExtensions",
2160        default,
2161        skip_serializing_if = "Option::is_none"
2162    )]
2163    pub client_extensions: Option<ClientExtensions>,
2164}
2165
2166provider_enum! {
2167    /// The type of the Order.
2168    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2169    #[non_exhaustive]
2170    pub enum OrderType {
2171        /// A Market Order
2172        Market => "MARKET",
2173        /// A Limit Order
2174        Limit => "LIMIT",
2175        /// A Stop Order
2176        Stop => "STOP",
2177        /// A Market-if-touched Order
2178        MarketIfTouched => "MARKET_IF_TOUCHED",
2179        /// A Take Profit Order
2180        TakeProfit => "TAKE_PROFIT",
2181        /// A Stop Loss Order
2182        StopLoss => "STOP_LOSS",
2183        /// A Guaranteed Stop Loss Order
2184        GuaranteedStopLoss => "GUARANTEED_STOP_LOSS",
2185        /// A Trailing Stop Loss Order
2186        TrailingStopLoss => "TRAILING_STOP_LOSS",
2187        /// A Fixed Price Order
2188        FixedPrice => "FIXED_PRICE",
2189        ;
2190        /// An unrecognized provider value, preserved for forward compatibility.
2191        Unknown(String),
2192    }
2193}
2194
2195provider_enum! {
2196    /// The type of the Order.
2197    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2198    #[non_exhaustive]
2199    pub enum CancellableOrderType {
2200        /// A Limit Order
2201        Limit => "LIMIT",
2202        /// A Stop Order
2203        Stop => "STOP",
2204        /// A Market-if-touched Order
2205        MarketIfTouched => "MARKET_IF_TOUCHED",
2206        /// A Take Profit Order
2207        TakeProfit => "TAKE_PROFIT",
2208        /// A Stop Loss Order
2209        StopLoss => "STOP_LOSS",
2210        /// A Guaranteed Stop Loss Order
2211        GuaranteedStopLoss => "GUARANTEED_STOP_LOSS",
2212        /// A Trailing Stop Loss Order
2213        TrailingStopLoss => "TRAILING_STOP_LOSS",
2214        ;
2215        /// An unrecognized provider value, preserved for forward compatibility.
2216        Unknown(String),
2217    }
2218}
2219
2220provider_enum! {
2221    /// The current state of the Order.
2222    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2223    #[non_exhaustive]
2224    pub enum OrderState {
2225        /// The Order is currently pending execution
2226        Pending => "PENDING",
2227        /// The Order has been filled
2228        Filled => "FILLED",
2229        /// The Order has been triggered
2230        Triggered => "TRIGGERED",
2231        /// The Order has been cancelled
2232        Cancelled => "CANCELLED",
2233        ;
2234        /// An unrecognized provider value, preserved for forward compatibility.
2235        Unknown(String),
2236    }
2237}
2238
2239provider_enum! {
2240    /// Unrecognized spellings are retained and serialized unchanged for provider
2241    /// compatibility; endpoint admission applies any operation-specific restrictions.
2242    /// The state to filter the requested Orders by.
2243    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2244    #[non_exhaustive]
2245    pub enum OrderStateFilter {
2246        /// The Orders that are currently pending execution
2247        Pending => "PENDING",
2248        /// The Orders that have been filled
2249        Filled => "FILLED",
2250        /// The Orders that have been triggered
2251        Triggered => "TRIGGERED",
2252        /// The Orders that have been cancelled
2253        Cancelled => "CANCELLED",
2254        /// The Orders that are in any of the possible states listed above
2255        All => "ALL",
2256        ;
2257        /// An unrecognized provider value, preserved for forward compatibility.
2258        Unknown(String),
2259    }
2260}
2261
2262/// An `OrderIdentifier` is used to refer to an Order, and contains both the `OrderID` and the `ClientOrderID`.
2263#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2264#[serde(rename_all = "camelCase")]
2265pub struct OrderIdentifier {
2266    /// The OANDA-assigned Order ID
2267    #[serde(rename = "orderID", default, skip_serializing_if = "Option::is_none")]
2268    pub order_id: Option<OrderID>,
2269    /// The client-provided client Order ID
2270    #[serde(
2271        rename = "clientOrderID",
2272        default,
2273        skip_serializing_if = "Option::is_none"
2274    )]
2275    pub client_order_id: Option<ClientID>,
2276}
2277
2278provider_enum! {
2279    /// The time-in-force of an Order. `TimeInForce` describes how long an Order should remain pending before
2280    /// being automatically cancelled by the execution system.
2281    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2282    #[non_exhaustive]
2283    pub enum TimeInForce {
2284        /// The Order is “Good unTil Cancelled”
2285        Gtc => "GTC",
2286        /// The Order is “Good unTil Date” and will be cancelled at the provided time
2287        Gtd => "GTD",
2288        /// The Order is “Good For Day” and will be cancelled at 5pm New York time
2289        Gfd => "GFD",
2290        /// The Order must be immediately “Filled Or Killed”
2291        Fok => "FOK",
2292        /// The Order must be “Immediately partially filled Or Cancelled”
2293        Ioc => "IOC",
2294        ;
2295        /// An unrecognized provider value, preserved for forward compatibility.
2296        Unknown(String),
2297    }
2298}
2299
2300provider_enum! {
2301    /// Specification of how Positions in the Account are modified when the Order is filled.
2302    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2303    #[non_exhaustive]
2304    pub enum OrderPositionFill {
2305        /// When the Order is filled, only allow Positions to be opened or extended.
2306        OpenOnly => "OPEN_ONLY",
2307        /// When the Order is filled, always fully reduce an existing Position before opening a new Position.
2308        ReduceFirst => "REDUCE_FIRST",
2309        /// When the Order is filled, only reduce an existing Position.
2310        ReduceOnly => "REDUCE_ONLY",
2311        /// When the Order is filled, use `REDUCE_FIRST` behaviour for non-client hedging Accounts, and `OPEN_ONLY`
2312        /// behaviour for client hedging Accounts.
2313        Default => "DEFAULT",
2314        ;
2315        /// An unrecognized provider value, preserved for forward compatibility.
2316        Unknown(String),
2317    }
2318}
2319
2320provider_enum! {
2321    /// Specification of which price component should be used when determining if an Order should be triggered
2322    /// and filled. This allows Orders to be triggered based on the bid, ask, mid, default (ask for buy, bid for
2323    /// sell) or inverse (ask for sell, bid for buy) price depending on the desired behaviour. Orders are always
2324    /// filled using their default price component. This feature is only provided through the REST API. Clients
2325    /// who choose to specify a non-default trigger condition will not see it reflected in any of OANDA’s
2326    /// proprietary or partner trading platforms, their transaction history or their account statements. OANDA
2327    /// platforms always assume that an Order’s trigger condition is set to the default value when indicating
2328    /// the distance from an Order’s trigger price, and will always provide the default trigger condition when
2329    /// creating or modifying an Order. A special restriction applies when creating a Guaranteed Stop Loss
2330    /// Order. In this case the `TriggerCondition` value must either be “DEFAULT”, or the “natural” trigger side
2331    /// “DEFAULT” results in. So for a Guaranteed Stop Loss Order for a long trade valid values are “DEFAULT”
2332    /// and “BID”, and for short trades “DEFAULT” and “ASK” are valid.
2333    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2334    #[non_exhaustive]
2335    pub enum OrderTriggerCondition {
2336        /// Trigger an Order the “natural” way: compare its price to the ask for long Orders and bid for short
2337        /// Orders.
2338        Default => "DEFAULT",
2339        /// Trigger an Order the opposite of the “natural” way: compare its price the bid for long Orders and ask
2340        /// for short Orders.
2341        Inverse => "INVERSE",
2342        /// Trigger an Order by comparing its price to the bid regardless of whether it is long or short.
2343        Bid => "BID",
2344        /// Trigger an Order by comparing its price to the ask regardless of whether it is long or short.
2345        Ask => "ASK",
2346        /// Trigger an Order by comparing its price to the midpoint regardless of whether it is long or short.
2347        Mid => "MID",
2348        ;
2349        /// An unrecognized provider value, preserved for forward compatibility.
2350        Unknown(String),
2351    }
2352}
2353
2354/// The dynamic state of an Order. This is only relevant to `TrailingStopLoss` Orders, as no other Order type
2355/// has dynamic state.
2356#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2357#[serde(rename_all = "camelCase")]
2358pub struct DynamicOrderState {
2359    /// The Order’s ID.
2360    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
2361    pub id: Option<OrderID>,
2362    /// The Order’s calculated trailing stop value.
2363    #[serde(
2364        rename = "trailingStopValue",
2365        default,
2366        skip_serializing_if = "Option::is_none"
2367    )]
2368    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2369    pub trailing_stop_value: Option<Decimal>,
2370    /// The distance between the Trailing Stop Loss Order’s trailingStopValue and the current Market Price. This
2371    /// represents the distance (in price units) of the Order from a triggering price. If the distance could not
2372    /// be determined, this value will not be set.
2373    #[serde(
2374        rename = "triggerDistance",
2375        default,
2376        skip_serializing_if = "Option::is_none"
2377    )]
2378    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2379    pub trigger_distance: Option<Decimal>,
2380    /// True if an exact trigger distance could be calculated. If false, it means the provided trigger distance
2381    /// is a best estimate. If the distance could not be determined, this value will not be set.
2382    #[serde(
2383        rename = "isTriggerDistanceExact",
2384        default,
2385        skip_serializing_if = "Option::is_none"
2386    )]
2387    pub is_trigger_distance_exact: Option<bool>,
2388}
2389
2390/// Representation of many units of an Instrument are available to be traded for both long and short Orders.
2391#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2392#[serde(rename_all = "camelCase")]
2393pub struct UnitsAvailableDetails {
2394    /// The units available for long Orders.
2395    #[serde(rename = "long", default, skip_serializing_if = "Option::is_none")]
2396    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2397    pub long: Option<Decimal>,
2398    /// The units available for short Orders.
2399    #[serde(rename = "short", default, skip_serializing_if = "Option::is_none")]
2400    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2401    pub short: Option<Decimal>,
2402}
2403
2404/// Representation of how many units of an Instrument are available to be traded by an Order depending on
2405/// its positionFill option.
2406#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2407#[serde(rename_all = "camelCase")]
2408pub struct UnitsAvailable {
2409    /// The number of units that are available to be traded using an Order with a positionFill option of
2410    /// “DEFAULT”. For an Account with hedging enabled, this value will be the same as the “`OPEN_ONLY`” value.
2411    /// For an Account without hedging enabled, this value will be the same as the “`REDUCE_FIRST`” value.
2412    #[serde(rename = "default", default, skip_serializing_if = "Option::is_none")]
2413    pub default: Option<UnitsAvailableDetails>,
2414    /// The number of units that may are available to be traded with an Order with a positionFill option of
2415    /// “`REDUCE_FIRST`”.
2416    #[serde(
2417        rename = "reduceFirst",
2418        default,
2419        skip_serializing_if = "Option::is_none"
2420    )]
2421    pub reduce_first: Option<UnitsAvailableDetails>,
2422    /// The number of units that may are available to be traded with an Order with a positionFill option of
2423    /// “`REDUCE_ONLY`”.
2424    #[serde(
2425        rename = "reduceOnly",
2426        default,
2427        skip_serializing_if = "Option::is_none"
2428    )]
2429    pub reduce_only: Option<UnitsAvailableDetails>,
2430    /// The number of units that may are available to be traded with an Order with a positionFill option of
2431    /// “`OPEN_ONLY`”.
2432    #[serde(rename = "openOnly", default, skip_serializing_if = "Option::is_none")]
2433    pub open_only: Option<UnitsAvailableDetails>,
2434}
2435
2436/// Details required by clients creating a Guaranteed Stop Loss Order
2437#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2438#[serde(rename_all = "camelCase")]
2439pub struct GuaranteedStopLossOrderEntryData {
2440    /// The minimum distance allowed between the Trade’s fill price and the configured price for guaranteed Stop
2441    /// Loss Orders created for this instrument. Specified in price units.
2442    #[serde(
2443        rename = "minimumDistance",
2444        default,
2445        skip_serializing_if = "Option::is_none"
2446    )]
2447    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2448    pub minimum_distance: Option<Decimal>,
2449    /// The amount that is charged to the account if a guaranteed Stop Loss Order is triggered and filled. The
2450    /// value is in price units and is charged for each unit of the Trade.
2451    #[serde(rename = "premium", default, skip_serializing_if = "Option::is_none")]
2452    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
2453    pub premium: Option<Decimal>,
2454    /// The guaranteed Stop Loss Order level restriction for this instrument.
2455    #[serde(
2456        rename = "levelRestriction",
2457        default,
2458        skip_serializing_if = "Option::is_none"
2459    )]
2460    pub level_restriction: Option<GuaranteedStopLossOrderLevelRestriction>,
2461}
2462
2463// A concrete DTO may omit its documented default, but cannot contradict its own type.
2464macro_rules! concrete_type_serializer {
2465    ($name:ident, $expected:literal) => {
2466        #[expect(
2467            clippy::ref_option,
2468            reason = "Serde serialize_with passes the optional field by reference"
2469        )]
2470        fn $name<S: serde::Serializer>(
2471            value: &Option<OrderType>,
2472            serializer: S,
2473        ) -> Result<S::Ok, S::Error> {
2474            if let Some(observed) = value
2475                && observed.as_str() != $expected
2476            {
2477                return Err(serde::ser::Error::custom(format!(
2478                    "OANDA type discriminator mismatch: expected {:?}, observed {:?}",
2479                    $expected,
2480                    observed.as_str()
2481                )));
2482            }
2483            value.serialize(serializer)
2484        }
2485    };
2486}
2487concrete_type_serializer!(serialize_market_order_type, "MARKET");
2488concrete_type_serializer!(serialize_limit_order_type, "LIMIT");
2489concrete_type_serializer!(serialize_stop_order_type, "STOP");
2490concrete_type_serializer!(serialize_market_if_touched_order_type, "MARKET_IF_TOUCHED");
2491concrete_type_serializer!(serialize_take_profit_order_type, "TAKE_PROFIT");
2492concrete_type_serializer!(serialize_stop_loss_order_type, "STOP_LOSS");
2493concrete_type_serializer!(
2494    serialize_guaranteed_stop_loss_order_type,
2495    "GUARANTEED_STOP_LOSS"
2496);
2497concrete_type_serializer!(
2498    serialize_trailing_stop_loss_order_type,
2499    "TRAILING_STOP_LOSS"
2500);
2501concrete_type_serializer!(serialize_fixed_price_order_type, "FIXED_PRICE");
2502concrete_type_serializer!(serialize_market_order_request_type, "MARKET");
2503concrete_type_serializer!(serialize_limit_order_request_type, "LIMIT");
2504concrete_type_serializer!(serialize_stop_order_request_type, "STOP");
2505concrete_type_serializer!(
2506    serialize_market_if_touched_order_request_type,
2507    "MARKET_IF_TOUCHED"
2508);
2509concrete_type_serializer!(serialize_take_profit_order_request_type, "TAKE_PROFIT");
2510concrete_type_serializer!(serialize_stop_loss_order_request_type, "STOP_LOSS");
2511concrete_type_serializer!(
2512    serialize_guaranteed_stop_loss_order_request_type,
2513    "GUARANTEED_STOP_LOSS"
2514);
2515concrete_type_serializer!(
2516    serialize_trailing_stop_loss_order_request_type,
2517    "TRAILING_STOP_LOSS"
2518);
2519
2520pub(super) fn validate_time_in_force(
2521    value: &TimeInForce,
2522    market: bool,
2523    gtd_time: Option<&Timestamp>,
2524    require_gtd_time: bool,
2525) -> crate::Result<()> {
2526    match value {
2527        TimeInForce::Unknown(_) => {
2528            return Err(crate::Error::InvalidInput("unsupported timeInForce".into()));
2529        }
2530        TimeInForce::Fok | TimeInForce::Ioc if !market => {
2531            return Err(crate::Error::InvalidInput(
2532                "non-market order cannot use FOK or IOC".into(),
2533            ));
2534        }
2535        TimeInForce::Gtc | TimeInForce::Gtd | TimeInForce::Gfd if market => {
2536            return Err(crate::Error::InvalidInput(
2537                "market order requires FOK or IOC".into(),
2538            ));
2539        }
2540        TimeInForce::Gtd if require_gtd_time && gtd_time.is_none() => {
2541            return Err(crate::Error::InvalidInput(
2542                "GTD order requires gtdTime".into(),
2543            ));
2544        }
2545        TimeInForce::Fok
2546        | TimeInForce::Ioc
2547        | TimeInForce::Gtc
2548        | TimeInForce::Gtd
2549        | TimeInForce::Gfd => {}
2550    }
2551    Ok(())
2552}
2553
2554// These details create dependent orders. Unlike a partial modification, a
2555// supplied GTD instruction cannot inherit its cancellation time from an order.
2556struct OnFill<'a> {
2557    take_profit: Option<&'a TakeProfitDetails>,
2558    stop_loss: Option<&'a StopLossDetails>,
2559    guaranteed_stop_loss: Option<&'a GuaranteedStopLossDetails>,
2560    trailing_stop_loss: Option<&'a TrailingStopLossDetails>,
2561}
2562
2563impl crate::validation::Validate for OnFill<'_> {
2564    fn validate(&self) -> crate::Result<()> {
2565        if let Some(details) = self.take_profit {
2566            details.validate()?;
2567            if let Some(time_in_force) = &details.time_in_force {
2568                validate_time_in_force(time_in_force, false, details.gtd_time.as_ref(), true)?;
2569            }
2570        }
2571        if let Some(details) = self.stop_loss {
2572            details.validate()?;
2573            if let Some(time_in_force) = &details.time_in_force {
2574                validate_time_in_force(time_in_force, false, details.gtd_time.as_ref(), true)?;
2575            }
2576        }
2577        if let Some(details) = self.guaranteed_stop_loss {
2578            details.validate()?;
2579            if let Some(time_in_force) = &details.time_in_force {
2580                validate_time_in_force(time_in_force, false, details.gtd_time.as_ref(), true)?;
2581            }
2582        }
2583        if let Some(details) = self.trailing_stop_loss {
2584            details.validate()?;
2585            if let Some(time_in_force) = &details.time_in_force {
2586                validate_time_in_force(time_in_force, false, details.gtd_time.as_ref(), true)?;
2587            }
2588        }
2589        Ok(())
2590    }
2591}
2592
2593impl crate::validation::Validate for MarketOrderRequest {
2594    fn validate(&self) -> crate::Result<()> {
2595        if self.units.is_zero() {
2596            return Err(crate::Error::InvalidInput(
2597                "order units must not be zero".into(),
2598            ));
2599        }
2600        validate_time_in_force(&self.time_in_force, true, None, true)?;
2601        if matches!(self.position_fill, OrderPositionFill::Unknown(_)) {
2602            return Err(crate::Error::InvalidInput(
2603                "unsupported positionFill".into(),
2604            ));
2605        }
2606        OnFill {
2607            take_profit: self.take_profit_on_fill.as_ref(),
2608            stop_loss: self.stop_loss_on_fill.as_ref(),
2609            guaranteed_stop_loss: self.guaranteed_stop_loss_on_fill.as_ref(),
2610            trailing_stop_loss: self.trailing_stop_loss_on_fill.as_ref(),
2611        }
2612        .validate()?;
2613        Ok(())
2614    }
2615}
2616
2617impl crate::validation::Validate for LimitOrderRequest {
2618    fn validate(&self) -> crate::Result<()> {
2619        if self.units.is_zero() {
2620            return Err(crate::Error::InvalidInput(
2621                "order units must not be zero".into(),
2622            ));
2623        }
2624        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2625        if matches!(self.position_fill, OrderPositionFill::Unknown(_)) {
2626            return Err(crate::Error::InvalidInput(
2627                "unsupported positionFill".into(),
2628            ));
2629        }
2630        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2631            return Err(crate::Error::InvalidInput(
2632                "unsupported triggerCondition".into(),
2633            ));
2634        }
2635        OnFill {
2636            take_profit: self.take_profit_on_fill.as_ref(),
2637            stop_loss: self.stop_loss_on_fill.as_ref(),
2638            guaranteed_stop_loss: self.guaranteed_stop_loss_on_fill.as_ref(),
2639            trailing_stop_loss: self.trailing_stop_loss_on_fill.as_ref(),
2640        }
2641        .validate()?;
2642        Ok(())
2643    }
2644}
2645
2646impl crate::validation::Validate for StopOrderRequest {
2647    fn validate(&self) -> crate::Result<()> {
2648        if self.units.is_zero() {
2649            return Err(crate::Error::InvalidInput(
2650                "order units must not be zero".into(),
2651            ));
2652        }
2653        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2654        if matches!(self.position_fill, OrderPositionFill::Unknown(_)) {
2655            return Err(crate::Error::InvalidInput(
2656                "unsupported positionFill".into(),
2657            ));
2658        }
2659        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2660            return Err(crate::Error::InvalidInput(
2661                "unsupported triggerCondition".into(),
2662            ));
2663        }
2664        OnFill {
2665            take_profit: self.take_profit_on_fill.as_ref(),
2666            stop_loss: self.stop_loss_on_fill.as_ref(),
2667            guaranteed_stop_loss: self.guaranteed_stop_loss_on_fill.as_ref(),
2668            trailing_stop_loss: self.trailing_stop_loss_on_fill.as_ref(),
2669        }
2670        .validate()?;
2671        Ok(())
2672    }
2673}
2674
2675impl crate::validation::Validate for MarketIfTouchedOrderRequest {
2676    fn validate(&self) -> crate::Result<()> {
2677        if self.units.is_zero() {
2678            return Err(crate::Error::InvalidInput(
2679                "order units must not be zero".into(),
2680            ));
2681        }
2682        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2683        if matches!(self.position_fill, OrderPositionFill::Unknown(_)) {
2684            return Err(crate::Error::InvalidInput(
2685                "unsupported positionFill".into(),
2686            ));
2687        }
2688        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2689            return Err(crate::Error::InvalidInput(
2690                "unsupported triggerCondition".into(),
2691            ));
2692        }
2693        OnFill {
2694            take_profit: self.take_profit_on_fill.as_ref(),
2695            stop_loss: self.stop_loss_on_fill.as_ref(),
2696            guaranteed_stop_loss: self.guaranteed_stop_loss_on_fill.as_ref(),
2697            trailing_stop_loss: self.trailing_stop_loss_on_fill.as_ref(),
2698        }
2699        .validate()?;
2700        Ok(())
2701    }
2702}
2703
2704impl crate::validation::Validate for TakeProfitOrderRequest {
2705    fn validate(&self) -> crate::Result<()> {
2706        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2707        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2708            return Err(crate::Error::InvalidInput(
2709                "unsupported triggerCondition".into(),
2710            ));
2711        }
2712        Ok(())
2713    }
2714}
2715
2716impl crate::validation::Validate for StopLossOrderRequest {
2717    fn validate(&self) -> crate::Result<()> {
2718        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2719        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2720            return Err(crate::Error::InvalidInput(
2721                "unsupported triggerCondition".into(),
2722            ));
2723        }
2724        if self.distance.is_some() {
2725            return Err(crate::Error::InvalidInput(
2726                "price and distance are mutually exclusive".into(),
2727            ));
2728        }
2729        Ok(())
2730    }
2731}
2732
2733impl crate::validation::Validate for GuaranteedStopLossOrderRequest {
2734    fn validate(&self) -> crate::Result<()> {
2735        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2736        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2737            return Err(crate::Error::InvalidInput(
2738                "unsupported triggerCondition".into(),
2739            ));
2740        }
2741        if self.distance.is_some() {
2742            return Err(crate::Error::InvalidInput(
2743                "price and distance are mutually exclusive".into(),
2744            ));
2745        }
2746        Ok(())
2747    }
2748}
2749
2750impl crate::validation::Validate for TrailingStopLossOrderRequest {
2751    fn validate(&self) -> crate::Result<()> {
2752        validate_time_in_force(&self.time_in_force, false, self.gtd_time.as_ref(), true)?;
2753        if matches!(self.trigger_condition, OrderTriggerCondition::Unknown(_)) {
2754            return Err(crate::Error::InvalidInput(
2755                "unsupported triggerCondition".into(),
2756            ));
2757        }
2758        Ok(())
2759    }
2760}