Skip to main content

oanda_client/models/
position.rs

1//! OANDA v20 position definitions.
2use crate::ids::{InstrumentName, TradeID};
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6/// The specification of a Position within an Account.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct Position {
10    /// The Position’s Instrument.
11    #[serde(
12        rename = "instrument",
13        default,
14        skip_serializing_if = "Option::is_none"
15    )]
16    pub instrument: Option<InstrumentName>,
17    /// Profit/loss realized by the Position over the lifetime of the Account.
18    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
19    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
20    pub pl: Option<Decimal>,
21    /// The unrealized profit/loss of all open Trades that contribute to this Position.
22    #[serde(
23        rename = "unrealizedPL",
24        default,
25        skip_serializing_if = "Option::is_none"
26    )]
27    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
28    pub unrealized_pl: Option<Decimal>,
29    /// Margin currently used by the Position.
30    #[serde(
31        rename = "marginUsed",
32        default,
33        skip_serializing_if = "Option::is_none"
34    )]
35    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
36    pub margin_used: Option<Decimal>,
37    /// Profit/loss realized by the Position since the Account’s resettablePL was last reset by the client.
38    #[serde(
39        rename = "resettablePL",
40        default,
41        skip_serializing_if = "Option::is_none"
42    )]
43    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
44    pub resettable_pl: Option<Decimal>,
45    /// The total amount of financing paid/collected for this instrument over the lifetime of the Account.
46    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
47    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
48    pub financing: Option<Decimal>,
49    /// The total amount of commission paid for this instrument over the lifetime of the Account.
50    #[serde(
51        rename = "commission",
52        default,
53        skip_serializing_if = "Option::is_none"
54    )]
55    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
56    pub commission: Option<Decimal>,
57    /// The total amount of dividend adjustment paid for this instrument over the lifetime of the Account.
58    #[serde(
59        rename = "dividendAdjustment",
60        default,
61        skip_serializing_if = "Option::is_none"
62    )]
63    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
64    pub dividend_adjustment: Option<Decimal>,
65    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
66    /// Loss Orders for this instrument.
67    #[serde(
68        rename = "guaranteedExecutionFees",
69        default,
70        skip_serializing_if = "Option::is_none"
71    )]
72    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
73    pub guaranteed_execution_fees: Option<Decimal>,
74    /// The details of the long side of the Position.
75    #[serde(rename = "long", default, skip_serializing_if = "Option::is_none")]
76    pub long: Option<PositionSide>,
77    /// The details of the short side of the Position.
78    #[serde(rename = "short", default, skip_serializing_if = "Option::is_none")]
79    pub short: Option<PositionSide>,
80}
81
82/// The representation of a Position for a single direction (long or short).
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct PositionSide {
86    /// Number of units in the position (negative value indicates short position, positive indicates long
87    /// position).
88    #[serde(rename = "units", default, skip_serializing_if = "Option::is_none")]
89    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
90    pub units: Option<Decimal>,
91    /// Volume-weighted average of the underlying Trade open prices for the Position.
92    #[serde(
93        rename = "averagePrice",
94        default,
95        skip_serializing_if = "Option::is_none"
96    )]
97    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
98    pub average_price: Option<Decimal>,
99    /// List of the open Trade IDs which contribute to the open Position.
100    #[serde(rename = "tradeIDs", default, skip_serializing_if = "Option::is_none")]
101    pub trade_ids: Option<Vec<TradeID>>,
102    /// Profit/loss realized by the `PositionSide` over the lifetime of the Account.
103    #[serde(rename = "pl", default, skip_serializing_if = "Option::is_none")]
104    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
105    pub pl: Option<Decimal>,
106    /// The unrealized profit/loss of all open Trades that contribute to this `PositionSide`.
107    #[serde(
108        rename = "unrealizedPL",
109        default,
110        skip_serializing_if = "Option::is_none"
111    )]
112    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
113    pub unrealized_pl: Option<Decimal>,
114    /// Profit/loss realized by the `PositionSide` since the Account’s resettablePL was last reset by the client.
115    #[serde(
116        rename = "resettablePL",
117        default,
118        skip_serializing_if = "Option::is_none"
119    )]
120    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
121    pub resettable_pl: Option<Decimal>,
122    /// The total amount of financing paid/collected for this `PositionSide` over the lifetime of the Account.
123    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
124    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
125    pub financing: Option<Decimal>,
126    /// The total amount of dividend adjustment paid for the `PositionSide` over the lifetime of the Account.
127    #[serde(
128        rename = "dividendAdjustment",
129        default,
130        skip_serializing_if = "Option::is_none"
131    )]
132    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
133    pub dividend_adjustment: Option<Decimal>,
134    /// The total amount of fees charged over the lifetime of the Account for the execution of guaranteed Stop
135    /// Loss Orders attached to Trades for this `PositionSide`.
136    #[serde(
137        rename = "guaranteedExecutionFees",
138        default,
139        skip_serializing_if = "Option::is_none"
140    )]
141    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
142    pub guaranteed_execution_fees: Option<Decimal>,
143}
144
145/// The dynamic (calculated) state of a Position
146#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
147#[serde(rename_all = "camelCase")]
148pub struct CalculatedPositionState {
149    /// The Position’s Instrument.
150    #[serde(
151        rename = "instrument",
152        default,
153        skip_serializing_if = "Option::is_none"
154    )]
155    pub instrument: Option<InstrumentName>,
156    /// The Position’s net unrealized profit/loss
157    #[serde(
158        rename = "netUnrealizedPL",
159        default,
160        skip_serializing_if = "Option::is_none"
161    )]
162    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
163    pub net_unrealized_pl: Option<Decimal>,
164    /// The unrealized profit/loss of the Position’s long open Trades
165    #[serde(
166        rename = "longUnrealizedPL",
167        default,
168        skip_serializing_if = "Option::is_none"
169    )]
170    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
171    pub long_unrealized_pl: Option<Decimal>,
172    /// The unrealized profit/loss of the Position’s short open Trades
173    #[serde(
174        rename = "shortUnrealizedPL",
175        default,
176        skip_serializing_if = "Option::is_none"
177    )]
178    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
179    pub short_unrealized_pl: Option<Decimal>,
180    /// Margin currently used by the Position.
181    #[serde(
182        rename = "marginUsed",
183        default,
184        skip_serializing_if = "Option::is_none"
185    )]
186    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
187    pub margin_used: Option<Decimal>,
188}