Skip to main content

oanda_client/models/
pricing.rs

1//! OANDA v20 pricing definitions.
2use super::{PriceBucket, UnitsAvailable};
3use crate::ids::{Currency, InstrumentName};
4use crate::timestamp::Timestamp;
5use rust_decimal::Decimal;
6use serde::{Deserialize, Serialize};
7
8/// The specification of an Account-specific Price.
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct ClientPrice {
12    /// The string “PRICE”. Used to identify the a Price object when found in a stream.
13    /// This optional wire field preserves provider evidence. Stream consumers use
14    /// [`crate::PriceStreamEvent`] for typed event dispatch.
15    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
16    pub r#type: Option<String>,
17    /// The Price’s Instrument.
18    #[serde(
19        rename = "instrument",
20        default,
21        skip_serializing_if = "Option::is_none"
22    )]
23    pub instrument: Option<InstrumentName>,
24    /// The date/time when the Price was created
25    #[serde(rename = "time", default, skip_serializing_if = "Option::is_none")]
26    pub time: Option<Timestamp>,
27    /// The status of the Price. Deprecated: Will be removed in a future API update.
28    #[serde(rename = "status", default, skip_serializing_if = "Option::is_none")]
29    pub status: Option<PriceStatus>,
30    /// Flag indicating if the Price is tradeable or not
31    #[serde(rename = "tradeable", default, skip_serializing_if = "Option::is_none")]
32    pub tradeable: Option<bool>,
33    /// The list of prices and liquidity available on the Instrument’s bid side. It is possible for this list to
34    /// be empty if there is no bid liquidity currently available for the Instrument in the Account.
35    #[serde(rename = "bids", default, skip_serializing_if = "Option::is_none")]
36    pub bids: Option<Vec<PriceBucket>>,
37    /// The list of prices and liquidity available on the Instrument’s ask side. It is possible for this list to
38    /// be empty if there is no ask liquidity currently available for the Instrument in the Account.
39    #[serde(rename = "asks", default, skip_serializing_if = "Option::is_none")]
40    pub asks: Option<Vec<PriceBucket>>,
41    /// The closeout bid Price. This Price is used when a bid is required to closeout a Position (margin
42    /// closeout or manual) yet there is no bid liquidity. The closeout bid is never used to open a new position.
43    #[serde(
44        rename = "closeoutBid",
45        default,
46        skip_serializing_if = "Option::is_none"
47    )]
48    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
49    pub closeout_bid: Option<Decimal>,
50    /// The closeout ask Price. This Price is used when a ask is required to closeout a Position (margin
51    /// closeout or manual) yet there is no ask liquidity. The closeout ask is never used to open a new position.
52    #[serde(
53        rename = "closeoutAsk",
54        default,
55        skip_serializing_if = "Option::is_none"
56    )]
57    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
58    pub closeout_ask: Option<Decimal>,
59    /// The factors used to convert quantities of this price’s Instrument’s quote currency into a quantity of
60    /// the Account’s home currency. When the includeHomeConversions is present in the pricing request
61    /// (regardless of its value), this field will not be present. Deprecated: Will be removed in a future API
62    /// update.
63    #[serde(
64        rename = "quoteHomeConversionFactors",
65        default,
66        skip_serializing_if = "Option::is_none"
67    )]
68    pub quote_home_conversion_factors: Option<QuoteHomeConversionFactors>,
69    /// Representation of how many units of an Instrument are available to be traded by an Order depending on
70    /// its positionFill option. Deprecated: Will be removed in a future API update.
71    #[serde(
72        rename = "unitsAvailable",
73        default,
74        skip_serializing_if = "Option::is_none"
75    )]
76    pub units_available: Option<UnitsAvailable>,
77}
78
79provider_enum! {
80    /// The status of the Price.
81    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
82    #[non_exhaustive]
83    pub enum PriceStatus {
84        /// The Instrument’s price is tradeable.
85        Tradeable => "tradeable",
86        /// The Instrument’s price is not tradeable.
87        NonTradeable => "non-tradeable",
88        /// The Instrument of the price is invalid or there is no valid Price for the Instrument.
89        Invalid => "invalid",
90        ;
91        /// An unrecognized provider value, preserved for forward compatibility.
92        Unknown(String),
93    }
94}
95
96/// `QuoteHomeConversionFactors` represents the factors that can be used to convert quantities of a Price’s
97/// Instrument’s quote currency into the Account’s home currency.
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
99#[serde(rename_all = "camelCase")]
100pub struct QuoteHomeConversionFactors {
101    /// The factor used to convert a positive amount of the Price’s Instrument’s quote currency into a positive
102    /// amount of the Account’s home currency. Conversion is performed by multiplying the quote units by the
103    /// conversion factor.
104    #[serde(
105        rename = "positiveUnits",
106        default,
107        skip_serializing_if = "Option::is_none"
108    )]
109    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
110    pub positive_units: Option<Decimal>,
111    /// The factor used to convert a negative amount of the Price’s Instrument’s quote currency into a negative
112    /// amount of the Account’s home currency. Conversion is performed by multiplying the quote units by the
113    /// conversion factor.
114    #[serde(
115        rename = "negativeUnits",
116        default,
117        skip_serializing_if = "Option::is_none"
118    )]
119    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
120    pub negative_units: Option<Decimal>,
121}
122
123/// `HomeConversions` represents the factors to use to convert quantities of a given currency into the
124/// Account’s home currency. The conversion factor depends on the scenario the conversion is required for.
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126#[serde(rename_all = "camelCase")]
127pub struct HomeConversions {
128    /// The currency to be converted into the home currency.
129    #[serde(rename = "currency", default, skip_serializing_if = "Option::is_none")]
130    pub currency: Option<Currency>,
131    /// The factor used to convert any gains for an Account in the specified currency into the Account’s home
132    /// currency. This would include positive realized P/L and positive financing amounts. Conversion is
133    /// performed by multiplying the positive P/L by the conversion factor.
134    #[serde(
135        rename = "accountGain",
136        default,
137        skip_serializing_if = "Option::is_none"
138    )]
139    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
140    pub account_gain: Option<Decimal>,
141    /// The factor used to convert any losses for an Account in the specified currency into the Account’s home
142    /// currency. This would include negative realized P/L and negative financing amounts. Conversion is
143    /// performed by multiplying the positive P/L by the conversion factor.
144    #[serde(
145        rename = "accountLoss",
146        default,
147        skip_serializing_if = "Option::is_none"
148    )]
149    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
150    pub account_loss: Option<Decimal>,
151    /// The factor used to convert a Position or Trade Value in the specified currency into the Account’s home
152    /// currency. Conversion is performed by multiplying the Position or Trade Value by the conversion factor.
153    #[serde(
154        rename = "positionValue",
155        default,
156        skip_serializing_if = "Option::is_none"
157    )]
158    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
159    pub position_value: Option<Decimal>,
160}
161
162/// A `PricingHeartbeat` object is injected into the Pricing stream to ensure that the HTTP connection remains
163/// active.
164#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct PricingHeartbeat {
167    /// The string “HEARTBEAT”
168    /// This optional wire field preserves provider evidence; use
169    /// [`crate::PriceStreamEvent`] for typed stream dispatch.
170    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
171    pub r#type: Option<String>,
172    /// The date/time when the Heartbeat was created.
173    #[serde(rename = "time", default, skip_serializing_if = "Option::is_none")]
174    pub time: Option<Timestamp>,
175}