Skip to main content

finance_query/
lib.rs

1//! # finance-query
2//!
3//! A Rust library for querying financial data.
4//! Inspired by yfinance, with smart lazy loading for efficient data fetching.
5//!
6//! ## Quick Start
7//!
8//! ```no_run
9//! use finance_query::Ticker;
10//!
11//! #[tokio::main]
12//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
13//!     // Simple: Create a ticker with default configuration
14//!     let ticker = Ticker::new("AAPL").await?;
15//!
16//!     // First access to any quote property fetches ALL quote modules in one request
17//!     if let Some(financials) = ticker.financial_data().await? {
18//!         println!("Financial data: {:?}", financials);
19//!     }
20//!
21//!     // Subsequent accesses use cached data (no additional network calls)
22//!     if let Some(profile) = ticker.asset_profile().await? {
23//!         println!("Company profile: {:?}", profile);
24//!     }
25//!
26//!     // Chart data is fetched separately and cached by interval/range
27//!     let chart = ticker.chart(
28//!         finance_query::Interval::OneDay,
29//!         finance_query::TimeRange::OneMonth
30//!     ).await?;
31//!     println!("Candles: {}", chart.candles.len());
32//!
33//!     // Builder pattern: Fluent configuration
34//!     let ticker_jp = Ticker::builder("7203.T")
35//!         .lang("ja-JP")
36//!         .region_code("JP")
37//!         .timeout(std::time::Duration::from_secs(30))
38//!         .build()
39//!         .await?;
40//!
41//!     Ok(())
42//! }
43//! ```
44//!
45//! ## Lazy Loading
46//!
47//! The library uses lazy loading:
48//! - **Quote data**: All ~30 quote modules fetched together on first property access
49//! - **Chart data**: Fetched per (interval, range) combination and cached
50//! - **Recommendations**: Fetched once and cached
51//!
52//! This approach minimizes network requests while keeping memory usage efficient.
53
54#![warn(missing_docs)]
55#![warn(rustdoc::missing_crate_level_docs)]
56
57// === Modules ===
58// Public modules
59/// External data source adapters (internal — use the public API modules).
60pub(crate) mod adapters;
61/// Error types and result definitions.
62pub mod error;
63/// Non-symbol-specific operations (search, lookup, screeners, market data, etc.).
64pub mod finance;
65pub mod edgar {
66    //! SEC EDGAR API client (keyless — always available, no feature flag needed).
67    //!
68    //!
69    //! Requires a one-time [`init`] call with a contact email address.
70    pub use crate::adapters::edgar::{
71        company_facts, filing_index, init, init_with_config, resolve_cik, search, submissions,
72    };
73}
74
75// Internal modules
76mod constants;
77mod models;
78mod providers;
79pub(crate) mod rate_limiter;
80mod scrapers;
81mod ticker;
82mod tickers;
83mod utils;
84
85// Feature-gated external data source modules
86#[cfg(feature = "fred")]
87pub mod fred {
88    //! FRED economic data API (requires `fred` feature).
89    //!
90    //! Access 800k+ macroeconomic time series and US Treasury yield curve data.
91    pub use crate::adapters::fred::{init, init_with_timeout, series, treasury_yields};
92    pub use crate::models::economic::{MacroObservation, MacroSeries, TreasuryYield};
93}
94
95#[cfg(feature = "crypto")]
96pub mod crypto {
97    //! CoinGecko cryptocurrency data (requires `crypto` feature).
98    pub use crate::adapters::coingecko::{CoinQuote, coin, coins};
99}
100
101pub mod feeds;
102
103#[cfg(feature = "risk")]
104pub mod risk;
105
106#[cfg(feature = "translation")]
107pub mod translation;
108
109// ============================================================================
110// High-level API - Primary interface for most use cases
111// ============================================================================
112pub mod domains;
113pub use providers::config::{Providers, ProvidersBuilder};
114pub use providers::{Capability, Fetch, Operation, Provider};
115pub use ticker::{ClientHandle, Ticker, TickerBuilder};
116
117// Domain-specific query handles — constructable via Providers factory methods.
118#[cfg(any(
119    feature = "alphavantage",
120    feature = "crypto",
121    feature = "fmp",
122    feature = "polygon"
123))]
124pub use domains::CryptoCoin;
125#[cfg(any(feature = "alphavantage", feature = "polygon", feature = "fred"))]
126pub use domains::EconomicIndicator;
127#[cfg(any(feature = "alphavantage", feature = "fmp", feature = "polygon"))]
128pub use domains::ForexPair;
129
130// Remaining Capability handles — indices, futures, commodities, filings
131#[cfg(any(feature = "fmp", feature = "alphavantage"))]
132pub use domains::Commodity;
133pub use domains::Filings;
134#[cfg(feature = "polygon")]
135pub use domains::FuturesContract;
136#[cfg(any(feature = "polygon", feature = "fmp"))]
137pub use domains::Index;
138
139// Provider-specific financial data functions
140// (FMP, Polygon, Alpha Vantage — defined in the finance module)
141#[cfg(feature = "polygon")]
142pub use finance::symbol_sentiment;
143#[cfg(feature = "fmp")]
144pub use finance::{
145    AnalystEstimate, AnalystRecommendation, InsiderTransaction, Period, analyst_estimates,
146    analyst_recommendations, insider_trading,
147};
148#[cfg(feature = "alphavantage")]
149pub use finance::{EarningsCalendarEntry, IpoCalendarEntry, earnings_calendar, ipo_calendar};
150
151pub use tickers::{
152    BatchCapitalGainsResponse, BatchChartsResponse, BatchDividendsResponse,
153    BatchFinancialsResponse, BatchNewsResponse, BatchOptionsResponse, BatchQuotesResponse,
154    BatchRecommendationsResponse, BatchSparksResponse, BatchSplitsResponse, Tickers,
155    TickersBuilder,
156};
157
158#[cfg(feature = "indicators")]
159pub use tickers::BatchIndicatorsResponse;
160
161// ============================================================================
162// Error types and results
163// ============================================================================
164pub use error::{ErrorCategory, FinanceError, Result};
165
166// ============================================================================
167// Options - Configure API requests
168// ============================================================================
169pub use finance::{LookupOptions, LookupType, SearchOptions};
170
171// ============================================================================
172// Parameter enums - Used with Ticker and finance methods
173// ============================================================================
174pub use constants::indices::Region as IndicesRegion;
175pub use constants::screeners::Screener;
176pub use constants::sectors::Sector;
177pub use constants::{Frequency, Interval, Region, StatementType, TimeRange, ValueFormat};
178
179// ============================================================================
180// Response types - Top-level types returned by API methods
181// ============================================================================
182pub use models::{
183    calendar::{CalendarEvent, EventKind},
184    chart::Chart,
185    chart::spark::Spark,
186    corporate::news::News,
187    corporate::recommendation::Recommendation,
188    corporate::transcript::{Transcript, TranscriptWithMeta},
189    discovery::lookup::LookupResults,
190    discovery::screeners::ScreenerResults,
191    discovery::search::SearchResults,
192    discovery::trending::TrendingQuote,
193    filings::{
194        CompanyFacts, EdgarSearchResults, EdgarSubmissions, ProviderFiling, ProviderFilings,
195    },
196    fundamentals::FinancialStatement,
197    market::currencies::Currency,
198    market::exchanges::Exchange,
199    market::hours::MarketHours,
200    market::industries::IndustryData,
201    market::market_summary::MarketSummaryQuote,
202    market::sectors::SectorData,
203    options::Options,
204    quote::Quote,
205    sentiment::{FearAndGreed, FearGreedLabel, SymbolSentiment},
206};
207// Offline VADER sentiment scoring (feature-gated)
208#[cfg(feature = "sentiment")]
209pub use models::sentiment::{Sentiment, SentimentLabel, analyze as analyze_sentiment};
210// Multi-provider capability response types (feature-gated)
211#[cfg(any(feature = "fmp", feature = "alphavantage"))]
212pub use models::commodities::CommodityQuote;
213#[cfg(any(
214    feature = "crypto",
215    feature = "alphavantage",
216    feature = "fmp",
217    feature = "polygon"
218))]
219pub use models::crypto::CryptoQuote;
220#[cfg(any(feature = "fred", feature = "alphavantage", feature = "polygon"))]
221pub use models::economic::EconomicSeries;
222#[cfg(any(feature = "alphavantage", feature = "fmp", feature = "polygon"))]
223pub use models::forex::ForexQuote;
224#[cfg(feature = "polygon")]
225pub use models::futures::FuturesQuote;
226#[cfg(any(feature = "polygon", feature = "fmp"))]
227pub use models::indices::IndexQuote;
228
229// ============================================================================
230// Nested types - Commonly accessed fields within response types
231// ============================================================================
232pub use models::{
233    chart::{Candle, CapitalGain, ChartMeta, Dividend, DividendAnalytics, Split},
234    corporate::recommendation::SimilarSymbol,
235    discovery::lookup::LookupQuote,
236    discovery::screeners::ScreenerQuote,
237    discovery::search::{
238        ResearchReport, ResearchReports, SearchNews, SearchNewsList, SearchQuote, SearchQuotes,
239    },
240    filings::filing_index::{EdgarFilingIndex, EdgarFilingIndexItem},
241    filings::{
242        CikEntry, EdgarFiling, EdgarFilingFile, EdgarFilingRecent, EdgarFilings, EdgarSearchHit,
243        EdgarSearchHitsContainer, EdgarSearchSource, EdgarSearchTotal, FactConcept, FactUnit,
244        FactsByTaxonomy,
245    },
246    market::hours::MarketTime,
247    market::market_summary::SparkData,
248    options::{Contracts, OptionChain, OptionContract, OptionsQuote},
249    quote::FormattedValue,
250};
251
252// ============================================================================
253// Query builders - Types for constructing custom screener queries
254// ============================================================================
255pub use constants::exchange_codes::ExchangeCode;
256pub use constants::industries::Industry;
257pub use models::discovery::screeners::{
258    ConditionValue, EquityField, EquityScreenerQuery, FundField, FundScreenerQuery,
259    LogicalOperator, Operator, QueryCondition, QueryGroup, QueryOperand, QuoteType, ScreenerField,
260    ScreenerFieldExt, ScreenerFundCategory, ScreenerPeerGroup, ScreenerQuery, SortType,
261};
262
263// ============================================================================
264// Real-time streaming
265// ============================================================================
266// WebSocket-based real-time price streaming with a Flow-like Stream API.
267pub mod streaming;
268
269// ============================================================================
270// Format type parameters — phantom types for compile-time format selection
271// ============================================================================
272
273/// Compile-time format type parameters for [`Quote`](crate::Quote) and other
274/// `FormattedValue`-bearing structs.
275///
276/// | Marker | `F::Value<f64>` | Access pattern |
277/// |---|---|---|
278/// | [`format::Both`]  | `FormattedValue<f64>` | `.raw` / `.fmt` / `.long_fmt` |
279/// | [`format::Raw`]   | `f64`                 | direct (no unwrapping) |
280/// | [`format::Pretty`] | `String`             | human-readable string |
281///
282/// ```no_run
283/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
284/// use finance_query::{format, Ticker};
285/// let ticker = Ticker::new("AAPL").await?;
286/// let quote: finance_query::Quote<format::Raw> = ticker.quote().await?;
287/// # Ok(())
288/// # }
289/// ```
290pub mod format {
291    pub use crate::models::format::{Both, Pretty, Raw};
292}
293
294// ============================================================================
295// DataFrame support (requires "dataframe" feature)
296// ============================================================================
297// When enabled, structs with #[derive(ToDataFrame)] get a to_dataframe() method.
298// The derive macro auto-generates DataFrame conversion for all scalar fields.
299#[cfg(feature = "dataframe")]
300pub use finance_query_derive::ToDataFrame;
301
302// ============================================================================
303// Technical Indicators (requires "indicators" feature)
304// ============================================================================
305// Technical analysis indicators for price data (SMA, EMA, RSI, MACD, Bollinger Bands).
306// When enabled, Chart gets extension methods: chart.sma(), chart.ema(), chart.rsi(), etc.
307#[cfg(feature = "indicators")]
308pub mod indicators;
309
310#[cfg(feature = "indicators")]
311pub use indicators::{
312    // Summary types
313    AroonData,
314    // Individual indicator types
315    BollingerBands,
316    BollingerBandsData,
317    BullBearPowerData,
318    // Candlestick pattern types
319    CandlePattern,
320    DonchianChannelsData,
321    ElderRayData,
322    IchimokuData,
323    Indicator,
324    IndicatorError,
325    IndicatorResult,
326    IndicatorsSummary,
327    KeltnerChannelsData,
328    MacdData,
329    MacdResult,
330    PatternSentiment,
331    StochasticData,
332    SuperTrendData,
333    atr,
334    patterns,
335};
336
337// ============================================================================
338// Backtesting Engine (requires "backtesting" feature)
339// ============================================================================
340// Strategy backtesting with pre-built and custom strategies, position tracking,
341// stop-loss/take-profit, comprehensive performance metrics, parameter optimization,
342// walk-forward validation, Monte Carlo simulation, and multi-symbol portfolio.
343#[cfg(feature = "backtesting")]
344pub mod backtesting;
345
346// ============================================================================
347// Compile-time thread-safety assertions
348// ============================================================================
349// Ticker and Tickers must be Send + Sync so they can be shared across
350// async tasks and held across .await points (e.g., in Arc, tokio::spawn).
351const _: () = {
352    const fn assert_send_sync<T: Send + Sync>() {}
353    let _ = assert_send_sync::<Ticker>;
354    let _ = assert_send_sync::<Tickers>;
355};