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}