use std::sync::Arc;
use crate::error::Result;
use crate::models::calendar::market::{CalendarKind, MarketCalendarEntry};
use crate::models::chart::Candle;
use crate::models::market::performance::{
IndustryPe, MoverDirection, MoverQuote, SectorPe, SectorPerformance,
};
use crate::providers::Capability;
use crate::providers::ProviderSet;
domain_handle! {
pub struct MarketCalendar
caches: { cache: Vec<MarketCalendarEntry> }
}
impl MarketCalendar {
pub async fn fetch(
&self,
kind: CalendarKind,
from: &str,
to: &str,
) -> Result<Vec<MarketCalendarEntry>> {
let key = format!("{kind:?}\u{1f}{from}\u{1f}{to}");
let providers = Arc::clone(&self.providers);
let (from, to) = (from.to_string(), to.to_string());
self.cache
.get_or_try(key, move || async move {
providers
.fetch(Capability::CALENDAR, move |p| {
let (from, to) = (from.clone(), to.clone());
let p = p.clone();
async move {
p.as_calendar()
.ok_or_else(|| p.not_supported(kind.operation()))?
.fetch_market_calendar(kind, &from, &to)
.await
}
})
.await
})
.await
}
pub async fn earnings(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::Earnings, from, to).await
}
pub async fn ipos(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::Ipo, from, to).await
}
pub async fn dividends(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::Dividend, from, to).await
}
pub async fn splits(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::Split, from, to).await
}
pub async fn economic(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::Economic, from, to).await
}
pub async fn holidays(&self) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::MarketHoliday, "", "").await
}
pub async fn market_status(&self) -> Result<Vec<MarketCalendarEntry>> {
self.fetch(CalendarKind::MarketStatus, "", "").await
}
}
pub struct Market {
providers: Arc<ProviderSet>,
}
impl Market {
pub(crate) fn with_providers(providers: Arc<ProviderSet>) -> Self {
Self { providers }
}
pub async fn sector_performance(&self) -> Result<Vec<SectorPerformance>> {
dispatch_via!(
self,
MARKET,
as_market,
SectorPerformance,
fetch_sector_performance,
[]
)
}
pub async fn sector_performance_history(
&self,
limit: u32,
) -> Result<Vec<crate::models::market::performance::SectorPerformanceHistory>> {
dispatch_via!(
self,
MARKET,
as_market,
SectorPerformanceHistory,
fetch_sector_performance_history,
[],
limit
)
}
pub async fn sector_pe(&self) -> Result<Vec<SectorPe>> {
dispatch_via!(
self,
MARKET,
as_market,
SectorPerformance,
fetch_sector_pe,
[]
)
}
pub async fn industry_pe(&self) -> Result<Vec<IndustryPe>> {
dispatch_via!(
self,
MARKET,
as_market,
SectorPerformance,
fetch_industry_pe,
[]
)
}
pub async fn movers(&self, direction: MoverDirection) -> Result<Vec<MoverQuote>> {
dispatch_via!(
self,
MARKET,
as_market,
MarketMovers,
fetch_market_movers,
[],
direction
)
}
pub async fn gainers(&self) -> Result<Vec<MoverQuote>> {
self.movers(MoverDirection::Gainers).await
}
pub async fn losers(&self) -> Result<Vec<MoverQuote>> {
self.movers(MoverDirection::Losers).await
}
pub async fn most_active(&self) -> Result<Vec<MoverQuote>> {
self.movers(MoverDirection::MostActive).await
}
pub async fn grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
let date = date.to_string();
dispatch_via!(
self,
CHART,
as_chart,
GroupedDaily,
fetch_grouped_daily,
[date],
&date
)
}
pub async fn crypto_grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
let date = date.to_string();
dispatch_via!(
self,
CHART,
as_chart,
CryptoGroupedDaily,
fetch_crypto_grouped_daily,
[date],
&date
)
}
pub async fn forex_grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
let date = date.to_string();
dispatch_via!(
self,
CHART,
as_chart,
ForexGroupedDaily,
fetch_forex_grouped_daily,
[date],
&date
)
}
#[cfg(feature = "crypto")]
pub async fn crypto_trending(&self) -> Result<Vec<crate::models::crypto::TrendingCoin>> {
dispatch_via!(
self,
CRYPTO,
as_crypto,
CryptoTrending,
fetch_crypto_trending,
[]
)
}
#[cfg(feature = "crypto")]
pub async fn crypto_global(&self) -> Result<crate::models::crypto::GlobalCryptoStats> {
dispatch_via!(
self,
CRYPTO,
as_crypto,
CryptoGlobal,
fetch_crypto_global,
[]
)
}
}