Skip to main content

oanda_client/models/
pricing.rs

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