Skip to main content

finance_query/domains/
economic.rs

1//! Macro-economic indicator query handle.
2//!
3//! Created via [`Providers::economic`](crate::Providers::economic).
4
5use std::sync::Arc;
6
7use crate::error::Result;
8use crate::models::economic::{EconomicCategory, EconomicRelease, EconomicSeriesMatch};
9#[cfg(feature = "fiscaldata")]
10use crate::models::economic::{TreasuryAuction, TreasuryAuctionQuery, UpcomingAuction};
11use crate::providers::{Capability, Operation, ProviderSet};
12
13domain_handle! {
14    /// A macro-economic data series backed by configured data providers.
15    ///
16    /// Created via [`Providers::economic`](crate::Providers::economic).
17    pub struct EconomicIndicator { series_id, series_id }
18    cache: crate::models::economic::EconomicSeries
19}
20
21impl EconomicIndicator {
22    /// Fetch the full data series for this economic indicator.
23    pub async fn series(&self) -> Result<crate::models::economic::EconomicSeries> {
24        fetch_via!(
25            self,
26            series_id,
27            ECONOMIC,
28            as_economic,
29            EconomicSeries,
30            fetch_economic_series,
31            crate::models::economic::EconomicSeries
32        )
33    }
34
35    /// Fetch this series as it stood on `date` (`YYYY-MM-DD`) instead of as
36    /// currently revised (FRED only, via ALFRED's realtime window).
37    ///
38    /// Macro data is revised after publication, so backtesting a rule against
39    /// today's series is look-ahead bias: the values it trades on were not
40    /// knowable at the time. This returns the vintage actually published as of
41    /// `date`. Cached per date.
42    pub async fn as_of(&self, date: &str) -> Result<crate::models::economic::EconomicSeries> {
43        let series_id: String = self.series_id().to_string();
44        let date = date.to_string();
45        let providers = Arc::clone(&self.providers);
46        self.cache
47            .get_or_try(format!("as_of\u{1f}{date}"), move || async move {
48                providers
49                    .fetch(Capability::ECONOMIC, move |p| {
50                        let (series_id, date) = (series_id.clone(), date.clone());
51                        let p = p.clone();
52                        async move {
53                            p.as_economic()
54                                .ok_or_else(|| p.not_supported(Operation::EconomicSeriesAsOf))?
55                                .fetch_economic_series_as_of(&series_id, &date)
56                                .await
57                        }
58                    })
59                    .await
60            })
61            .await
62    }
63}
64
65/// The macro-economic series catalog: search and browse rather than fetch.
66///
67/// Routes through [`Capability::ECONOMIC`]. [`EconomicIndicator`] needs a
68/// series id you already know; this handle is how you find one. FRED serves
69/// the catalog searches; US Treasury FiscalData serves the auction methods.
70///
71/// Created via [`Providers::economic_catalog`](crate::Providers::economic_catalog).
72pub struct EconomicCatalog {
73    providers: Arc<ProviderSet>,
74}
75
76impl EconomicCatalog {
77    pub(crate) fn with_providers(providers: Arc<ProviderSet>) -> Self {
78        Self { providers }
79    }
80
81    /// Search the series catalog by free text, most popular first.
82    pub async fn search(&self, query: &str, limit: u32) -> Result<Vec<EconomicSeriesMatch>> {
83        let query = query.to_string();
84        dispatch_via!(
85            self,
86            ECONOMIC,
87            as_economic,
88            EconomicSearch,
89            fetch_economic_search,
90            [query],
91            &query,
92            limit
93        )
94    }
95
96    /// List the child categories of `parent_id`. Pass `0` for the root.
97    pub async fn categories(&self, parent_id: i64) -> Result<Vec<EconomicCategory>> {
98        dispatch_via!(
99            self,
100            ECONOMIC,
101            as_economic,
102            EconomicCategories,
103            fetch_economic_categories,
104            [],
105            parent_id
106        )
107    }
108
109    /// List every scheduled data release the provider publishes.
110    pub async fn releases(&self) -> Result<Vec<EconomicRelease>> {
111        dispatch_via!(
112            self,
113            ECONOMIC,
114            as_economic,
115            EconomicReleases,
116            fetch_economic_releases,
117            []
118        )
119    }
120
121    /// Fetch US Treasury securities auctions matching `query`, most recent
122    /// auction date first.
123    ///
124    /// Covers auctions from announcement onwards, so the newest rows carry
125    /// their terms with the result figures still unset. US Treasury FiscalData
126    /// is the only provider.
127    #[cfg(feature = "fiscaldata")]
128    pub async fn treasury_auctions(
129        &self,
130        query: &TreasuryAuctionQuery,
131    ) -> Result<Vec<TreasuryAuction>> {
132        let query = query.clone();
133        dispatch_via!(
134            self,
135            ECONOMIC,
136            as_economic,
137            TreasuryAuctions,
138            fetch_treasury_auctions,
139            [query],
140            &query
141        )
142    }
143
144    /// Fetch the US Treasury auctions scheduled but not yet held, soonest
145    /// first.
146    ///
147    /// US Treasury FiscalData is the only provider.
148    #[cfg(feature = "fiscaldata")]
149    pub async fn upcoming_auctions(&self) -> Result<Vec<UpcomingAuction>> {
150        dispatch_via!(
151            self,
152            ECONOMIC,
153            as_economic,
154            UpcomingAuctions,
155            fetch_upcoming_auctions,
156            []
157        )
158    }
159}