Skip to main content

oanda_client/models/
account.rs

1//! OANDA v20 account definitions.
2// Shared imports vary by definition family; unused ones are deliberately allowed.
3#[allow(unused_imports)]
4use super::*;
5#[allow(unused_imports)]
6use crate::ids::*;
7#[allow(unused_imports)]
8use crate::timestamp::Timestamp;
9#[allow(unused_imports)]
10use rust_decimal::Decimal;
11#[allow(unused_imports)]
12use serde::{Deserialize, Serialize};
13
14/// The full details of a client’s Account. This includes full open Trade, open Position and pending Order
15/// representation.
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase")]
18pub struct Account {
19    /// The Account’s identifier
20    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
21    pub id: Option<AccountID>,
22    /// Client-assigned alias for the Account. Only provided if the Account has an alias set
23    #[serde(rename = "alias", default, skip_serializing_if = "Option::is_none")]
24    pub alias: Option<String>,
25    /// The home currency of the Account
26    #[serde(rename = "currency", default, skip_serializing_if = "Option::is_none")]
27    pub currency: Option<Currency>,
28    /// ID of the user that created the Account.
29    #[serde(
30        rename = "createdByUserID",
31        default,
32        skip_serializing_if = "Option::is_none"
33    )]
34    pub created_by_user_id: Option<i64>,
35    /// The date/time when the Account was created.
36    #[serde(
37        rename = "createdTime",
38        default,
39        skip_serializing_if = "Option::is_none"
40    )]
41    pub created_time: Option<Timestamp>,
42    /// The current guaranteed Stop Loss Order settings of the Account. This field will only be present if the
43    /// guaranteedStopLossOrderMode is not ‘DISABLED’.
44    #[serde(
45        rename = "guaranteedStopLossOrderParameters",
46        default,
47        skip_serializing_if = "Option::is_none"
48    )]
49    pub guaranteed_stop_loss_order_parameters: Option<GuaranteedStopLossOrderParameters>,
50    /// The current guaranteed Stop Loss Order mode of the Account.
51    #[serde(
52        rename = "guaranteedStopLossOrderMode",
53        default,
54        skip_serializing_if = "Option::is_none"
55    )]
56    pub guaranteed_stop_loss_order_mode: Option<GuaranteedStopLossOrderMode>,
57    /// The current guaranteed Stop Loss Order mutability setting of the Account. This field will only be
58    /// present if the guaranteedStopLossOrderMode is not ‘DISABLED’. Deprecated: Will be removed in a future
59    /// API update.
60    #[serde(
61        rename = "guaranteedStopLossOrderMutability",
62        default,
63        skip_serializing_if = "Option::is_none"
64    )]
65    pub guaranteed_stop_loss_order_mutability: Option<GuaranteedStopLossOrderMutability>,
66    /// The date/time that the Account’s resettablePL was last reset.
67    #[serde(
68        rename = "resettablePLTime",
69        default,
70        skip_serializing_if = "Option::is_none"
71    )]
72    pub resettable_pl_time: Option<Timestamp>,
73    /// Client-provided margin rate override for the Account. The effective margin rate of the Account is the
74    /// lesser of this value and the OANDA margin rate for the Account’s division. This value is only provided
75    /// if a margin rate override exists for the Account.
76    #[serde(
77        rename = "marginRate",
78        default,
79        skip_serializing_if = "Option::is_none"
80    )]
81    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
82    pub margin_rate: Option<Decimal>,
83    /// The number of Trades currently open in the Account.
84    #[serde(
85        rename = "openTradeCount",
86        default,
87        skip_serializing_if = "Option::is_none"
88    )]
89    pub open_trade_count: Option<i64>,
90    /// The number of Positions currently open in the Account.
91    #[serde(
92        rename = "openPositionCount",
93        default,
94        skip_serializing_if = "Option::is_none"
95    )]
96    pub open_position_count: Option<i64>,
97    /// The number of Orders currently pending in the Account.
98    #[serde(
99        rename = "pendingOrderCount",
100        default,
101        skip_serializing_if = "Option::is_none"
102    )]
103    pub pending_order_count: Option<i64>,
104    /// Flag indicating that the Account has hedging enabled.
105    #[serde(
106        rename = "hedgingEnabled",
107        default,
108        skip_serializing_if = "Option::is_none"
109    )]
110    pub hedging_enabled: Option<bool>,
111    /// The total unrealized profit/loss for all Trades currently open in the Account.
112    #[serde(
113        rename = "unrealizedPL",
114        default,
115        skip_serializing_if = "Option::is_none"
116    )]
117    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
118    pub unrealized_pl: Option<Decimal>,
119    /// The net asset value of the Account. Equal to Account balance + unrealizedPL.
120    #[serde(rename = "NAV", default, skip_serializing_if = "Option::is_none")]
121    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
122    pub nav: Option<Decimal>,
123    /// Margin currently used for the Account.
124    #[serde(
125        rename = "marginUsed",
126        default,
127        skip_serializing_if = "Option::is_none"
128    )]
129    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
130    pub margin_used: Option<Decimal>,
131    /// Margin available for Account currency.
132    #[serde(
133        rename = "marginAvailable",
134        default,
135        skip_serializing_if = "Option::is_none"
136    )]
137    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
138    pub margin_available: Option<Decimal>,
139    /// The value of the Account’s open positions represented in the Account’s home currency.
140    #[serde(
141        rename = "positionValue",
142        default,
143        skip_serializing_if = "Option::is_none"
144    )]
145    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
146    pub position_value: Option<Decimal>,
147    /// The Account’s margin closeout unrealized PL.
148    #[serde(
149        rename = "marginCloseoutUnrealizedPL",
150        default,
151        skip_serializing_if = "Option::is_none"
152    )]
153    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
154    pub margin_closeout_unrealized_pl: Option<Decimal>,
155    /// The Account’s margin closeout NAV.
156    #[serde(
157        rename = "marginCloseoutNAV",
158        default,
159        skip_serializing_if = "Option::is_none"
160    )]
161    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
162    pub margin_closeout_nav: Option<Decimal>,
163    /// The Account’s margin closeout margin used.
164    #[serde(
165        rename = "marginCloseoutMarginUsed",
166        default,
167        skip_serializing_if = "Option::is_none"
168    )]
169    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
170    pub margin_closeout_margin_used: Option<Decimal>,
171    /// The Account’s margin closeout percentage. When this value is 1.0 or above the Account is in a margin
172    /// closeout situation.
173    #[serde(
174        rename = "marginCloseoutPercent",
175        default,
176        skip_serializing_if = "Option::is_none"
177    )]
178    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
179    pub margin_closeout_percent: Option<Decimal>,
180    /// The value of the Account’s open positions as used for margin closeout calculations represented in the
181    /// Account’s home currency.
182    #[serde(
183        rename = "marginCloseoutPositionValue",
184        default,
185        skip_serializing_if = "Option::is_none"
186    )]
187    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
188    pub margin_closeout_position_value: Option<Decimal>,
189    /// The current WithdrawalLimit for the account which will be zero or a positive value indicating how much
190    /// can be withdrawn from the account.
191    #[serde(
192        rename = "withdrawalLimit",
193        default,
194        skip_serializing_if = "Option::is_none"
195    )]
196    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
197    pub withdrawal_limit: Option<Decimal>,
198    /// The Account’s margin call margin used.
199    #[serde(
200        rename = "marginCallMarginUsed",
201        default,
202        skip_serializing_if = "Option::is_none"
203    )]
204    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
205    pub margin_call_margin_used: Option<Decimal>,
206    /// The Account’s margin call percentage. When this value is 1.0 or above the Account is in a margin call
207    /// situation.
208    #[serde(
209        rename = "marginCallPercent",
210        default,
211        skip_serializing_if = "Option::is_none"
212    )]
213    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
214    pub margin_call_percent: Option<Decimal>,
215    /// The current balance of the account.
216    #[serde(rename = "balance", default, skip_serializing_if = "Option::is_none")]
217    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
218    pub balance: Option<Decimal>,
219    /// The total profit/loss realized over the lifetime of the Account.
220    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
221    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
222    pub pl: Option<Decimal>,
223    /// The total realized profit/loss for the account since it was last reset by the client.
224    #[serde(
225        rename = "resettablePL",
226        default,
227        skip_serializing_if = "Option::is_none"
228    )]
229    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
230    pub resettable_pl: Option<Decimal>,
231    /// The total amount of financing paid/collected over the lifetime of the account.
232    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
233    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
234    pub financing: Option<Decimal>,
235    /// The total amount of commission paid over the lifetime of the Account.
236    #[serde(
237        rename = "commission",
238        default,
239        skip_serializing_if = "Option::is_none"
240    )]
241    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
242    pub commission: Option<Decimal>,
243    /// The total amount of dividend adjustment paid over the lifetime of the Account in the Account’s home
244    /// currency.
245    #[serde(
246        rename = "dividendAdjustment",
247        default,
248        skip_serializing_if = "Option::is_none"
249    )]
250    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
251    pub dividend_adjustment: Option<Decimal>,
252    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
253    /// Loss Orders.
254    #[serde(
255        rename = "guaranteedExecutionFees",
256        default,
257        skip_serializing_if = "Option::is_none"
258    )]
259    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
260    pub guaranteed_execution_fees: Option<Decimal>,
261    /// The date/time when the Account entered a margin call state. Only provided if the Account is in a margin
262    /// call.
263    #[serde(
264        rename = "marginCallEnterTime",
265        default,
266        skip_serializing_if = "Option::is_none"
267    )]
268    pub margin_call_enter_time: Option<Timestamp>,
269    /// The number of times that the Account’s current margin call was extended.
270    #[serde(
271        rename = "marginCallExtensionCount",
272        default,
273        skip_serializing_if = "Option::is_none"
274    )]
275    pub margin_call_extension_count: Option<i64>,
276    /// The date/time of the Account’s last margin call extension.
277    #[serde(
278        rename = "lastMarginCallExtensionTime",
279        default,
280        skip_serializing_if = "Option::is_none"
281    )]
282    pub last_margin_call_extension_time: Option<Timestamp>,
283    /// The date/time of the last order that was filled for this account.
284    ///
285    /// Not on the website's definition page; documented by the pinned OpenAPI spec and read by
286    /// OANDA's own v20 clients. `None` when OANDA does not send it.
287    #[serde(
288        rename = "lastOrderFillTimestamp",
289        default,
290        skip_serializing_if = "Option::is_none"
291    )]
292    pub last_order_fill_timestamp: Option<Timestamp>,
293    /// The ID of the last Transaction created for the Account.
294    #[serde(
295        rename = "lastTransactionID",
296        default,
297        skip_serializing_if = "Option::is_none"
298    )]
299    pub last_transaction_id: Option<TransactionID>,
300    /// The details of the Trades currently open in the Account.
301    #[serde(rename = "trades", default, skip_serializing_if = "Option::is_none")]
302    pub trades: Option<Vec<TradeSummary>>,
303    /// The details all Account Positions.
304    #[serde(rename = "positions", default, skip_serializing_if = "Option::is_none")]
305    pub positions: Option<Vec<Position>>,
306    /// The details of the Orders currently pending in the Account.
307    #[serde(rename = "orders", default, skip_serializing_if = "Option::is_none")]
308    pub orders: Option<Vec<Order>>,
309}
310
311/// An AccountState Object is used to represent an Account’s current price-dependent state. Price-dependent
312/// Account state is dependent on OANDA’s current Prices, and includes things like unrealized PL, NAV and
313/// Trailing Stop Loss Order state. Fields will be omitted if their value has not changed since the
314/// specified transaction ID.
315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316#[serde(rename_all = "camelCase")]
317pub struct AccountChangesState {
318    /// The total unrealized profit/loss for all Trades currently open in the Account.
319    #[serde(
320        rename = "unrealizedPL",
321        default,
322        skip_serializing_if = "Option::is_none"
323    )]
324    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
325    pub unrealized_pl: Option<Decimal>,
326    /// The net asset value of the Account. Equal to Account balance + unrealizedPL.
327    #[serde(rename = "NAV", default, skip_serializing_if = "Option::is_none")]
328    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
329    pub nav: Option<Decimal>,
330    /// Margin currently used for the Account.
331    #[serde(
332        rename = "marginUsed",
333        default,
334        skip_serializing_if = "Option::is_none"
335    )]
336    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
337    pub margin_used: Option<Decimal>,
338    /// Margin available for Account currency.
339    #[serde(
340        rename = "marginAvailable",
341        default,
342        skip_serializing_if = "Option::is_none"
343    )]
344    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
345    pub margin_available: Option<Decimal>,
346    /// The value of the Account’s open positions represented in the Account’s home currency.
347    #[serde(
348        rename = "positionValue",
349        default,
350        skip_serializing_if = "Option::is_none"
351    )]
352    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
353    pub position_value: Option<Decimal>,
354    /// The Account’s margin closeout unrealized PL.
355    #[serde(
356        rename = "marginCloseoutUnrealizedPL",
357        default,
358        skip_serializing_if = "Option::is_none"
359    )]
360    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
361    pub margin_closeout_unrealized_pl: Option<Decimal>,
362    /// The Account’s margin closeout NAV.
363    #[serde(
364        rename = "marginCloseoutNAV",
365        default,
366        skip_serializing_if = "Option::is_none"
367    )]
368    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
369    pub margin_closeout_nav: Option<Decimal>,
370    /// The Account’s margin closeout margin used.
371    #[serde(
372        rename = "marginCloseoutMarginUsed",
373        default,
374        skip_serializing_if = "Option::is_none"
375    )]
376    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
377    pub margin_closeout_margin_used: Option<Decimal>,
378    /// The Account’s margin closeout percentage. When this value is 1.0 or above the Account is in a margin
379    /// closeout situation.
380    #[serde(
381        rename = "marginCloseoutPercent",
382        default,
383        skip_serializing_if = "Option::is_none"
384    )]
385    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
386    pub margin_closeout_percent: Option<Decimal>,
387    /// The value of the Account’s open positions as used for margin closeout calculations represented in the
388    /// Account’s home currency.
389    #[serde(
390        rename = "marginCloseoutPositionValue",
391        default,
392        skip_serializing_if = "Option::is_none"
393    )]
394    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
395    pub margin_closeout_position_value: Option<Decimal>,
396    /// The current WithdrawalLimit for the account which will be zero or a positive value indicating how much
397    /// can be withdrawn from the account.
398    #[serde(
399        rename = "withdrawalLimit",
400        default,
401        skip_serializing_if = "Option::is_none"
402    )]
403    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
404    pub withdrawal_limit: Option<Decimal>,
405    /// The Account’s margin call margin used.
406    #[serde(
407        rename = "marginCallMarginUsed",
408        default,
409        skip_serializing_if = "Option::is_none"
410    )]
411    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
412    pub margin_call_margin_used: Option<Decimal>,
413    /// The Account’s margin call percentage. When this value is 1.0 or above the Account is in a margin call
414    /// situation.
415    #[serde(
416        rename = "marginCallPercent",
417        default,
418        skip_serializing_if = "Option::is_none"
419    )]
420    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
421    pub margin_call_percent: Option<Decimal>,
422    /// The current balance of the account.
423    #[serde(rename = "balance", default, skip_serializing_if = "Option::is_none")]
424    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
425    pub balance: Option<Decimal>,
426    /// The total profit/loss realized over the lifetime of the Account.
427    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
428    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
429    pub pl: Option<Decimal>,
430    /// The total realized profit/loss for the account since it was last reset by the client.
431    #[serde(
432        rename = "resettablePL",
433        default,
434        skip_serializing_if = "Option::is_none"
435    )]
436    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
437    pub resettable_pl: Option<Decimal>,
438    /// The total amount of financing paid/collected over the lifetime of the account.
439    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
440    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
441    pub financing: Option<Decimal>,
442    /// The total amount of commission paid over the lifetime of the Account.
443    #[serde(
444        rename = "commission",
445        default,
446        skip_serializing_if = "Option::is_none"
447    )]
448    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
449    pub commission: Option<Decimal>,
450    /// The total amount of dividend adjustment paid over the lifetime of the Account in the Account’s home
451    /// currency.
452    #[serde(
453        rename = "dividendAdjustment",
454        default,
455        skip_serializing_if = "Option::is_none"
456    )]
457    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
458    pub dividend_adjustment: Option<Decimal>,
459    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
460    /// Loss Orders.
461    #[serde(
462        rename = "guaranteedExecutionFees",
463        default,
464        skip_serializing_if = "Option::is_none"
465    )]
466    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
467    pub guaranteed_execution_fees: Option<Decimal>,
468    /// The date/time when the Account entered a margin call state. Only provided if the Account is in a margin
469    /// call.
470    #[serde(
471        rename = "marginCallEnterTime",
472        default,
473        skip_serializing_if = "Option::is_none"
474    )]
475    pub margin_call_enter_time: Option<Timestamp>,
476    /// The number of times that the Account’s current margin call was extended.
477    #[serde(
478        rename = "marginCallExtensionCount",
479        default,
480        skip_serializing_if = "Option::is_none"
481    )]
482    pub margin_call_extension_count: Option<i64>,
483    /// The date/time of the Account’s last margin call extension.
484    #[serde(
485        rename = "lastMarginCallExtensionTime",
486        default,
487        skip_serializing_if = "Option::is_none"
488    )]
489    pub last_margin_call_extension_time: Option<Timestamp>,
490    /// The price-dependent state of each pending Order in the Account.
491    #[serde(rename = "orders", default, skip_serializing_if = "Option::is_none")]
492    pub orders: Option<Vec<DynamicOrderState>>,
493    /// The price-dependent state for each open Trade in the Account.
494    #[serde(rename = "trades", default, skip_serializing_if = "Option::is_none")]
495    pub trades: Option<Vec<CalculatedTradeState>>,
496    /// The price-dependent state for each open Position in the Account.
497    #[serde(rename = "positions", default, skip_serializing_if = "Option::is_none")]
498    pub positions: Option<Vec<CalculatedPositionState>>,
499}
500
501/// Properties related to an Account.
502#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
503#[serde(rename_all = "camelCase")]
504pub struct AccountProperties {
505    /// The Account’s identifier
506    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
507    pub id: Option<AccountID>,
508    /// The Account’s associated MT4 Account ID. This field will not be present if the Account is not an MT4
509    /// account.
510    #[serde(
511        rename = "mt4AccountID",
512        default,
513        skip_serializing_if = "Option::is_none"
514    )]
515    pub mt4_account_id: Option<i64>,
516    /// The Account’s tags
517    #[serde(rename = "tags", default, skip_serializing_if = "Option::is_none")]
518    pub tags: Option<Vec<String>>,
519}
520
521/// The current mutability and hedging settings related to guaranteed Stop Loss orders.
522#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
523#[serde(rename_all = "camelCase")]
524pub struct GuaranteedStopLossOrderParameters {
525    /// The current guaranteed Stop Loss Order mutability setting of the Account when market is open.
526    #[serde(
527        rename = "mutabilityMarketOpen",
528        default,
529        skip_serializing_if = "Option::is_none"
530    )]
531    pub mutability_market_open: Option<GuaranteedStopLossOrderMutability>,
532    /// The current guaranteed Stop Loss Order mutability setting of the Account when market is halted.
533    #[serde(
534        rename = "mutabilityMarketHalted",
535        default,
536        skip_serializing_if = "Option::is_none"
537    )]
538    pub mutability_market_halted: Option<GuaranteedStopLossOrderMutability>,
539}
540
541/// The overall behaviour of the Account regarding guaranteed Stop Loss Orders.
542#[derive(Debug, Clone, PartialEq, Eq, Hash)]
543#[non_exhaustive]
544pub enum GuaranteedStopLossOrderMode {
545    /// The Account is not permitted to create guaranteed Stop Loss Orders.
546    Disabled,
547    /// The Account is able, but not required to have guaranteed Stop Loss Orders for open Trades.
548    Allowed,
549    /// The Account is required to have guaranteed Stop Loss Orders for all open Trades.
550    Required,
551    /// An unrecognized provider value, preserved for forward compatibility.
552    Unknown(String),
553}
554
555impl GuaranteedStopLossOrderMode {
556    /// Return the exact provider spelling.
557    pub fn as_str(&self) -> &str {
558        match self {
559            Self::Disabled => "DISABLED",
560            Self::Allowed => "ALLOWED",
561            Self::Required => "REQUIRED",
562            Self::Unknown(value) => value,
563        }
564    }
565}
566
567impl Serialize for GuaranteedStopLossOrderMode {
568    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
569        serializer.serialize_str(self.as_str())
570    }
571}
572
573impl<'de> Deserialize<'de> for GuaranteedStopLossOrderMode {
574    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
575        let value = String::deserialize(deserializer)?;
576        Ok(match value.as_str() {
577            "DISABLED" => Self::Disabled,
578            "ALLOWED" => Self::Allowed,
579            "REQUIRED" => Self::Required,
580            _ => Self::Unknown(value),
581        })
582    }
583}
584
585/// For Accounts that support guaranteed Stop Loss Orders, describes the actions that can be performed on
586/// guaranteed Stop Loss Orders.
587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
588#[non_exhaustive]
589pub enum GuaranteedStopLossOrderMutability {
590    /// Once a guaranteed Stop Loss Order has been created it cannot be replaced or cancelled.
591    Fixed,
592    /// An existing guaranteed Stop Loss Order can only be replaced, not cancelled.
593    Replaceable,
594    /// Once a guaranteed Stop Loss Order has been created it can be either replaced or cancelled.
595    Cancelable,
596    /// An existing guaranteed Stop Loss Order can only be replaced to widen the gap from the current price, not
597    /// cancelled.
598    PriceWidenOnly,
599    /// An unrecognized provider value, preserved for forward compatibility.
600    Unknown(String),
601}
602
603impl GuaranteedStopLossOrderMutability {
604    /// Return the exact provider spelling.
605    pub fn as_str(&self) -> &str {
606        match self {
607            Self::Fixed => "FIXED",
608            Self::Replaceable => "REPLACEABLE",
609            Self::Cancelable => "CANCELABLE",
610            Self::PriceWidenOnly => "PRICE_WIDEN_ONLY",
611            Self::Unknown(value) => value,
612        }
613    }
614}
615
616impl Serialize for GuaranteedStopLossOrderMutability {
617    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
618        serializer.serialize_str(self.as_str())
619    }
620}
621
622impl<'de> Deserialize<'de> for GuaranteedStopLossOrderMutability {
623    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
624        let value = String::deserialize(deserializer)?;
625        Ok(match value.as_str() {
626            "FIXED" => Self::Fixed,
627            "REPLACEABLE" => Self::Replaceable,
628            "CANCELABLE" => Self::Cancelable,
629            "PRICE_WIDEN_ONLY" => Self::PriceWidenOnly,
630            _ => Self::Unknown(value),
631        })
632    }
633}
634
635/// A summary representation of a client’s Account. The AccountSummary does not provide a full specification
636/// of pending Orders, open Trades and Positions.
637#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
638#[serde(rename_all = "camelCase")]
639pub struct AccountSummary {
640    /// The Account’s identifier
641    #[serde(rename = "id", default, skip_serializing_if = "Option::is_none")]
642    pub id: Option<AccountID>,
643    /// Client-assigned alias for the Account. Only provided if the Account has an alias set
644    #[serde(rename = "alias", default, skip_serializing_if = "Option::is_none")]
645    pub alias: Option<String>,
646    /// The home currency of the Account
647    #[serde(rename = "currency", default, skip_serializing_if = "Option::is_none")]
648    pub currency: Option<Currency>,
649    /// ID of the user that created the Account.
650    #[serde(
651        rename = "createdByUserID",
652        default,
653        skip_serializing_if = "Option::is_none"
654    )]
655    pub created_by_user_id: Option<i64>,
656    /// The date/time when the Account was created.
657    #[serde(
658        rename = "createdTime",
659        default,
660        skip_serializing_if = "Option::is_none"
661    )]
662    pub created_time: Option<Timestamp>,
663    /// The current guaranteed Stop Loss Order settings of the Account. This field will only be present if the
664    /// guaranteedStopLossOrderMode is not ‘DISABLED’.
665    #[serde(
666        rename = "guaranteedStopLossOrderParameters",
667        default,
668        skip_serializing_if = "Option::is_none"
669    )]
670    pub guaranteed_stop_loss_order_parameters: Option<GuaranteedStopLossOrderParameters>,
671    /// The current guaranteed Stop Loss Order mode of the Account.
672    #[serde(
673        rename = "guaranteedStopLossOrderMode",
674        default,
675        skip_serializing_if = "Option::is_none"
676    )]
677    pub guaranteed_stop_loss_order_mode: Option<GuaranteedStopLossOrderMode>,
678    /// The current guaranteed Stop Loss Order mutability setting of the Account. This field will only be
679    /// present if the guaranteedStopLossOrderMode is not ‘DISABLED’. Deprecated: Will be removed in a future
680    /// API update.
681    #[serde(
682        rename = "guaranteedStopLossOrderMutability",
683        default,
684        skip_serializing_if = "Option::is_none"
685    )]
686    pub guaranteed_stop_loss_order_mutability: Option<GuaranteedStopLossOrderMutability>,
687    /// The date/time that the Account’s resettablePL was last reset.
688    #[serde(
689        rename = "resettablePLTime",
690        default,
691        skip_serializing_if = "Option::is_none"
692    )]
693    pub resettable_pl_time: Option<Timestamp>,
694    /// Client-provided margin rate override for the Account. The effective margin rate of the Account is the
695    /// lesser of this value and the OANDA margin rate for the Account’s division. This value is only provided
696    /// if a margin rate override exists for the Account.
697    #[serde(
698        rename = "marginRate",
699        default,
700        skip_serializing_if = "Option::is_none"
701    )]
702    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
703    pub margin_rate: Option<Decimal>,
704    /// The number of Trades currently open in the Account.
705    #[serde(
706        rename = "openTradeCount",
707        default,
708        skip_serializing_if = "Option::is_none"
709    )]
710    pub open_trade_count: Option<i64>,
711    /// The number of Positions currently open in the Account.
712    #[serde(
713        rename = "openPositionCount",
714        default,
715        skip_serializing_if = "Option::is_none"
716    )]
717    pub open_position_count: Option<i64>,
718    /// The number of Orders currently pending in the Account.
719    #[serde(
720        rename = "pendingOrderCount",
721        default,
722        skip_serializing_if = "Option::is_none"
723    )]
724    pub pending_order_count: Option<i64>,
725    /// Flag indicating that the Account has hedging enabled.
726    #[serde(
727        rename = "hedgingEnabled",
728        default,
729        skip_serializing_if = "Option::is_none"
730    )]
731    pub hedging_enabled: Option<bool>,
732    /// The total unrealized profit/loss for all Trades currently open in the Account.
733    #[serde(
734        rename = "unrealizedPL",
735        default,
736        skip_serializing_if = "Option::is_none"
737    )]
738    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
739    pub unrealized_pl: Option<Decimal>,
740    /// The net asset value of the Account. Equal to Account balance + unrealizedPL.
741    #[serde(rename = "NAV", default, skip_serializing_if = "Option::is_none")]
742    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
743    pub nav: Option<Decimal>,
744    /// Margin currently used for the Account.
745    #[serde(
746        rename = "marginUsed",
747        default,
748        skip_serializing_if = "Option::is_none"
749    )]
750    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
751    pub margin_used: Option<Decimal>,
752    /// Margin available for Account currency.
753    #[serde(
754        rename = "marginAvailable",
755        default,
756        skip_serializing_if = "Option::is_none"
757    )]
758    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
759    pub margin_available: Option<Decimal>,
760    /// The value of the Account’s open positions represented in the Account’s home currency.
761    #[serde(
762        rename = "positionValue",
763        default,
764        skip_serializing_if = "Option::is_none"
765    )]
766    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
767    pub position_value: Option<Decimal>,
768    /// The Account’s margin closeout unrealized PL.
769    #[serde(
770        rename = "marginCloseoutUnrealizedPL",
771        default,
772        skip_serializing_if = "Option::is_none"
773    )]
774    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
775    pub margin_closeout_unrealized_pl: Option<Decimal>,
776    /// The Account’s margin closeout NAV.
777    #[serde(
778        rename = "marginCloseoutNAV",
779        default,
780        skip_serializing_if = "Option::is_none"
781    )]
782    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
783    pub margin_closeout_nav: Option<Decimal>,
784    /// The Account’s margin closeout margin used.
785    #[serde(
786        rename = "marginCloseoutMarginUsed",
787        default,
788        skip_serializing_if = "Option::is_none"
789    )]
790    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
791    pub margin_closeout_margin_used: Option<Decimal>,
792    /// The Account’s margin closeout percentage. When this value is 1.0 or above the Account is in a margin
793    /// closeout situation.
794    #[serde(
795        rename = "marginCloseoutPercent",
796        default,
797        skip_serializing_if = "Option::is_none"
798    )]
799    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
800    pub margin_closeout_percent: Option<Decimal>,
801    /// The value of the Account’s open positions as used for margin closeout calculations represented in the
802    /// Account’s home currency.
803    #[serde(
804        rename = "marginCloseoutPositionValue",
805        default,
806        skip_serializing_if = "Option::is_none"
807    )]
808    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
809    pub margin_closeout_position_value: Option<Decimal>,
810    /// The current WithdrawalLimit for the account which will be zero or a positive value indicating how much
811    /// can be withdrawn from the account.
812    #[serde(
813        rename = "withdrawalLimit",
814        default,
815        skip_serializing_if = "Option::is_none"
816    )]
817    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
818    pub withdrawal_limit: Option<Decimal>,
819    /// The Account’s margin call margin used.
820    #[serde(
821        rename = "marginCallMarginUsed",
822        default,
823        skip_serializing_if = "Option::is_none"
824    )]
825    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
826    pub margin_call_margin_used: Option<Decimal>,
827    /// The Account’s margin call percentage. When this value is 1.0 or above the Account is in a margin call
828    /// situation.
829    #[serde(
830        rename = "marginCallPercent",
831        default,
832        skip_serializing_if = "Option::is_none"
833    )]
834    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
835    pub margin_call_percent: Option<Decimal>,
836    /// The current balance of the account.
837    #[serde(rename = "balance", default, skip_serializing_if = "Option::is_none")]
838    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
839    pub balance: Option<Decimal>,
840    /// The total profit/loss realized over the lifetime of the Account.
841    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
842    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
843    pub pl: Option<Decimal>,
844    /// The total realized profit/loss for the account since it was last reset by the client.
845    #[serde(
846        rename = "resettablePL",
847        default,
848        skip_serializing_if = "Option::is_none"
849    )]
850    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
851    pub resettable_pl: Option<Decimal>,
852    /// The total amount of financing paid/collected over the lifetime of the account.
853    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
854    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
855    pub financing: Option<Decimal>,
856    /// The total amount of commission paid over the lifetime of the Account.
857    #[serde(
858        rename = "commission",
859        default,
860        skip_serializing_if = "Option::is_none"
861    )]
862    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
863    pub commission: Option<Decimal>,
864    /// The total amount of dividend adjustment paid over the lifetime of the Account in the Account’s home
865    /// currency.
866    #[serde(
867        rename = "dividendAdjustment",
868        default,
869        skip_serializing_if = "Option::is_none"
870    )]
871    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
872    pub dividend_adjustment: Option<Decimal>,
873    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
874    /// Loss Orders.
875    #[serde(
876        rename = "guaranteedExecutionFees",
877        default,
878        skip_serializing_if = "Option::is_none"
879    )]
880    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
881    pub guaranteed_execution_fees: Option<Decimal>,
882    /// The date/time when the Account entered a margin call state. Only provided if the Account is in a margin
883    /// call.
884    #[serde(
885        rename = "marginCallEnterTime",
886        default,
887        skip_serializing_if = "Option::is_none"
888    )]
889    pub margin_call_enter_time: Option<Timestamp>,
890    /// The number of times that the Account’s current margin call was extended.
891    #[serde(
892        rename = "marginCallExtensionCount",
893        default,
894        skip_serializing_if = "Option::is_none"
895    )]
896    pub margin_call_extension_count: Option<i64>,
897    /// The date/time of the Account’s last margin call extension.
898    #[serde(
899        rename = "lastMarginCallExtensionTime",
900        default,
901        skip_serializing_if = "Option::is_none"
902    )]
903    pub last_margin_call_extension_time: Option<Timestamp>,
904    /// The date/time of the last order that was filled for this account.
905    ///
906    /// Not on the website's definition page; documented by the pinned OpenAPI spec and read by
907    /// OANDA's own v20 clients. `None` when OANDA does not send it.
908    #[serde(
909        rename = "lastOrderFillTimestamp",
910        default,
911        skip_serializing_if = "Option::is_none"
912    )]
913    pub last_order_fill_timestamp: Option<Timestamp>,
914    /// The ID of the last Transaction created for the Account.
915    #[serde(
916        rename = "lastTransactionID",
917        default,
918        skip_serializing_if = "Option::is_none"
919    )]
920    pub last_transaction_id: Option<TransactionID>,
921}
922
923/// The mutable state of a client’s Account.
924#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
925#[serde(rename_all = "camelCase")]
926pub struct AccumulatedAccountState {
927    /// The current balance of the account.
928    #[serde(rename = "balance", default, skip_serializing_if = "Option::is_none")]
929    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
930    pub balance: Option<Decimal>,
931    /// The total profit/loss realized over the lifetime of the Account.
932    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
933    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
934    pub pl: Option<Decimal>,
935    /// The total realized profit/loss for the account since it was last reset by the client.
936    #[serde(
937        rename = "resettablePL",
938        default,
939        skip_serializing_if = "Option::is_none"
940    )]
941    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
942    pub resettable_pl: Option<Decimal>,
943    /// The total amount of financing paid/collected over the lifetime of the account.
944    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
945    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
946    pub financing: Option<Decimal>,
947    /// The total amount of commission paid over the lifetime of the Account.
948    #[serde(
949        rename = "commission",
950        default,
951        skip_serializing_if = "Option::is_none"
952    )]
953    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
954    pub commission: Option<Decimal>,
955    /// The total amount of dividend adjustment paid over the lifetime of the Account in the Account’s home
956    /// currency.
957    #[serde(
958        rename = "dividendAdjustment",
959        default,
960        skip_serializing_if = "Option::is_none"
961    )]
962    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
963    pub dividend_adjustment: Option<Decimal>,
964    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
965    /// Loss Orders.
966    #[serde(
967        rename = "guaranteedExecutionFees",
968        default,
969        skip_serializing_if = "Option::is_none"
970    )]
971    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
972    pub guaranteed_execution_fees: Option<Decimal>,
973    /// The date/time when the Account entered a margin call state. Only provided if the Account is in a margin
974    /// call.
975    #[serde(
976        rename = "marginCallEnterTime",
977        default,
978        skip_serializing_if = "Option::is_none"
979    )]
980    pub margin_call_enter_time: Option<Timestamp>,
981    /// The number of times that the Account’s current margin call was extended.
982    #[serde(
983        rename = "marginCallExtensionCount",
984        default,
985        skip_serializing_if = "Option::is_none"
986    )]
987    pub margin_call_extension_count: Option<i64>,
988    /// The date/time of the Account’s last margin call extension.
989    #[serde(
990        rename = "lastMarginCallExtensionTime",
991        default,
992        skip_serializing_if = "Option::is_none"
993    )]
994    pub last_margin_call_extension_time: Option<Timestamp>,
995}
996
997/// The dynamically calculated state of a client’s Account.
998#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
999#[serde(rename_all = "camelCase")]
1000pub struct CalculatedAccountState {
1001    /// The total unrealized profit/loss for all Trades currently open in the Account.
1002    #[serde(
1003        rename = "unrealizedPL",
1004        default,
1005        skip_serializing_if = "Option::is_none"
1006    )]
1007    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1008    pub unrealized_pl: Option<Decimal>,
1009    /// The net asset value of the Account. Equal to Account balance + unrealizedPL.
1010    #[serde(rename = "NAV", default, skip_serializing_if = "Option::is_none")]
1011    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1012    pub nav: Option<Decimal>,
1013    /// Margin currently used for the Account.
1014    #[serde(
1015        rename = "marginUsed",
1016        default,
1017        skip_serializing_if = "Option::is_none"
1018    )]
1019    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1020    pub margin_used: Option<Decimal>,
1021    /// Margin available for Account currency.
1022    #[serde(
1023        rename = "marginAvailable",
1024        default,
1025        skip_serializing_if = "Option::is_none"
1026    )]
1027    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1028    pub margin_available: Option<Decimal>,
1029    /// The value of the Account’s open positions represented in the Account’s home currency.
1030    #[serde(
1031        rename = "positionValue",
1032        default,
1033        skip_serializing_if = "Option::is_none"
1034    )]
1035    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1036    pub position_value: Option<Decimal>,
1037    /// The Account’s margin closeout unrealized PL.
1038    #[serde(
1039        rename = "marginCloseoutUnrealizedPL",
1040        default,
1041        skip_serializing_if = "Option::is_none"
1042    )]
1043    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1044    pub margin_closeout_unrealized_pl: Option<Decimal>,
1045    /// The Account’s margin closeout NAV.
1046    #[serde(
1047        rename = "marginCloseoutNAV",
1048        default,
1049        skip_serializing_if = "Option::is_none"
1050    )]
1051    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1052    pub margin_closeout_nav: Option<Decimal>,
1053    /// The Account’s margin closeout margin used.
1054    #[serde(
1055        rename = "marginCloseoutMarginUsed",
1056        default,
1057        skip_serializing_if = "Option::is_none"
1058    )]
1059    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1060    pub margin_closeout_margin_used: Option<Decimal>,
1061    /// The Account’s margin closeout percentage. When this value is 1.0 or above the Account is in a margin
1062    /// closeout situation.
1063    #[serde(
1064        rename = "marginCloseoutPercent",
1065        default,
1066        skip_serializing_if = "Option::is_none"
1067    )]
1068    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1069    pub margin_closeout_percent: Option<Decimal>,
1070    /// The value of the Account’s open positions as used for margin closeout calculations represented in the
1071    /// Account’s home currency.
1072    #[serde(
1073        rename = "marginCloseoutPositionValue",
1074        default,
1075        skip_serializing_if = "Option::is_none"
1076    )]
1077    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1078    pub margin_closeout_position_value: Option<Decimal>,
1079    /// The current WithdrawalLimit for the account which will be zero or a positive value indicating how much
1080    /// can be withdrawn from the account.
1081    #[serde(
1082        rename = "withdrawalLimit",
1083        default,
1084        skip_serializing_if = "Option::is_none"
1085    )]
1086    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1087    pub withdrawal_limit: Option<Decimal>,
1088    /// The Account’s margin call margin used.
1089    #[serde(
1090        rename = "marginCallMarginUsed",
1091        default,
1092        skip_serializing_if = "Option::is_none"
1093    )]
1094    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1095    pub margin_call_margin_used: Option<Decimal>,
1096    /// The Account’s margin call percentage. When this value is 1.0 or above the Account is in a margin call
1097    /// situation.
1098    #[serde(
1099        rename = "marginCallPercent",
1100        default,
1101        skip_serializing_if = "Option::is_none"
1102    )]
1103    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
1104    pub margin_call_percent: Option<Decimal>,
1105}
1106
1107/// An AccountChanges Object is used to represent the changes to an Account’s Orders, Trades and Positions
1108/// since a specified Account TransactionID in the past.
1109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1110#[serde(rename_all = "camelCase")]
1111pub struct AccountChanges {
1112    /// The Orders created. These Orders may have been filled, cancelled or triggered in the same period.
1113    #[serde(
1114        rename = "ordersCreated",
1115        default,
1116        skip_serializing_if = "Option::is_none"
1117    )]
1118    pub orders_created: Option<Vec<Order>>,
1119    /// The Orders cancelled.
1120    #[serde(
1121        rename = "ordersCancelled",
1122        default,
1123        skip_serializing_if = "Option::is_none"
1124    )]
1125    pub orders_cancelled: Option<Vec<Order>>,
1126    /// The Orders filled.
1127    #[serde(
1128        rename = "ordersFilled",
1129        default,
1130        skip_serializing_if = "Option::is_none"
1131    )]
1132    pub orders_filled: Option<Vec<Order>>,
1133    /// The Orders triggered.
1134    #[serde(
1135        rename = "ordersTriggered",
1136        default,
1137        skip_serializing_if = "Option::is_none"
1138    )]
1139    pub orders_triggered: Option<Vec<Order>>,
1140    /// The Trades opened.
1141    #[serde(
1142        rename = "tradesOpened",
1143        default,
1144        skip_serializing_if = "Option::is_none"
1145    )]
1146    pub trades_opened: Option<Vec<TradeSummary>>,
1147    /// The Trades reduced.
1148    #[serde(
1149        rename = "tradesReduced",
1150        default,
1151        skip_serializing_if = "Option::is_none"
1152    )]
1153    pub trades_reduced: Option<Vec<TradeSummary>>,
1154    /// The Trades closed.
1155    #[serde(
1156        rename = "tradesClosed",
1157        default,
1158        skip_serializing_if = "Option::is_none"
1159    )]
1160    pub trades_closed: Option<Vec<TradeSummary>>,
1161    /// The Positions changed.
1162    #[serde(rename = "positions", default, skip_serializing_if = "Option::is_none")]
1163    pub positions: Option<Vec<Position>>,
1164    /// The Transactions that have been generated.
1165    #[serde(
1166        rename = "transactions",
1167        default,
1168        skip_serializing_if = "Option::is_none"
1169    )]
1170    pub transactions: Option<Vec<Transaction>>,
1171}
1172
1173/// The financing mode of an Account
1174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1175#[non_exhaustive]
1176pub enum AccountFinancingMode {
1177    /// No financing is paid/charged for open Trades in the Account
1178    NoFinancing,
1179    /// Second-by-second financing is paid/charged for open Trades in the Account, both daily and when the the
1180    /// Trade is closed
1181    SecondBySecond,
1182    /// A full day’s worth of financing is paid/charged for open Trades in the Account daily at 5pm New York time
1183    Daily,
1184    /// An unrecognized provider value, preserved for forward compatibility.
1185    Unknown(String),
1186}
1187
1188impl AccountFinancingMode {
1189    /// Return the exact provider spelling.
1190    pub fn as_str(&self) -> &str {
1191        match self {
1192            Self::NoFinancing => "NO_FINANCING",
1193            Self::SecondBySecond => "SECOND_BY_SECOND",
1194            Self::Daily => "DAILY",
1195            Self::Unknown(value) => value,
1196        }
1197    }
1198}
1199
1200impl Serialize for AccountFinancingMode {
1201    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1202        serializer.serialize_str(self.as_str())
1203    }
1204}
1205
1206impl<'de> Deserialize<'de> for AccountFinancingMode {
1207    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1208        let value = String::deserialize(deserializer)?;
1209        Ok(match value.as_str() {
1210            "NO_FINANCING" => Self::NoFinancing,
1211            "SECOND_BY_SECOND" => Self::SecondBySecond,
1212            "DAILY" => Self::Daily,
1213            _ => Self::Unknown(value),
1214        })
1215    }
1216}
1217
1218/// Contains the attributes of a user.
1219#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1220#[serde(rename_all = "camelCase")]
1221pub struct UserAttributes {
1222    /// The user’s OANDA-assigned user ID.
1223    #[serde(rename = "userID", default, skip_serializing_if = "Option::is_none")]
1224    pub user_id: Option<i64>,
1225    /// The user-provided username.
1226    #[serde(rename = "username", default, skip_serializing_if = "Option::is_none")]
1227    pub username: Option<String>,
1228    /// The user’s title.
1229    #[serde(rename = "title", default, skip_serializing_if = "Option::is_none")]
1230    pub title: Option<String>,
1231    /// The user’s name.
1232    #[serde(rename = "name", default, skip_serializing_if = "Option::is_none")]
1233    pub name: Option<String>,
1234    /// The user’s email address.
1235    #[serde(rename = "email", default, skip_serializing_if = "Option::is_none")]
1236    pub email: Option<String>,
1237    /// The OANDA division the user belongs to.
1238    #[serde(
1239        rename = "divisionAbbreviation",
1240        default,
1241        skip_serializing_if = "Option::is_none"
1242    )]
1243    pub division_abbreviation: Option<String>,
1244    /// The user’s preferred language.
1245    #[serde(
1246        rename = "languageAbbreviation",
1247        default,
1248        skip_serializing_if = "Option::is_none"
1249    )]
1250    pub language_abbreviation: Option<String>,
1251    /// The home currency of the Account.
1252    #[serde(
1253        rename = "homeCurrency",
1254        default,
1255        skip_serializing_if = "Option::is_none"
1256    )]
1257    pub home_currency: Option<Currency>,
1258}
1259
1260/// The way that position values for an Account are calculated and aggregated.
1261#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1262#[non_exhaustive]
1263pub enum PositionAggregationMode {
1264    /// The Position value or margin for each side (long and short) of the Position are computed independently
1265    /// and added together.
1266    AbsoluteSum,
1267    /// The Position value or margin for each side (long and short) of the Position are computed independently.
1268    /// The Position value or margin chosen is the maximal absolute value of the two.
1269    MaximalSide,
1270    /// The units for each side (long and short) of the Position are netted together and the resulting value
1271    /// (long or short) is used to compute the Position value or margin.
1272    NetSum,
1273    /// An unrecognized provider value, preserved for forward compatibility.
1274    Unknown(String),
1275}
1276
1277impl PositionAggregationMode {
1278    /// Return the exact provider spelling.
1279    pub fn as_str(&self) -> &str {
1280        match self {
1281            Self::AbsoluteSum => "ABSOLUTE_SUM",
1282            Self::MaximalSide => "MAXIMAL_SIDE",
1283            Self::NetSum => "NET_SUM",
1284            Self::Unknown(value) => value,
1285        }
1286    }
1287}
1288
1289impl Serialize for PositionAggregationMode {
1290    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1291        serializer.serialize_str(self.as_str())
1292    }
1293}
1294
1295impl<'de> Deserialize<'de> for PositionAggregationMode {
1296    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1297        let value = String::deserialize(deserializer)?;
1298        Ok(match value.as_str() {
1299            "ABSOLUTE_SUM" => Self::AbsoluteSum,
1300            "MAXIMAL_SIDE" => Self::MaximalSide,
1301            "NET_SUM" => Self::NetSum,
1302            _ => Self::Unknown(value),
1303        })
1304    }
1305}