1use std::sync::Arc;
7
8use crate::error::Result;
9use crate::models::calendar::market::{CalendarKind, MarketCalendarEntry};
10use crate::models::chart::Candle;
11use crate::models::market::performance::{
12 IndustryPe, MoverDirection, MoverQuote, SectorPe, SectorPerformance,
13};
14use crate::providers::Capability;
15use crate::providers::ProviderSet;
16
17domain_handle! {
18 pub struct MarketCalendar
26 caches: { cache: Vec<MarketCalendarEntry> }
27}
28
29impl MarketCalendar {
30 pub async fn fetch(
34 &self,
35 kind: CalendarKind,
36 from: &str,
37 to: &str,
38 ) -> Result<Vec<MarketCalendarEntry>> {
39 let key = format!("{kind:?}\u{1f}{from}\u{1f}{to}");
40 let providers = Arc::clone(&self.providers);
41 let (from, to) = (from.to_string(), to.to_string());
42 self.cache
43 .get_or_try(key, move || async move {
44 providers
45 .fetch(Capability::CALENDAR, move |p| {
46 let (from, to) = (from.clone(), to.clone());
47 let p = p.clone();
48 async move {
49 p.as_calendar()
50 .ok_or_else(|| p.not_supported(kind.operation()))?
51 .fetch_market_calendar(kind, &from, &to)
52 .await
53 }
54 })
55 .await
56 })
57 .await
58 }
59
60 pub async fn earnings(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
62 self.fetch(CalendarKind::Earnings, from, to).await
63 }
64
65 pub async fn ipos(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
67 self.fetch(CalendarKind::Ipo, from, to).await
68 }
69
70 pub async fn dividends(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
72 self.fetch(CalendarKind::Dividend, from, to).await
73 }
74
75 pub async fn splits(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
77 self.fetch(CalendarKind::Split, from, to).await
78 }
79
80 pub async fn economic(&self, from: &str, to: &str) -> Result<Vec<MarketCalendarEntry>> {
82 self.fetch(CalendarKind::Economic, from, to).await
83 }
84
85 pub async fn holidays(&self) -> Result<Vec<MarketCalendarEntry>> {
88 self.fetch(CalendarKind::MarketHoliday, "", "").await
89 }
90
91 pub async fn market_status(&self) -> Result<Vec<MarketCalendarEntry>> {
94 self.fetch(CalendarKind::MarketStatus, "", "").await
95 }
96}
97
98pub struct Market {
106 providers: Arc<ProviderSet>,
107}
108
109impl Market {
110 pub(crate) fn with_providers(providers: Arc<ProviderSet>) -> Self {
111 Self { providers }
112 }
113
114 pub async fn sector_performance(&self) -> Result<Vec<SectorPerformance>> {
116 dispatch_via!(
117 self,
118 MARKET,
119 as_market,
120 SectorPerformance,
121 fetch_sector_performance,
122 []
123 )
124 }
125
126 pub async fn sector_performance_history(
128 &self,
129 limit: u32,
130 ) -> Result<Vec<crate::models::market::performance::SectorPerformanceHistory>> {
131 dispatch_via!(
132 self,
133 MARKET,
134 as_market,
135 SectorPerformanceHistory,
136 fetch_sector_performance_history,
137 [],
138 limit
139 )
140 }
141
142 pub async fn sector_pe(&self) -> Result<Vec<SectorPe>> {
144 dispatch_via!(
145 self,
146 MARKET,
147 as_market,
148 SectorPerformance,
149 fetch_sector_pe,
150 []
151 )
152 }
153
154 pub async fn industry_pe(&self) -> Result<Vec<IndustryPe>> {
156 dispatch_via!(
157 self,
158 MARKET,
159 as_market,
160 SectorPerformance,
161 fetch_industry_pe,
162 []
163 )
164 }
165
166 pub async fn movers(&self, direction: MoverDirection) -> Result<Vec<MoverQuote>> {
168 dispatch_via!(
169 self,
170 MARKET,
171 as_market,
172 MarketMovers,
173 fetch_market_movers,
174 [],
175 direction
176 )
177 }
178
179 pub async fn gainers(&self) -> Result<Vec<MoverQuote>> {
181 self.movers(MoverDirection::Gainers).await
182 }
183
184 pub async fn losers(&self) -> Result<Vec<MoverQuote>> {
186 self.movers(MoverDirection::Losers).await
187 }
188
189 pub async fn most_active(&self) -> Result<Vec<MoverQuote>> {
191 self.movers(MoverDirection::MostActive).await
192 }
193
194 pub async fn grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
203 let date = date.to_string();
204 dispatch_via!(
205 self,
206 CHART,
207 as_chart,
208 GroupedDaily,
209 fetch_grouped_daily,
210 [date],
211 &date
212 )
213 }
214
215 pub async fn crypto_grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
218 let date = date.to_string();
219 dispatch_via!(
220 self,
221 CHART,
222 as_chart,
223 CryptoGroupedDaily,
224 fetch_crypto_grouped_daily,
225 [date],
226 &date
227 )
228 }
229
230 pub async fn forex_grouped_daily(&self, date: &str) -> Result<Vec<(String, Candle)>> {
233 let date = date.to_string();
234 dispatch_via!(
235 self,
236 CHART,
237 as_chart,
238 ForexGroupedDaily,
239 fetch_forex_grouped_daily,
240 [date],
241 &date
242 )
243 }
244
245 #[cfg(feature = "crypto")]
250 pub async fn crypto_trending(&self) -> Result<Vec<crate::models::crypto::TrendingCoin>> {
251 dispatch_via!(
252 self,
253 CRYPTO,
254 as_crypto,
255 CryptoTrending,
256 fetch_crypto_trending,
257 []
258 )
259 }
260
261 #[cfg(feature = "crypto")]
266 pub async fn crypto_global(&self) -> Result<crate::models::crypto::GlobalCryptoStats> {
267 dispatch_via!(
268 self,
269 CRYPTO,
270 as_crypto,
271 CryptoGlobal,
272 fetch_crypto_global,
273 []
274 )
275 }
276}