ig_client/application/services/interfaces/market.rs
1use crate::application::models::market::{
2 HistoricalPricesResponse, MarketDetails, MarketNavigationResponse, MarketSearchResult,
3};
4use crate::application::services::types::DBEntry;
5use crate::error::AppError;
6use crate::session::interface::IgSession;
7use async_trait::async_trait;
8
9/// Parameters for getting recent prices (API v3)
10#[derive(Debug, Clone, Default)]
11pub struct RecentPricesParams<'a> {
12 /// Instrument epic
13 pub epic: &'a str,
14 /// Optional price resolution (default: MINUTE)
15 pub resolution: Option<&'a str>,
16 /// Optional start date time (yyyy-MM-dd'T'HH:mm:ss)
17 pub from: Option<&'a str>,
18 /// Optional end date time (yyyy-MM-dd'T'HH:mm:ss)
19 pub to: Option<&'a str>,
20 /// Optional max number of price points (default: 10)
21 pub max_points: Option<i32>,
22 /// Optional page size (default: 20, disable paging = 0)
23 pub page_size: Option<i32>,
24 /// Optional page number (default: 1)
25 pub page_number: Option<i32>,
26}
27
28impl<'a> RecentPricesParams<'a> {
29 /// Create new parameters with just the epic (required field)
30 pub fn new(epic: &'a str) -> Self {
31 Self {
32 epic,
33 ..Default::default()
34 }
35 }
36
37 /// Set the resolution
38 pub fn with_resolution(mut self, resolution: &'a str) -> Self {
39 self.resolution = Some(resolution);
40 self
41 }
42
43 /// Set the from date
44 pub fn with_from(mut self, from: &'a str) -> Self {
45 self.from = Some(from);
46 self
47 }
48
49 /// Set the to date
50 pub fn with_to(mut self, to: &'a str) -> Self {
51 self.to = Some(to);
52 self
53 }
54
55 /// Set the max points
56 pub fn with_max_points(mut self, max_points: i32) -> Self {
57 self.max_points = Some(max_points);
58 self
59 }
60
61 /// Set the page size
62 pub fn with_page_size(mut self, page_size: i32) -> Self {
63 self.page_size = Some(page_size);
64 self
65 }
66
67 /// Set the page number
68 pub fn with_page_number(mut self, page_number: i32) -> Self {
69 self.page_number = Some(page_number);
70 self
71 }
72}
73
74/// Interface for the market service
75#[async_trait]
76pub trait MarketService: Send + Sync {
77 /// Searches markets by search term
78 async fn search_markets(
79 &self,
80 session: &IgSession,
81 search_term: &str,
82 ) -> Result<MarketSearchResult, AppError>;
83
84 /// Gets details of a specific market by its EPIC
85 async fn get_market_details(
86 &self,
87 session: &IgSession,
88 epic: &str,
89 ) -> Result<MarketDetails, AppError>;
90
91 /// Gets details of multiple markets by their EPICs in a single request
92 ///
93 /// This method accepts a vector of EPICs and returns a vector of market details.
94 /// The EPICs are sent as a comma-separated list in a single API request.
95 ///
96 /// # Arguments
97 /// * `session` - The active IG session
98 /// * `epics` - A slice of EPICs to get details for
99 ///
100 /// # Returns
101 /// A vector of market details in the same order as the input EPICs
102 async fn get_multiple_market_details(
103 &self,
104 session: &IgSession,
105 epics: &[String],
106 ) -> Result<Vec<MarketDetails>, AppError>;
107
108 /// Gets historical prices for a market
109 async fn get_historical_prices(
110 &self,
111 session: &IgSession,
112 epic: &str,
113 resolution: &str,
114 from: &str,
115 to: &str,
116 ) -> Result<HistoricalPricesResponse, AppError>;
117
118 /// Gets historical prices for a market using path parameters (API v2)
119 ///
120 /// # Arguments
121 /// * `epic` - Instrument epic
122 /// * `resolution` - Price resolution (SECOND, MINUTE, MINUTE_2, MINUTE_3, MINUTE_5, MINUTE_10, MINUTE_15, MINUTE_30, HOUR, HOUR_2, HOUR_3, HOUR_4, DAY, WEEK, MONTH)
123 /// * `start_date` - Start date (yyyy-MM-dd HH:mm:ss)
124 /// * `end_date` - End date (yyyy-MM-dd HH:mm:ss). Must be later than the start date
125 async fn get_historical_prices_by_date_range(
126 &self,
127 session: &IgSession,
128 epic: &str,
129 resolution: &str,
130 start_date: &str,
131 end_date: &str,
132 ) -> Result<HistoricalPricesResponse, AppError>;
133
134 /// Gets recent historical prices for an instrument (API v3)
135 /// Returns minute prices within the last 10 minutes by default
136 ///
137 /// # Arguments
138 /// * `session` - The authenticated IG session
139 /// * `params` - Parameters for the recent prices request
140 ///
141 /// # Example
142 /// ```rust,no_run
143 /// use ig_client::application::services::{MarketService, RecentPricesParams};
144 /// # use ig_client::application::services::market_service::MarketServiceImpl;
145 /// # use ig_client::transport::http_client::IgHttpClientImpl;
146 /// # use ig_client::config::Config;
147 /// # use std::sync::Arc;
148 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
149 /// # let config = Arc::new(Config::default());
150 /// # let http_client = Arc::new(IgHttpClientImpl::new(config.clone()));
151 /// # let market_service = MarketServiceImpl::new(config, http_client);
152 /// # let session = ig_client::session::interface::IgSession::new(
153 /// # "cst_token".to_string(),
154 /// # "security_token".to_string(),
155 /// # "account_id".to_string()
156 /// # );
157 ///
158 /// let params = RecentPricesParams::new("CS.D.EURUSD.TODAY.IP")
159 /// .with_resolution("MINUTE_5")
160 /// .with_max_points(10);
161 /// let prices = market_service.get_recent_prices(&session, ¶ms).await?;
162 /// # Ok(())
163 /// # }
164 /// ```
165 async fn get_recent_prices(
166 &self,
167 session: &IgSession,
168 params: &RecentPricesParams<'_>,
169 ) -> Result<HistoricalPricesResponse, AppError>;
170
171 /// Gets historical prices by number of data points (API v1)
172 ///
173 /// # Arguments
174 /// * `epic` - Instrument epic
175 /// * `resolution` - Price resolution
176 /// * `num_points` - Number of data points required
177 async fn get_historical_prices_by_count_v1(
178 &self,
179 session: &IgSession,
180 epic: &str,
181 resolution: &str,
182 num_points: i32,
183 ) -> Result<HistoricalPricesResponse, AppError>;
184
185 /// Gets historical prices by number of data points (API v2)
186 ///
187 /// # Arguments
188 /// * `epic` - Instrument epic
189 /// * `resolution` - Price resolution
190 /// * `num_points` - Number of data points required
191 async fn get_historical_prices_by_count_v2(
192 &self,
193 session: &IgSession,
194 epic: &str,
195 resolution: &str,
196 num_points: i32,
197 ) -> Result<HistoricalPricesResponse, AppError>;
198
199 /// Gets the top-level market navigation nodes
200 ///
201 /// This method returns the root nodes of the market hierarchy, which can be used
202 /// to navigate through the available markets.
203 async fn get_market_navigation(
204 &self,
205 session: &IgSession,
206 ) -> Result<MarketNavigationResponse, AppError>;
207
208 /// Gets the market navigation node with the specified ID
209 ///
210 /// This method returns the child nodes and markets under the specified node ID.
211 ///
212 /// # Arguments
213 /// * `node_id` - The ID of the navigation node to retrieve
214 async fn get_market_navigation_node(
215 &self,
216 session: &IgSession,
217 node_id: &str,
218 ) -> Result<MarketNavigationResponse, AppError>;
219
220 /// Navigates through all levels of the market hierarchy and collects all MarketData
221 ///
222 /// This method performs a comprehensive traversal of the IG Markets hierarchy,
223 /// starting from the root navigation and going through multiple levels to collect
224 /// all available market instruments.
225 ///
226 /// # Arguments
227 /// * `session` - The authenticated IG session
228 /// * `max_levels` - Maximum depth to traverse (default: 5 levels)
229 ///
230 /// # Returns
231 /// * `Result<Vec<MarketData>, AppError>` - Vector containing all found market instruments
232 async fn get_all_markets(
233 &self,
234 session: &IgSession,
235 ) -> Result<Vec<crate::application::models::market::MarketData>, AppError>;
236
237 /// Gets all markets converted to database entries format
238 ///
239 /// This method retrieves all available markets and converts them to a standardized
240 /// database entry format for storage or further processing.
241 ///
242 /// # Arguments
243 /// * `session` - The authenticated IG session
244 ///
245 /// # Returns
246 /// * `Result<Vec<DBEntry>, AppError>` - Vector of database entries representing all markets
247 async fn get_vec_db_entries(&self, session: &IgSession) -> Result<Vec<DBEntry>, AppError>;
248}