use crate::adapters::yahoo::client::ClientConfig;
use crate::error::Result;
use crate::providers::{Fetch, Provider, ProviderSet, Routes, build_providers};
use std::sync::Arc;
use std::time::Duration;
pub struct Providers {
pub(crate) set: Arc<ProviderSet>,
}
impl Providers {
pub fn builder() -> ProvidersBuilder {
ProvidersBuilder::default()
}
pub fn ticker(&self, symbol: impl Into<String>) -> crate::TickerBuilder {
crate::Ticker::builder(symbol).with_provider_set(Arc::clone(&self.set))
}
pub fn tickers<S, I>(&self, symbols: I) -> crate::TickersBuilder
where
S: Into<String>,
I: IntoIterator<Item = S>,
{
crate::Tickers::builder(symbols).with_provider_set(Arc::clone(&self.set))
}
#[cfg(any(
feature = "alphavantage",
feature = "crypto",
feature = "fmp",
feature = "polygon"
))]
pub fn crypto(&self, id: impl Into<String>) -> crate::domains::CryptoCoin {
crate::domains::CryptoCoin::with_providers(id.into().into(), Arc::clone(&self.set))
}
#[cfg(any(feature = "alphavantage", feature = "fmp", feature = "polygon"))]
pub fn forex(
&self,
from: impl Into<String>,
to: impl Into<String>,
) -> crate::domains::ForexPair {
crate::domains::ForexPair::with_providers(
from.into().into(),
to.into().into(),
Arc::clone(&self.set),
)
}
#[cfg(any(feature = "alphavantage", feature = "polygon", feature = "fred"))]
pub fn economic(&self, series_id: impl Into<String>) -> crate::domains::EconomicIndicator {
crate::domains::EconomicIndicator::with_providers(
series_id.into().into(),
Arc::clone(&self.set),
)
}
#[cfg(any(feature = "polygon", feature = "fmp"))]
pub fn index(&self, symbol: impl Into<String>) -> crate::domains::Index {
crate::domains::Index::with_providers(symbol.into().into(), Arc::clone(&self.set))
}
#[cfg(feature = "polygon")]
pub fn futures(&self, symbol: impl Into<String>) -> crate::domains::FuturesContract {
crate::domains::FuturesContract::with_providers(symbol.into().into(), Arc::clone(&self.set))
}
#[cfg(any(feature = "fmp", feature = "alphavantage"))]
pub fn commodity(&self, symbol: impl Into<String>) -> crate::domains::Commodity {
crate::domains::Commodity::with_providers(symbol.into().into(), Arc::clone(&self.set))
}
pub fn filings(&self, symbol: impl Into<String>) -> crate::domains::Filings {
crate::domains::Filings::with_providers(symbol.into().into(), Arc::clone(&self.set))
}
}
pub struct ProvidersBuilder {
provider_ids: Vec<Provider>,
config: ClientConfig,
routes: Routes,
}
impl Default for ProvidersBuilder {
fn default() -> Self {
Self {
provider_ids: vec![Provider::Yahoo],
config: ClientConfig::default(),
routes: Routes::new(Fetch::Sequential),
}
}
}
impl ProvidersBuilder {
pub fn fetch(mut self, mode: Fetch) -> Self {
self.routes.fetch = mode;
self
}
pub fn route(mut self, cap: crate::providers::Capability, providers: &[Provider]) -> Self {
self.routes.map.insert(cap, providers.to_vec());
for provider in providers {
if !self.provider_ids.contains(provider) {
self.provider_ids.push(*provider);
}
}
self
}
pub fn region(mut self, region: crate::constants::Region) -> Self {
self.config.lang = region.lang().to_string();
self.config.region = region.region().to_string();
self
}
pub fn timeout(mut self, t: Duration) -> Self {
self.config.timeout = t;
self
}
pub fn proxy(mut self, p: impl Into<String>) -> Self {
self.config.proxy = Some(p.into());
self
}
pub async fn build(self) -> Result<Providers> {
let set = build_providers(&self.provider_ids, &self.config, self.routes).await?;
Ok(Providers { set: Arc::new(set) })
}
}