Skip to main content

oanda_client/models/
primitives.rs

1//! OANDA v20 primitives definitions.
2use crate::ids::InstrumentName;
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6/// A tag associated with an entity.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct Tag {
10    /// The type of the tag.
11    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
12    pub r#type: Option<String>,
13    /// The name of the tag.
14    #[serde(rename = "name", default, skip_serializing_if = "Option::is_none")]
15    pub name: Option<String>,
16}
17
18provider_enum! {
19    /// The type of an Instrument.
20    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
21    #[non_exhaustive]
22    pub enum InstrumentType {
23        /// Currency
24        Currency => "CURRENCY",
25        /// Contract For Difference
26        Cfd => "CFD",
27        /// Metal
28        Metal => "METAL",
29        ;
30        /// An unrecognized provider value, preserved for forward compatibility.
31        Unknown(String),
32    }
33}
34
35provider_enum! {
36    /// The `DayOfWeek` provides a representation of the day of the week.
37    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
38    #[non_exhaustive]
39    pub enum DayOfWeek {
40        /// Sunday
41        Sunday => "SUNDAY",
42        /// Monday
43        Monday => "MONDAY",
44        /// Tuesday
45        Tuesday => "TUESDAY",
46        /// Wednesday
47        Wednesday => "WEDNESDAY",
48        /// Thursday
49        Thursday => "THURSDAY",
50        /// Friday
51        Friday => "FRIDAY",
52        /// Saturday
53        Saturday => "SATURDAY",
54        ;
55        /// An unrecognized provider value, preserved for forward compatibility.
56        Unknown(String),
57    }
58}
59
60/// A `FinancingDayOfWeek` message defines a day of the week when financing charges are debited or credited.
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62#[serde(rename_all = "camelCase")]
63pub struct FinancingDayOfWeek {
64    /// The day of the week to charge the financing.
65    #[serde(rename = "dayOfWeek", default, skip_serializing_if = "Option::is_none")]
66    pub day_of_week: Option<DayOfWeek>,
67    /// The number of days worth of financing to be charged on dayOfWeek.
68    #[serde(
69        rename = "daysCharged",
70        default,
71        skip_serializing_if = "Option::is_none"
72    )]
73    pub days_charged: Option<i64>,
74}
75
76/// Financing data for the instrument.
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct InstrumentFinancing {
80    /// The financing rate to be used for a long position for the instrument. The value is in decimal rather
81    /// than percentage points, i.e. 5% is represented as 0.05.
82    #[serde(rename = "longRate", default, skip_serializing_if = "Option::is_none")]
83    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
84    pub long_rate: Option<Decimal>,
85    /// The financing rate to be used for a short position for the instrument. The value is in decimal rather
86    /// than percentage points, i.e. 5% is represented as 0.05.
87    #[serde(rename = "shortRate", default, skip_serializing_if = "Option::is_none")]
88    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
89    pub short_rate: Option<Decimal>,
90    /// The days of the week to debit or credit financing charges; the exact time of day at which to charge the
91    /// financing is set in the `DivisionTradingGroup` for the client’s account.
92    #[serde(
93        rename = "financingDaysOfWeek",
94        default,
95        skip_serializing_if = "Option::is_none"
96    )]
97    pub financing_days_of_week: Option<Vec<FinancingDayOfWeek>>,
98}
99
100/// Full specification of an Instrument.
101#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct Instrument {
104    /// The name of the Instrument
105    #[serde(rename = "name", default, skip_serializing_if = "Option::is_none")]
106    pub name: Option<InstrumentName>,
107    /// The type of the Instrument
108    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
109    pub r#type: Option<InstrumentType>,
110    /// The display name of the Instrument
111    #[serde(
112        rename = "displayName",
113        default,
114        skip_serializing_if = "Option::is_none"
115    )]
116    pub display_name: Option<String>,
117    /// The location of the “pip” for this instrument. The decimal position of the pip in this Instrument’s
118    /// price can be found at 10 ^ pipLocation (e.g. -4 pipLocation results in a decimal pip position of 10 ^ -4
119    /// = 0.0001).
120    #[serde(
121        rename = "pipLocation",
122        default,
123        skip_serializing_if = "Option::is_none"
124    )]
125    pub pip_location: Option<i64>,
126    /// The number of decimal places that should be used to display prices for this instrument. (e.g. a
127    /// displayPrecision of 5 would result in a price of “1” being displayed as “1.00000”)
128    #[serde(
129        rename = "displayPrecision",
130        default,
131        skip_serializing_if = "Option::is_none"
132    )]
133    pub display_precision: Option<i64>,
134    /// The amount of decimal places that may be provided when specifying the number of units traded for this
135    /// instrument.
136    #[serde(
137        rename = "tradeUnitsPrecision",
138        default,
139        skip_serializing_if = "Option::is_none"
140    )]
141    pub trade_units_precision: Option<i64>,
142    /// The smallest number of units allowed to be traded for this instrument.
143    #[serde(
144        rename = "minimumTradeSize",
145        default,
146        skip_serializing_if = "Option::is_none"
147    )]
148    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
149    pub minimum_trade_size: Option<Decimal>,
150    /// The maximum trailing stop distance allowed for a trailing stop loss created for this instrument.
151    /// Specified in price units.
152    #[serde(
153        rename = "maximumTrailingStopDistance",
154        default,
155        skip_serializing_if = "Option::is_none"
156    )]
157    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
158    pub maximum_trailing_stop_distance: Option<Decimal>,
159    /// The minimum distance allowed between the Trade’s fill price and the configured price for guaranteed Stop
160    /// Loss Orders created for this instrument. Specified in price units.
161    #[serde(
162        rename = "minimumGuaranteedStopLossDistance",
163        default,
164        skip_serializing_if = "Option::is_none"
165    )]
166    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
167    pub minimum_guaranteed_stop_loss_distance: Option<Decimal>,
168    /// The minimum trailing stop distance allowed for a trailing stop loss created for this instrument.
169    /// Specified in price units.
170    #[serde(
171        rename = "minimumTrailingStopDistance",
172        default,
173        skip_serializing_if = "Option::is_none"
174    )]
175    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
176    pub minimum_trailing_stop_distance: Option<Decimal>,
177    /// The maximum position size allowed for this instrument. Specified in units.
178    #[serde(
179        rename = "maximumPositionSize",
180        default,
181        skip_serializing_if = "Option::is_none"
182    )]
183    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
184    pub maximum_position_size: Option<Decimal>,
185    /// The maximum units allowed for an Order placed for this instrument. Specified in units.
186    #[serde(
187        rename = "maximumOrderUnits",
188        default,
189        skip_serializing_if = "Option::is_none"
190    )]
191    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
192    pub maximum_order_units: Option<Decimal>,
193    /// The margin rate for this instrument.
194    #[serde(
195        rename = "marginRate",
196        default,
197        skip_serializing_if = "Option::is_none"
198    )]
199    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
200    pub margin_rate: Option<Decimal>,
201    /// The commission structure for this instrument.
202    #[serde(
203        rename = "commission",
204        default,
205        skip_serializing_if = "Option::is_none"
206    )]
207    pub commission: Option<InstrumentCommission>,
208    /// The current Guaranteed Stop Loss Order mode of the Account for this Instrument.
209    #[serde(
210        rename = "guaranteedStopLossOrderMode",
211        default,
212        skip_serializing_if = "Option::is_none"
213    )]
214    pub guaranteed_stop_loss_order_mode: Option<GuaranteedStopLossOrderModeForInstrument>,
215    /// The amount that is charged to the account if a guaranteed Stop Loss Order is triggered and filled. The
216    /// value is in price units and is charged for each unit of the Trade. This field will only be present if
217    /// the Account’s guaranteedStopLossOrderMode for this Instrument is not ‘DISABLED’.
218    #[serde(
219        rename = "guaranteedStopLossOrderExecutionPremium",
220        default,
221        skip_serializing_if = "Option::is_none"
222    )]
223    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
224    pub guaranteed_stop_loss_order_execution_premium: Option<Decimal>,
225    /// The guaranteed Stop Loss Order level restriction for this instrument. This field will only be present if
226    /// the Account’s guaranteedStopLossOrderMode for this Instrument is not ‘DISABLED’.
227    #[serde(
228        rename = "guaranteedStopLossOrderLevelRestriction",
229        default,
230        skip_serializing_if = "Option::is_none"
231    )]
232    pub guaranteed_stop_loss_order_level_restriction:
233        Option<GuaranteedStopLossOrderLevelRestriction>,
234    /// Financing data for this instrument.
235    #[serde(rename = "financing", default, skip_serializing_if = "Option::is_none")]
236    pub financing: Option<InstrumentFinancing>,
237    /// The tags associated with this instrument.
238    #[serde(rename = "tags", default, skip_serializing_if = "Option::is_none")]
239    pub tags: Option<Vec<Tag>>,
240}
241
242provider_enum! {
243    /// Unrecognized spellings are retained and serialized unchanged for provider
244    /// compatibility; endpoint admission applies any operation-specific restrictions.
245    /// `DateTime` header
246    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
247    #[non_exhaustive]
248    pub enum AcceptDatetimeFormat {
249        /// If “UNIX” is specified `DateTime` fields will be specified or returned in the “12345678.000000123” format.
250        Unix => "UNIX",
251        /// If “RFC3339” is specified `DateTime` will be specified or returned in “YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ”
252        /// format.
253        Rfc3339 => "RFC3339",
254        ;
255        /// An unrecognized provider value, preserved for forward compatibility.
256        Unknown(String),
257    }
258}
259
260/// An `InstrumentCommission` represents an instrument-specific commission
261#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
262#[serde(rename_all = "camelCase")]
263pub struct InstrumentCommission {
264    /// The commission amount (in the Account’s home currency) charged per unitsTraded of the instrument
265    #[serde(
266        rename = "commission",
267        default,
268        skip_serializing_if = "Option::is_none"
269    )]
270    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
271    pub commission: Option<Decimal>,
272    /// The number of units traded that the commission amount is based on.
273    #[serde(
274        rename = "unitsTraded",
275        default,
276        skip_serializing_if = "Option::is_none"
277    )]
278    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
279    pub units_traded: Option<Decimal>,
280    /// The minimum commission amount (in the Account’s home currency) that is charged when an Order is filled
281    /// for this instrument.
282    #[serde(
283        rename = "minimumCommission",
284        default,
285        skip_serializing_if = "Option::is_none"
286    )]
287    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
288    pub minimum_commission: Option<Decimal>,
289}
290
291provider_enum! {
292    /// The overall behaviour of the Account regarding Guaranteed Stop Loss Orders for a specific Instrument.
293    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
294    #[non_exhaustive]
295    pub enum GuaranteedStopLossOrderModeForInstrument {
296        /// The Account is not permitted to create Guaranteed Stop Loss Orders for this Instrument.
297        Disabled => "DISABLED",
298        /// The Account is able, but not required to have Guaranteed Stop Loss Orders for open Trades for this
299        /// Instrument.
300        Allowed => "ALLOWED",
301        /// The Account is required to have Guaranteed Stop Loss Orders for all open Trades for this Instrument.
302        Required => "REQUIRED",
303        ;
304        /// An unrecognized provider value, preserved for forward compatibility.
305        Unknown(String),
306    }
307}
308
309/// A `GuaranteedStopLossOrderLevelRestriction` represents the total position size that can exist within a
310/// given price window for Trades with guaranteed Stop Loss Orders attached for a specific Instrument.
311#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
312#[serde(rename_all = "camelCase")]
313pub struct GuaranteedStopLossOrderLevelRestriction {
314    /// Applies to Trades with a guaranteed Stop Loss Order attached for the specified Instrument. This is the
315    /// total allowed Trade volume that can exist within the priceRange based on the trigger prices of the
316    /// guaranteed Stop Loss Orders.
317    #[serde(rename = "volume", default, skip_serializing_if = "Option::is_none")]
318    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
319    pub volume: Option<Decimal>,
320    /// The price range the volume applies to. This value is in price units.
321    #[serde(
322        rename = "priceRange",
323        default,
324        skip_serializing_if = "Option::is_none"
325    )]
326    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
327    pub price_range: Option<Decimal>,
328}
329
330provider_enum! {
331    /// In the context of an Order or a Trade, defines whether the units are positive or negative.
332    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
333    #[non_exhaustive]
334    pub enum Direction {
335        /// A long Order is used to to buy units of an Instrument. A Trade is long when it has bought units of an
336        /// Instrument.
337        Long => "LONG",
338        /// A short Order is used to to sell units of an Instrument. A Trade is short when it has sold units of an
339        /// Instrument.
340        Short => "SHORT",
341        ;
342        /// An unrecognized provider value, preserved for forward compatibility.
343        Unknown(String),
344    }
345}
346
347/// A `ConversionFactor` contains information used to convert an amount, from an Instrument’s base or quote
348/// currency, to the home currency of an Account.
349#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
350#[serde(rename_all = "camelCase")]
351pub struct ConversionFactor {
352    /// The factor by which to multiply the amount in the given currency to obtain the amount in the home
353    /// currency of the Account.
354    #[serde(rename = "factor", default, skip_serializing_if = "Option::is_none")]
355    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
356    pub factor: Option<Decimal>,
357}
358
359/// A `HomeConversionFactors` message contains information used to convert amounts, from an Instrument’s base
360/// or quote currency, to the home currency of an Account.
361#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
362#[serde(rename_all = "camelCase")]
363pub struct HomeConversionFactors {
364    /// The `ConversionFactor` in effect for the Account for converting any gains realized in Instrument quote
365    /// units into units of the Account’s home currency.
366    #[serde(
367        rename = "gainQuoteHome",
368        default,
369        skip_serializing_if = "Option::is_none"
370    )]
371    pub gain_quote_home: Option<ConversionFactor>,
372    /// The `ConversionFactor` in effect for the Account for converting any losses realized in Instrument quote
373    /// units into units of the Account’s home currency.
374    #[serde(
375        rename = "lossQuoteHome",
376        default,
377        skip_serializing_if = "Option::is_none"
378    )]
379    pub loss_quote_home: Option<ConversionFactor>,
380    /// The `ConversionFactor` in effect for the Account for converting any gains realized in Instrument base
381    /// units into units of the Account’s home currency.
382    #[serde(
383        rename = "gainBaseHome",
384        default,
385        skip_serializing_if = "Option::is_none"
386    )]
387    pub gain_base_home: Option<ConversionFactor>,
388    /// The `ConversionFactor` in effect for the Account for converting any losses realized in Instrument base
389    /// units into units of the Account’s home currency.
390    #[serde(
391        rename = "lossBaseHome",
392        default,
393        skip_serializing_if = "Option::is_none"
394    )]
395    pub loss_base_home: Option<ConversionFactor>,
396}