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 249)
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}Sourcepub fn secid(&self) -> &SecId
pub fn secid(&self) -> &SecId
Идентификатор инструмента (secid).
Examples found in repository?
examples/actual_indexes_dump.rs (line 140)
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}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 149)
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}Sourcepub fn last(&self) -> Option<f64>
pub fn last(&self) -> Option<f64>
Последняя цена (LAST), если поле присутствует в ISS.
Examples found in repository?
examples/actual_indexes_dump.rs (line 150)
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}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 (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 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