pub struct IndexAnalytics { /* private fields */ }Expand description
Компонент индекса из таблицы analytics.
Implementations§
Source§impl IndexAnalytics
impl IndexAnalytics
Sourcepub fn ticker(&self) -> &SecId
pub fn ticker(&self) -> &SecId
Тикер компонента.
Examples found in repository?
examples/actual_indexes_dump.rs (line 342)
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Sourcepub fn shortnames(&self) -> &str
pub fn shortnames(&self) -> &str
Краткие имена бумаг.
Examples found in repository?
examples/actual_indexes_dump.rs (line 343)
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Sourcepub fn secid(&self) -> &SecId
pub fn secid(&self) -> &SecId
Идентификатор инструмента компонента.
Examples found in repository?
examples/actual_indexes_dump.rs (line 112)
109fn collect_unique_secids(index_dumps: &[IndexDump]) -> HashSet<SecId> {
110 index_dumps
111 .iter()
112 .flat_map(|index| index.components.iter().map(|row| row.secid().clone()))
113 .collect()
114}
115
116fn load_security_snapshots(
117 moex_client: &Client,
118 wanted_secids: &HashSet<SecId>,
119) -> Result<(HashMap<SecId, ResolvedSnapshot>, Vec<SecId>), ExampleError> {
120 let stock_scope = moex_client
121 .stock()
122 .expect("stock engine literal must be valid");
123 let markets = with_retry(retry_policy(), || stock_scope.markets())?;
124 let mut snapshots = HashMap::with_capacity(wanted_secids.len());
125
126 'markets: for market in markets {
127 let boards = with_retry(retry_policy(), || {
128 moex_client.boards(stock_scope.engine(), market.name())
129 })?;
130
131 for board in boards.into_iter().filter(|board| board.is_traded()) {
132 let board_snapshots = load_board_snapshots_all_pages(
133 moex_client,
134 stock_scope.engine().as_str(),
135 market.name().as_str(),
136 board.boardid().as_str(),
137 )?;
138
139 for snapshot in board_snapshots {
140 if !wanted_secids.contains(snapshot.secid()) {
141 continue;
142 }
143
144 snapshots
145 .entry(snapshot.secid().clone())
146 .or_insert_with(|| ResolvedSnapshot {
147 market: market.name().as_str().to_owned().into_boxed_str(),
148 board: board.boardid().as_str().to_owned().into_boxed_str(),
149 lot_size: snapshot.lot_size(),
150 last: snapshot.last(),
151 });
152 }
153
154 if snapshots.len() == wanted_secids.len() {
155 break 'markets;
156 }
157 }
158 }
159
160 let missing_mapping = wanted_secids
161 .iter()
162 .filter(|secid| !snapshots.contains_key(*secid))
163 .cloned()
164 .collect();
165
166 Ok((snapshots, missing_mapping))
167}
168
169fn load_board_snapshots_all_pages(
170 moex_client: &Client,
171 engine: &str,
172 market: &str,
173 board: &str,
174) -> Result<Vec<SecuritySnapshot>, MoexError> {
175 let endpoint = format!("engines/{engine}/markets/{market}/boards/{board}/securities.json");
176 let mut start = 0_u32;
177 let mut snapshots = Vec::new();
178 let mut first_secid_on_previous_page = None;
179 let limit = BOARD_SNAPSHOTS_PAGE_LIMIT.to_string();
180
181 loop {
182 let payload = with_retry(retry_policy(), || {
183 moex_client
184 .raw()
185 .path(endpoint.as_str())
186 .only("securities,marketdata")
187 .columns("securities", "SECID,LOTSIZE")
188 .columns("marketdata", "SECID,LAST")
189 .param("start", start.to_string())
190 .param("limit", limit.as_str())
191 .send_payload()
192 })?;
193
194 let (page, first_secid_on_page) = parse_board_snapshots_page(&payload, endpoint.as_str())?;
195 if page.is_empty() {
196 break;
197 }
198
199 if let (Some(previous), Some(current)) =
200 (&first_secid_on_previous_page, &first_secid_on_page)
201 && previous == current
202 {
203 break;
204 }
205 first_secid_on_previous_page = first_secid_on_page;
206
207 let page_len = u32::try_from(page.len()).map_err(|_| MoexError::PaginationOverflow {
208 endpoint: endpoint.clone().into_boxed_str(),
209 start,
210 limit: BOARD_SNAPSHOTS_PAGE_LIMIT,
211 })?;
212
213 snapshots.extend(page);
214 if page_len < BOARD_SNAPSHOTS_PAGE_LIMIT {
215 break;
216 }
217 start = start
218 .checked_add(page_len)
219 .ok_or_else(|| MoexError::PaginationOverflow {
220 endpoint: endpoint.clone().into_boxed_str(),
221 start,
222 limit: BOARD_SNAPSHOTS_PAGE_LIMIT,
223 })?;
224 }
225
226 Ok(snapshots)
227}
228
229fn parse_board_snapshots_page(
230 payload: &str,
231 endpoint: &str,
232) -> Result<(Vec<SecuritySnapshot>, Option<SecId>), MoexError> {
233 let mut tables = decode::raw_tables_json(payload, endpoint)?;
234 let security_rows: Vec<RawSecuritySnapshotRow> = tables.take_rows("securities")?;
235 let marketdata_rows: Vec<RawMarketdataSnapshotRow> = tables.take_rows("marketdata")?;
236
237 let mut marketdata_by_secid = HashMap::with_capacity(marketdata_rows.len());
238 for (row, marketdata) in marketdata_rows.into_iter().enumerate() {
239 marketdata_by_secid.insert(marketdata.secid, (row, marketdata.last));
240 }
241
242 let mut first_secid_on_page = None;
243 let mut snapshots = Vec::with_capacity(security_rows.len().max(marketdata_by_secid.len()));
244
245 for (row, security) in security_rows.into_iter().enumerate() {
246 let last = marketdata_by_secid
247 .remove(security.secid.as_str())
248 .and_then(|(_, last)| last);
249 let snapshot = SecuritySnapshot::try_new(security.secid, security.lot_size, last).map_err(
250 |source| MoexError::InvalidSecuritySnapshot {
251 endpoint: endpoint.to_owned().into_boxed_str(),
252 table: "securities",
253 row,
254 source,
255 },
256 )?;
257 if first_secid_on_page.is_none() {
258 first_secid_on_page = Some(snapshot.secid().clone());
259 }
260 snapshots.push(snapshot);
261 }
262
263 for (secid, (row, last)) in marketdata_by_secid {
264 let snapshot = SecuritySnapshot::try_new(secid, None, last).map_err(|source| {
265 MoexError::InvalidSecuritySnapshot {
266 endpoint: endpoint.to_owned().into_boxed_str(),
267 table: "marketdata",
268 row,
269 source,
270 }
271 })?;
272 if first_secid_on_page.is_none() {
273 first_secid_on_page = Some(snapshot.secid().clone());
274 }
275 snapshots.push(snapshot);
276 }
277
278 Ok((snapshots, first_secid_on_page))
279}
280
281fn retry_policy() -> RetryPolicy {
282 RetryPolicy::new(
283 NonZeroU32::new(REQUEST_RETRIES)
284 .expect("REQUEST_RETRIES constant must be greater than zero"),
285 )
286 .with_delay(Duration::from_millis(RETRY_DELAY_MILLIS))
287}
288
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Sourcepub fn weight(&self) -> f64
pub fn weight(&self) -> f64
Вес компонента в индексе.
Examples found in repository?
examples/actual_indexes_dump.rs (line 344)
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Sourcepub fn tradingsession(&self) -> u8
pub fn tradingsession(&self) -> u8
Торговая сессия (1..=3).
Examples found in repository?
examples/actual_indexes_dump.rs (line 323)
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Sourcepub fn trade_session_date(&self) -> NaiveDate
pub fn trade_session_date(&self) -> NaiveDate
Дата торговой сессии (tradedate в источнике analytics).
Examples found in repository?
examples/actual_indexes_dump.rs (line 322)
289fn print_dump(
290 index_dumps: &[IndexDump],
291 snapshots: &HashMap<SecId, ResolvedSnapshot>,
292 missing_mapping: &[SecId],
293) {
294 println!("active indexes: {}", index_dumps.len());
295
296 let total_components = index_dumps
297 .iter()
298 .map(|index| index.components.len())
299 .sum::<usize>();
300 println!("total components across active indexes: {total_components}");
301 println!("resolved security snapshots: {}", snapshots.len());
302
303 if !missing_mapping.is_empty() {
304 let preview = missing_mapping
305 .iter()
306 .take(10)
307 .map(SecId::as_str)
308 .collect::<Vec<_>>()
309 .join(", ");
310 println!(
311 "warning: {} securities have no stock snapshot data (first 10): {preview}",
312 missing_mapping.len()
313 );
314 }
315
316 for index in index_dumps {
317 println!();
318 println!("=== {} | {} ===", index.index_id, index.short_name);
319 if let Some(first_component) = index.components.first() {
320 println!(
321 "trade_session_date={} tradingsession={} components={}",
322 first_component.trade_session_date(),
323 first_component.tradingsession(),
324 index.components.len()
325 );
326 } else {
327 println!("components=0");
328 }
329
330 println!("SECID\tTICKER\tSHORTNAME\tWEIGHT\tLAST\tLOTSIZE\tMARKET\tBOARD");
331 for component in &index.components {
332 let snapshot = snapshots.get(component.secid());
333
334 let last = format_optional_f64(snapshot.and_then(|item| item.last));
335 let lot_size = format_optional_u32(snapshot.and_then(|item| item.lot_size));
336 let market = snapshot.map_or("N/A", |item| item.market.as_ref());
337 let board = snapshot.map_or("N/A", |item| item.board.as_ref());
338
339 println!(
340 "{}\t{}\t{}\t{:.6}\t{}\t{}\t{}\t{}",
341 component.secid(),
342 component.ticker(),
343 component.shortnames(),
344 component.weight(),
345 last,
346 lot_size,
347 market,
348 board,
349 );
350 }
351 }
352}Trait Implementations§
Source§impl Clone for IndexAnalytics
impl Clone for IndexAnalytics
Source§fn clone(&self) -> IndexAnalytics
fn clone(&self) -> IndexAnalytics
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for IndexAnalytics
impl Debug for IndexAnalytics
Source§impl PartialEq for IndexAnalytics
impl PartialEq for IndexAnalytics
impl StructuralPartialEq for IndexAnalytics
Auto Trait Implementations§
impl Freeze for IndexAnalytics
impl RefUnwindSafe for IndexAnalytics
impl Send for IndexAnalytics
impl Sync for IndexAnalytics
impl Unpin for IndexAnalytics
impl UnsafeUnpin for IndexAnalytics
impl UnwindSafe for IndexAnalytics
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more