yfinance-rs 0.1.1

Ergonomic Rust client for Yahoo Finance, supporting historical prices, real-time streaming, options, fundamentals, and more.
Documentation
use crate::core::client::CacheMode;
use crate::core::client::RetryConfig;
use crate::core::{Quote, YfClient, YfError, quotes as core_quotes};

/// A convenience function to fetch quotes for multiple symbols with default settings.
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.clone())
        .symbols(symbols)
        .fetch()
        .await
}

/// A builder for fetching quotes for one or more symbols.
pub struct QuotesBuilder {
    client: YfClient,
    symbols: Vec<String>,
    cache_mode: CacheMode,
    retry_override: Option<RetryConfig>,
}

impl QuotesBuilder {
    /// Creates a new `QuotesBuilder`.
    pub fn new(client: YfClient) -> Self {
        Self {
            client,
            symbols: Vec::new(),
            cache_mode: CacheMode::Use,
            retry_override: None,
        }
    }

    /// Sets the cache mode for this specific API call.
    pub fn cache_mode(mut self, mode: CacheMode) -> Self {
        self.cache_mode = mode;
        self
    }

    /// Overrides the default retry policy for this specific API call.
    pub fn retry_policy(mut self, cfg: Option<RetryConfig>) -> Self {
        self.retry_override = cfg;
        self
    }

    /// Replaces the current list of symbols with a new list.
    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
    }

    /// Adds a single symbol to the list.
    pub fn add_symbol(mut self, sym: impl Into<String>) -> Self {
        self.symbols.push(sym.into());
        self
    }

    /// Executes the request and fetches the quotes.
    pub async fn fetch(self) -> Result<Vec<crate::core::Quote>, crate::core::YfError> {
        if self.symbols.is_empty() {
            return Err(crate::core::YfError::Data(
                "quotes: at least one symbol required".into(),
            ));
        }

        let symbol_slices: Vec<&str> = self.symbols.iter().map(AsRef::as_ref).collect();
        let results = core_quotes::fetch_v7_quotes(
            &self.client,
            &symbol_slices,
            self.cache_mode,
            self.retry_override.as_ref(),
        )
        .await?;

        Ok(results.into_iter().map(Into::into).collect())
    }
}