pub struct SecuritySnapshot { /* private fields */ }Expand description
Снимок инструмента с полями LOTSIZE и LAST.
Implementations§
Source§impl SecuritySnapshot
impl SecuritySnapshot
Sourcepub fn try_new(
secid: String,
lot_size: Option<i64>,
last: Option<f64>,
) -> Result<Self, ParseSecuritySnapshotError>
pub fn try_new( secid: String, lot_size: Option<i64>, last: Option<f64>, ) -> Result<Self, ParseSecuritySnapshotError>
Построить снимок инструмента из wire-значений ISS.
Examples found in repository?
examples/actual_indexes_dump.rs (line 233)
213fn parse_board_snapshots_page(
214 payload: &str,
215 endpoint: &str,
216) -> Result<(Vec<SecuritySnapshot>, Option<SecId>), MoexError> {
217 let mut tables = decode::raw_tables_json(payload, endpoint)?;
218 let security_rows: Vec<RawSecuritySnapshotRow> = tables.take_rows("securities")?;
219 let marketdata_rows: Vec<RawMarketdataSnapshotRow> = tables.take_rows("marketdata")?;
220
221 let mut marketdata_by_secid = HashMap::with_capacity(marketdata_rows.len());
222 for (row, marketdata) in marketdata_rows.into_iter().enumerate() {
223 marketdata_by_secid.insert(marketdata.secid, (row, marketdata.last));
224 }
225
226 let mut first_secid_on_page = None;
227 let mut snapshots = Vec::with_capacity(security_rows.len().max(marketdata_by_secid.len()));
228
229 for (row, security) in security_rows.into_iter().enumerate() {
230 let last = marketdata_by_secid
231 .remove(security.secid.as_str())
232 .and_then(|(_, last)| last);
233 let snapshot = SecuritySnapshot::try_new(security.secid, security.lot_size, last).map_err(
234 |source| MoexError::InvalidSecuritySnapshot {
235 endpoint: endpoint.to_owned().into_boxed_str(),
236 table: "securities",
237 row,
238 source,
239 },
240 )?;
241 if first_secid_on_page.is_none() {
242 first_secid_on_page = Some(snapshot.secid().clone());
243 }
244 snapshots.push(snapshot);
245 }
246
247 for (secid, (row, last)) in marketdata_by_secid {
248 let snapshot = SecuritySnapshot::try_new(secid, None, last).map_err(|source| {
249 MoexError::InvalidSecuritySnapshot {
250 endpoint: endpoint.to_owned().into_boxed_str(),
251 table: "marketdata",
252 row,
253 source,
254 }
255 })?;
256 if first_secid_on_page.is_none() {
257 first_secid_on_page = Some(snapshot.secid().clone());
258 }
259 snapshots.push(snapshot);
260 }
261
262 Ok((snapshots, first_secid_on_page))
263}Sourcepub fn secid(&self) -> &SecId
pub fn secid(&self) -> &SecId
Идентификатор инструмента (secid).
Examples found in repository?
examples/actual_indexes_dump.rs (line 124)
100fn load_security_snapshots(
101 moex_client: &Client,
102 wanted_secids: &HashSet<SecId>,
103) -> Result<(HashMap<SecId, ResolvedSnapshot>, Vec<SecId>), ExampleError> {
104 let stock_scope = moex_client
105 .stock()
106 .expect("stock engine literal must be valid");
107 let markets = with_retry(retry_policy(), || stock_scope.markets())?;
108 let mut snapshots = HashMap::with_capacity(wanted_secids.len());
109
110 'markets: for market in markets {
111 let boards = with_retry(retry_policy(), || {
112 moex_client.boards(stock_scope.engine(), market.name())
113 })?;
114
115 for board in boards.into_iter().filter(|board| board.is_traded()) {
116 let board_snapshots = load_board_snapshots_all_pages(
117 moex_client,
118 stock_scope.engine().as_str(),
119 market.name().as_str(),
120 board.boardid().as_str(),
121 )?;
122
123 for snapshot in board_snapshots {
124 if !wanted_secids.contains(snapshot.secid()) {
125 continue;
126 }
127
128 snapshots
129 .entry(snapshot.secid().clone())
130 .or_insert_with(|| ResolvedSnapshot {
131 market: market.name().as_str().to_owned().into_boxed_str(),
132 board: board.boardid().as_str().to_owned().into_boxed_str(),
133 lot_size: snapshot.lot_size(),
134 last: snapshot.last(),
135 });
136 }
137
138 if snapshots.len() == wanted_secids.len() {
139 break 'markets;
140 }
141 }
142 }
143
144 let missing_mapping = wanted_secids
145 .iter()
146 .filter(|secid| !snapshots.contains_key(*secid))
147 .cloned()
148 .collect();
149
150 Ok((snapshots, missing_mapping))
151}
152
153fn load_board_snapshots_all_pages(
154 moex_client: &Client,
155 engine: &str,
156 market: &str,
157 board: &str,
158) -> Result<Vec<SecuritySnapshot>, MoexError> {
159 let endpoint = format!("engines/{engine}/markets/{market}/boards/{board}/securities.json");
160 let mut start = 0_u32;
161 let mut snapshots = Vec::new();
162 let mut first_secid_on_previous_page = None;
163 let limit = BOARD_SNAPSHOTS_PAGE_LIMIT.to_string();
164
165 loop {
166 let payload = with_retry(retry_policy(), || {
167 moex_client
168 .raw()
169 .path(endpoint.as_str())
170 .only("securities,marketdata")
171 .columns("securities", "SECID,LOTSIZE")
172 .columns("marketdata", "SECID,LAST")
173 .param("start", start.to_string())
174 .param("limit", limit.as_str())
175 .send_payload()
176 })?;
177
178 let (page, first_secid_on_page) = parse_board_snapshots_page(&payload, endpoint.as_str())?;
179 if page.is_empty() {
180 break;
181 }
182
183 if let (Some(previous), Some(current)) =
184 (&first_secid_on_previous_page, &first_secid_on_page)
185 && previous == current
186 {
187 break;
188 }
189 first_secid_on_previous_page = first_secid_on_page;
190
191 let page_len = u32::try_from(page.len()).map_err(|_| MoexError::PaginationOverflow {
192 endpoint: endpoint.clone().into_boxed_str(),
193 start,
194 limit: BOARD_SNAPSHOTS_PAGE_LIMIT,
195 })?;
196
197 snapshots.extend(page);
198 if page_len < BOARD_SNAPSHOTS_PAGE_LIMIT {
199 break;
200 }
201 start = start
202 .checked_add(page_len)
203 .ok_or_else(|| MoexError::PaginationOverflow {
204 endpoint: endpoint.clone().into_boxed_str(),
205 start,
206 limit: BOARD_SNAPSHOTS_PAGE_LIMIT,
207 })?;
208 }
209
210 Ok(snapshots)
211}
212
213fn parse_board_snapshots_page(
214 payload: &str,
215 endpoint: &str,
216) -> Result<(Vec<SecuritySnapshot>, Option<SecId>), MoexError> {
217 let mut tables = decode::raw_tables_json(payload, endpoint)?;
218 let security_rows: Vec<RawSecuritySnapshotRow> = tables.take_rows("securities")?;
219 let marketdata_rows: Vec<RawMarketdataSnapshotRow> = tables.take_rows("marketdata")?;
220
221 let mut marketdata_by_secid = HashMap::with_capacity(marketdata_rows.len());
222 for (row, marketdata) in marketdata_rows.into_iter().enumerate() {
223 marketdata_by_secid.insert(marketdata.secid, (row, marketdata.last));
224 }
225
226 let mut first_secid_on_page = None;
227 let mut snapshots = Vec::with_capacity(security_rows.len().max(marketdata_by_secid.len()));
228
229 for (row, security) in security_rows.into_iter().enumerate() {
230 let last = marketdata_by_secid
231 .remove(security.secid.as_str())
232 .and_then(|(_, last)| last);
233 let snapshot = SecuritySnapshot::try_new(security.secid, security.lot_size, last).map_err(
234 |source| MoexError::InvalidSecuritySnapshot {
235 endpoint: endpoint.to_owned().into_boxed_str(),
236 table: "securities",
237 row,
238 source,
239 },
240 )?;
241 if first_secid_on_page.is_none() {
242 first_secid_on_page = Some(snapshot.secid().clone());
243 }
244 snapshots.push(snapshot);
245 }
246
247 for (secid, (row, last)) in marketdata_by_secid {
248 let snapshot = SecuritySnapshot::try_new(secid, None, last).map_err(|source| {
249 MoexError::InvalidSecuritySnapshot {
250 endpoint: endpoint.to_owned().into_boxed_str(),
251 table: "marketdata",
252 row,
253 source,
254 }
255 })?;
256 if first_secid_on_page.is_none() {
257 first_secid_on_page = Some(snapshot.secid().clone());
258 }
259 snapshots.push(snapshot);
260 }
261
262 Ok((snapshots, first_secid_on_page))
263}Sourcepub fn lot_size(&self) -> Option<u32>
pub fn lot_size(&self) -> Option<u32>
Размер лота (LOTSIZE), если поле присутствует в ISS.
Examples found in repository?
examples/actual_indexes_dump.rs (line 133)
100fn load_security_snapshots(
101 moex_client: &Client,
102 wanted_secids: &HashSet<SecId>,
103) -> Result<(HashMap<SecId, ResolvedSnapshot>, Vec<SecId>), ExampleError> {
104 let stock_scope = moex_client
105 .stock()
106 .expect("stock engine literal must be valid");
107 let markets = with_retry(retry_policy(), || stock_scope.markets())?;
108 let mut snapshots = HashMap::with_capacity(wanted_secids.len());
109
110 'markets: for market in markets {
111 let boards = with_retry(retry_policy(), || {
112 moex_client.boards(stock_scope.engine(), market.name())
113 })?;
114
115 for board in boards.into_iter().filter(|board| board.is_traded()) {
116 let board_snapshots = load_board_snapshots_all_pages(
117 moex_client,
118 stock_scope.engine().as_str(),
119 market.name().as_str(),
120 board.boardid().as_str(),
121 )?;
122
123 for snapshot in board_snapshots {
124 if !wanted_secids.contains(snapshot.secid()) {
125 continue;
126 }
127
128 snapshots
129 .entry(snapshot.secid().clone())
130 .or_insert_with(|| ResolvedSnapshot {
131 market: market.name().as_str().to_owned().into_boxed_str(),
132 board: board.boardid().as_str().to_owned().into_boxed_str(),
133 lot_size: snapshot.lot_size(),
134 last: snapshot.last(),
135 });
136 }
137
138 if snapshots.len() == wanted_secids.len() {
139 break 'markets;
140 }
141 }
142 }
143
144 let missing_mapping = wanted_secids
145 .iter()
146 .filter(|secid| !snapshots.contains_key(*secid))
147 .cloned()
148 .collect();
149
150 Ok((snapshots, missing_mapping))
151}Sourcepub fn last(&self) -> Option<f64>
pub fn last(&self) -> Option<f64>
Последняя цена (LAST), если поле присутствует в ISS.
Examples found in repository?
examples/actual_indexes_dump.rs (line 134)
100fn load_security_snapshots(
101 moex_client: &Client,
102 wanted_secids: &HashSet<SecId>,
103) -> Result<(HashMap<SecId, ResolvedSnapshot>, Vec<SecId>), ExampleError> {
104 let stock_scope = moex_client
105 .stock()
106 .expect("stock engine literal must be valid");
107 let markets = with_retry(retry_policy(), || stock_scope.markets())?;
108 let mut snapshots = HashMap::with_capacity(wanted_secids.len());
109
110 'markets: for market in markets {
111 let boards = with_retry(retry_policy(), || {
112 moex_client.boards(stock_scope.engine(), market.name())
113 })?;
114
115 for board in boards.into_iter().filter(|board| board.is_traded()) {
116 let board_snapshots = load_board_snapshots_all_pages(
117 moex_client,
118 stock_scope.engine().as_str(),
119 market.name().as_str(),
120 board.boardid().as_str(),
121 )?;
122
123 for snapshot in board_snapshots {
124 if !wanted_secids.contains(snapshot.secid()) {
125 continue;
126 }
127
128 snapshots
129 .entry(snapshot.secid().clone())
130 .or_insert_with(|| ResolvedSnapshot {
131 market: market.name().as_str().to_owned().into_boxed_str(),
132 board: board.boardid().as_str().to_owned().into_boxed_str(),
133 lot_size: snapshot.lot_size(),
134 last: snapshot.last(),
135 });
136 }
137
138 if snapshots.len() == wanted_secids.len() {
139 break 'markets;
140 }
141 }
142 }
143
144 let missing_mapping = wanted_secids
145 .iter()
146 .filter(|secid| !snapshots.contains_key(*secid))
147 .cloned()
148 .collect();
149
150 Ok((snapshots, missing_mapping))
151}Trait Implementations§
Source§impl Clone for SecuritySnapshot
impl Clone for SecuritySnapshot
Source§fn clone(&self) -> SecuritySnapshot
fn clone(&self) -> SecuritySnapshot
Returns a duplicate of the value. Read more
1.0.0 · 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 SecuritySnapshot
impl Debug for SecuritySnapshot
Source§impl PartialEq for SecuritySnapshot
impl PartialEq for SecuritySnapshot
impl StructuralPartialEq for SecuritySnapshot
Auto Trait Implementations§
impl Freeze for SecuritySnapshot
impl RefUnwindSafe for SecuritySnapshot
impl Send for SecuritySnapshot
impl Sync for SecuritySnapshot
impl Unpin for SecuritySnapshot
impl UnsafeUnpin for SecuritySnapshot
impl UnwindSafe for SecuritySnapshot
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