Skip to main content

finance_query/providers/
operation.rs

1//! The [`Operation`] enum: one variant per adapter method.
2
3use super::{Capability, Provider};
4use crate::error::FinanceError;
5
6/// A single provider-adapter operation — finer-grained than [`Capability`]
7/// (e.g. `Chart`, `ChartRange`, and `Spark` all fall under `Capability::CHART`).
8///
9/// Used in [`crate::FinanceError::NotSupported`] to say exactly which method a
10/// provider doesn't implement; [`Operation::capability`] recovers the coarser
11/// bit for computing which other providers could satisfy it.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[non_exhaustive]
14pub enum Operation {
15    /// One resumable page of delisted stocks.
16    DelistedStocksPage,
17    /// One independently numbered delisted-stock page.
18    DelistedStocksPageAt,
19    /// Current provider-wide symbol directory.
20    StockList,
21    /// One numbered part of bulk company profiles.
22    CompanyProfilesBulk,
23    /// One historical stock-directory page.
24    StockListingsPage,
25    /// Company details on a specified date.
26    SymbolDetailsAt,
27    /// Provider stock-type vocabulary.
28    StockTypes,
29    /// Dated ticker changes of one security.
30    TickerChanges,
31    /// One lossless stock-bar page.
32    StockBarsPage,
33    /// Single-symbol quote.
34    Quote,
35    /// Historical OHLCV chart over an interval/range.
36    Chart,
37    /// Historical OHLCV chart over a custom timestamp range.
38    ChartRange,
39    /// Financial statements (income/balance/cash flow).
40    Financials,
41    /// Symbol news.
42    News,
43    /// Similar-symbol recommendations.
44    Recommendations,
45    /// Options chain.
46    Options,
47    /// Corporate calendar events (earnings, dividends, splits).
48    Events,
49    /// Batch quotes for multiple symbols in one request.
50    QuotesBatch,
51    /// Lightweight sparkline data for multiple symbols in one request.
52    Spark,
53    /// Cryptocurrency quote.
54    CryptoQuote,
55    /// Market-wide crypto news.
56    CryptoNews,
57    /// Macro-economic data series.
58    EconomicSeries,
59    /// Foreign exchange currency pair quote.
60    ForexQuote,
61    /// Market-wide forex news.
62    ForexNews,
63    /// Stock market index quote.
64    IndicesQuote,
65    /// Futures contract quote.
66    FuturesQuote,
67    /// Commodity price quote.
68    CommoditiesQuote,
69    /// SEC EDGAR filing data.
70    Filings,
71    /// Symbol search by free-text query.
72    SymbolSearch,
73    /// Detailed reference data for one symbol.
74    SymbolDetails,
75    /// Tradable exchange listing.
76    Exchanges,
77    /// Screener query over the provider's universe.
78    Screener,
79    /// Market-wide earnings calendar.
80    EarningsCalendar,
81    /// Market-wide IPO calendar.
82    IpoCalendar,
83    /// Market-wide dividend calendar.
84    DividendCalendar,
85    /// Market-wide stock split calendar.
86    SplitCalendar,
87    /// Market-wide economic event calendar.
88    EconomicCalendar,
89    /// Sector and industry performance statistics.
90    SectorPerformance,
91    /// Market movers — gainers, losers, most active.
92    MarketMovers,
93    /// Historical sector performance.
94    SectorPerformanceHistory,
95    /// Market-wide holiday calendar.
96    HolidayCalendar,
97    /// Live exchange open/closed status.
98    MarketStatus,
99    /// Current constituents of a major index.
100    IndexConstituents,
101    /// Historical constituent changes of a major index.
102    IndexConstituentChanges,
103    /// Short interest (settlement-date positions).
104    ShortInterest,
105    /// Daily short volume.
106    ShortVolume,
107    /// Share float and shares outstanding.
108    ShareFloat,
109    /// Sectioned text of an SEC filing.
110    FilingSections,
111    /// Risk factors extracted from SEC filings.
112    RiskFactors,
113    /// Company press releases.
114    PressReleases,
115    /// Earnings call transcript, provider-neutral shape.
116    EarningsTranscript,
117    /// Total value locked in a DeFi protocol.
118    #[cfg(feature = "defi")]
119    ProtocolTvl,
120    /// Historical total value locked in a DeFi protocol.
121    #[cfg(feature = "defi")]
122    ProtocolTvlHistory,
123    /// Weekly CFTC Commitments of Traders futures positioning.
124    #[cfg(feature = "cftc")]
125    CommitmentsOfTraders,
126    /// Aggregated analyst price-target consensus.
127    PriceTargetConsensus,
128    /// Price-target publication activity over trailing windows.
129    PriceTargetSummary,
130    /// Aggregated analyst rating consensus.
131    RatingConsensus,
132    /// Trailing-twelve-month key-metrics snapshot.
133    KeyMetricsTtm,
134    /// Trailing-twelve-month ratios snapshot.
135    RatiosTtm,
136    /// Reported executive compensation.
137    ExecutiveCompensation,
138    /// Reported employee headcount.
139    EmployeeCount,
140    /// Company identity/classification profile.
141    CompanyProfile,
142    /// Cross-market snapshot for symbols spanning several asset classes.
143    UnifiedSnapshot,
144    /// Full-text search over filing content.
145    FilingSearch,
146    /// Insider transactions reported on Forms 3/4/5.
147    InsiderTrades,
148    /// Institutional holdings reported on Form 13F-HR.
149    InstitutionalHoldings,
150    /// Congressional (senate) stock-trade disclosures.
151    CongressionalTrades,
152    /// SEC fails-to-deliver data.
153    FailsToDeliver,
154    /// A macro series as it stood on a past date (vintage/ALFRED view).
155    EconomicSeriesAsOf,
156    /// Free-text search over the macro series catalog.
157    EconomicSearch,
158    /// Macro series category browsing.
159    EconomicCategories,
160    /// Scheduled macro data releases.
161    EconomicReleases,
162    /// US Treasury securities auctions, announced through settled.
163    #[cfg(feature = "fiscaldata")]
164    TreasuryAuctions,
165    /// US Treasury auctions scheduled but not yet held.
166    #[cfg(feature = "fiscaldata")]
167    UpcomingAuctions,
168    /// ETF profile and portfolio holdings.
169    EtfProfile,
170    /// Earnings-surprise history.
171    EarningsSurprises,
172    /// Raw per-analyst grade-action history.
173    GradingHistory,
174    /// The provider's whole listed-security universe.
175    ListingStatus,
176    /// Grouped daily OHLCV bars for every stock ticker on one date.
177    GroupedDaily,
178    /// Grouped daily OHLCV bars for every crypto ticker on one date.
179    CryptoGroupedDaily,
180    /// Grouped daily OHLCV bars for every forex ticker on one date.
181    ForexGroupedDaily,
182    /// Coins/nfts/categories trending in the last 24h.
183    #[cfg(feature = "crypto")]
184    CryptoTrending,
185    /// Aggregate global cryptocurrency market statistics.
186    #[cfg(feature = "crypto")]
187    CryptoGlobal,
188}
189
190impl Operation {
191    /// Short lowercase identifier (e.g. `"chart_range"`, `"crypto_quote"`).
192    pub fn as_str(self) -> &'static str {
193        match self {
194            Self::DelistedStocksPage => "delisted_stocks_page",
195            Self::DelistedStocksPageAt => "delisted_stocks_page_at",
196            Self::StockList => "stock_list",
197            Self::CompanyProfilesBulk => "company_profiles_bulk",
198            Self::StockListingsPage => "stock_listings_page",
199            Self::SymbolDetailsAt => "symbol_details_at",
200            Self::StockTypes => "stock_types",
201            Self::TickerChanges => "ticker_changes",
202            Self::StockBarsPage => "stock_bars_page",
203            Self::Quote => "quote",
204            Self::Chart => "chart",
205            Self::ChartRange => "chart_range",
206            Self::Financials => "financials",
207            Self::News => "news",
208            Self::Recommendations => "recommendations",
209            Self::Options => "options",
210            Self::Events => "events",
211            Self::QuotesBatch => "quotes_batch",
212            Self::Spark => "spark",
213            Self::CryptoQuote => "crypto_quote",
214            Self::CryptoNews => "crypto_news",
215            Self::EconomicSeries => "economic_series",
216            Self::ForexQuote => "forex_quote",
217            Self::ForexNews => "forex_news",
218            Self::IndicesQuote => "indices_quote",
219            Self::FuturesQuote => "futures_quote",
220            Self::CommoditiesQuote => "commodities_quote",
221            Self::Filings => "filings",
222            Self::SymbolSearch => "symbol_search",
223            Self::SymbolDetails => "symbol_details",
224            Self::Exchanges => "exchanges",
225            Self::Screener => "screener",
226            Self::EarningsCalendar => "earnings_calendar",
227            Self::IpoCalendar => "ipo_calendar",
228            Self::DividendCalendar => "dividend_calendar",
229            Self::SplitCalendar => "split_calendar",
230            Self::EconomicCalendar => "economic_calendar",
231            Self::SectorPerformance => "sector_performance",
232            Self::MarketMovers => "market_movers",
233            Self::SectorPerformanceHistory => "sector_performance_history",
234            Self::HolidayCalendar => "holiday_calendar",
235            Self::MarketStatus => "market_status",
236            Self::IndexConstituents => "index_constituents",
237            Self::IndexConstituentChanges => "index_constituent_changes",
238            Self::ShortInterest => "short_interest",
239            Self::ShortVolume => "short_volume",
240            Self::ShareFloat => "share_float",
241            Self::FilingSections => "filing_sections",
242            Self::RiskFactors => "risk_factors",
243            Self::PressReleases => "press_releases",
244            Self::EarningsTranscript => "earnings_transcript",
245            #[cfg(feature = "defi")]
246            Self::ProtocolTvl => "protocol_tvl",
247            #[cfg(feature = "defi")]
248            Self::ProtocolTvlHistory => "protocol_tvl_history",
249            #[cfg(feature = "cftc")]
250            Self::CommitmentsOfTraders => "commitments_of_traders",
251            Self::PriceTargetConsensus => "price_target_consensus",
252            Self::PriceTargetSummary => "price_target_summary",
253            Self::RatingConsensus => "rating_consensus",
254            Self::KeyMetricsTtm => "key_metrics_ttm",
255            Self::RatiosTtm => "ratios_ttm",
256            Self::ExecutiveCompensation => "executive_compensation",
257            Self::EmployeeCount => "employee_count",
258            Self::CompanyProfile => "company_profile",
259            Self::UnifiedSnapshot => "unified_snapshot",
260            Self::FilingSearch => "filing_search",
261            Self::InsiderTrades => "insider_trades",
262            Self::InstitutionalHoldings => "institutional_holdings",
263            Self::CongressionalTrades => "congressional_trades",
264            Self::FailsToDeliver => "fails_to_deliver",
265            Self::EconomicSeriesAsOf => "economic_series_as_of",
266            Self::EconomicSearch => "economic_search",
267            Self::EconomicCategories => "economic_categories",
268            Self::EconomicReleases => "economic_releases",
269            #[cfg(feature = "fiscaldata")]
270            Self::TreasuryAuctions => "treasury_auctions",
271            #[cfg(feature = "fiscaldata")]
272            Self::UpcomingAuctions => "upcoming_auctions",
273            Self::EtfProfile => "etf_profile",
274            Self::EarningsSurprises => "earnings_surprises",
275            Self::GradingHistory => "grading_history",
276            Self::ListingStatus => "listing_status",
277            Self::GroupedDaily => "grouped_daily",
278            Self::CryptoGroupedDaily => "crypto_grouped_daily",
279            Self::ForexGroupedDaily => "forex_grouped_daily",
280            #[cfg(feature = "crypto")]
281            Self::CryptoTrending => "crypto_trending",
282            #[cfg(feature = "crypto")]
283            Self::CryptoGlobal => "crypto_global",
284        }
285    }
286
287    /// The coarser [`Capability`] bit this operation falls under.
288    pub fn capability(self) -> Capability {
289        match self {
290            Self::DelistedStocksPage
291            | Self::DelistedStocksPageAt
292            | Self::StockList
293            | Self::CompanyProfilesBulk
294            | Self::StockListingsPage
295            | Self::SymbolDetailsAt
296            | Self::StockTypes
297            | Self::TickerChanges => Capability::DISCOVERY,
298            Self::StockBarsPage => Capability::CHART,
299            Self::Quote | Self::QuotesBatch | Self::UnifiedSnapshot => Capability::QUOTE,
300            Self::Chart
301            | Self::ChartRange
302            | Self::Spark
303            | Self::GroupedDaily
304            | Self::CryptoGroupedDaily
305            | Self::ForexGroupedDaily => Capability::CHART,
306            Self::Financials
307            | Self::ShortInterest
308            | Self::ShortVolume
309            | Self::ShareFloat
310            | Self::PriceTargetConsensus
311            | Self::PriceTargetSummary
312            | Self::RatingConsensus
313            | Self::KeyMetricsTtm
314            | Self::RatiosTtm
315            | Self::EtfProfile
316            | Self::EarningsSurprises
317            | Self::GradingHistory
318            | Self::CompanyProfile => Capability::FUNDAMENTALS,
319            Self::News
320            | Self::Recommendations
321            | Self::Events
322            | Self::PressReleases
323            | Self::ExecutiveCompensation
324            | Self::EmployeeCount
325            | Self::EarningsTranscript => Capability::CORPORATE,
326            Self::Options => Capability::OPTIONS,
327            Self::CryptoQuote | Self::CryptoNews => Capability::CRYPTO,
328            #[cfg(feature = "defi")]
329            Self::ProtocolTvl | Self::ProtocolTvlHistory => Capability::CRYPTO,
330            #[cfg(feature = "crypto")]
331            Self::CryptoTrending | Self::CryptoGlobal => Capability::CRYPTO,
332            Self::EconomicSeries
333            | Self::EconomicSeriesAsOf
334            | Self::EconomicSearch
335            | Self::EconomicCategories
336            | Self::EconomicReleases => Capability::ECONOMIC,
337            #[cfg(feature = "fiscaldata")]
338            Self::TreasuryAuctions | Self::UpcomingAuctions => Capability::ECONOMIC,
339            Self::ForexQuote | Self::ForexNews => Capability::FOREX,
340            Self::IndicesQuote | Self::IndexConstituents | Self::IndexConstituentChanges => {
341                Capability::INDICES
342            }
343            Self::FuturesQuote => Capability::FUTURES,
344            #[cfg(feature = "cftc")]
345            Self::CommitmentsOfTraders => Capability::FUTURES,
346            Self::CommoditiesQuote => Capability::COMMODITIES,
347            Self::Filings
348            | Self::FilingSections
349            | Self::RiskFactors
350            | Self::FilingSearch
351            | Self::InsiderTrades
352            | Self::InstitutionalHoldings
353            | Self::CongressionalTrades
354            | Self::FailsToDeliver => Capability::FILINGS,
355            Self::SymbolSearch
356            | Self::SymbolDetails
357            | Self::Exchanges
358            | Self::Screener
359            | Self::ListingStatus => Capability::DISCOVERY,
360            Self::EarningsCalendar
361            | Self::IpoCalendar
362            | Self::DividendCalendar
363            | Self::SplitCalendar
364            | Self::EconomicCalendar
365            | Self::HolidayCalendar
366            | Self::MarketStatus => Capability::CALENDAR,
367            Self::SectorPerformance | Self::MarketMovers | Self::SectorPerformanceHistory => {
368                Capability::MARKET
369            }
370        }
371    }
372
373    /// The error reported when `provider` does not serve this operation.
374    ///
375    /// Adapters reach for this when they detect the gap before dispatch has a
376    /// `&dyn ProviderAdapter` to hand (e.g. a symbol an exchange cannot name);
377    /// `ProviderCore::not_supported` is the same error built from an instance.
378    pub(crate) fn not_supported(self, provider: Provider) -> FinanceError {
379        FinanceError::NotSupported {
380            provider,
381            operation: self,
382            candidates: self.capability().candidate_providers(),
383        }
384    }
385}
386
387impl std::fmt::Display for Operation {
388    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
389        f.write_str(self.as_str())
390    }
391}