1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use crate::error::AppError;
use crate::model::requests::RecentPricesRequest;
use crate::model::responses::{
CategoriesResponse, CategoryInstrumentsResponse, DBEntryResponse, HistoricalPricesResponse,
MarketNavigationResponse, MarketSearchResponse, MultipleMarketDetailsResponse,
};
use crate::presentation::market::{MarketData, MarketDetails};
use async_trait::async_trait;
/// Interface for the market service
#[async_trait]
pub trait MarketService: Send + Sync {
/// Searches markets by search term
async fn search_markets(&self, search_term: &str) -> Result<MarketSearchResponse, AppError>;
/// Gets details of a specific market by its EPIC
async fn get_market_details(&self, epic: &str) -> Result<MarketDetails, AppError>;
/// Gets details of multiple markets by their EPICs in a single request
///
/// This method accepts a vector of EPICs and returns a vector of market details.
/// The EPICs are sent as a comma-separated list in a single API request.
///
/// # Arguments
/// * `session` - The active IG session
/// * `epics` - A slice of EPICs to get details for
///
/// # Returns
/// A vector of market details in the same order as the input EPICs
async fn get_multiple_market_details(
&self,
epics: &[String],
) -> Result<MultipleMarketDetailsResponse, AppError>;
/// Gets historical prices for a market
async fn get_historical_prices(
&self,
epic: &str,
resolution: &str,
from: &str,
to: &str,
) -> Result<HistoricalPricesResponse, AppError>;
/// Gets historical prices for a market using path parameters (API v2)
///
/// # Arguments
/// * `epic` - Instrument epic
/// * `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)
/// * `start_date` - Start date (yyyy-MM-dd HH:mm:ss)
/// * `end_date` - End date (yyyy-MM-dd HH:mm:ss). Must be later than the start date
async fn get_historical_prices_by_date_range(
&self,
epic: &str,
resolution: &str,
start_date: &str,
end_date: &str,
) -> Result<HistoricalPricesResponse, AppError>;
/// Gets recent historical prices with custom parameters
///
/// # Arguments
/// * `params` - Request parameters including epic, resolution, and date range
///
/// # Returns
/// Historical price data for the specified parameters
async fn get_recent_prices(
&self,
params: &RecentPricesRequest<'_>,
) -> Result<HistoricalPricesResponse, AppError>;
/// Gets historical prices by number of data points (API v1)
///
/// # Arguments
/// * `epic` - Instrument epic
/// * `resolution` - Price resolution
/// * `num_points` - Number of data points required
async fn get_historical_prices_by_count_v1(
&self,
epic: &str,
resolution: &str,
num_points: i32,
) -> Result<HistoricalPricesResponse, AppError>;
/// Gets historical prices by number of data points (API v2)
///
/// # Arguments
/// * `epic` - Instrument epic
/// * `resolution` - Price resolution
/// * `num_points` - Number of data points required
async fn get_historical_prices_by_count_v2(
&self,
epic: &str,
resolution: &str,
num_points: i32,
) -> Result<HistoricalPricesResponse, AppError>;
/// Gets the top-level market navigation nodes
///
/// This method returns the root nodes of the market hierarchy, which can be used
/// to navigate through the available markets.
async fn get_market_navigation(&self) -> Result<MarketNavigationResponse, AppError>;
/// Gets the market navigation node with the specified ID
///
/// This method returns the child nodes and markets under the specified node ID.
///
/// # Arguments
/// * `node_id` - The ID of the navigation node to retrieve
async fn get_market_navigation_node(
&self,
node_id: &str,
) -> Result<MarketNavigationResponse, AppError>;
/// Navigates through all levels of the market hierarchy and collects all MarketData
///
/// This method performs a comprehensive traversal of the IG Markets hierarchy,
/// starting from the root navigation and going through multiple levels to collect
/// all available market instruments.
///
/// # Arguments
/// * `session` - The authenticated IG session
/// * `max_levels` - Maximum depth to traverse (default: 5 levels)
///
/// # Returns
/// * `Result<Vec<MarketData>, AppError>` - Vector containing all found market instruments
async fn get_all_markets(&self) -> Result<Vec<MarketData>, AppError>;
/// Gets all markets converted to database entries format
///
/// This method retrieves all available markets and converts them to a standardized
/// database entry format for storage or further processing.
///
/// # Arguments
/// * `session` - The authenticated IG session
///
/// # Returns
/// * `Result<Vec<DBEntry>, AppError>` - Vector of database entries representing all markets
async fn get_vec_db_entries(&self) -> Result<Vec<DBEntryResponse>, AppError>;
/// Gets all categories of instruments enabled for the IG account
///
/// This method returns a list of all categories of instruments that are
/// available for trading on the account.
///
/// # Returns
/// * `Result<CategoriesResponse, AppError>` - List of available categories
async fn get_categories(&self) -> Result<CategoriesResponse, AppError>;
/// Gets all instruments for a specific category
///
/// This method returns all instruments belonging to the specified category,
/// with optional pagination support.
///
/// # Arguments
/// * `category_id` - The identifier of the category
/// * `page_number` - Optional page number (default: 0)
/// * `page_size` - Optional page size (default: 150, max: 1000)
///
/// # Returns
/// * `Result<CategoryInstrumentsResponse, AppError>` - List of instruments in the category
async fn get_category_instruments(
&self,
category_id: &str,
page_number: Option<i32>,
page_size: Option<i32>,
) -> Result<CategoryInstrumentsResponse, AppError>;
}