ig_client/application/models/
market.rs1pub(crate) use crate::presentation::InstrumentType;
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4
5#[derive(Debug, Clone, Deserialize, PartialEq)]
7pub struct Instrument {
8 pub epic: String,
10 pub name: String,
12 pub expiry: String,
14 #[serde(rename = "contractSize")]
16 pub contract_size: String,
17 #[serde(rename = "lotSize")]
19 pub lot_size: Option<f64>,
20 #[serde(rename = "highLimitPrice")]
22 pub high_limit_price: Option<f64>,
23 #[serde(rename = "lowLimitPrice")]
25 pub low_limit_price: Option<f64>,
26 #[serde(rename = "marginFactor")]
28 pub margin_factor: Option<f64>,
29 #[serde(rename = "marginFactorUnit")]
31 pub margin_factor_unit: Option<String>,
32 pub currencies: Option<Vec<Currency>>,
34 #[serde(rename = "valueOfOnePip")]
35 pub value_of_one_pip: String,
37 #[serde(rename = "instrumentType")]
39 pub instrument_type: Option<InstrumentType>,
40 #[serde(rename = "expiryDetails")]
42 pub expiry_details: Option<ExpiryDetails>,
43 #[serde(rename = "slippageFactor")]
44 pub slippage_factor: Option<StepDistance>,
46 #[serde(rename = "limitedRiskPremium")]
47 pub limited_risk_premium: Option<StepDistance>,
49 #[serde(rename = "newsCode")]
50 pub news_code: Option<String>,
52 #[serde(rename = "chartCode")]
53 pub chart_code: Option<String>,
55}
56
57#[derive(Debug, Clone, Deserialize, PartialEq)]
59pub struct Currency {
60 pub code: String,
62 pub symbol: Option<String>,
64 #[serde(rename = "baseExchangeRate")]
66 pub base_exchange_rate: Option<f64>,
67 #[serde(rename = "exchangeRate")]
69 pub exchange_rate: Option<f64>,
70 #[serde(rename = "isDefault")]
72 pub is_default: Option<bool>,
73}
74
75#[derive(Debug, Clone, Deserialize)]
77pub struct MarketDetails {
78 pub instrument: Instrument,
80 pub snapshot: MarketSnapshot,
82 #[serde(rename = "dealingRules")]
84 pub dealing_rules: DealingRules,
85}
86
87#[derive(Debug, Clone, Deserialize)]
89pub struct DealingRules {
90 #[serde(rename = "minStepDistance")]
92 pub min_step_distance: StepDistance,
93
94 #[serde(rename = "minDealSize")]
96 pub min_deal_size: StepDistance,
97
98 #[serde(rename = "minControlledRiskStopDistance")]
100 pub min_controlled_risk_stop_distance: StepDistance,
101
102 #[serde(rename = "minNormalStopOrLimitDistance")]
104 pub min_normal_stop_or_limit_distance: StepDistance,
105
106 #[serde(rename = "maxStopOrLimitDistance")]
108 pub max_stop_or_limit_distance: StepDistance,
109
110 #[serde(rename = "controlledRiskSpacing")]
112 pub controlled_risk_spacing: StepDistance,
113
114 #[serde(rename = "marketOrderPreference")]
116 pub market_order_preference: String,
117
118 #[serde(rename = "trailingStopsPreference")]
120 pub trailing_stops_preference: String,
121
122 #[serde(rename = "maxDealSize")]
123 pub max_deal_size: Option<f64>,
125}
126
127#[derive(Debug, Clone, Deserialize)]
129pub struct MarketSnapshot {
130 #[serde(rename = "marketStatus")]
132 pub market_status: String,
133
134 #[serde(rename = "netChange")]
136 pub net_change: Option<f64>,
137
138 #[serde(rename = "percentageChange")]
140 pub percentage_change: Option<f64>,
141
142 #[serde(rename = "updateTime")]
144 pub update_time: Option<String>,
145
146 #[serde(rename = "delayTime")]
148 pub delay_time: Option<i64>,
149
150 pub bid: Option<f64>,
152
153 pub offer: Option<f64>,
155
156 pub high: Option<f64>,
158
159 pub low: Option<f64>,
161
162 #[serde(rename = "binaryOdds")]
164 pub binary_odds: Option<f64>,
165
166 #[serde(rename = "decimalPlacesFactor")]
168 pub decimal_places_factor: Option<i64>,
169
170 #[serde(rename = "scalingFactor")]
172 pub scaling_factor: Option<i64>,
173
174 #[serde(rename = "controlledRiskExtraSpread")]
176 pub controlled_risk_extra_spread: Option<f64>,
177}
178
179#[derive(Debug, Clone, Deserialize)]
181pub struct MarketSearchResult {
182 pub markets: Vec<MarketData>,
184}
185
186#[derive(Debug, Clone, Deserialize, Serialize)]
188pub struct MarketData {
189 pub epic: String,
191 #[serde(rename = "instrumentName")]
193 pub instrument_name: String,
194 #[serde(rename = "instrumentType")]
196 pub instrument_type: InstrumentType,
197 pub expiry: String,
199 #[serde(rename = "highLimitPrice")]
201 pub high_limit_price: Option<f64>,
202 #[serde(rename = "lowLimitPrice")]
204 pub low_limit_price: Option<f64>,
205 #[serde(rename = "marketStatus")]
207 pub market_status: String,
208 #[serde(rename = "netChange")]
210 pub net_change: Option<f64>,
211 #[serde(rename = "percentageChange")]
213 pub percentage_change: Option<f64>,
214 #[serde(rename = "updateTime")]
216 pub update_time: Option<String>,
217 #[serde(rename = "updateTimeUTC")]
219 pub update_time_utc: Option<String>,
220 pub bid: Option<f64>,
222 pub offer: Option<f64>,
224}
225
226impl Display for MarketData {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 let json = serde_json::to_string(self).unwrap_or_else(|_| "Invalid JSON".to_string());
229 write!(f, "{json}")
230 }
231}
232
233#[derive(Debug, Clone, Deserialize)]
235pub struct HistoricalPricesResponse {
236 pub prices: Vec<HistoricalPrice>,
238 #[serde(rename = "instrumentType")]
240 pub instrument_type: InstrumentType,
241 #[serde(rename = "allowance", skip_serializing_if = "Option::is_none", default)]
243 pub allowance: Option<PriceAllowance>,
244}
245
246#[derive(Debug, Clone, Deserialize)]
248pub struct HistoricalPrice {
249 #[serde(rename = "snapshotTime")]
251 pub snapshot_time: String,
252 #[serde(rename = "openPrice")]
254 pub open_price: PricePoint,
255 #[serde(rename = "highPrice")]
257 pub high_price: PricePoint,
258 #[serde(rename = "lowPrice")]
260 pub low_price: PricePoint,
261 #[serde(rename = "closePrice")]
263 pub close_price: PricePoint,
264 #[serde(rename = "lastTradedVolume")]
266 pub last_traded_volume: Option<i64>,
267}
268
269#[derive(Debug, Clone, Deserialize)]
271pub struct PricePoint {
272 pub bid: Option<f64>,
274 pub ask: Option<f64>,
276 #[serde(rename = "lastTraded")]
278 pub last_traded: Option<f64>,
279}
280
281#[derive(Debug, Clone, Deserialize)]
283pub struct PriceAllowance {
284 #[serde(rename = "remainingAllowance")]
286 pub remaining_allowance: i64,
287 #[serde(rename = "totalAllowance")]
289 pub total_allowance: i64,
290 #[serde(rename = "allowanceExpiry")]
292 pub allowance_expiry: i64,
293}
294
295#[derive(Debug, Clone, Deserialize, Serialize)]
297pub struct MarketNavigationResponse {
298 #[serde(default, deserialize_with = "deserialize_null_as_empty_vec")]
300 pub nodes: Vec<MarketNavigationNode>,
301 #[serde(default, deserialize_with = "deserialize_null_as_empty_vec")]
303 pub markets: Vec<MarketData>,
304}
305
306#[derive(Debug, Clone, Deserialize, PartialEq)]
308pub struct ExpiryDetails {
309 #[serde(rename = "lastDealingDate")]
311 pub last_dealing_date: String,
312
313 #[serde(rename = "settlementInfo")]
315 pub settlement_info: Option<String>,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
319pub enum StepUnit {
321 #[serde(rename = "POINTS")]
322 Points,
324 #[serde(rename = "PERCENTAGE")]
325 Percentage,
327 #[serde(rename = "pct")]
328 Pct,
330}
331
332#[derive(Debug, Clone, Deserialize, PartialEq)]
334pub struct StepDistance {
335 pub unit: Option<StepUnit>,
337 pub value: Option<f64>,
339}
340
341#[allow(dead_code)]
343fn deserialize_null_as_empty_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
344where
345 D: serde::Deserializer<'de>,
346 T: serde::Deserialize<'de>,
347{
348 let opt = Option::deserialize(deserializer)?;
349 Ok(opt.unwrap_or_default())
350}
351
352#[derive(Debug, Clone, Deserialize, Serialize)]
354pub struct MarketNavigationNode {
355 pub id: String,
357 pub name: String,
359}
360
361#[derive(Debug, Clone, Serialize, Deserialize)]
363pub struct MarketNode {
364 pub id: String,
366 pub name: String,
368 #[serde(skip_serializing_if = "Vec::is_empty", default)]
370 pub children: Vec<MarketNode>,
371 #[serde(skip_serializing_if = "Vec::is_empty", default)]
373 pub markets: Vec<MarketData>,
374}