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