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
38 #[serde(rename = "instrumentType")]
40 pub instrument_type: Option<InstrumentType>,
41
42 #[serde(rename = "expiryDetails")]
44 pub expiry_details: Option<ExpiryDetails>,
45
46 #[serde(rename = "slippageFactor")]
47 pub slippage_factor: Option<StepDistance>,
49
50 #[serde(rename = "limitedRiskPremium")]
51 pub limited_risk_premium: Option<StepDistance>,
53 #[serde(rename = "newsCode")]
54 pub news_code: Option<String>,
56 #[serde(rename = "chartCode")]
57 pub chart_code: Option<String>,
59}
60
61#[derive(Debug, Clone, Deserialize, PartialEq)]
63pub struct Currency {
64 pub code: String,
66 pub symbol: Option<String>,
68 #[serde(rename = "baseExchangeRate")]
70 pub base_exchange_rate: Option<f64>,
71 #[serde(rename = "exchangeRate")]
73 pub exchange_rate: Option<f64>,
74 #[serde(rename = "isDefault")]
76 pub is_default: Option<bool>,
77}
78
79#[derive(Debug, Clone, Deserialize)]
81pub struct MarketDetails {
82 pub instrument: Instrument,
84 pub snapshot: MarketSnapshot,
86 #[serde(rename = "dealingRules")]
88 pub dealing_rules: DealingRules,
89}
90
91#[derive(Debug, Clone, Deserialize)]
93pub struct DealingRules {
94 #[serde(rename = "minStepDistance")]
96 pub min_step_distance: StepDistance,
97
98 #[serde(rename = "minDealSize")]
100 pub min_deal_size: StepDistance,
101
102 #[serde(rename = "minControlledRiskStopDistance")]
104 pub min_controlled_risk_stop_distance: StepDistance,
105
106 #[serde(rename = "minNormalStopOrLimitDistance")]
108 pub min_normal_stop_or_limit_distance: StepDistance,
109
110 #[serde(rename = "maxStopOrLimitDistance")]
112 pub max_stop_or_limit_distance: StepDistance,
113
114 #[serde(rename = "controlledRiskSpacing")]
116 pub controlled_risk_spacing: StepDistance,
117
118 #[serde(rename = "marketOrderPreference")]
120 pub market_order_preference: String,
121
122 #[serde(rename = "trailingStopsPreference")]
124 pub trailing_stops_preference: String,
125
126 #[serde(rename = "maxDealSize")]
127 pub max_deal_size: Option<f64>,
129}
130
131#[derive(Debug, Clone, Deserialize)]
133pub struct MarketSnapshot {
134 #[serde(rename = "marketStatus")]
136 pub market_status: String,
137
138 #[serde(rename = "netChange")]
140 pub net_change: Option<f64>,
141
142 #[serde(rename = "percentageChange")]
144 pub percentage_change: Option<f64>,
145
146 #[serde(rename = "updateTime")]
148 pub update_time: Option<String>,
149
150 #[serde(rename = "delayTime")]
152 pub delay_time: Option<i64>,
153
154 pub bid: Option<f64>,
156
157 pub offer: Option<f64>,
159
160 pub high: Option<f64>,
162
163 pub low: Option<f64>,
165
166 #[serde(rename = "binaryOdds")]
168 pub binary_odds: Option<f64>,
169
170 #[serde(rename = "decimalPlacesFactor")]
172 pub decimal_places_factor: Option<i64>,
173
174 #[serde(rename = "scalingFactor")]
176 pub scaling_factor: Option<i64>,
177
178 #[serde(rename = "controlledRiskExtraSpread")]
180 pub controlled_risk_extra_spread: Option<f64>,
181}
182
183#[derive(Debug, Clone, Deserialize)]
185pub struct MarketSearchResult {
186 pub markets: Vec<MarketData>,
188}
189
190#[derive(Debug, Clone, Deserialize, Serialize)]
192pub struct MarketData {
193 pub epic: String,
195 #[serde(rename = "instrumentName")]
197 pub instrument_name: String,
198 #[serde(rename = "instrumentType")]
200 pub instrument_type: InstrumentType,
201 pub expiry: String,
203 #[serde(rename = "highLimitPrice")]
205 pub high_limit_price: Option<f64>,
206 #[serde(rename = "lowLimitPrice")]
208 pub low_limit_price: Option<f64>,
209 #[serde(rename = "marketStatus")]
211 pub market_status: String,
212 #[serde(rename = "netChange")]
214 pub net_change: Option<f64>,
215 #[serde(rename = "percentageChange")]
217 pub percentage_change: Option<f64>,
218 #[serde(rename = "updateTime")]
220 pub update_time: Option<String>,
221 #[serde(rename = "updateTimeUTC")]
223 pub update_time_utc: Option<String>,
224 pub bid: Option<f64>,
226 pub offer: Option<f64>,
228}
229
230impl Display for MarketData {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 let json = serde_json::to_string(self).unwrap_or_else(|_| "Invalid JSON".to_string());
233 write!(f, "{json}")
234 }
235}
236
237#[derive(Debug, Clone, Deserialize)]
239pub struct HistoricalPricesResponse {
240 pub prices: Vec<HistoricalPrice>,
242 #[serde(rename = "instrumentType")]
244 pub instrument_type: InstrumentType,
245 #[serde(rename = "allowance", skip_serializing_if = "Option::is_none", default)]
247 pub allowance: Option<PriceAllowance>,
248}
249
250#[derive(Debug, Clone, Deserialize)]
252pub struct HistoricalPrice {
253 #[serde(rename = "snapshotTime")]
255 pub snapshot_time: String,
256 #[serde(rename = "openPrice")]
258 pub open_price: PricePoint,
259 #[serde(rename = "highPrice")]
261 pub high_price: PricePoint,
262 #[serde(rename = "lowPrice")]
264 pub low_price: PricePoint,
265 #[serde(rename = "closePrice")]
267 pub close_price: PricePoint,
268 #[serde(rename = "lastTradedVolume")]
270 pub last_traded_volume: Option<i64>,
271}
272
273#[derive(Debug, Clone, Deserialize)]
275pub struct PricePoint {
276 pub bid: Option<f64>,
278 pub ask: Option<f64>,
280 #[serde(rename = "lastTraded")]
282 pub last_traded: Option<f64>,
283}
284
285#[derive(Debug, Clone, Deserialize)]
287pub struct PriceAllowance {
288 #[serde(rename = "remainingAllowance")]
290 pub remaining_allowance: i64,
291 #[serde(rename = "totalAllowance")]
293 pub total_allowance: i64,
294 #[serde(rename = "allowanceExpiry")]
296 pub allowance_expiry: i64,
297}
298
299#[derive(Debug, Clone, Deserialize, Serialize)]
301pub struct MarketNavigationResponse {
302 #[serde(default, deserialize_with = "deserialize_null_as_empty_vec")]
304 pub nodes: Vec<MarketNavigationNode>,
305 #[serde(default, deserialize_with = "deserialize_null_as_empty_vec")]
307 pub markets: Vec<MarketData>,
308}
309
310#[derive(Debug, Clone, Deserialize, PartialEq)]
312pub struct ExpiryDetails {
313 #[serde(rename = "lastDealingDate")]
315 pub last_dealing_date: String,
316
317 #[serde(rename = "settlementInfo")]
319 pub settlement_info: Option<String>,
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
323pub enum StepUnit {
325 #[serde(rename = "POINTS")]
326 Points,
328 #[serde(rename = "PERCENTAGE")]
329 Percentage,
331 #[serde(rename = "pct")]
332 Pct,
334}
335
336#[derive(Debug, Clone, Deserialize, PartialEq)]
338pub struct StepDistance {
339 pub unit: Option<StepUnit>,
341 pub value: Option<f64>,
343}
344
345#[allow(dead_code)]
347fn deserialize_null_as_empty_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
348where
349 D: serde::Deserializer<'de>,
350 T: serde::Deserialize<'de>,
351{
352 let opt = Option::deserialize(deserializer)?;
353 Ok(opt.unwrap_or_default())
354}
355
356#[derive(Debug, Clone, Deserialize, Serialize)]
358pub struct MarketNavigationNode {
359 pub id: String,
361 pub name: String,
363}
364
365#[derive(Debug, Serialize, Deserialize)]
367pub struct MarketNode {
368 pub id: String,
370 pub name: String,
372 #[serde(skip_serializing_if = "Vec::is_empty")]
374 pub children: Vec<MarketNode>,
375 #[serde(skip_serializing_if = "Vec::is_empty")]
377 pub markets: Vec<MarketData>,
378}