use crate::core::{
CallOptions, ProjectionContext, Quote, YfClient, YfError, YfResponse, quotes as core_quotes,
};
pub async fn quotes<I, S>(client: &YfClient, symbols: I) -> Result<Vec<Quote>, YfError>
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
QuotesBuilder::new(client).symbols(symbols).fetch().await
}
pub async fn quotes_with_diagnostics<I, S>(
client: &YfClient,
symbols: I,
) -> Result<YfResponse<Vec<Quote>>, YfError>
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
QuotesBuilder::new(client)
.symbols(symbols)
.fetch_with_diagnostics()
.await
}
pub struct QuotesBuilder {
client: YfClient,
symbols: Vec<String>,
options: CallOptions,
}
impl QuotesBuilder {
#[must_use]
pub fn new(client: &YfClient) -> Self {
Self {
client: client.clone(),
symbols: Vec::new(),
options: CallOptions::default(),
}
}
crate::core::impl_call_option_setters!(
strict_doc = "Fails when Yahoo quote data cannot be projected losslessly."
);
#[must_use]
pub fn symbols<I, S>(mut self, syms: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.symbols = syms.into_iter().map(Into::into).collect();
self
}
#[must_use]
pub fn add_symbol(mut self, sym: impl Into<String>) -> Self {
self.symbols.push(sym.into());
self
}
pub async fn fetch(&self) -> Result<Vec<crate::core::Quote>, crate::core::YfError> {
Ok(self.fetch_with_diagnostics().await?.into_data())
}
pub async fn fetch_with_diagnostics(
&self,
) -> Result<YfResponse<Vec<crate::core::Quote>>, crate::core::YfError> {
if self.symbols.is_empty() {
return Err(crate::core::YfError::InvalidParams(
"symbols list cannot be empty".into(),
));
}
let symbol_slices: Vec<&str> = self.symbols.iter().map(AsRef::as_ref).collect();
let results =
core_quotes::fetch_v7_quote_values(&self.client, &symbol_slices, &self.options).await?;
let mut ctx = ProjectionContext::new("quotes", self.options.data_quality());
core_quotes::report_missing_requested_quote_values(&symbol_slices, &results, &mut ctx)?;
let nodes = core_quotes::quote_nodes_from_values_with_context(
&self.client,
&symbol_slices,
results,
&mut ctx,
)?;
let mut quotes = Vec::with_capacity(nodes.len());
for result in nodes {
if let Some(quote) = result.to_quote_item_with_context(&mut ctx)? {
quotes.push(quote);
}
}
Ok(ctx.finish(quotes))
}
}