Skip to main content

finance_query/
constants.rs

1use serde::{Deserialize, Serialize};
2
3/// Predefined screener selectors for Yahoo Finance
4pub mod screeners {
5    /// Predefined Yahoo Finance screener selector
6    ///
7    /// Passed to `finance::screener()` or `client.get_screener()` to select one of the
8    /// 15 built-in Yahoo Finance screeners (equity or fund).
9    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10    pub enum Screener {
11        // Equity screeners
12        /// Small caps with high EPS growth, sorted by volume
13        AggressiveSmallCaps,
14        /// Top gaining stocks (>3% change, >$2B market cap)
15        DayGainers,
16        /// Top losing stocks (<-2.5% change, >$2B market cap)
17        DayLosers,
18        /// Tech stocks with 25%+ revenue and EPS growth
19        GrowthTechnologyStocks,
20        /// Most actively traded stocks by volume
21        MostActives,
22        /// Stocks with highest short interest percentage
23        MostShortedStocks,
24        /// Small cap gainers (<$2B market cap)
25        SmallCapGainers,
26        /// Low P/E (<20), low PEG (<1), high EPS growth (25%+)
27        UndervaluedGrowthStocks,
28        /// Large caps ($10B-$100B) with low P/E and PEG
29        UndervaluedLargeCaps,
30        // Fund screeners
31        /// Low-risk foreign large cap funds (4-5 star rated)
32        ConservativeForeignFunds,
33        /// High yield bond funds (4-5 star rated)
34        HighYieldBond,
35        /// Large blend core funds (4-5 star rated)
36        PortfolioAnchors,
37        /// Large growth funds (4-5 star rated)
38        SolidLargeGrowthFunds,
39        /// Mid-cap growth funds (4-5 star rated)
40        SolidMidcapGrowthFunds,
41        /// Top performing mutual funds by percent change
42        TopMutualFunds,
43    }
44
45    impl Screener {
46        /// Convert to Yahoo Finance scrId parameter value (SCREAMING_SNAKE_CASE)
47        pub fn as_scr_id(&self) -> &'static str {
48            match self {
49                Screener::AggressiveSmallCaps => "aggressive_small_caps",
50                Screener::DayGainers => "day_gainers",
51                Screener::DayLosers => "day_losers",
52                Screener::GrowthTechnologyStocks => "growth_technology_stocks",
53                Screener::MostActives => "most_actives",
54                Screener::MostShortedStocks => "most_shorted_stocks",
55                Screener::SmallCapGainers => "small_cap_gainers",
56                Screener::UndervaluedGrowthStocks => "undervalued_growth_stocks",
57                Screener::UndervaluedLargeCaps => "undervalued_large_caps",
58                Screener::ConservativeForeignFunds => "conservative_foreign_funds",
59                Screener::HighYieldBond => "high_yield_bond",
60                Screener::PortfolioAnchors => "portfolio_anchors",
61                Screener::SolidLargeGrowthFunds => "solid_large_growth_funds",
62                Screener::SolidMidcapGrowthFunds => "solid_midcap_growth_funds",
63                Screener::TopMutualFunds => "top_mutual_funds",
64            }
65        }
66
67        /// Parse from string, returns None on invalid input
68        ///
69        /// # Example
70        /// ```
71        /// use finance_query::Screener;
72        ///
73        /// assert_eq!(Screener::parse("most-actives"), Some(Screener::MostActives));
74        /// assert_eq!(Screener::parse("day-gainers"), Some(Screener::DayGainers));
75        /// ```
76        pub fn parse(s: &str) -> Option<Self> {
77            s.parse().ok()
78        }
79
80        /// List all valid screener types for error messages
81        pub fn valid_types() -> &'static str {
82            "aggressive-small-caps, day-gainers, day-losers, growth-technology-stocks, \
83             most-actives, most-shorted-stocks, small-cap-gainers, undervalued-growth-stocks, \
84             undervalued-large-caps, conservative-foreign-funds, high-yield-bond, \
85             portfolio-anchors, solid-large-growth-funds, solid-midcap-growth-funds, \
86             top-mutual-funds"
87        }
88
89        /// Get all screener types as an array
90        pub fn all() -> &'static [Screener] {
91            &[
92                Screener::AggressiveSmallCaps,
93                Screener::DayGainers,
94                Screener::DayLosers,
95                Screener::GrowthTechnologyStocks,
96                Screener::MostActives,
97                Screener::MostShortedStocks,
98                Screener::SmallCapGainers,
99                Screener::UndervaluedGrowthStocks,
100                Screener::UndervaluedLargeCaps,
101                Screener::ConservativeForeignFunds,
102                Screener::HighYieldBond,
103                Screener::PortfolioAnchors,
104                Screener::SolidLargeGrowthFunds,
105                Screener::SolidMidcapGrowthFunds,
106                Screener::TopMutualFunds,
107            ]
108        }
109    }
110
111    impl std::str::FromStr for Screener {
112        type Err = ();
113
114        fn from_str(s: &str) -> Result<Self, Self::Err> {
115            match s.to_lowercase().replace('_', "-").as_str() {
116                "aggressive-small-caps" => Ok(Screener::AggressiveSmallCaps),
117                "day-gainers" | "gainers" => Ok(Screener::DayGainers),
118                "day-losers" | "losers" => Ok(Screener::DayLosers),
119                "growth-technology-stocks" | "growth-tech" => Ok(Screener::GrowthTechnologyStocks),
120                "most-actives" | "actives" => Ok(Screener::MostActives),
121                "most-shorted-stocks" | "most-shorted" => Ok(Screener::MostShortedStocks),
122                "small-cap-gainers" => Ok(Screener::SmallCapGainers),
123                "undervalued-growth-stocks" | "undervalued-growth" => {
124                    Ok(Screener::UndervaluedGrowthStocks)
125                }
126                "undervalued-large-caps" | "undervalued-large" => {
127                    Ok(Screener::UndervaluedLargeCaps)
128                }
129                "conservative-foreign-funds" => Ok(Screener::ConservativeForeignFunds),
130                "high-yield-bond" => Ok(Screener::HighYieldBond),
131                "portfolio-anchors" => Ok(Screener::PortfolioAnchors),
132                "solid-large-growth-funds" => Ok(Screener::SolidLargeGrowthFunds),
133                "solid-midcap-growth-funds" => Ok(Screener::SolidMidcapGrowthFunds),
134                "top-mutual-funds" => Ok(Screener::TopMutualFunds),
135                _ => Err(()),
136            }
137        }
138    }
139}
140
141/// Yahoo Finance sector types
142///
143/// These are the 11 GICS sectors available on Yahoo Finance.
144pub mod sectors {
145    use serde::{Deserialize, Serialize};
146
147    /// Market sector types available on Yahoo Finance
148    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149    #[serde(rename_all = "kebab-case")]
150    pub enum Sector {
151        /// Technology sector (software, semiconductors, hardware)
152        Technology,
153        /// Financial Services sector (banks, insurance, asset management)
154        FinancialServices,
155        /// Consumer Cyclical sector (retail, automotive, leisure)
156        ConsumerCyclical,
157        /// Communication Services sector (telecom, media, entertainment)
158        CommunicationServices,
159        /// Healthcare sector (pharma, biotech, medical devices)
160        Healthcare,
161        /// Industrials sector (aerospace, machinery, construction)
162        Industrials,
163        /// Consumer Defensive sector (food, beverages, household products)
164        ConsumerDefensive,
165        /// Energy sector (oil, gas, renewable energy)
166        Energy,
167        /// Basic Materials sector (chemicals, metals, mining)
168        BasicMaterials,
169        /// Real Estate sector (REITs, property management)
170        RealEstate,
171        /// Utilities sector (electric, gas, water utilities)
172        Utilities,
173    }
174
175    impl Sector {
176        /// Convert to Yahoo Finance API path segment (lowercase with hyphens)
177        pub fn as_api_path(&self) -> &'static str {
178            match self {
179                Sector::Technology => "technology",
180                Sector::FinancialServices => "financial-services",
181                Sector::ConsumerCyclical => "consumer-cyclical",
182                Sector::CommunicationServices => "communication-services",
183                Sector::Healthcare => "healthcare",
184                Sector::Industrials => "industrials",
185                Sector::ConsumerDefensive => "consumer-defensive",
186                Sector::Energy => "energy",
187                Sector::BasicMaterials => "basic-materials",
188                Sector::RealEstate => "real-estate",
189                Sector::Utilities => "utilities",
190            }
191        }
192
193        /// Get human-readable display name
194        pub fn display_name(&self) -> &'static str {
195            match self {
196                Sector::Technology => "Technology",
197                Sector::FinancialServices => "Financial Services",
198                Sector::ConsumerCyclical => "Consumer Cyclical",
199                Sector::CommunicationServices => "Communication Services",
200                Sector::Healthcare => "Healthcare",
201                Sector::Industrials => "Industrials",
202                Sector::ConsumerDefensive => "Consumer Defensive",
203                Sector::Energy => "Energy",
204                Sector::BasicMaterials => "Basic Materials",
205                Sector::RealEstate => "Real Estate",
206                Sector::Utilities => "Utilities",
207            }
208        }
209
210        /// List all valid sector types for error messages
211        pub fn valid_types() -> &'static str {
212            "technology, financial-services, consumer-cyclical, communication-services, \
213             healthcare, industrials, consumer-defensive, energy, basic-materials, \
214             real-estate, utilities"
215        }
216
217        /// Get all sector types as an array
218        pub fn all() -> &'static [Sector] {
219            &[
220                Sector::Technology,
221                Sector::FinancialServices,
222                Sector::ConsumerCyclical,
223                Sector::CommunicationServices,
224                Sector::Healthcare,
225                Sector::Industrials,
226                Sector::ConsumerDefensive,
227                Sector::Energy,
228                Sector::BasicMaterials,
229                Sector::RealEstate,
230                Sector::Utilities,
231            ]
232        }
233    }
234
235    impl std::str::FromStr for Sector {
236        type Err = ();
237
238        fn from_str(s: &str) -> Result<Self, Self::Err> {
239            match s.to_lowercase().replace('_', "-").as_str() {
240                "technology" | "tech" => Ok(Sector::Technology),
241                "financial-services" | "financials" | "financial" => Ok(Sector::FinancialServices),
242                "consumer-cyclical" => Ok(Sector::ConsumerCyclical),
243                "communication-services" | "communication" => Ok(Sector::CommunicationServices),
244                "healthcare" | "health" => Ok(Sector::Healthcare),
245                "industrials" | "industrial" => Ok(Sector::Industrials),
246                "consumer-defensive" => Ok(Sector::ConsumerDefensive),
247                "energy" => Ok(Sector::Energy),
248                "basic-materials" | "materials" => Ok(Sector::BasicMaterials),
249                "real-estate" | "realestate" => Ok(Sector::RealEstate),
250                "utilities" | "utility" => Ok(Sector::Utilities),
251                _ => Err(()),
252            }
253        }
254    }
255
256    impl std::fmt::Display for Sector {
257        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258            write!(f, "{}", self.display_name())
259        }
260    }
261
262    impl From<Sector> for String {
263        /// Returns the display name used by Yahoo Finance screener (e.g. `"Technology"`).
264        fn from(v: Sector) -> Self {
265            v.display_name().to_string()
266        }
267    }
268}
269
270/// World market indices
271pub mod indices {
272    /// Region categories for world indices
273    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
274    pub enum Region {
275        /// North and South America
276        Americas,
277        /// European markets
278        Europe,
279        /// Asia and Pacific markets
280        AsiaPacific,
281        /// Middle East and Africa
282        MiddleEastAfrica,
283        /// Currency indices
284        Currencies,
285    }
286
287    impl std::str::FromStr for Region {
288        type Err = ();
289
290        fn from_str(s: &str) -> Result<Self, Self::Err> {
291            match s.to_lowercase().replace(['-', '_'], "").as_str() {
292                "americas" | "america" => Ok(Region::Americas),
293                "europe" | "eu" => Ok(Region::Europe),
294                "asiapacific" | "asia" | "apac" => Ok(Region::AsiaPacific),
295                "middleeastafrica" | "mea" | "emea" => Ok(Region::MiddleEastAfrica),
296                "currencies" | "currency" | "fx" => Ok(Region::Currencies),
297                _ => Err(()),
298            }
299        }
300    }
301
302    impl Region {
303        /// Parse from string, returns None on invalid input
304        pub fn parse(s: &str) -> Option<Self> {
305            s.parse().ok()
306        }
307
308        /// Get the symbols for this region
309        pub fn symbols(&self) -> &'static [&'static str] {
310            match self {
311                Region::Americas => AMERICAS,
312                Region::Europe => EUROPE,
313                Region::AsiaPacific => ASIA_PACIFIC,
314                Region::MiddleEastAfrica => MIDDLE_EAST_AFRICA,
315                Region::Currencies => CURRENCIES,
316            }
317        }
318
319        /// Convert to string representation
320        pub fn as_str(&self) -> &'static str {
321            match self {
322                Region::Americas => "americas",
323                Region::Europe => "europe",
324                Region::AsiaPacific => "asia-pacific",
325                Region::MiddleEastAfrica => "middle-east-africa",
326                Region::Currencies => "currencies",
327            }
328        }
329
330        /// All region variants
331        pub fn all() -> &'static [Region] {
332            &[
333                Region::Americas,
334                Region::Europe,
335                Region::AsiaPacific,
336                Region::MiddleEastAfrica,
337                Region::Currencies,
338            ]
339        }
340    }
341
342    /// Americas indices
343    pub const AMERICAS: &[&str] = &[
344        "^GSPC",   // S&P 500
345        "^DJI",    // Dow Jones Industrial Average
346        "^IXIC",   // NASDAQ Composite
347        "^NYA",    // NYSE Composite Index
348        "^XAX",    // NYSE American Composite Index
349        "^RUT",    // Russell 2000 Index
350        "^VIX",    // CBOE Volatility Index
351        "^GSPTSE", // S&P/TSX Composite (Canada)
352        "^BVSP",   // IBOVESPA (Brazil)
353        "^MXX",    // IPC MEXICO
354        "^IPSA",   // S&P IPSA (Chile)
355        "^MERV",   // MERVAL (Argentina)
356    ];
357
358    /// Europe indices
359    pub const EUROPE: &[&str] = &[
360        "^FTSE",            // FTSE 100 (UK)
361        "^GDAXI",           // DAX (Germany)
362        "^FCHI",            // CAC 40 (France)
363        "^STOXX50E",        // EURO STOXX 50
364        "^N100",            // Euronext 100 Index
365        "^BFX",             // BEL 20 (Belgium)
366        "^BUK100P",         // Cboe UK 100
367        "MOEX.ME",          // Moscow Exchange
368        "^125904-USD-STRD", // MSCI EUROPE
369    ];
370
371    /// Asia Pacific indices
372    pub const ASIA_PACIFIC: &[&str] = &[
373        "^N225",     // Nikkei 225 (Japan)
374        "^HSI",      // Hang Seng Index (Hong Kong)
375        "000001.SS", // SSE Composite Index (China)
376        "^KS11",     // KOSPI (South Korea)
377        "^TWII",     // Taiwan Weighted Index
378        "^STI",      // STI Index (Singapore)
379        "^AXJO",     // S&P/ASX 200 (Australia)
380        "^AORD",     // All Ordinaries (Australia)
381        "^NZ50",     // S&P/NZX 50 (New Zealand)
382        "^BSESN",    // S&P BSE SENSEX (India)
383        "^JKSE",     // IDX Composite (Indonesia)
384        "^KLSE",     // FTSE Bursa Malaysia KLCI
385    ];
386
387    /// Middle East & Africa indices
388    pub const MIDDLE_EAST_AFRICA: &[&str] = &[
389        "^TA125.TA", // TA-125 (Israel)
390        "^CASE30",   // EGX 30 (Egypt)
391        "^JN0U.JO",  // Top 40 USD Net TRI (South Africa)
392    ];
393
394    /// Currency indices
395    pub const CURRENCIES: &[&str] = &[
396        "DX-Y.NYB", // US Dollar Index
397        "^XDB",     // British Pound Currency Index
398        "^XDE",     // Euro Currency Index
399        "^XDN",     // Japanese Yen Currency Index
400        "^XDA",     // Australian Dollar Currency Index
401    ];
402
403    /// All world indices (all regions combined)
404    pub fn all_symbols() -> Vec<&'static str> {
405        Region::all()
406            .iter()
407            .flat_map(|r| r.symbols().iter().copied())
408            .collect()
409    }
410}
411
412/// Fundamental timeseries field types for financial statements
413///
414/// These constants represent field names that must be prefixed with frequency ("annual" or "quarterly")
415/// Example: "annualTotalRevenue", "quarterlyTotalRevenue"
416#[allow(missing_docs)]
417pub mod fundamental_types {
418    // ==================
419    // INCOME STATEMENT (48 fields)
420    // ==================
421    pub const TOTAL_REVENUE: &str = "TotalRevenue";
422    pub const OPERATING_REVENUE: &str = "OperatingRevenue";
423    pub const COST_OF_REVENUE: &str = "CostOfRevenue";
424    pub const GROSS_PROFIT: &str = "GrossProfit";
425    pub const OPERATING_EXPENSE: &str = "OperatingExpense";
426    pub const SELLING_GENERAL_AND_ADMIN: &str = "SellingGeneralAndAdministration";
427    pub const RESEARCH_AND_DEVELOPMENT: &str = "ResearchAndDevelopment";
428    pub const OPERATING_INCOME: &str = "OperatingIncome";
429    pub const NET_INTEREST_INCOME: &str = "NetInterestIncome";
430    pub const INTEREST_EXPENSE: &str = "InterestExpense";
431    pub const INTEREST_INCOME: &str = "InterestIncome";
432    pub const NET_NON_OPERATING_INTEREST_INCOME_EXPENSE: &str =
433        "NetNonOperatingInterestIncomeExpense";
434    pub const OTHER_INCOME_EXPENSE: &str = "OtherIncomeExpense";
435    pub const PRETAX_INCOME: &str = "PretaxIncome";
436    pub const TAX_PROVISION: &str = "TaxProvision";
437    pub const NET_INCOME_COMMON_STOCKHOLDERS: &str = "NetIncomeCommonStockholders";
438    pub const NET_INCOME: &str = "NetIncome";
439    pub const DILUTED_EPS: &str = "DilutedEPS";
440    pub const BASIC_EPS: &str = "BasicEPS";
441    pub const DILUTED_AVERAGE_SHARES: &str = "DilutedAverageShares";
442    pub const BASIC_AVERAGE_SHARES: &str = "BasicAverageShares";
443    pub const EBIT: &str = "EBIT";
444    pub const EBITDA: &str = "EBITDA";
445    pub const RECONCILED_COST_OF_REVENUE: &str = "ReconciledCostOfRevenue";
446    pub const RECONCILED_DEPRECIATION: &str = "ReconciledDepreciation";
447    pub const NET_INCOME_FROM_CONTINUING_OPERATION_NET_MINORITY_INTEREST: &str =
448        "NetIncomeFromContinuingOperationNetMinorityInterest";
449    pub const NORMALIZED_EBITDA: &str = "NormalizedEBITDA";
450    pub const TOTAL_EXPENSES: &str = "TotalExpenses";
451    pub const TOTAL_OPERATING_INCOME_AS_REPORTED: &str = "TotalOperatingIncomeAsReported";
452
453    // ==================
454    // BALANCE SHEET (42 fields)
455    // ==================
456    pub const TOTAL_ASSETS: &str = "TotalAssets";
457    pub const CURRENT_ASSETS: &str = "CurrentAssets";
458    pub const CASH_CASH_EQUIVALENTS_AND_SHORT_TERM_INVESTMENTS: &str =
459        "CashCashEquivalentsAndShortTermInvestments";
460    pub const CASH_AND_CASH_EQUIVALENTS: &str = "CashAndCashEquivalents";
461    pub const CASH_FINANCIAL: &str = "CashFinancial";
462    pub const RECEIVABLES: &str = "Receivables";
463    pub const ACCOUNTS_RECEIVABLE: &str = "AccountsReceivable";
464    pub const INVENTORY: &str = "Inventory";
465    pub const PREPAID_ASSETS: &str = "PrepaidAssets";
466    pub const OTHER_CURRENT_ASSETS: &str = "OtherCurrentAssets";
467    pub const TOTAL_NON_CURRENT_ASSETS: &str = "TotalNonCurrentAssets";
468    pub const NET_PPE: &str = "NetPPE";
469    pub const GROSS_PPE: &str = "GrossPPE";
470    pub const ACCUMULATED_DEPRECIATION: &str = "AccumulatedDepreciation";
471    pub const GOODWILL: &str = "Goodwill";
472    pub const GOODWILL_AND_OTHER_INTANGIBLE_ASSETS: &str = "GoodwillAndOtherIntangibleAssets";
473    pub const OTHER_INTANGIBLE_ASSETS: &str = "OtherIntangibleAssets";
474    pub const INVESTMENTS_AND_ADVANCES: &str = "InvestmentsAndAdvances";
475    pub const LONG_TERM_EQUITY_INVESTMENT: &str = "LongTermEquityInvestment";
476    pub const OTHER_NON_CURRENT_ASSETS: &str = "OtherNonCurrentAssets";
477    pub const TOTAL_LIABILITIES_NET_MINORITY_INTEREST: &str = "TotalLiabilitiesNetMinorityInterest";
478    pub const CURRENT_LIABILITIES: &str = "CurrentLiabilities";
479    pub const PAYABLES_AND_ACCRUED_EXPENSES: &str = "PayablesAndAccruedExpenses";
480    pub const ACCOUNTS_PAYABLE: &str = "AccountsPayable";
481    pub const CURRENT_DEBT: &str = "CurrentDebt";
482    pub const CURRENT_DEFERRED_REVENUE: &str = "CurrentDeferredRevenue";
483    pub const OTHER_CURRENT_LIABILITIES: &str = "OtherCurrentLiabilities";
484    pub const TOTAL_NON_CURRENT_LIABILITIES_NET_MINORITY_INTEREST: &str =
485        "TotalNonCurrentLiabilitiesNetMinorityInterest";
486    pub const LONG_TERM_DEBT: &str = "LongTermDebt";
487    pub const LONG_TERM_DEBT_AND_CAPITAL_LEASE_OBLIGATION: &str =
488        "LongTermDebtAndCapitalLeaseObligation";
489    pub const NON_CURRENT_DEFERRED_REVENUE: &str = "NonCurrentDeferredRevenue";
490    pub const NON_CURRENT_DEFERRED_TAXES_LIABILITIES: &str = "NonCurrentDeferredTaxesLiabilities";
491    pub const OTHER_NON_CURRENT_LIABILITIES: &str = "OtherNonCurrentLiabilities";
492    pub const STOCKHOLDERS_EQUITY: &str = "StockholdersEquity";
493    pub const COMMON_STOCK_EQUITY: &str = "CommonStockEquity";
494    pub const COMMON_STOCK: &str = "CommonStock";
495    pub const RETAINED_EARNINGS: &str = "RetainedEarnings";
496    pub const ADDITIONAL_PAID_IN_CAPITAL: &str = "AdditionalPaidInCapital";
497    pub const TREASURY_STOCK: &str = "TreasuryStock";
498    pub const TOTAL_EQUITY_GROSS_MINORITY_INTEREST: &str = "TotalEquityGrossMinorityInterest";
499    pub const WORKING_CAPITAL: &str = "WorkingCapital";
500    pub const INVESTED_CAPITAL: &str = "InvestedCapital";
501    pub const TANGIBLE_BOOK_VALUE: &str = "TangibleBookValue";
502    pub const TOTAL_DEBT: &str = "TotalDebt";
503    pub const NET_DEBT: &str = "NetDebt";
504    pub const SHARE_ISSUED: &str = "ShareIssued";
505    pub const ORDINARY_SHARES_NUMBER: &str = "OrdinarySharesNumber";
506
507    // ==================
508    // CASH FLOW STATEMENT (48 fields)
509    // ==================
510    pub const OPERATING_CASH_FLOW: &str = "OperatingCashFlow";
511    pub const CASH_FLOW_FROM_CONTINUING_OPERATING_ACTIVITIES: &str =
512        "CashFlowFromContinuingOperatingActivities";
513    pub const NET_INCOME_FROM_CONTINUING_OPERATIONS: &str = "NetIncomeFromContinuingOperations";
514    pub const DEPRECIATION_AND_AMORTIZATION: &str = "DepreciationAndAmortization";
515    pub const DEFERRED_INCOME_TAX: &str = "DeferredIncomeTax";
516    pub const CHANGE_IN_WORKING_CAPITAL: &str = "ChangeInWorkingCapital";
517    pub const CHANGE_IN_RECEIVABLES: &str = "ChangeInReceivables";
518    pub const CHANGES_IN_ACCOUNT_RECEIVABLES: &str = "ChangesInAccountReceivables";
519    pub const CHANGE_IN_INVENTORY: &str = "ChangeInInventory";
520    pub const CHANGE_IN_ACCOUNT_PAYABLE: &str = "ChangeInAccountPayable";
521    pub const CHANGE_IN_OTHER_WORKING_CAPITAL: &str = "ChangeInOtherWorkingCapital";
522    pub const STOCK_BASED_COMPENSATION: &str = "StockBasedCompensation";
523    pub const OTHER_NON_CASH_ITEMS: &str = "OtherNonCashItems";
524    pub const INVESTING_CASH_FLOW: &str = "InvestingCashFlow";
525    pub const CASH_FLOW_FROM_CONTINUING_INVESTING_ACTIVITIES: &str =
526        "CashFlowFromContinuingInvestingActivities";
527    pub const NET_PPE_PURCHASE_AND_SALE: &str = "NetPPEPurchaseAndSale";
528    pub const PURCHASE_OF_PPE: &str = "PurchaseOfPPE";
529    pub const SALE_OF_PPE: &str = "SaleOfPPE";
530    pub const CAPITAL_EXPENDITURE: &str = "CapitalExpenditure";
531    pub const NET_BUSINESS_PURCHASE_AND_SALE: &str = "NetBusinessPurchaseAndSale";
532    pub const PURCHASE_OF_BUSINESS: &str = "PurchaseOfBusiness";
533    pub const SALE_OF_BUSINESS: &str = "SaleOfBusiness";
534    pub const NET_INVESTMENT_PURCHASE_AND_SALE: &str = "NetInvestmentPurchaseAndSale";
535    pub const PURCHASE_OF_INVESTMENT: &str = "PurchaseOfInvestment";
536    pub const SALE_OF_INVESTMENT: &str = "SaleOfInvestment";
537    pub const NET_OTHER_INVESTING_CHANGES: &str = "NetOtherInvestingChanges";
538    pub const FINANCING_CASH_FLOW: &str = "FinancingCashFlow";
539    pub const CASH_FLOW_FROM_CONTINUING_FINANCING_ACTIVITIES: &str =
540        "CashFlowFromContinuingFinancingActivities";
541    pub const NET_ISSUANCE_PAYMENTS_OF_DEBT: &str = "NetIssuancePaymentsOfDebt";
542    pub const NET_LONG_TERM_DEBT_ISSUANCE: &str = "NetLongTermDebtIssuance";
543    pub const LONG_TERM_DEBT_ISSUANCE: &str = "LongTermDebtIssuance";
544    pub const LONG_TERM_DEBT_PAYMENTS: &str = "LongTermDebtPayments";
545    pub const NET_SHORT_TERM_DEBT_ISSUANCE: &str = "NetShortTermDebtIssuance";
546    pub const NET_COMMON_STOCK_ISSUANCE: &str = "NetCommonStockIssuance";
547    pub const COMMON_STOCK_ISSUANCE: &str = "CommonStockIssuance";
548    pub const COMMON_STOCK_PAYMENTS: &str = "CommonStockPayments";
549    pub const REPURCHASE_OF_CAPITAL_STOCK: &str = "RepurchaseOfCapitalStock";
550    pub const CASH_DIVIDENDS_PAID: &str = "CashDividendsPaid";
551    pub const COMMON_STOCK_DIVIDEND_PAID: &str = "CommonStockDividendPaid";
552    pub const NET_OTHER_FINANCING_CHARGES: &str = "NetOtherFinancingCharges";
553    pub const END_CASH_POSITION: &str = "EndCashPosition";
554    pub const BEGINNING_CASH_POSITION: &str = "BeginningCashPosition";
555    pub const CHANGESIN_CASH: &str = "ChangesinCash";
556    pub const EFFECT_OF_EXCHANGE_RATE_CHANGES: &str = "EffectOfExchangeRateChanges";
557    pub const FREE_CASH_FLOW: &str = "FreeCashFlow";
558    pub const CAPITAL_EXPENDITURE_REPORTED: &str = "CapitalExpenditureReported";
559}
560
561/// Statement types for financial data
562#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
563pub enum StatementType {
564    /// Income statement
565    Income,
566    /// Balance sheet
567    Balance,
568    /// Cash flow statement
569    CashFlow,
570}
571
572impl StatementType {
573    /// Convert statement type to string representation
574    pub fn as_str(&self) -> &'static str {
575        match self {
576            StatementType::Income => "income",
577            StatementType::Balance => "balance",
578            StatementType::CashFlow => "cashflow",
579        }
580    }
581
582    /// Get the list of fields for this statement type
583    ///
584    /// Returns field names without frequency prefix (e.g., "TotalRevenue" not "annualTotalRevenue")
585    pub fn get_fields(&self) -> &'static [&'static str] {
586        match self {
587            StatementType::Income => &INCOME_STATEMENT_FIELDS,
588            StatementType::Balance => &BALANCE_SHEET_FIELDS,
589            StatementType::CashFlow => &CASH_FLOW_FIELDS,
590        }
591    }
592}
593
594/// Income statement fields (without frequency prefix)
595const INCOME_STATEMENT_FIELDS: [&str; 30] = [
596    fundamental_types::TOTAL_REVENUE,
597    fundamental_types::OPERATING_REVENUE,
598    fundamental_types::COST_OF_REVENUE,
599    fundamental_types::GROSS_PROFIT,
600    fundamental_types::OPERATING_EXPENSE,
601    fundamental_types::SELLING_GENERAL_AND_ADMIN,
602    fundamental_types::RESEARCH_AND_DEVELOPMENT,
603    fundamental_types::OPERATING_INCOME,
604    fundamental_types::NET_INTEREST_INCOME,
605    fundamental_types::INTEREST_EXPENSE,
606    fundamental_types::INTEREST_INCOME,
607    fundamental_types::NET_NON_OPERATING_INTEREST_INCOME_EXPENSE,
608    fundamental_types::OTHER_INCOME_EXPENSE,
609    fundamental_types::PRETAX_INCOME,
610    fundamental_types::TAX_PROVISION,
611    fundamental_types::NET_INCOME_COMMON_STOCKHOLDERS,
612    fundamental_types::NET_INCOME,
613    fundamental_types::DILUTED_EPS,
614    fundamental_types::BASIC_EPS,
615    fundamental_types::DILUTED_AVERAGE_SHARES,
616    fundamental_types::BASIC_AVERAGE_SHARES,
617    fundamental_types::EBIT,
618    fundamental_types::EBITDA,
619    fundamental_types::RECONCILED_COST_OF_REVENUE,
620    fundamental_types::RECONCILED_DEPRECIATION,
621    fundamental_types::NET_INCOME_FROM_CONTINUING_OPERATION_NET_MINORITY_INTEREST,
622    fundamental_types::NORMALIZED_EBITDA,
623    fundamental_types::TOTAL_EXPENSES,
624    fundamental_types::TOTAL_OPERATING_INCOME_AS_REPORTED,
625    fundamental_types::DEPRECIATION_AND_AMORTIZATION,
626];
627
628/// Balance sheet fields (without frequency prefix)
629const BALANCE_SHEET_FIELDS: [&str; 48] = [
630    fundamental_types::TOTAL_ASSETS,
631    fundamental_types::CURRENT_ASSETS,
632    fundamental_types::CASH_CASH_EQUIVALENTS_AND_SHORT_TERM_INVESTMENTS,
633    fundamental_types::CASH_AND_CASH_EQUIVALENTS,
634    fundamental_types::CASH_FINANCIAL,
635    fundamental_types::RECEIVABLES,
636    fundamental_types::ACCOUNTS_RECEIVABLE,
637    fundamental_types::INVENTORY,
638    fundamental_types::PREPAID_ASSETS,
639    fundamental_types::OTHER_CURRENT_ASSETS,
640    fundamental_types::TOTAL_NON_CURRENT_ASSETS,
641    fundamental_types::NET_PPE,
642    fundamental_types::GROSS_PPE,
643    fundamental_types::ACCUMULATED_DEPRECIATION,
644    fundamental_types::GOODWILL,
645    fundamental_types::GOODWILL_AND_OTHER_INTANGIBLE_ASSETS,
646    fundamental_types::OTHER_INTANGIBLE_ASSETS,
647    fundamental_types::INVESTMENTS_AND_ADVANCES,
648    fundamental_types::LONG_TERM_EQUITY_INVESTMENT,
649    fundamental_types::OTHER_NON_CURRENT_ASSETS,
650    fundamental_types::TOTAL_LIABILITIES_NET_MINORITY_INTEREST,
651    fundamental_types::CURRENT_LIABILITIES,
652    fundamental_types::PAYABLES_AND_ACCRUED_EXPENSES,
653    fundamental_types::ACCOUNTS_PAYABLE,
654    fundamental_types::CURRENT_DEBT,
655    fundamental_types::CURRENT_DEFERRED_REVENUE,
656    fundamental_types::OTHER_CURRENT_LIABILITIES,
657    fundamental_types::TOTAL_NON_CURRENT_LIABILITIES_NET_MINORITY_INTEREST,
658    fundamental_types::LONG_TERM_DEBT,
659    fundamental_types::LONG_TERM_DEBT_AND_CAPITAL_LEASE_OBLIGATION,
660    fundamental_types::NON_CURRENT_DEFERRED_REVENUE,
661    fundamental_types::NON_CURRENT_DEFERRED_TAXES_LIABILITIES,
662    fundamental_types::OTHER_NON_CURRENT_LIABILITIES,
663    fundamental_types::STOCKHOLDERS_EQUITY,
664    fundamental_types::COMMON_STOCK_EQUITY,
665    fundamental_types::COMMON_STOCK,
666    fundamental_types::RETAINED_EARNINGS,
667    fundamental_types::ADDITIONAL_PAID_IN_CAPITAL,
668    fundamental_types::TREASURY_STOCK,
669    fundamental_types::TOTAL_EQUITY_GROSS_MINORITY_INTEREST,
670    fundamental_types::WORKING_CAPITAL,
671    fundamental_types::INVESTED_CAPITAL,
672    fundamental_types::TANGIBLE_BOOK_VALUE,
673    fundamental_types::TOTAL_DEBT,
674    fundamental_types::NET_DEBT,
675    fundamental_types::SHARE_ISSUED,
676    fundamental_types::ORDINARY_SHARES_NUMBER,
677    fundamental_types::DEPRECIATION_AND_AMORTIZATION,
678];
679
680/// Cash flow statement fields (without frequency prefix)
681const CASH_FLOW_FIELDS: [&str; 47] = [
682    fundamental_types::OPERATING_CASH_FLOW,
683    fundamental_types::CASH_FLOW_FROM_CONTINUING_OPERATING_ACTIVITIES,
684    fundamental_types::NET_INCOME_FROM_CONTINUING_OPERATIONS,
685    fundamental_types::DEPRECIATION_AND_AMORTIZATION,
686    fundamental_types::DEFERRED_INCOME_TAX,
687    fundamental_types::CHANGE_IN_WORKING_CAPITAL,
688    fundamental_types::CHANGE_IN_RECEIVABLES,
689    fundamental_types::CHANGES_IN_ACCOUNT_RECEIVABLES,
690    fundamental_types::CHANGE_IN_INVENTORY,
691    fundamental_types::CHANGE_IN_ACCOUNT_PAYABLE,
692    fundamental_types::CHANGE_IN_OTHER_WORKING_CAPITAL,
693    fundamental_types::STOCK_BASED_COMPENSATION,
694    fundamental_types::OTHER_NON_CASH_ITEMS,
695    fundamental_types::INVESTING_CASH_FLOW,
696    fundamental_types::CASH_FLOW_FROM_CONTINUING_INVESTING_ACTIVITIES,
697    fundamental_types::NET_PPE_PURCHASE_AND_SALE,
698    fundamental_types::PURCHASE_OF_PPE,
699    fundamental_types::SALE_OF_PPE,
700    fundamental_types::CAPITAL_EXPENDITURE,
701    fundamental_types::NET_BUSINESS_PURCHASE_AND_SALE,
702    fundamental_types::PURCHASE_OF_BUSINESS,
703    fundamental_types::SALE_OF_BUSINESS,
704    fundamental_types::NET_INVESTMENT_PURCHASE_AND_SALE,
705    fundamental_types::PURCHASE_OF_INVESTMENT,
706    fundamental_types::SALE_OF_INVESTMENT,
707    fundamental_types::NET_OTHER_INVESTING_CHANGES,
708    fundamental_types::FINANCING_CASH_FLOW,
709    fundamental_types::CASH_FLOW_FROM_CONTINUING_FINANCING_ACTIVITIES,
710    fundamental_types::NET_ISSUANCE_PAYMENTS_OF_DEBT,
711    fundamental_types::NET_LONG_TERM_DEBT_ISSUANCE,
712    fundamental_types::LONG_TERM_DEBT_ISSUANCE,
713    fundamental_types::LONG_TERM_DEBT_PAYMENTS,
714    fundamental_types::NET_SHORT_TERM_DEBT_ISSUANCE,
715    fundamental_types::NET_COMMON_STOCK_ISSUANCE,
716    fundamental_types::COMMON_STOCK_ISSUANCE,
717    fundamental_types::COMMON_STOCK_PAYMENTS,
718    fundamental_types::REPURCHASE_OF_CAPITAL_STOCK,
719    fundamental_types::CASH_DIVIDENDS_PAID,
720    fundamental_types::COMMON_STOCK_DIVIDEND_PAID,
721    fundamental_types::NET_OTHER_FINANCING_CHARGES,
722    fundamental_types::END_CASH_POSITION,
723    fundamental_types::BEGINNING_CASH_POSITION,
724    fundamental_types::CHANGESIN_CASH,
725    fundamental_types::EFFECT_OF_EXCHANGE_RATE_CHANGES,
726    fundamental_types::FREE_CASH_FLOW,
727    fundamental_types::CAPITAL_EXPENDITURE_REPORTED,
728    fundamental_types::DEPRECIATION_AND_AMORTIZATION,
729];
730
731/// Frequency for financial data (annual or quarterly)
732#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
733pub enum Frequency {
734    /// Annual financial data
735    Annual,
736    /// Quarterly financial data
737    Quarterly,
738}
739
740impl Frequency {
741    /// Convert frequency to string representation
742    pub fn as_str(&self) -> &'static str {
743        match self {
744            Frequency::Annual => "annual",
745            Frequency::Quarterly => "quarterly",
746        }
747    }
748
749    /// Build a fundamental type string with frequency prefix
750    ///
751    /// # Example
752    ///
753    /// ```
754    /// use finance_query::Frequency;
755    ///
756    /// let field = Frequency::Annual.prefix("TotalRevenue");
757    /// assert_eq!(field, "annualTotalRevenue");
758    /// ```
759    pub fn prefix(&self, field: &str) -> String {
760        format!("{}{}", self.as_str(), field)
761    }
762}
763
764/// Chart intervals
765#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
766pub enum Interval {
767    /// 1 minute
768    #[serde(rename = "1m")]
769    OneMinute,
770    /// 5 minutes
771    #[serde(rename = "5m")]
772    FiveMinutes,
773    /// 15 minutes
774    #[serde(rename = "15m")]
775    FifteenMinutes,
776    /// 30 minutes
777    #[serde(rename = "30m")]
778    ThirtyMinutes,
779    /// 1 hour
780    #[serde(rename = "1h")]
781    OneHour,
782    /// 1 day
783    #[serde(rename = "1d")]
784    OneDay,
785    /// 1 week
786    #[serde(rename = "1wk")]
787    OneWeek,
788    /// 1 month
789    #[serde(rename = "1mo")]
790    OneMonth,
791    /// 3 months
792    #[serde(rename = "3mo")]
793    ThreeMonths,
794}
795
796impl Interval {
797    /// Convert interval to Yahoo Finance API format
798    pub fn as_str(&self) -> &'static str {
799        match self {
800            Interval::OneMinute => "1m",
801            Interval::FiveMinutes => "5m",
802            Interval::FifteenMinutes => "15m",
803            Interval::ThirtyMinutes => "30m",
804            Interval::OneHour => "1h",
805            Interval::OneDay => "1d",
806            Interval::OneWeek => "1wk",
807            Interval::OneMonth => "1mo",
808            Interval::ThreeMonths => "3mo",
809        }
810    }
811}
812
813impl std::fmt::Display for Interval {
814    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
815        f.write_str(self.as_str())
816    }
817}
818
819/// Time ranges for chart data
820#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
821pub enum TimeRange {
822    /// 1 day
823    #[serde(rename = "1d")]
824    OneDay,
825    /// 5 days
826    #[serde(rename = "5d")]
827    FiveDays,
828    /// 1 month
829    #[serde(rename = "1mo")]
830    OneMonth,
831    /// 3 months
832    #[serde(rename = "3mo")]
833    ThreeMonths,
834    /// 6 months
835    #[serde(rename = "6mo")]
836    SixMonths,
837    /// 1 year
838    #[serde(rename = "1y")]
839    OneYear,
840    /// 2 years
841    #[serde(rename = "2y")]
842    TwoYears,
843    /// 5 years
844    #[serde(rename = "5y")]
845    FiveYears,
846    /// 10 years
847    #[serde(rename = "10y")]
848    TenYears,
849    /// Year to date
850    #[serde(rename = "ytd")]
851    YearToDate,
852    /// Maximum available
853    #[serde(rename = "max")]
854    Max,
855}
856
857impl TimeRange {
858    /// Convert time range to Yahoo Finance API format
859    pub fn as_str(&self) -> &'static str {
860        match self {
861            TimeRange::OneDay => "1d",
862            TimeRange::FiveDays => "5d",
863            TimeRange::OneMonth => "1mo",
864            TimeRange::ThreeMonths => "3mo",
865            TimeRange::SixMonths => "6mo",
866            TimeRange::OneYear => "1y",
867            TimeRange::TwoYears => "2y",
868            TimeRange::FiveYears => "5y",
869            TimeRange::TenYears => "10y",
870            TimeRange::YearToDate => "ytd",
871            TimeRange::Max => "max",
872        }
873    }
874}
875
876impl std::fmt::Display for TimeRange {
877    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
878        f.write_str(self.as_str())
879    }
880}
881
882/// Supported regions for Yahoo Finance regional APIs
883///
884/// Each region has predefined language and region codes that work together.
885/// Using the Region enum ensures correct lang/region pairing.
886#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
887pub enum Region {
888    /// Argentina (es-AR, AR)
889    Argentina,
890    /// Australia (en-AU, AU)
891    Australia,
892    /// Brazil (pt-BR, BR)
893    Brazil,
894    /// Canada (en-CA, CA)
895    Canada,
896    /// China (zh-CN, CN)
897    China,
898    /// Denmark (da-DK, DK)
899    Denmark,
900    /// Finland (fi-FI, FI)
901    Finland,
902    /// France (fr-FR, FR)
903    France,
904    /// Germany (de-DE, DE)
905    Germany,
906    /// Greece (el-GR, GR)
907    Greece,
908    /// Hong Kong (zh-Hant-HK, HK)
909    HongKong,
910    /// India (en-IN, IN)
911    India,
912    /// Israel (he-IL, IL)
913    Israel,
914    /// Italy (it-IT, IT)
915    Italy,
916    /// Malaysia (ms-MY, MY)
917    Malaysia,
918    /// New Zealand (en-NZ, NZ)
919    NewZealand,
920    /// Norway (nb-NO, NO)
921    Norway,
922    /// Portugal (pt-PT, PT)
923    Portugal,
924    /// Russia (ru-RU, RU)
925    Russia,
926    /// Singapore (en-SG, SG)
927    Singapore,
928    /// Spain (es-ES, ES)
929    Spain,
930    /// Sweden (sv-SE, SE)
931    Sweden,
932    /// Taiwan (zh-TW, TW)
933    Taiwan,
934    /// Thailand (th-TH, TH)
935    Thailand,
936    /// Turkey (tr-TR, TR)
937    Turkey,
938    /// United Kingdom (en-GB, GB)
939    UnitedKingdom,
940    /// United States (en-US, US) - Default
941    #[default]
942    UnitedStates,
943    /// Vietnam (vi-VN, VN)
944    Vietnam,
945}
946
947impl Region {
948    /// Get the language code for this region
949    ///
950    /// # Example
951    ///
952    /// ```
953    /// use finance_query::Region;
954    ///
955    /// assert_eq!(Region::France.lang(), "fr-FR");
956    /// assert_eq!(Region::UnitedStates.lang(), "en-US");
957    /// ```
958    pub fn lang(&self) -> &'static str {
959        match self {
960            Region::Argentina => "es-AR",
961            Region::Australia => "en-AU",
962            Region::Brazil => "pt-BR",
963            Region::Canada => "en-CA",
964            Region::China => "zh-CN",
965            Region::Denmark => "da-DK",
966            Region::Finland => "fi-FI",
967            Region::France => "fr-FR",
968            Region::Germany => "de-DE",
969            Region::Greece => "el-GR",
970            Region::HongKong => "zh-Hant-HK",
971            Region::India => "en-IN",
972            Region::Israel => "he-IL",
973            Region::Italy => "it-IT",
974            Region::Malaysia => "ms-MY",
975            Region::NewZealand => "en-NZ",
976            Region::Norway => "nb-NO",
977            Region::Portugal => "pt-PT",
978            Region::Russia => "ru-RU",
979            Region::Singapore => "en-SG",
980            Region::Spain => "es-ES",
981            Region::Sweden => "sv-SE",
982            Region::Taiwan => "zh-TW",
983            Region::Thailand => "th-TH",
984            Region::Turkey => "tr-TR",
985            Region::UnitedKingdom => "en-GB",
986            Region::UnitedStates => "en-US",
987            Region::Vietnam => "vi-VN",
988        }
989    }
990
991    /// Get the region code for this region
992    ///
993    /// # Example
994    ///
995    /// ```
996    /// use finance_query::Region;
997    ///
998    /// assert_eq!(Region::France.region(), "FR");
999    /// assert_eq!(Region::UnitedStates.region(), "US");
1000    /// ```
1001    pub fn region(&self) -> &'static str {
1002        match self {
1003            Region::Argentina => "AR",
1004            Region::Australia => "AU",
1005            Region::Brazil => "BR",
1006            Region::Canada => "CA",
1007            Region::China => "CN",
1008            Region::Denmark => "DK",
1009            Region::Finland => "FI",
1010            Region::France => "FR",
1011            Region::Germany => "DE",
1012            Region::Greece => "GR",
1013            Region::HongKong => "HK",
1014            Region::India => "IN",
1015            Region::Israel => "IL",
1016            Region::Italy => "IT",
1017            Region::Malaysia => "MY",
1018            Region::NewZealand => "NZ",
1019            Region::Norway => "NO",
1020            Region::Portugal => "PT",
1021            Region::Russia => "RU",
1022            Region::Singapore => "SG",
1023            Region::Spain => "ES",
1024            Region::Sweden => "SE",
1025            Region::Taiwan => "TW",
1026            Region::Thailand => "TH",
1027            Region::Turkey => "TR",
1028            Region::UnitedKingdom => "GB",
1029            Region::UnitedStates => "US",
1030            Region::Vietnam => "VN",
1031        }
1032    }
1033
1034    /// Get the CORS domain for this region
1035    ///
1036    /// # Example
1037    ///
1038    /// ```
1039    /// use finance_query::Region;
1040    ///
1041    /// assert_eq!(Region::UnitedStates.cors_domain(), "finance.yahoo.com");
1042    /// assert_eq!(Region::France.cors_domain(), "fr.finance.yahoo.com");
1043    /// ```
1044    pub fn cors_domain(&self) -> &'static str {
1045        match self {
1046            Region::Argentina => "ar.finance.yahoo.com",
1047            Region::Australia => "au.finance.yahoo.com",
1048            Region::Brazil => "br.financas.yahoo.com",
1049            Region::Canada => "ca.finance.yahoo.com",
1050            Region::China => "cn.finance.yahoo.com",
1051            Region::Denmark => "dk.finance.yahoo.com",
1052            Region::Finland => "fi.finance.yahoo.com",
1053            Region::France => "fr.finance.yahoo.com",
1054            Region::Germany => "de.finance.yahoo.com",
1055            Region::Greece => "gr.finance.yahoo.com",
1056            Region::HongKong => "hk.finance.yahoo.com",
1057            Region::India => "in.finance.yahoo.com",
1058            Region::Israel => "il.finance.yahoo.com",
1059            Region::Italy => "it.finance.yahoo.com",
1060            Region::Malaysia => "my.finance.yahoo.com",
1061            Region::NewZealand => "nz.finance.yahoo.com",
1062            Region::Norway => "no.finance.yahoo.com",
1063            Region::Portugal => "pt.finance.yahoo.com",
1064            Region::Russia => "ru.finance.yahoo.com",
1065            Region::Singapore => "sg.finance.yahoo.com",
1066            Region::Spain => "es.finance.yahoo.com",
1067            Region::Sweden => "se.finance.yahoo.com",
1068            Region::Taiwan => "tw.finance.yahoo.com",
1069            Region::Thailand => "th.finance.yahoo.com",
1070            Region::Turkey => "tr.finance.yahoo.com",
1071            Region::UnitedKingdom => "uk.finance.yahoo.com",
1072            Region::UnitedStates => "finance.yahoo.com",
1073            Region::Vietnam => "vn.finance.yahoo.com",
1074        }
1075    }
1076}
1077
1078impl std::str::FromStr for Region {
1079    type Err = ();
1080
1081    fn from_str(s: &str) -> Result<Self, Self::Err> {
1082        match s.to_uppercase().as_str() {
1083            "AR" => Ok(Region::Argentina),
1084            "AU" => Ok(Region::Australia),
1085            "BR" => Ok(Region::Brazil),
1086            "CA" => Ok(Region::Canada),
1087            "CN" => Ok(Region::China),
1088            "DK" => Ok(Region::Denmark),
1089            "FI" => Ok(Region::Finland),
1090            "FR" => Ok(Region::France),
1091            "DE" => Ok(Region::Germany),
1092            "GR" => Ok(Region::Greece),
1093            "HK" => Ok(Region::HongKong),
1094            "IN" => Ok(Region::India),
1095            "IL" => Ok(Region::Israel),
1096            "IT" => Ok(Region::Italy),
1097            "MY" => Ok(Region::Malaysia),
1098            "NZ" => Ok(Region::NewZealand),
1099            "NO" => Ok(Region::Norway),
1100            "PT" => Ok(Region::Portugal),
1101            "RU" => Ok(Region::Russia),
1102            "SG" => Ok(Region::Singapore),
1103            "ES" => Ok(Region::Spain),
1104            "SE" => Ok(Region::Sweden),
1105            "TW" => Ok(Region::Taiwan),
1106            "TH" => Ok(Region::Thailand),
1107            "TR" => Ok(Region::Turkey),
1108            "GB" | "UK" => Ok(Region::UnitedKingdom),
1109            "US" => Ok(Region::UnitedStates),
1110            "VN" => Ok(Region::Vietnam),
1111            _ => Err(()),
1112        }
1113    }
1114}
1115
1116impl From<Region> for String {
1117    /// Returns the lowercase two-letter country code used by the Yahoo Finance screener
1118    /// (e.g. `"us"`, `"gb"`).
1119    fn from(v: Region) -> Self {
1120        v.region().to_lowercase()
1121    }
1122}
1123
1124/// Value format for API responses
1125///
1126/// Controls how `FormattedValue<T>` fields are serialized in responses.
1127/// This allows API consumers to choose between raw numeric values,
1128/// human-readable formatted strings, or both.
1129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
1130pub enum ValueFormat {
1131    /// Return only raw numeric values (e.g., `123.45`) - default
1132    /// Best for programmatic use, calculations, charts
1133    #[default]
1134    Raw,
1135    /// Return only formatted strings (e.g., `"$123.45"`, `"1.2B"`)
1136    /// Best for display purposes
1137    Pretty,
1138    /// Return both raw and formatted values
1139    /// Returns the full `{raw, fmt, longFmt}` object
1140    Both,
1141}
1142
1143impl std::str::FromStr for ValueFormat {
1144    type Err = ();
1145
1146    fn from_str(s: &str) -> Result<Self, Self::Err> {
1147        match s.to_lowercase().as_str() {
1148            "raw" => Ok(ValueFormat::Raw),
1149            "pretty" | "fmt" => Ok(ValueFormat::Pretty),
1150            "both" | "full" => Ok(ValueFormat::Both),
1151            _ => Err(()),
1152        }
1153    }
1154}
1155
1156impl ValueFormat {
1157    /// Parse from string (case-insensitive), returns None on invalid input
1158    pub fn parse(s: &str) -> Option<Self> {
1159        s.parse().ok()
1160    }
1161
1162    /// Convert to string representation
1163    pub fn as_str(&self) -> &'static str {
1164        match self {
1165            ValueFormat::Raw => "raw",
1166            ValueFormat::Pretty => "pretty",
1167            ValueFormat::Both => "both",
1168        }
1169    }
1170
1171    /// Transform a JSON value based on this format
1172    ///
1173    /// Recursively processes the JSON, detecting FormattedValue objects
1174    /// (objects with `raw` key and optionally `fmt`/`longFmt`) and
1175    /// transforming them according to the format setting.
1176    ///
1177    /// # Example
1178    ///
1179    /// ```
1180    /// use finance_query::ValueFormat;
1181    /// use serde_json::json;
1182    ///
1183    /// let data = json!({"price": {"raw": 123.45, "fmt": "$123.45"}});
1184    ///
1185    /// // Raw format extracts just the raw value (default)
1186    /// let raw = ValueFormat::default().transform(data.clone());
1187    /// assert_eq!(raw, json!({"price": 123.45}));
1188    ///
1189    /// // Pretty extracts just the formatted string
1190    /// let pretty = ValueFormat::Pretty.transform(data.clone());
1191    /// assert_eq!(pretty, json!({"price": "$123.45"}));
1192    ///
1193    /// // Both keeps the full object
1194    /// let both = ValueFormat::Both.transform(data);
1195    /// assert_eq!(both, json!({"price": {"raw": 123.45, "fmt": "$123.45"}}));
1196    /// ```
1197    pub fn transform(&self, value: serde_json::Value) -> serde_json::Value {
1198        match self {
1199            ValueFormat::Both => value, // No transformation needed
1200            _ => self.transform_recursive(value),
1201        }
1202    }
1203
1204    fn transform_recursive(&self, value: serde_json::Value) -> serde_json::Value {
1205        use serde_json::Value;
1206
1207        match value {
1208            Value::Object(map) => {
1209                // Check if this looks like a FormattedValue (has 'raw' key)
1210                if self.is_formatted_value(&map) {
1211                    return self.extract_value(&map);
1212                }
1213
1214                // Otherwise, recursively transform all values
1215                let transformed: serde_json::Map<String, Value> = map
1216                    .into_iter()
1217                    .map(|(k, v)| (k, self.transform_recursive(v)))
1218                    .collect();
1219                Value::Object(transformed)
1220            }
1221            Value::Array(arr) => Value::Array(
1222                arr.into_iter()
1223                    .map(|v| self.transform_recursive(v))
1224                    .collect(),
1225            ),
1226            // Primitives pass through unchanged
1227            other => other,
1228        }
1229    }
1230
1231    /// Check if an object looks like a FormattedValue
1232    fn is_formatted_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> bool {
1233        // Must have 'raw' key (can be null)
1234        // May have 'fmt' and/or 'longFmt'
1235        // Should not have many other keys (FormattedValue only has these 3)
1236        if !map.contains_key("raw") {
1237            return false;
1238        }
1239
1240        let known_keys = ["raw", "fmt", "longFmt"];
1241        let unknown_keys = map
1242            .keys()
1243            .filter(|k| !known_keys.contains(&k.as_str()))
1244            .count();
1245
1246        // If there are unknown keys, it's probably not a FormattedValue
1247        unknown_keys == 0
1248    }
1249
1250    /// Extract the appropriate value based on format
1251    fn extract_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> serde_json::Value {
1252        match self {
1253            ValueFormat::Raw => {
1254                // Return raw value directly (or null if not present)
1255                map.get("raw").cloned().unwrap_or(serde_json::Value::Null)
1256            }
1257            ValueFormat::Pretty => {
1258                // Prefer fmt, fall back to longFmt, then null
1259                map.get("fmt")
1260                    .or_else(|| map.get("longFmt"))
1261                    .cloned()
1262                    .unwrap_or(serde_json::Value::Null)
1263            }
1264            ValueFormat::Both => {
1265                // Keep as-is (shouldn't reach here, but handle anyway)
1266                serde_json::Value::Object(map.clone())
1267            }
1268        }
1269    }
1270}
1271
1272/// Typed industry identifiers shared between the industry endpoint and screener queries.
1273///
1274/// Use with [`finance::industry()`](crate::finance::industry) for the data endpoint, and with
1275/// [`EquityField::Industry`](crate::EquityField::Industry) +
1276/// [`ScreenerFieldExt::eq_str`](crate::ScreenerFieldExt::eq_str) for screener filtering.
1277///
1278/// - `as_slug()` → lowercase hyphenated key for `finance::industry()` (e.g. `"semiconductors"`)
1279/// - `From<Industry> for String` → screener display name (e.g. `"Semiconductors"`)
1280///
1281/// # Example
1282///
1283/// ```no_run
1284/// use finance_query::{finance, Industry, EquityField, EquityScreenerQuery, ScreenerFieldExt};
1285///
1286/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1287/// // Industry endpoint
1288/// let data = finance::industry(Industry::Semiconductors).await?;
1289///
1290/// // Screener filter
1291/// let query = EquityScreenerQuery::new()
1292///     .add_condition(EquityField::Industry.eq_str(Industry::Semiconductors));
1293/// # Ok(())
1294/// # }
1295/// ```
1296pub mod industries {
1297    /// Typed industry identifier for the industry endpoint and custom screener queries.
1298    ///
1299    /// See the module-level doc for usage.
1300    #[non_exhaustive]
1301    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1302    pub enum Industry {
1303        // ── Agriculture / Raw Materials ──────────────────────────────────────
1304        /// Agricultural inputs, fertilizers, and crop chemicals
1305        AgriculturalInputs,
1306        /// Aluminum production and processing companies
1307        Aluminum,
1308        /// Coal mining and processing companies
1309        Coal,
1310        /// Copper mining and processing companies
1311        Copper,
1312        /// Farm products including grains, livestock, and produce
1313        FarmProducts,
1314        /// Forest products including timber and paper pulp
1315        ForestProducts,
1316        /// Gold mining and royalty companies
1317        Gold,
1318        /// Lumber and wood production companies
1319        LumberAndWoodProduction,
1320        /// Other industrial metals and mining (zinc, nickel, etc.)
1321        OtherIndustrialMetalsAndMining,
1322        /// Other precious metals and mining (platinum, palladium, etc.)
1323        OtherPreciousMetalsAndMining,
1324        /// Silver mining and streaming companies
1325        Silver,
1326        /// Steel production and processing companies
1327        Steel,
1328        /// Thermal coal mining for electricity generation
1329        ThermalCoal,
1330        /// Uranium mining companies
1331        Uranium,
1332        // ── Consumer ─────────────────────────────────────────────────────────
1333        /// Clothing and apparel manufacturing companies
1334        ApparelManufacturing,
1335        /// Clothing and apparel retail chains
1336        ApparelRetail,
1337        /// Automotive and truck dealerships
1338        AutoAndTruckDealerships,
1339        /// Automobile manufacturers and assemblers
1340        AutoManufacturers,
1341        /// Automotive parts manufacturers and distributors
1342        AutoParts,
1343        /// Beer brewing and distribution companies
1344        BeveragesBrewers,
1345        /// Non-alcoholic beverages including soft drinks and juices
1346        BeveragesNonAlcoholic,
1347        /// Wineries, distilleries, and spirits producers
1348        BeveragesWineriesAndDistilleries,
1349        /// Candy, chocolate, and confectionery makers
1350        Confectioners,
1351        /// Traditional department store retailers
1352        DepartmentStores,
1353        /// Discount and value retail stores
1354        DiscountStores,
1355        /// Electronic gaming software and multimedia entertainment
1356        ElectronicGamingAndMultimedia,
1357        /// Wholesale food distribution companies
1358        FoodDistribution,
1359        /// Footwear, handbags, and fashion accessories
1360        FootwearAndAccessories,
1361        /// Furniture, fixtures, and household appliances
1362        FurnishingsFixturesAndAppliances,
1363        /// Casinos, online gambling, and gaming operators
1364        Gambling,
1365        /// Supermarkets and grocery retail chains
1366        GroceryStores,
1367        /// Home improvement retail stores
1368        HomeImprovementRetail,
1369        /// Household cleaning products and personal care items
1370        HouseholdAndPersonalProducts,
1371        /// Online retail and e-commerce marketplaces
1372        InternetRetail,
1373        /// Leisure, recreation, and entertainment companies
1374        Leisure,
1375        /// Hotels and lodging companies
1376        Lodging,
1377        /// Luxury goods, fashion, and premium consumer brands
1378        LuxuryGoods,
1379        /// Packaged and processed food manufacturers
1380        PackagedFoods,
1381        /// Personal care, laundry, and household services
1382        PersonalServices,
1383        /// Home builders and residential construction
1384        ResidentialConstruction,
1385        /// Resorts, integrated casinos, and hotel-casinos
1386        ResortsAndCasinos,
1387        /// Restaurant chains and food service operators
1388        Restaurants,
1389        /// Specialty retail stores (pets, books, electronics, etc.)
1390        SpecialtyRetail,
1391        /// Textile and fabric manufacturers
1392        TextileManufacturing,
1393        /// Tobacco product manufacturers
1394        Tobacco,
1395        /// Travel agencies, booking platforms, and tour operators
1396        TravelServices,
1397        // ── Energy ───────────────────────────────────────────────────────────
1398        /// Oil and gas contract drilling services
1399        OilAndGasDrilling,
1400        /// Oil and gas exploration and production companies
1401        OilAndGasEAndP,
1402        /// Oil field equipment, services, and engineering
1403        OilAndGasEquipmentAndServices,
1404        /// Vertically integrated oil and gas majors
1405        OilAndGasIntegrated,
1406        /// Oil and gas pipelines, storage, and transportation
1407        OilAndGasMidstream,
1408        /// Oil refining, wholesale fuel, and marketing
1409        OilAndGasRefiningAndMarketing,
1410        /// Solar panel manufacturers and solar energy producers
1411        Solar,
1412        // ── Financial Services ───────────────────────────────────────────────
1413        /// Asset managers, fund sponsors, and investment advisors
1414        AssetManagement,
1415        /// Large diversified national and international banks
1416        BanksDiversified,
1417        /// Regional and community banks
1418        BanksRegional,
1419        /// Investment banks, brokers, and financial exchanges
1420        CapitalMarkets,
1421        /// Credit card issuers and consumer credit services
1422        CreditServices,
1423        /// Financial data, analytics, and stock exchange operators
1424        FinancialDataAndStockExchanges,
1425        /// Insurance brokers and agencies
1426        InsuranceBrokers,
1427        /// Diversified multi-line insurance companies
1428        InsuranceDiversified,
1429        /// Life insurance and annuity providers
1430        InsuranceLife,
1431        /// Property and casualty insurance companies
1432        InsurancePropertyAndCasualty,
1433        /// Reinsurance companies
1434        InsuranceReinsurance,
1435        /// Specialty insurance lines (title, mortgage, etc.)
1436        InsuranceSpecialty,
1437        /// Mortgage banking and loan origination
1438        MortgageFinance,
1439        /// Blank-check and shell holding companies
1440        ShellCompanies,
1441        // ── Healthcare ───────────────────────────────────────────────────────
1442        /// Biotechnology drug development companies
1443        Biotechnology,
1444        /// Medical diagnostics labs and clinical research
1445        DiagnosticsAndResearch,
1446        /// Large branded pharmaceutical manufacturers
1447        DrugManufacturersGeneral,
1448        /// Specialty drugs, generics, and biosimilars
1449        DrugManufacturersSpecialtyAndGeneric,
1450        /// Healthcare IT, EHR, and health data services
1451        HealthInformationServices,
1452        /// Managed care organizations and health insurers
1453        HealthcarePlans,
1454        /// Hospitals, clinics, and outpatient care facilities
1455        MedicalCareFacilities,
1456        /// Medical device manufacturers (implants, diagnostics equipment)
1457        MedicalDevices,
1458        /// Medical product wholesalers and distributors
1459        MedicalDistribution,
1460        /// Surgical instruments, disposables, and medical supplies
1461        MedicalInstrumentsAndSupplies,
1462        /// Retail pharmacies and drug store chains
1463        PharmaceuticalRetailers,
1464        // ── Industrials ──────────────────────────────────────────────────────
1465        /// Defense contractors, aircraft, and space systems
1466        AerospaceAndDefense,
1467        /// Construction aggregates, cement, and building materials
1468        BuildingMaterials,
1469        /// HVAC, plumbing, windows, and building equipment
1470        BuildingProductsAndEquipment,
1471        /// Office supplies, commercial equipment, and printers
1472        BusinessEquipmentAndSupplies,
1473        /// Specialty chemical manufacturing for industrial use
1474        ChemicalManufacturing,
1475        /// Diversified commodity chemicals producers
1476        Chemicals,
1477        /// Diversified industrial holding companies
1478        Conglomerates,
1479        /// Management consulting and professional advisory services
1480        ConsultingServices,
1481        /// Electrical components, motors, and power equipment
1482        ElectricalEquipmentAndParts,
1483        /// Civil engineering, construction, and infrastructure projects
1484        EngineeringAndConstruction,
1485        /// Agricultural equipment and heavy construction machinery
1486        FarmAndHeavyConstructionMachinery,
1487        /// Industrial goods wholesalers and distributors
1488        IndustrialDistribution,
1489        /// Toll roads, airports, and infrastructure operators
1490        InfrastructureOperations,
1491        /// Third-party logistics and supply chain management
1492        IntegratedFreightAndLogistics,
1493        /// Diversified manufacturers across multiple industrial segments
1494        ManufacturingDiversified,
1495        /// Port operators and marine terminal services
1496        MarinePortsAndServices,
1497        /// Bulk cargo and tanker shipping companies
1498        MarineShipping,
1499        /// Custom metal fabrication and machined components
1500        MetalFabrication,
1501        /// Paper, packaging, and pulp product manufacturers
1502        PaperAndPaperProducts,
1503        /// Environmental controls, water treatment, and remediation
1504        PollutionAndTreatmentControls,
1505        /// Rail freight carriers and passenger rail operators
1506        Railroads,
1507        /// Equipment rental, leasing, and fleet management
1508        RentalAndLeasingServices,
1509        /// Security systems, guards, and monitoring services
1510        SecurityAndProtectionServices,
1511        /// Outsourced business services and BPO companies
1512        SpecialtyBusinessServices,
1513        /// High-value specialty chemicals and advanced materials
1514        SpecialtyChemicals,
1515        /// Specialized industrial machinery and equipment makers
1516        SpecialtyIndustrialMachinery,
1517        /// Staffing agencies and employment service providers
1518        StaffingAndEmploymentServices,
1519        /// Hand tools, power tools, and hardware accessories
1520        ToolsAndAccessories,
1521        /// Freight trucking and less-than-truckload carriers
1522        Trucking,
1523        /// Waste collection, recycling, and disposal services
1524        WasteManagement,
1525        // ── Real Estate ──────────────────────────────────────────────────────
1526        /// Real estate developers and homebuilders
1527        RealEstateDevelopment,
1528        /// Diversified real estate companies with mixed portfolios
1529        RealEstateDiversified,
1530        /// Real estate brokers, agents, and property managers
1531        RealEstateServices,
1532        /// Diversified REITs across multiple property types
1533        ReitDiversified,
1534        /// Healthcare and senior living facility REITs
1535        ReitHealthcareFacilities,
1536        /// Hotel and motel property REITs
1537        ReitHotelAndMotel,
1538        /// Industrial, warehouse, and logistics property REITs
1539        ReitIndustrial,
1540        /// Mortgage REITs investing in real estate debt
1541        ReitMortgage,
1542        /// Office building and commercial property REITs
1543        ReitOffice,
1544        /// Apartment, multifamily, and residential property REITs
1545        ReitResidential,
1546        /// Shopping center and retail property REITs
1547        ReitRetail,
1548        /// Specialty REITs (data centers, cell towers, self-storage)
1549        ReitSpecialty,
1550        // ── Technology ───────────────────────────────────────────────────────
1551        /// Networking hardware, routers, and communication equipment
1552        CommunicationEquipment,
1553        /// PCs, servers, and computer hardware manufacturers
1554        ComputerHardware,
1555        /// Smartphones, TVs, and consumer electronic devices
1556        ConsumerElectronics,
1557        /// Data analytics, business intelligence, and AI platforms
1558        DataAnalytics,
1559        /// Passive electronic components and circuit boards
1560        ElectronicComponents,
1561        /// Distributors of electronics and computer products
1562        ElectronicsAndComputerDistribution,
1563        /// Value-added resellers and software/hardware distributors
1564        HardwareAndSoftwareDistribution,
1565        /// IT services, outsourcing, and technology consulting
1566        InformationTechnologyServices,
1567        /// Online media, search engines, and digital content platforms
1568        InternetContentAndInformation,
1569        /// Precision instruments, sensors, and test equipment
1570        ScientificAndTechnicalInstruments,
1571        /// Semiconductor manufacturing equipment and materials
1572        SemiconductorEquipmentAndMaterials,
1573        /// Integrated circuit and chip designers and manufacturers
1574        Semiconductors,
1575        /// Business application software companies
1576        SoftwareApplication,
1577        /// Operating systems, middleware, and infrastructure software
1578        SoftwareInfrastructure,
1579        // ── Communication Services ───────────────────────────────────────────
1580        /// Television, radio, and broadcast media companies
1581        Broadcasting,
1582        /// Film studios, streaming, and live entertainment
1583        Entertainment,
1584        /// Book, magazine, newspaper, and digital media publishers
1585        Publishing,
1586        /// Wireless carriers and wireline telephone companies
1587        TelecomServices,
1588        // ── Utilities ────────────────────────────────────────────────────────
1589        /// Multi-utility companies serving electricity, gas, and water
1590        UtilitiesDiversified,
1591        /// Independent power producers and energy traders
1592        UtilitiesIndependentPowerProducers,
1593        /// Regulated electric utility companies
1594        UtilitiesRegulatedElectric,
1595        /// Regulated natural gas distribution utilities
1596        UtilitiesRegulatedGas,
1597        /// Regulated water and wastewater utilities
1598        UtilitiesRegulatedWater,
1599        /// Renewable energy generation companies (wind, solar, hydro)
1600        UtilitiesRenewable,
1601        // ── Special ──────────────────────────────────────────────────────────
1602        /// Closed-end funds investing in debt instruments
1603        ClosedEndFundDebt,
1604        /// Closed-end funds investing in equities
1605        ClosedEndFundEquity,
1606        /// Closed-end funds investing in foreign securities
1607        ClosedEndFundForeign,
1608        /// Exchange-traded fund products
1609        ExchangeTradedFund,
1610    }
1611
1612    impl Industry {
1613        /// Returns the lowercase hyphenated slug used by `finance::industry()`.
1614        ///
1615        /// # Example
1616        ///
1617        /// ```
1618        /// use finance_query::Industry;
1619        /// assert_eq!(Industry::Semiconductors.as_slug(), "semiconductors");
1620        /// assert_eq!(Industry::SoftwareApplication.as_slug(), "software-application");
1621        /// ```
1622        pub fn as_slug(self) -> &'static str {
1623            match self {
1624                Industry::AgriculturalInputs => "agricultural-inputs",
1625                Industry::Aluminum => "aluminum",
1626                Industry::Coal => "coal",
1627                Industry::Copper => "copper",
1628                Industry::FarmProducts => "farm-products",
1629                Industry::ForestProducts => "forest-products",
1630                Industry::Gold => "gold",
1631                Industry::LumberAndWoodProduction => "lumber-wood-production",
1632                Industry::OtherIndustrialMetalsAndMining => "other-industrial-metals-mining",
1633                Industry::OtherPreciousMetalsAndMining => "other-precious-metals-mining",
1634                Industry::Silver => "silver",
1635                Industry::Steel => "steel",
1636                Industry::ThermalCoal => "thermal-coal",
1637                Industry::Uranium => "uranium",
1638                Industry::ApparelManufacturing => "apparel-manufacturing",
1639                Industry::ApparelRetail => "apparel-retail",
1640                Industry::AutoAndTruckDealerships => "auto-truck-dealerships",
1641                Industry::AutoManufacturers => "auto-manufacturers",
1642                Industry::AutoParts => "auto-parts",
1643                Industry::BeveragesBrewers => "beverages-brewers",
1644                Industry::BeveragesNonAlcoholic => "beverages-non-alcoholic",
1645                Industry::BeveragesWineriesAndDistilleries => "beverages-wineries-distilleries",
1646                Industry::Confectioners => "confectioners",
1647                Industry::DepartmentStores => "department-stores",
1648                Industry::DiscountStores => "discount-stores",
1649                Industry::ElectronicGamingAndMultimedia => "electronic-gaming-multimedia",
1650                Industry::FoodDistribution => "food-distribution",
1651                Industry::FootwearAndAccessories => "footwear-accessories",
1652                Industry::FurnishingsFixturesAndAppliances => "furnishings-fixtures-appliances",
1653                Industry::Gambling => "gambling",
1654                Industry::GroceryStores => "grocery-stores",
1655                Industry::HomeImprovementRetail => "home-improvement-retail",
1656                Industry::HouseholdAndPersonalProducts => "household-personal-products",
1657                Industry::InternetRetail => "internet-retail",
1658                Industry::Leisure => "leisure",
1659                Industry::Lodging => "lodging",
1660                Industry::LuxuryGoods => "luxury-goods",
1661                Industry::PackagedFoods => "packaged-foods",
1662                Industry::PersonalServices => "personal-services",
1663                Industry::ResidentialConstruction => "residential-construction",
1664                Industry::ResortsAndCasinos => "resorts-casinos",
1665                Industry::Restaurants => "restaurants",
1666                Industry::SpecialtyRetail => "specialty-retail",
1667                Industry::TextileManufacturing => "textile-manufacturing",
1668                Industry::Tobacco => "tobacco",
1669                Industry::TravelServices => "travel-services",
1670                Industry::OilAndGasDrilling => "oil-gas-drilling",
1671                Industry::OilAndGasEAndP => "oil-gas-ep",
1672                Industry::OilAndGasEquipmentAndServices => "oil-gas-equipment-services",
1673                Industry::OilAndGasIntegrated => "oil-gas-integrated",
1674                Industry::OilAndGasMidstream => "oil-gas-midstream",
1675                Industry::OilAndGasRefiningAndMarketing => "oil-gas-refining-marketing",
1676                Industry::Solar => "solar",
1677                Industry::AssetManagement => "asset-management",
1678                Industry::BanksDiversified => "banks-diversified",
1679                Industry::BanksRegional => "banks-regional",
1680                Industry::CapitalMarkets => "capital-markets",
1681                Industry::CreditServices => "credit-services",
1682                Industry::FinancialDataAndStockExchanges => "financial-data-stock-exchanges",
1683                Industry::InsuranceBrokers => "insurance-brokers",
1684                Industry::InsuranceDiversified => "insurance-diversified",
1685                Industry::InsuranceLife => "insurance-life",
1686                Industry::InsurancePropertyAndCasualty => "insurance-property-casualty",
1687                Industry::InsuranceReinsurance => "insurance-reinsurance",
1688                Industry::InsuranceSpecialty => "insurance-specialty",
1689                Industry::MortgageFinance => "mortgage-finance",
1690                Industry::ShellCompanies => "shell-companies",
1691                Industry::Biotechnology => "biotechnology",
1692                Industry::DiagnosticsAndResearch => "diagnostics-research",
1693                Industry::DrugManufacturersGeneral => "drug-manufacturers-general",
1694                Industry::DrugManufacturersSpecialtyAndGeneric => {
1695                    "drug-manufacturers-specialty-generic"
1696                }
1697                Industry::HealthInformationServices => "health-information-services",
1698                Industry::HealthcarePlans => "healthcare-plans",
1699                Industry::MedicalCareFacilities => "medical-care-facilities",
1700                Industry::MedicalDevices => "medical-devices",
1701                Industry::MedicalDistribution => "medical-distribution",
1702                Industry::MedicalInstrumentsAndSupplies => "medical-instruments-supplies",
1703                Industry::PharmaceuticalRetailers => "pharmaceutical-retailers",
1704                Industry::AerospaceAndDefense => "aerospace-defense",
1705                Industry::BuildingMaterials => "building-materials",
1706                Industry::BuildingProductsAndEquipment => "building-products-equipment",
1707                Industry::BusinessEquipmentAndSupplies => "business-equipment-supplies",
1708                Industry::ChemicalManufacturing => "chemical-manufacturing",
1709                Industry::Chemicals => "chemicals",
1710                Industry::Conglomerates => "conglomerates",
1711                Industry::ConsultingServices => "consulting-services",
1712                Industry::ElectricalEquipmentAndParts => "electrical-equipment-parts",
1713                Industry::EngineeringAndConstruction => "engineering-construction",
1714                Industry::FarmAndHeavyConstructionMachinery => "farm-heavy-construction-machinery",
1715                Industry::IndustrialDistribution => "industrial-distribution",
1716                Industry::InfrastructureOperations => "infrastructure-operations",
1717                Industry::IntegratedFreightAndLogistics => "integrated-freight-logistics",
1718                Industry::ManufacturingDiversified => "manufacturing-diversified",
1719                Industry::MarinePortsAndServices => "marine-ports-services",
1720                Industry::MarineShipping => "marine-shipping",
1721                Industry::MetalFabrication => "metal-fabrication",
1722                Industry::PaperAndPaperProducts => "paper-paper-products",
1723                Industry::PollutionAndTreatmentControls => "pollution-treatment-controls",
1724                Industry::Railroads => "railroads",
1725                Industry::RentalAndLeasingServices => "rental-leasing-services",
1726                Industry::SecurityAndProtectionServices => "security-protection-services",
1727                Industry::SpecialtyBusinessServices => "specialty-business-services",
1728                Industry::SpecialtyChemicals => "specialty-chemicals",
1729                Industry::SpecialtyIndustrialMachinery => "specialty-industrial-machinery",
1730                Industry::StaffingAndEmploymentServices => "staffing-employment-services",
1731                Industry::ToolsAndAccessories => "tools-accessories",
1732                Industry::Trucking => "trucking",
1733                Industry::WasteManagement => "waste-management",
1734                Industry::RealEstateDevelopment => "real-estate-development",
1735                Industry::RealEstateDiversified => "real-estate-diversified",
1736                Industry::RealEstateServices => "real-estate-services",
1737                Industry::ReitDiversified => "reit-diversified",
1738                Industry::ReitHealthcareFacilities => "reit-healthcare-facilities",
1739                Industry::ReitHotelAndMotel => "reit-hotel-motel",
1740                Industry::ReitIndustrial => "reit-industrial",
1741                Industry::ReitMortgage => "reit-mortgage",
1742                Industry::ReitOffice => "reit-office",
1743                Industry::ReitResidential => "reit-residential",
1744                Industry::ReitRetail => "reit-retail",
1745                Industry::ReitSpecialty => "reit-specialty",
1746                Industry::CommunicationEquipment => "communication-equipment",
1747                Industry::ComputerHardware => "computer-hardware",
1748                Industry::ConsumerElectronics => "consumer-electronics",
1749                Industry::DataAnalytics => "data-analytics",
1750                Industry::ElectronicComponents => "electronic-components",
1751                Industry::ElectronicsAndComputerDistribution => "electronics-computer-distribution",
1752                Industry::HardwareAndSoftwareDistribution => "hardware-software-distribution",
1753                Industry::InformationTechnologyServices => "information-technology-services",
1754                Industry::InternetContentAndInformation => "internet-content-information",
1755                Industry::ScientificAndTechnicalInstruments => "scientific-technical-instruments",
1756                Industry::SemiconductorEquipmentAndMaterials => "semiconductor-equipment-materials",
1757                Industry::Semiconductors => "semiconductors",
1758                Industry::SoftwareApplication => "software-application",
1759                Industry::SoftwareInfrastructure => "software-infrastructure",
1760                Industry::Broadcasting => "broadcasting",
1761                Industry::Entertainment => "entertainment",
1762                Industry::Publishing => "publishing",
1763                Industry::TelecomServices => "telecom-services",
1764                Industry::UtilitiesDiversified => "utilities-diversified",
1765                Industry::UtilitiesIndependentPowerProducers => {
1766                    "utilities-independent-power-producers"
1767                }
1768                Industry::UtilitiesRegulatedElectric => "utilities-regulated-electric",
1769                Industry::UtilitiesRegulatedGas => "utilities-regulated-gas",
1770                Industry::UtilitiesRegulatedWater => "utilities-regulated-water",
1771                Industry::UtilitiesRenewable => "utilities-renewable",
1772                Industry::ClosedEndFundDebt => "closed-end-fund-debt",
1773                Industry::ClosedEndFundEquity => "closed-end-fund-equity",
1774                Industry::ClosedEndFundForeign => "closed-end-fund-foreign",
1775                Industry::ExchangeTradedFund => "exchange-traded-fund",
1776            }
1777        }
1778
1779        /// Returns the display name used by the Yahoo Finance screener.
1780        ///
1781        /// # Example
1782        ///
1783        /// ```
1784        /// use finance_query::Industry;
1785        /// assert_eq!(Industry::Semiconductors.screener_value(), "Semiconductors");
1786        /// assert_eq!(Industry::OilAndGasDrilling.screener_value(), "Oil & Gas Drilling");
1787        /// ```
1788        pub fn screener_value(self) -> &'static str {
1789            match self {
1790                Industry::AgriculturalInputs => "Agricultural Inputs",
1791                Industry::Aluminum => "Aluminum",
1792                Industry::Coal => "Coal",
1793                Industry::Copper => "Copper",
1794                Industry::FarmProducts => "Farm Products",
1795                Industry::ForestProducts => "Forest Products",
1796                Industry::Gold => "Gold",
1797                Industry::LumberAndWoodProduction => "Lumber & Wood Production",
1798                Industry::OtherIndustrialMetalsAndMining => "Other Industrial Metals & Mining",
1799                Industry::OtherPreciousMetalsAndMining => "Other Precious Metals & Mining",
1800                Industry::Silver => "Silver",
1801                Industry::Steel => "Steel",
1802                Industry::ThermalCoal => "Thermal Coal",
1803                Industry::Uranium => "Uranium",
1804                Industry::ApparelManufacturing => "Apparel Manufacturing",
1805                Industry::ApparelRetail => "Apparel Retail",
1806                Industry::AutoAndTruckDealerships => "Auto & Truck Dealerships",
1807                Industry::AutoManufacturers => "Auto Manufacturers",
1808                Industry::AutoParts => "Auto Parts",
1809                Industry::BeveragesBrewers => "Beverages - Brewers",
1810                Industry::BeveragesNonAlcoholic => "Beverages - Non-Alcoholic",
1811                Industry::BeveragesWineriesAndDistilleries => "Beverages - Wineries & Distilleries",
1812                Industry::Confectioners => "Confectioners",
1813                Industry::DepartmentStores => "Department Stores",
1814                Industry::DiscountStores => "Discount Stores",
1815                Industry::ElectronicGamingAndMultimedia => "Electronic Gaming & Multimedia",
1816                Industry::FoodDistribution => "Food Distribution",
1817                Industry::FootwearAndAccessories => "Footwear & Accessories",
1818                Industry::FurnishingsFixturesAndAppliances => "Furnishings, Fixtures & Appliances",
1819                Industry::Gambling => "Gambling",
1820                Industry::GroceryStores => "Grocery Stores",
1821                Industry::HomeImprovementRetail => "Home Improvement Retail",
1822                Industry::HouseholdAndPersonalProducts => "Household & Personal Products",
1823                Industry::InternetRetail => "Internet Retail",
1824                Industry::Leisure => "Leisure",
1825                Industry::Lodging => "Lodging",
1826                Industry::LuxuryGoods => "Luxury Goods",
1827                Industry::PackagedFoods => "Packaged Foods",
1828                Industry::PersonalServices => "Personal Services",
1829                Industry::ResidentialConstruction => "Residential Construction",
1830                Industry::ResortsAndCasinos => "Resorts & Casinos",
1831                Industry::Restaurants => "Restaurants",
1832                Industry::SpecialtyRetail => "Specialty Retail",
1833                Industry::TextileManufacturing => "Textile Manufacturing",
1834                Industry::Tobacco => "Tobacco",
1835                Industry::TravelServices => "Travel Services",
1836                Industry::OilAndGasDrilling => "Oil & Gas Drilling",
1837                Industry::OilAndGasEAndP => "Oil & Gas E&P",
1838                Industry::OilAndGasEquipmentAndServices => "Oil & Gas Equipment & Services",
1839                Industry::OilAndGasIntegrated => "Oil & Gas Integrated",
1840                Industry::OilAndGasMidstream => "Oil & Gas Midstream",
1841                Industry::OilAndGasRefiningAndMarketing => "Oil & Gas Refining & Marketing",
1842                Industry::Solar => "Solar",
1843                Industry::AssetManagement => "Asset Management",
1844                Industry::BanksDiversified => "Banks - Diversified",
1845                Industry::BanksRegional => "Banks - Regional",
1846                Industry::CapitalMarkets => "Capital Markets",
1847                Industry::CreditServices => "Credit Services",
1848                Industry::FinancialDataAndStockExchanges => "Financial Data & Stock Exchanges",
1849                Industry::InsuranceBrokers => "Insurance Brokers",
1850                Industry::InsuranceDiversified => "Insurance - Diversified",
1851                Industry::InsuranceLife => "Insurance - Life",
1852                Industry::InsurancePropertyAndCasualty => "Insurance - Property & Casualty",
1853                Industry::InsuranceReinsurance => "Insurance - Reinsurance",
1854                Industry::InsuranceSpecialty => "Insurance - Specialty",
1855                Industry::MortgageFinance => "Mortgage Finance",
1856                Industry::ShellCompanies => "Shell Companies",
1857                Industry::Biotechnology => "Biotechnology",
1858                Industry::DiagnosticsAndResearch => "Diagnostics & Research",
1859                Industry::DrugManufacturersGeneral => "Drug Manufacturers - General",
1860                Industry::DrugManufacturersSpecialtyAndGeneric => {
1861                    "Drug Manufacturers - Specialty & Generic"
1862                }
1863                Industry::HealthInformationServices => "Health Information Services",
1864                Industry::HealthcarePlans => "Healthcare Plans",
1865                Industry::MedicalCareFacilities => "Medical Care Facilities",
1866                Industry::MedicalDevices => "Medical Devices",
1867                Industry::MedicalDistribution => "Medical Distribution",
1868                Industry::MedicalInstrumentsAndSupplies => "Medical Instruments & Supplies",
1869                Industry::PharmaceuticalRetailers => "Pharmaceutical Retailers",
1870                Industry::AerospaceAndDefense => "Aerospace & Defense",
1871                Industry::BuildingMaterials => "Building Materials",
1872                Industry::BuildingProductsAndEquipment => "Building Products & Equipment",
1873                Industry::BusinessEquipmentAndSupplies => "Business Equipment & Supplies",
1874                Industry::ChemicalManufacturing => "Chemical Manufacturing",
1875                Industry::Chemicals => "Chemicals",
1876                Industry::Conglomerates => "Conglomerates",
1877                Industry::ConsultingServices => "Consulting Services",
1878                Industry::ElectricalEquipmentAndParts => "Electrical Equipment & Parts",
1879                Industry::EngineeringAndConstruction => "Engineering & Construction",
1880                Industry::FarmAndHeavyConstructionMachinery => {
1881                    "Farm & Heavy Construction Machinery"
1882                }
1883                Industry::IndustrialDistribution => "Industrial Distribution",
1884                Industry::InfrastructureOperations => "Infrastructure Operations",
1885                Industry::IntegratedFreightAndLogistics => "Integrated Freight & Logistics",
1886                Industry::ManufacturingDiversified => "Manufacturing - Diversified",
1887                Industry::MarinePortsAndServices => "Marine Ports & Services",
1888                Industry::MarineShipping => "Marine Shipping",
1889                Industry::MetalFabrication => "Metal Fabrication",
1890                Industry::PaperAndPaperProducts => "Paper & Paper Products",
1891                Industry::PollutionAndTreatmentControls => "Pollution & Treatment Controls",
1892                Industry::Railroads => "Railroads",
1893                Industry::RentalAndLeasingServices => "Rental & Leasing Services",
1894                Industry::SecurityAndProtectionServices => "Security & Protection Services",
1895                Industry::SpecialtyBusinessServices => "Specialty Business Services",
1896                Industry::SpecialtyChemicals => "Specialty Chemicals",
1897                Industry::SpecialtyIndustrialMachinery => "Specialty Industrial Machinery",
1898                Industry::StaffingAndEmploymentServices => "Staffing & Employment Services",
1899                Industry::ToolsAndAccessories => "Tools & Accessories",
1900                Industry::Trucking => "Trucking",
1901                Industry::WasteManagement => "Waste Management",
1902                Industry::RealEstateDevelopment => "Real Estate - Development",
1903                Industry::RealEstateDiversified => "Real Estate - Diversified",
1904                Industry::RealEstateServices => "Real Estate Services",
1905                Industry::ReitDiversified => "REIT - Diversified",
1906                Industry::ReitHealthcareFacilities => "REIT - Healthcare Facilities",
1907                Industry::ReitHotelAndMotel => "REIT - Hotel & Motel",
1908                Industry::ReitIndustrial => "REIT - Industrial",
1909                Industry::ReitMortgage => "REIT - Mortgage",
1910                Industry::ReitOffice => "REIT - Office",
1911                Industry::ReitResidential => "REIT - Residential",
1912                Industry::ReitRetail => "REIT - Retail",
1913                Industry::ReitSpecialty => "REIT - Specialty",
1914                Industry::CommunicationEquipment => "Communication Equipment",
1915                Industry::ComputerHardware => "Computer Hardware",
1916                Industry::ConsumerElectronics => "Consumer Electronics",
1917                Industry::DataAnalytics => "Data Analytics",
1918                Industry::ElectronicComponents => "Electronic Components",
1919                Industry::ElectronicsAndComputerDistribution => {
1920                    "Electronics & Computer Distribution"
1921                }
1922                Industry::HardwareAndSoftwareDistribution => "Hardware & Software Distribution",
1923                Industry::InformationTechnologyServices => "Information Technology Services",
1924                Industry::InternetContentAndInformation => "Internet Content & Information",
1925                Industry::ScientificAndTechnicalInstruments => "Scientific & Technical Instruments",
1926                Industry::SemiconductorEquipmentAndMaterials => {
1927                    "Semiconductor Equipment & Materials"
1928                }
1929                Industry::Semiconductors => "Semiconductors",
1930                Industry::SoftwareApplication => "Software - Application",
1931                Industry::SoftwareInfrastructure => "Software - Infrastructure",
1932                Industry::Broadcasting => "Broadcasting",
1933                Industry::Entertainment => "Entertainment",
1934                Industry::Publishing => "Publishing",
1935                Industry::TelecomServices => "Telecom Services",
1936                Industry::UtilitiesDiversified => "Utilities - Diversified",
1937                Industry::UtilitiesIndependentPowerProducers => {
1938                    "Utilities - Independent Power Producers"
1939                }
1940                Industry::UtilitiesRegulatedElectric => "Utilities - Regulated Electric",
1941                Industry::UtilitiesRegulatedGas => "Utilities - Regulated Gas",
1942                Industry::UtilitiesRegulatedWater => "Utilities - Regulated Water",
1943                Industry::UtilitiesRenewable => "Utilities - Renewable",
1944                Industry::ClosedEndFundDebt => "Closed-End Fund - Debt",
1945                Industry::ClosedEndFundEquity => "Closed-End Fund - Equity",
1946                Industry::ClosedEndFundForeign => "Closed-End Fund - Foreign",
1947                Industry::ExchangeTradedFund => "Exchange Traded Fund",
1948            }
1949        }
1950    }
1951
1952    impl AsRef<str> for Industry {
1953        /// Returns the slug, enabling `finance::industry(Industry::Semiconductors)`.
1954        fn as_ref(&self) -> &str {
1955            self.as_slug()
1956        }
1957    }
1958
1959    impl From<Industry> for String {
1960        /// Returns the screener display name, enabling `EquityField::Industry.eq_str(Industry::Semiconductors)`.
1961        fn from(v: Industry) -> Self {
1962            v.screener_value().to_string()
1963        }
1964    }
1965}
1966
1967/// Typed exchange codes for screener queries.
1968///
1969/// Use with [`EquityField::Exchange`](crate::EquityField::Exchange) or
1970/// [`FundField::Exchange`](crate::FundField::Exchange) and
1971/// [`ScreenerFieldExt::eq_str`](crate::ScreenerFieldExt::eq_str).
1972///
1973/// For mutual fund queries use [`ExchangeCode::Nas`].
1974///
1975/// # Example
1976///
1977/// ```
1978/// use finance_query::{EquityField, EquityScreenerQuery, ScreenerFieldExt, ExchangeCode};
1979///
1980/// let query = EquityScreenerQuery::new()
1981///     .add_condition(EquityField::Exchange.eq_str(ExchangeCode::Nms));
1982/// ```
1983pub mod exchange_codes {
1984    /// Typed exchange code for screener queries.
1985    #[non_exhaustive]
1986    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1987    pub enum ExchangeCode {
1988        // ── US Equity ─────────────────────────────────────────────────────────
1989        /// NYSE American / AMEX ("ASE")
1990        Ase,
1991        /// OTC Bulletin Board ("BTS")
1992        Bts,
1993        /// NASDAQ Capital Market ("NCM")
1994        Ncm,
1995        /// NASDAQ Global Market ("NGM")
1996        Ngm,
1997        /// NASDAQ Global Select Market ("NMS") — primary NASDAQ tier
1998        Nms,
1999        /// New York Stock Exchange ("NYQ")
2000        Nyq,
2001        /// NYSE Arca ("PCX")
2002        Pcx,
2003        /// OTC Pink Sheets / OTC Markets ("PNK")
2004        Pnk,
2005        // ── US Funds ──────────────────────────────────────────────────────────
2006        /// NASDAQ — used for US mutual funds ("NAS")
2007        Nas,
2008        // ── International ─────────────────────────────────────────────────────
2009        /// Australian Securities Exchange ("ASX")
2010        Asx,
2011        /// Bombay Stock Exchange ("BSE")
2012        Bse,
2013        /// Hong Kong Stock Exchange ("HKG")
2014        Hkg,
2015        /// Korea Exchange ("KRX")
2016        Krx,
2017        /// London Stock Exchange ("LSE")
2018        Lse,
2019        /// National Stock Exchange of India ("NSI")
2020        Nsi,
2021        /// Shanghai Stock Exchange ("SHH")
2022        Shh,
2023        /// Shenzhen Stock Exchange ("SHZ")
2024        Shz,
2025        /// Tokyo Stock Exchange ("TYO")
2026        Tyo,
2027        /// Toronto Stock Exchange ("TOR")
2028        Tor,
2029        /// XETRA / Deutsche Börse ("GER")
2030        Ger,
2031    }
2032
2033    impl ExchangeCode {
2034        /// Returns the exchange code string used by Yahoo Finance.
2035        pub fn as_str(self) -> &'static str {
2036            match self {
2037                ExchangeCode::Ase => "ASE",
2038                ExchangeCode::Bts => "BTS",
2039                ExchangeCode::Ncm => "NCM",
2040                ExchangeCode::Ngm => "NGM",
2041                ExchangeCode::Nms => "NMS",
2042                ExchangeCode::Nyq => "NYQ",
2043                ExchangeCode::Pcx => "PCX",
2044                ExchangeCode::Pnk => "PNK",
2045                ExchangeCode::Nas => "NAS",
2046                ExchangeCode::Asx => "ASX",
2047                ExchangeCode::Bse => "BSE",
2048                ExchangeCode::Hkg => "HKG",
2049                ExchangeCode::Krx => "KRX",
2050                ExchangeCode::Lse => "LSE",
2051                ExchangeCode::Nsi => "NSI",
2052                ExchangeCode::Shh => "SHH",
2053                ExchangeCode::Shz => "SHZ",
2054                ExchangeCode::Tyo => "TYO",
2055                ExchangeCode::Tor => "TOR",
2056                ExchangeCode::Ger => "GER",
2057            }
2058        }
2059    }
2060
2061    impl From<ExchangeCode> for String {
2062        fn from(v: ExchangeCode) -> Self {
2063            v.as_str().to_string()
2064        }
2065    }
2066}
2067
2068#[cfg(test)]
2069mod tests {
2070    use super::*;
2071
2072    #[test]
2073    fn test_interval_as_str() {
2074        assert_eq!(Interval::OneMinute.as_str(), "1m");
2075        assert_eq!(Interval::FiveMinutes.as_str(), "5m");
2076        assert_eq!(Interval::OneDay.as_str(), "1d");
2077        assert_eq!(Interval::OneWeek.as_str(), "1wk");
2078    }
2079
2080    #[test]
2081    fn test_time_range_as_str() {
2082        assert_eq!(TimeRange::OneDay.as_str(), "1d");
2083        assert_eq!(TimeRange::OneMonth.as_str(), "1mo");
2084        assert_eq!(TimeRange::OneYear.as_str(), "1y");
2085        assert_eq!(TimeRange::Max.as_str(), "max");
2086    }
2087}