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    /// UTC offset in seconds for the region's primary exchange.
1078    ///
1079    /// Returns the standard-time (non-DST) UTC offset of each country's main
1080    /// exchange. This is used by the backtesting engine to align higher-timeframe
1081    /// resampling bucket boundaries to local calendar weeks and months, preventing
1082    /// APAC and other non-UTC exchanges from having bars mis-bucketed into the
1083    /// prior week due to UTC midnight falling inside their local trading day.
1084    ///
1085    /// # Note
1086    ///
1087    /// DST transitions are not modelled. For exchanges in regions with DST
1088    /// (e.g. NYSE, LSE) the boundary shift is at most ±1 hour and affects only
1089    /// the transition candles. This is a deliberate simplification — exact DST
1090    /// handling would require a timezone database dependency.
1091    pub const fn utc_offset_secs(&self) -> i64 {
1092        match self {
1093            // UTC-5 (NYSE/TSX winter)
1094            Region::UnitedStates | Region::Canada => -18_000,
1095            // UTC-3 (BYMA / B3 winter)
1096            Region::Argentina | Region::Brazil => -10_800,
1097            // UTC+0 (LSE / Euronext Lisbon)
1098            Region::UnitedKingdom | Region::Portugal => 0,
1099            // UTC+1 (Euronext Paris/Amsterdam/Milan/Madrid, Oslo, Stockholm, Copenhagen, Helsinki)
1100            Region::France
1101            | Region::Germany
1102            | Region::Italy
1103            | Region::Spain
1104            | Region::Norway
1105            | Region::Sweden
1106            | Region::Denmark
1107            | Region::Finland => 3_600,
1108            // UTC+2 (Athens, Tel Aviv, Moscow — note Russia stays UTC+3 year-round)
1109            Region::Greece | Region::Israel => 7_200,
1110            // UTC+3 (MOEX — no DST since 2014)
1111            Region::Turkey | Region::Russia => 10_800,
1112            // UTC+5:30 (BSE/NSE — India has no DST)
1113            Region::India => 19_800,
1114            // UTC+7 (SET Bangkok, HSX Hanoi)
1115            Region::Thailand | Region::Vietnam => 25_200,
1116            // UTC+8 (SSE/SZSE, HKEX, SGX, Bursa Malaysia, TWSE)
1117            Region::China
1118            | Region::HongKong
1119            | Region::Singapore
1120            | Region::Malaysia
1121            | Region::Taiwan => 28_800,
1122            // UTC+10 (ASX — AEST winter)
1123            Region::Australia => 36_000,
1124            // UTC+12 (NZX — NZST winter)
1125            Region::NewZealand => 43_200,
1126        }
1127    }
1128}
1129
1130impl std::str::FromStr for Region {
1131    type Err = ();
1132
1133    fn from_str(s: &str) -> Result<Self, Self::Err> {
1134        match s.to_uppercase().as_str() {
1135            "AR" => Ok(Region::Argentina),
1136            "AU" => Ok(Region::Australia),
1137            "BR" => Ok(Region::Brazil),
1138            "CA" => Ok(Region::Canada),
1139            "CN" => Ok(Region::China),
1140            "DK" => Ok(Region::Denmark),
1141            "FI" => Ok(Region::Finland),
1142            "FR" => Ok(Region::France),
1143            "DE" => Ok(Region::Germany),
1144            "GR" => Ok(Region::Greece),
1145            "HK" => Ok(Region::HongKong),
1146            "IN" => Ok(Region::India),
1147            "IL" => Ok(Region::Israel),
1148            "IT" => Ok(Region::Italy),
1149            "MY" => Ok(Region::Malaysia),
1150            "NZ" => Ok(Region::NewZealand),
1151            "NO" => Ok(Region::Norway),
1152            "PT" => Ok(Region::Portugal),
1153            "RU" => Ok(Region::Russia),
1154            "SG" => Ok(Region::Singapore),
1155            "ES" => Ok(Region::Spain),
1156            "SE" => Ok(Region::Sweden),
1157            "TW" => Ok(Region::Taiwan),
1158            "TH" => Ok(Region::Thailand),
1159            "TR" => Ok(Region::Turkey),
1160            "GB" | "UK" => Ok(Region::UnitedKingdom),
1161            "US" => Ok(Region::UnitedStates),
1162            "VN" => Ok(Region::Vietnam),
1163            _ => Err(()),
1164        }
1165    }
1166}
1167
1168impl From<Region> for String {
1169    /// Returns the lowercase two-letter country code used by the Yahoo Finance screener
1170    /// (e.g. `"us"`, `"gb"`).
1171    fn from(v: Region) -> Self {
1172        v.region().to_lowercase()
1173    }
1174}
1175
1176/// Value format for API responses
1177///
1178/// Controls how `FormattedValue<T>` fields are serialized in responses.
1179/// This allows API consumers to choose between raw numeric values,
1180/// human-readable formatted strings, or both.
1181#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
1182pub enum ValueFormat {
1183    /// Return only raw numeric values (e.g., `123.45`) - default
1184    /// Best for programmatic use, calculations, charts
1185    #[default]
1186    Raw,
1187    /// Return only formatted strings (e.g., `"$123.45"`, `"1.2B"`)
1188    /// Best for display purposes
1189    Pretty,
1190    /// Return both raw and formatted values
1191    /// Returns the full `{raw, fmt, longFmt}` object
1192    Both,
1193}
1194
1195impl std::str::FromStr for ValueFormat {
1196    type Err = ();
1197
1198    fn from_str(s: &str) -> Result<Self, Self::Err> {
1199        match s.to_lowercase().as_str() {
1200            "raw" => Ok(ValueFormat::Raw),
1201            "pretty" | "fmt" => Ok(ValueFormat::Pretty),
1202            "both" | "full" => Ok(ValueFormat::Both),
1203            _ => Err(()),
1204        }
1205    }
1206}
1207
1208impl ValueFormat {
1209    /// Parse from string (case-insensitive), returns None on invalid input
1210    pub fn parse(s: &str) -> Option<Self> {
1211        s.parse().ok()
1212    }
1213
1214    /// Convert to string representation
1215    pub fn as_str(&self) -> &'static str {
1216        match self {
1217            ValueFormat::Raw => "raw",
1218            ValueFormat::Pretty => "pretty",
1219            ValueFormat::Both => "both",
1220        }
1221    }
1222
1223    /// Transform a JSON value based on this format
1224    ///
1225    /// Recursively processes the JSON, detecting FormattedValue objects
1226    /// (objects with `raw` key and optionally `fmt`/`longFmt`) and
1227    /// transforming them according to the format setting.
1228    ///
1229    /// # Example
1230    ///
1231    /// ```
1232    /// use finance_query::ValueFormat;
1233    /// use serde_json::json;
1234    ///
1235    /// let data = json!({"price": {"raw": 123.45, "fmt": "$123.45"}});
1236    ///
1237    /// // Raw format extracts just the raw value (default)
1238    /// let raw = ValueFormat::default().transform(data.clone());
1239    /// assert_eq!(raw, json!({"price": 123.45}));
1240    ///
1241    /// // Pretty extracts just the formatted string
1242    /// let pretty = ValueFormat::Pretty.transform(data.clone());
1243    /// assert_eq!(pretty, json!({"price": "$123.45"}));
1244    ///
1245    /// // Both keeps the full object
1246    /// let both = ValueFormat::Both.transform(data);
1247    /// assert_eq!(both, json!({"price": {"raw": 123.45, "fmt": "$123.45"}}));
1248    /// ```
1249    pub fn transform(&self, value: serde_json::Value) -> serde_json::Value {
1250        match self {
1251            ValueFormat::Both => value, // No transformation needed
1252            _ => self.transform_recursive(value),
1253        }
1254    }
1255
1256    fn transform_recursive(&self, value: serde_json::Value) -> serde_json::Value {
1257        use serde_json::Value;
1258
1259        match value {
1260            Value::Object(map) => {
1261                // Check if this looks like a FormattedValue (has 'raw' key)
1262                if self.is_formatted_value(&map) {
1263                    return self.extract_value(&map);
1264                }
1265
1266                // Otherwise, recursively transform all values
1267                let transformed: serde_json::Map<String, Value> = map
1268                    .into_iter()
1269                    .map(|(k, v)| (k, self.transform_recursive(v)))
1270                    .collect();
1271                Value::Object(transformed)
1272            }
1273            Value::Array(arr) => Value::Array(
1274                arr.into_iter()
1275                    .map(|v| self.transform_recursive(v))
1276                    .collect(),
1277            ),
1278            // Primitives pass through unchanged
1279            other => other,
1280        }
1281    }
1282
1283    /// Check if an object looks like a FormattedValue
1284    fn is_formatted_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> bool {
1285        // Must have 'raw' key (can be null)
1286        // May have 'fmt' and/or 'longFmt'
1287        // Should not have many other keys (FormattedValue only has these 3)
1288        if !map.contains_key("raw") {
1289            return false;
1290        }
1291
1292        let known_keys = ["raw", "fmt", "longFmt"];
1293        let unknown_keys = map
1294            .keys()
1295            .filter(|k| !known_keys.contains(&k.as_str()))
1296            .count();
1297
1298        // If there are unknown keys, it's probably not a FormattedValue
1299        unknown_keys == 0
1300    }
1301
1302    /// Extract the appropriate value based on format
1303    fn extract_value(&self, map: &serde_json::Map<String, serde_json::Value>) -> serde_json::Value {
1304        match self {
1305            ValueFormat::Raw => {
1306                // Return raw value directly (or null if not present)
1307                map.get("raw").cloned().unwrap_or(serde_json::Value::Null)
1308            }
1309            ValueFormat::Pretty => {
1310                // Prefer fmt, fall back to longFmt, then null
1311                map.get("fmt")
1312                    .or_else(|| map.get("longFmt"))
1313                    .cloned()
1314                    .unwrap_or(serde_json::Value::Null)
1315            }
1316            ValueFormat::Both => {
1317                // Keep as-is (shouldn't reach here, but handle anyway)
1318                serde_json::Value::Object(map.clone())
1319            }
1320        }
1321    }
1322}
1323
1324/// Typed industry identifiers shared between the industry endpoint and screener queries.
1325///
1326/// Use with [`finance::industry()`](crate::finance::industry) for the data endpoint, and with
1327/// [`EquityField::Industry`](crate::EquityField::Industry) +
1328/// [`ScreenerFieldExt::eq_str`](crate::ScreenerFieldExt::eq_str) for screener filtering.
1329///
1330/// - `as_slug()` → lowercase hyphenated key for `finance::industry()` (e.g. `"semiconductors"`)
1331/// - `From<Industry> for String` → screener display name (e.g. `"Semiconductors"`)
1332///
1333/// # Example
1334///
1335/// ```no_run
1336/// use finance_query::{finance, Industry, EquityField, EquityScreenerQuery, ScreenerFieldExt};
1337///
1338/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1339/// // Industry endpoint
1340/// let data = finance::industry(Industry::Semiconductors).await?;
1341///
1342/// // Screener filter
1343/// let query = EquityScreenerQuery::new()
1344///     .add_condition(EquityField::Industry.eq_str(Industry::Semiconductors));
1345/// # Ok(())
1346/// # }
1347/// ```
1348pub mod industries {
1349    /// Typed industry identifier for the industry endpoint and custom screener queries.
1350    ///
1351    /// See the module-level doc for usage.
1352    #[non_exhaustive]
1353    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1354    pub enum Industry {
1355        // ── Agriculture / Raw Materials ──────────────────────────────────────
1356        /// Agricultural inputs, fertilizers, and crop chemicals
1357        AgriculturalInputs,
1358        /// Aluminum production and processing companies
1359        Aluminum,
1360        /// Coal mining and processing companies
1361        Coal,
1362        /// Copper mining and processing companies
1363        Copper,
1364        /// Farm products including grains, livestock, and produce
1365        FarmProducts,
1366        /// Forest products including timber and paper pulp
1367        ForestProducts,
1368        /// Gold mining and royalty companies
1369        Gold,
1370        /// Lumber and wood production companies
1371        LumberAndWoodProduction,
1372        /// Other industrial metals and mining (zinc, nickel, etc.)
1373        OtherIndustrialMetalsAndMining,
1374        /// Other precious metals and mining (platinum, palladium, etc.)
1375        OtherPreciousMetalsAndMining,
1376        /// Silver mining and streaming companies
1377        Silver,
1378        /// Steel production and processing companies
1379        Steel,
1380        /// Thermal coal mining for electricity generation
1381        ThermalCoal,
1382        /// Uranium mining companies
1383        Uranium,
1384        // ── Consumer ─────────────────────────────────────────────────────────
1385        /// Clothing and apparel manufacturing companies
1386        ApparelManufacturing,
1387        /// Clothing and apparel retail chains
1388        ApparelRetail,
1389        /// Automotive and truck dealerships
1390        AutoAndTruckDealerships,
1391        /// Automobile manufacturers and assemblers
1392        AutoManufacturers,
1393        /// Automotive parts manufacturers and distributors
1394        AutoParts,
1395        /// Beer brewing and distribution companies
1396        BeveragesBrewers,
1397        /// Non-alcoholic beverages including soft drinks and juices
1398        BeveragesNonAlcoholic,
1399        /// Wineries, distilleries, and spirits producers
1400        BeveragesWineriesAndDistilleries,
1401        /// Candy, chocolate, and confectionery makers
1402        Confectioners,
1403        /// Traditional department store retailers
1404        DepartmentStores,
1405        /// Discount and value retail stores
1406        DiscountStores,
1407        /// Electronic gaming software and multimedia entertainment
1408        ElectronicGamingAndMultimedia,
1409        /// Wholesale food distribution companies
1410        FoodDistribution,
1411        /// Footwear, handbags, and fashion accessories
1412        FootwearAndAccessories,
1413        /// Furniture, fixtures, and household appliances
1414        FurnishingsFixturesAndAppliances,
1415        /// Casinos, online gambling, and gaming operators
1416        Gambling,
1417        /// Supermarkets and grocery retail chains
1418        GroceryStores,
1419        /// Home improvement retail stores
1420        HomeImprovementRetail,
1421        /// Household cleaning products and personal care items
1422        HouseholdAndPersonalProducts,
1423        /// Online retail and e-commerce marketplaces
1424        InternetRetail,
1425        /// Leisure, recreation, and entertainment companies
1426        Leisure,
1427        /// Hotels and lodging companies
1428        Lodging,
1429        /// Luxury goods, fashion, and premium consumer brands
1430        LuxuryGoods,
1431        /// Packaged and processed food manufacturers
1432        PackagedFoods,
1433        /// Personal care, laundry, and household services
1434        PersonalServices,
1435        /// Home builders and residential construction
1436        ResidentialConstruction,
1437        /// Resorts, integrated casinos, and hotel-casinos
1438        ResortsAndCasinos,
1439        /// Restaurant chains and food service operators
1440        Restaurants,
1441        /// Specialty retail stores (pets, books, electronics, etc.)
1442        SpecialtyRetail,
1443        /// Textile and fabric manufacturers
1444        TextileManufacturing,
1445        /// Tobacco product manufacturers
1446        Tobacco,
1447        /// Travel agencies, booking platforms, and tour operators
1448        TravelServices,
1449        // ── Energy ───────────────────────────────────────────────────────────
1450        /// Oil and gas contract drilling services
1451        OilAndGasDrilling,
1452        /// Oil and gas exploration and production companies
1453        OilAndGasEAndP,
1454        /// Oil field equipment, services, and engineering
1455        OilAndGasEquipmentAndServices,
1456        /// Vertically integrated oil and gas majors
1457        OilAndGasIntegrated,
1458        /// Oil and gas pipelines, storage, and transportation
1459        OilAndGasMidstream,
1460        /// Oil refining, wholesale fuel, and marketing
1461        OilAndGasRefiningAndMarketing,
1462        /// Solar panel manufacturers and solar energy producers
1463        Solar,
1464        // ── Financial Services ───────────────────────────────────────────────
1465        /// Asset managers, fund sponsors, and investment advisors
1466        AssetManagement,
1467        /// Large diversified national and international banks
1468        BanksDiversified,
1469        /// Regional and community banks
1470        BanksRegional,
1471        /// Investment banks, brokers, and financial exchanges
1472        CapitalMarkets,
1473        /// Credit card issuers and consumer credit services
1474        CreditServices,
1475        /// Financial data, analytics, and stock exchange operators
1476        FinancialDataAndStockExchanges,
1477        /// Insurance brokers and agencies
1478        InsuranceBrokers,
1479        /// Diversified multi-line insurance companies
1480        InsuranceDiversified,
1481        /// Life insurance and annuity providers
1482        InsuranceLife,
1483        /// Property and casualty insurance companies
1484        InsurancePropertyAndCasualty,
1485        /// Reinsurance companies
1486        InsuranceReinsurance,
1487        /// Specialty insurance lines (title, mortgage, etc.)
1488        InsuranceSpecialty,
1489        /// Mortgage banking and loan origination
1490        MortgageFinance,
1491        /// Blank-check and shell holding companies
1492        ShellCompanies,
1493        // ── Healthcare ───────────────────────────────────────────────────────
1494        /// Biotechnology drug development companies
1495        Biotechnology,
1496        /// Medical diagnostics labs and clinical research
1497        DiagnosticsAndResearch,
1498        /// Large branded pharmaceutical manufacturers
1499        DrugManufacturersGeneral,
1500        /// Specialty drugs, generics, and biosimilars
1501        DrugManufacturersSpecialtyAndGeneric,
1502        /// Healthcare IT, EHR, and health data services
1503        HealthInformationServices,
1504        /// Managed care organizations and health insurers
1505        HealthcarePlans,
1506        /// Hospitals, clinics, and outpatient care facilities
1507        MedicalCareFacilities,
1508        /// Medical device manufacturers (implants, diagnostics equipment)
1509        MedicalDevices,
1510        /// Medical product wholesalers and distributors
1511        MedicalDistribution,
1512        /// Surgical instruments, disposables, and medical supplies
1513        MedicalInstrumentsAndSupplies,
1514        /// Retail pharmacies and drug store chains
1515        PharmaceuticalRetailers,
1516        // ── Industrials ──────────────────────────────────────────────────────
1517        /// Defense contractors, aircraft, and space systems
1518        AerospaceAndDefense,
1519        /// Construction aggregates, cement, and building materials
1520        BuildingMaterials,
1521        /// HVAC, plumbing, windows, and building equipment
1522        BuildingProductsAndEquipment,
1523        /// Office supplies, commercial equipment, and printers
1524        BusinessEquipmentAndSupplies,
1525        /// Specialty chemical manufacturing for industrial use
1526        ChemicalManufacturing,
1527        /// Diversified commodity chemicals producers
1528        Chemicals,
1529        /// Diversified industrial holding companies
1530        Conglomerates,
1531        /// Management consulting and professional advisory services
1532        ConsultingServices,
1533        /// Electrical components, motors, and power equipment
1534        ElectricalEquipmentAndParts,
1535        /// Civil engineering, construction, and infrastructure projects
1536        EngineeringAndConstruction,
1537        /// Agricultural equipment and heavy construction machinery
1538        FarmAndHeavyConstructionMachinery,
1539        /// Industrial goods wholesalers and distributors
1540        IndustrialDistribution,
1541        /// Toll roads, airports, and infrastructure operators
1542        InfrastructureOperations,
1543        /// Third-party logistics and supply chain management
1544        IntegratedFreightAndLogistics,
1545        /// Diversified manufacturers across multiple industrial segments
1546        ManufacturingDiversified,
1547        /// Port operators and marine terminal services
1548        MarinePortsAndServices,
1549        /// Bulk cargo and tanker shipping companies
1550        MarineShipping,
1551        /// Custom metal fabrication and machined components
1552        MetalFabrication,
1553        /// Paper, packaging, and pulp product manufacturers
1554        PaperAndPaperProducts,
1555        /// Environmental controls, water treatment, and remediation
1556        PollutionAndTreatmentControls,
1557        /// Rail freight carriers and passenger rail operators
1558        Railroads,
1559        /// Equipment rental, leasing, and fleet management
1560        RentalAndLeasingServices,
1561        /// Security systems, guards, and monitoring services
1562        SecurityAndProtectionServices,
1563        /// Outsourced business services and BPO companies
1564        SpecialtyBusinessServices,
1565        /// High-value specialty chemicals and advanced materials
1566        SpecialtyChemicals,
1567        /// Specialized industrial machinery and equipment makers
1568        SpecialtyIndustrialMachinery,
1569        /// Staffing agencies and employment service providers
1570        StaffingAndEmploymentServices,
1571        /// Hand tools, power tools, and hardware accessories
1572        ToolsAndAccessories,
1573        /// Freight trucking and less-than-truckload carriers
1574        Trucking,
1575        /// Waste collection, recycling, and disposal services
1576        WasteManagement,
1577        // ── Real Estate ──────────────────────────────────────────────────────
1578        /// Real estate developers and homebuilders
1579        RealEstateDevelopment,
1580        /// Diversified real estate companies with mixed portfolios
1581        RealEstateDiversified,
1582        /// Real estate brokers, agents, and property managers
1583        RealEstateServices,
1584        /// Diversified REITs across multiple property types
1585        ReitDiversified,
1586        /// Healthcare and senior living facility REITs
1587        ReitHealthcareFacilities,
1588        /// Hotel and motel property REITs
1589        ReitHotelAndMotel,
1590        /// Industrial, warehouse, and logistics property REITs
1591        ReitIndustrial,
1592        /// Mortgage REITs investing in real estate debt
1593        ReitMortgage,
1594        /// Office building and commercial property REITs
1595        ReitOffice,
1596        /// Apartment, multifamily, and residential property REITs
1597        ReitResidential,
1598        /// Shopping center and retail property REITs
1599        ReitRetail,
1600        /// Specialty REITs (data centers, cell towers, self-storage)
1601        ReitSpecialty,
1602        // ── Technology ───────────────────────────────────────────────────────
1603        /// Networking hardware, routers, and communication equipment
1604        CommunicationEquipment,
1605        /// PCs, servers, and computer hardware manufacturers
1606        ComputerHardware,
1607        /// Smartphones, TVs, and consumer electronic devices
1608        ConsumerElectronics,
1609        /// Data analytics, business intelligence, and AI platforms
1610        DataAnalytics,
1611        /// Passive electronic components and circuit boards
1612        ElectronicComponents,
1613        /// Distributors of electronics and computer products
1614        ElectronicsAndComputerDistribution,
1615        /// Value-added resellers and software/hardware distributors
1616        HardwareAndSoftwareDistribution,
1617        /// IT services, outsourcing, and technology consulting
1618        InformationTechnologyServices,
1619        /// Online media, search engines, and digital content platforms
1620        InternetContentAndInformation,
1621        /// Precision instruments, sensors, and test equipment
1622        ScientificAndTechnicalInstruments,
1623        /// Semiconductor manufacturing equipment and materials
1624        SemiconductorEquipmentAndMaterials,
1625        /// Integrated circuit and chip designers and manufacturers
1626        Semiconductors,
1627        /// Business application software companies
1628        SoftwareApplication,
1629        /// Operating systems, middleware, and infrastructure software
1630        SoftwareInfrastructure,
1631        // ── Communication Services ───────────────────────────────────────────
1632        /// Television, radio, and broadcast media companies
1633        Broadcasting,
1634        /// Film studios, streaming, and live entertainment
1635        Entertainment,
1636        /// Book, magazine, newspaper, and digital media publishers
1637        Publishing,
1638        /// Wireless carriers and wireline telephone companies
1639        TelecomServices,
1640        // ── Utilities ────────────────────────────────────────────────────────
1641        /// Multi-utility companies serving electricity, gas, and water
1642        UtilitiesDiversified,
1643        /// Independent power producers and energy traders
1644        UtilitiesIndependentPowerProducers,
1645        /// Regulated electric utility companies
1646        UtilitiesRegulatedElectric,
1647        /// Regulated natural gas distribution utilities
1648        UtilitiesRegulatedGas,
1649        /// Regulated water and wastewater utilities
1650        UtilitiesRegulatedWater,
1651        /// Renewable energy generation companies (wind, solar, hydro)
1652        UtilitiesRenewable,
1653        // ── Special ──────────────────────────────────────────────────────────
1654        /// Closed-end funds investing in debt instruments
1655        ClosedEndFundDebt,
1656        /// Closed-end funds investing in equities
1657        ClosedEndFundEquity,
1658        /// Closed-end funds investing in foreign securities
1659        ClosedEndFundForeign,
1660        /// Exchange-traded fund products
1661        ExchangeTradedFund,
1662    }
1663
1664    impl Industry {
1665        /// Returns the lowercase hyphenated slug used by `finance::industry()`.
1666        ///
1667        /// # Example
1668        ///
1669        /// ```
1670        /// use finance_query::Industry;
1671        /// assert_eq!(Industry::Semiconductors.as_slug(), "semiconductors");
1672        /// assert_eq!(Industry::SoftwareApplication.as_slug(), "software-application");
1673        /// ```
1674        pub fn as_slug(self) -> &'static str {
1675            match self {
1676                Industry::AgriculturalInputs => "agricultural-inputs",
1677                Industry::Aluminum => "aluminum",
1678                Industry::Coal => "coal",
1679                Industry::Copper => "copper",
1680                Industry::FarmProducts => "farm-products",
1681                Industry::ForestProducts => "forest-products",
1682                Industry::Gold => "gold",
1683                Industry::LumberAndWoodProduction => "lumber-wood-production",
1684                Industry::OtherIndustrialMetalsAndMining => "other-industrial-metals-mining",
1685                Industry::OtherPreciousMetalsAndMining => "other-precious-metals-mining",
1686                Industry::Silver => "silver",
1687                Industry::Steel => "steel",
1688                Industry::ThermalCoal => "thermal-coal",
1689                Industry::Uranium => "uranium",
1690                Industry::ApparelManufacturing => "apparel-manufacturing",
1691                Industry::ApparelRetail => "apparel-retail",
1692                Industry::AutoAndTruckDealerships => "auto-truck-dealerships",
1693                Industry::AutoManufacturers => "auto-manufacturers",
1694                Industry::AutoParts => "auto-parts",
1695                Industry::BeveragesBrewers => "beverages-brewers",
1696                Industry::BeveragesNonAlcoholic => "beverages-non-alcoholic",
1697                Industry::BeveragesWineriesAndDistilleries => "beverages-wineries-distilleries",
1698                Industry::Confectioners => "confectioners",
1699                Industry::DepartmentStores => "department-stores",
1700                Industry::DiscountStores => "discount-stores",
1701                Industry::ElectronicGamingAndMultimedia => "electronic-gaming-multimedia",
1702                Industry::FoodDistribution => "food-distribution",
1703                Industry::FootwearAndAccessories => "footwear-accessories",
1704                Industry::FurnishingsFixturesAndAppliances => "furnishings-fixtures-appliances",
1705                Industry::Gambling => "gambling",
1706                Industry::GroceryStores => "grocery-stores",
1707                Industry::HomeImprovementRetail => "home-improvement-retail",
1708                Industry::HouseholdAndPersonalProducts => "household-personal-products",
1709                Industry::InternetRetail => "internet-retail",
1710                Industry::Leisure => "leisure",
1711                Industry::Lodging => "lodging",
1712                Industry::LuxuryGoods => "luxury-goods",
1713                Industry::PackagedFoods => "packaged-foods",
1714                Industry::PersonalServices => "personal-services",
1715                Industry::ResidentialConstruction => "residential-construction",
1716                Industry::ResortsAndCasinos => "resorts-casinos",
1717                Industry::Restaurants => "restaurants",
1718                Industry::SpecialtyRetail => "specialty-retail",
1719                Industry::TextileManufacturing => "textile-manufacturing",
1720                Industry::Tobacco => "tobacco",
1721                Industry::TravelServices => "travel-services",
1722                Industry::OilAndGasDrilling => "oil-gas-drilling",
1723                Industry::OilAndGasEAndP => "oil-gas-ep",
1724                Industry::OilAndGasEquipmentAndServices => "oil-gas-equipment-services",
1725                Industry::OilAndGasIntegrated => "oil-gas-integrated",
1726                Industry::OilAndGasMidstream => "oil-gas-midstream",
1727                Industry::OilAndGasRefiningAndMarketing => "oil-gas-refining-marketing",
1728                Industry::Solar => "solar",
1729                Industry::AssetManagement => "asset-management",
1730                Industry::BanksDiversified => "banks-diversified",
1731                Industry::BanksRegional => "banks-regional",
1732                Industry::CapitalMarkets => "capital-markets",
1733                Industry::CreditServices => "credit-services",
1734                Industry::FinancialDataAndStockExchanges => "financial-data-stock-exchanges",
1735                Industry::InsuranceBrokers => "insurance-brokers",
1736                Industry::InsuranceDiversified => "insurance-diversified",
1737                Industry::InsuranceLife => "insurance-life",
1738                Industry::InsurancePropertyAndCasualty => "insurance-property-casualty",
1739                Industry::InsuranceReinsurance => "insurance-reinsurance",
1740                Industry::InsuranceSpecialty => "insurance-specialty",
1741                Industry::MortgageFinance => "mortgage-finance",
1742                Industry::ShellCompanies => "shell-companies",
1743                Industry::Biotechnology => "biotechnology",
1744                Industry::DiagnosticsAndResearch => "diagnostics-research",
1745                Industry::DrugManufacturersGeneral => "drug-manufacturers-general",
1746                Industry::DrugManufacturersSpecialtyAndGeneric => {
1747                    "drug-manufacturers-specialty-generic"
1748                }
1749                Industry::HealthInformationServices => "health-information-services",
1750                Industry::HealthcarePlans => "healthcare-plans",
1751                Industry::MedicalCareFacilities => "medical-care-facilities",
1752                Industry::MedicalDevices => "medical-devices",
1753                Industry::MedicalDistribution => "medical-distribution",
1754                Industry::MedicalInstrumentsAndSupplies => "medical-instruments-supplies",
1755                Industry::PharmaceuticalRetailers => "pharmaceutical-retailers",
1756                Industry::AerospaceAndDefense => "aerospace-defense",
1757                Industry::BuildingMaterials => "building-materials",
1758                Industry::BuildingProductsAndEquipment => "building-products-equipment",
1759                Industry::BusinessEquipmentAndSupplies => "business-equipment-supplies",
1760                Industry::ChemicalManufacturing => "chemical-manufacturing",
1761                Industry::Chemicals => "chemicals",
1762                Industry::Conglomerates => "conglomerates",
1763                Industry::ConsultingServices => "consulting-services",
1764                Industry::ElectricalEquipmentAndParts => "electrical-equipment-parts",
1765                Industry::EngineeringAndConstruction => "engineering-construction",
1766                Industry::FarmAndHeavyConstructionMachinery => "farm-heavy-construction-machinery",
1767                Industry::IndustrialDistribution => "industrial-distribution",
1768                Industry::InfrastructureOperations => "infrastructure-operations",
1769                Industry::IntegratedFreightAndLogistics => "integrated-freight-logistics",
1770                Industry::ManufacturingDiversified => "manufacturing-diversified",
1771                Industry::MarinePortsAndServices => "marine-ports-services",
1772                Industry::MarineShipping => "marine-shipping",
1773                Industry::MetalFabrication => "metal-fabrication",
1774                Industry::PaperAndPaperProducts => "paper-paper-products",
1775                Industry::PollutionAndTreatmentControls => "pollution-treatment-controls",
1776                Industry::Railroads => "railroads",
1777                Industry::RentalAndLeasingServices => "rental-leasing-services",
1778                Industry::SecurityAndProtectionServices => "security-protection-services",
1779                Industry::SpecialtyBusinessServices => "specialty-business-services",
1780                Industry::SpecialtyChemicals => "specialty-chemicals",
1781                Industry::SpecialtyIndustrialMachinery => "specialty-industrial-machinery",
1782                Industry::StaffingAndEmploymentServices => "staffing-employment-services",
1783                Industry::ToolsAndAccessories => "tools-accessories",
1784                Industry::Trucking => "trucking",
1785                Industry::WasteManagement => "waste-management",
1786                Industry::RealEstateDevelopment => "real-estate-development",
1787                Industry::RealEstateDiversified => "real-estate-diversified",
1788                Industry::RealEstateServices => "real-estate-services",
1789                Industry::ReitDiversified => "reit-diversified",
1790                Industry::ReitHealthcareFacilities => "reit-healthcare-facilities",
1791                Industry::ReitHotelAndMotel => "reit-hotel-motel",
1792                Industry::ReitIndustrial => "reit-industrial",
1793                Industry::ReitMortgage => "reit-mortgage",
1794                Industry::ReitOffice => "reit-office",
1795                Industry::ReitResidential => "reit-residential",
1796                Industry::ReitRetail => "reit-retail",
1797                Industry::ReitSpecialty => "reit-specialty",
1798                Industry::CommunicationEquipment => "communication-equipment",
1799                Industry::ComputerHardware => "computer-hardware",
1800                Industry::ConsumerElectronics => "consumer-electronics",
1801                Industry::DataAnalytics => "data-analytics",
1802                Industry::ElectronicComponents => "electronic-components",
1803                Industry::ElectronicsAndComputerDistribution => "electronics-computer-distribution",
1804                Industry::HardwareAndSoftwareDistribution => "hardware-software-distribution",
1805                Industry::InformationTechnologyServices => "information-technology-services",
1806                Industry::InternetContentAndInformation => "internet-content-information",
1807                Industry::ScientificAndTechnicalInstruments => "scientific-technical-instruments",
1808                Industry::SemiconductorEquipmentAndMaterials => "semiconductor-equipment-materials",
1809                Industry::Semiconductors => "semiconductors",
1810                Industry::SoftwareApplication => "software-application",
1811                Industry::SoftwareInfrastructure => "software-infrastructure",
1812                Industry::Broadcasting => "broadcasting",
1813                Industry::Entertainment => "entertainment",
1814                Industry::Publishing => "publishing",
1815                Industry::TelecomServices => "telecom-services",
1816                Industry::UtilitiesDiversified => "utilities-diversified",
1817                Industry::UtilitiesIndependentPowerProducers => {
1818                    "utilities-independent-power-producers"
1819                }
1820                Industry::UtilitiesRegulatedElectric => "utilities-regulated-electric",
1821                Industry::UtilitiesRegulatedGas => "utilities-regulated-gas",
1822                Industry::UtilitiesRegulatedWater => "utilities-regulated-water",
1823                Industry::UtilitiesRenewable => "utilities-renewable",
1824                Industry::ClosedEndFundDebt => "closed-end-fund-debt",
1825                Industry::ClosedEndFundEquity => "closed-end-fund-equity",
1826                Industry::ClosedEndFundForeign => "closed-end-fund-foreign",
1827                Industry::ExchangeTradedFund => "exchange-traded-fund",
1828            }
1829        }
1830
1831        /// Returns the display name used by the Yahoo Finance screener.
1832        ///
1833        /// # Example
1834        ///
1835        /// ```
1836        /// use finance_query::Industry;
1837        /// assert_eq!(Industry::Semiconductors.screener_value(), "Semiconductors");
1838        /// assert_eq!(Industry::OilAndGasDrilling.screener_value(), "Oil & Gas Drilling");
1839        /// ```
1840        pub fn screener_value(self) -> &'static str {
1841            match self {
1842                Industry::AgriculturalInputs => "Agricultural Inputs",
1843                Industry::Aluminum => "Aluminum",
1844                Industry::Coal => "Coal",
1845                Industry::Copper => "Copper",
1846                Industry::FarmProducts => "Farm Products",
1847                Industry::ForestProducts => "Forest Products",
1848                Industry::Gold => "Gold",
1849                Industry::LumberAndWoodProduction => "Lumber & Wood Production",
1850                Industry::OtherIndustrialMetalsAndMining => "Other Industrial Metals & Mining",
1851                Industry::OtherPreciousMetalsAndMining => "Other Precious Metals & Mining",
1852                Industry::Silver => "Silver",
1853                Industry::Steel => "Steel",
1854                Industry::ThermalCoal => "Thermal Coal",
1855                Industry::Uranium => "Uranium",
1856                Industry::ApparelManufacturing => "Apparel Manufacturing",
1857                Industry::ApparelRetail => "Apparel Retail",
1858                Industry::AutoAndTruckDealerships => "Auto & Truck Dealerships",
1859                Industry::AutoManufacturers => "Auto Manufacturers",
1860                Industry::AutoParts => "Auto Parts",
1861                Industry::BeveragesBrewers => "Beverages - Brewers",
1862                Industry::BeveragesNonAlcoholic => "Beverages - Non-Alcoholic",
1863                Industry::BeveragesWineriesAndDistilleries => "Beverages - Wineries & Distilleries",
1864                Industry::Confectioners => "Confectioners",
1865                Industry::DepartmentStores => "Department Stores",
1866                Industry::DiscountStores => "Discount Stores",
1867                Industry::ElectronicGamingAndMultimedia => "Electronic Gaming & Multimedia",
1868                Industry::FoodDistribution => "Food Distribution",
1869                Industry::FootwearAndAccessories => "Footwear & Accessories",
1870                Industry::FurnishingsFixturesAndAppliances => "Furnishings, Fixtures & Appliances",
1871                Industry::Gambling => "Gambling",
1872                Industry::GroceryStores => "Grocery Stores",
1873                Industry::HomeImprovementRetail => "Home Improvement Retail",
1874                Industry::HouseholdAndPersonalProducts => "Household & Personal Products",
1875                Industry::InternetRetail => "Internet Retail",
1876                Industry::Leisure => "Leisure",
1877                Industry::Lodging => "Lodging",
1878                Industry::LuxuryGoods => "Luxury Goods",
1879                Industry::PackagedFoods => "Packaged Foods",
1880                Industry::PersonalServices => "Personal Services",
1881                Industry::ResidentialConstruction => "Residential Construction",
1882                Industry::ResortsAndCasinos => "Resorts & Casinos",
1883                Industry::Restaurants => "Restaurants",
1884                Industry::SpecialtyRetail => "Specialty Retail",
1885                Industry::TextileManufacturing => "Textile Manufacturing",
1886                Industry::Tobacco => "Tobacco",
1887                Industry::TravelServices => "Travel Services",
1888                Industry::OilAndGasDrilling => "Oil & Gas Drilling",
1889                Industry::OilAndGasEAndP => "Oil & Gas E&P",
1890                Industry::OilAndGasEquipmentAndServices => "Oil & Gas Equipment & Services",
1891                Industry::OilAndGasIntegrated => "Oil & Gas Integrated",
1892                Industry::OilAndGasMidstream => "Oil & Gas Midstream",
1893                Industry::OilAndGasRefiningAndMarketing => "Oil & Gas Refining & Marketing",
1894                Industry::Solar => "Solar",
1895                Industry::AssetManagement => "Asset Management",
1896                Industry::BanksDiversified => "Banks - Diversified",
1897                Industry::BanksRegional => "Banks - Regional",
1898                Industry::CapitalMarkets => "Capital Markets",
1899                Industry::CreditServices => "Credit Services",
1900                Industry::FinancialDataAndStockExchanges => "Financial Data & Stock Exchanges",
1901                Industry::InsuranceBrokers => "Insurance Brokers",
1902                Industry::InsuranceDiversified => "Insurance - Diversified",
1903                Industry::InsuranceLife => "Insurance - Life",
1904                Industry::InsurancePropertyAndCasualty => "Insurance - Property & Casualty",
1905                Industry::InsuranceReinsurance => "Insurance - Reinsurance",
1906                Industry::InsuranceSpecialty => "Insurance - Specialty",
1907                Industry::MortgageFinance => "Mortgage Finance",
1908                Industry::ShellCompanies => "Shell Companies",
1909                Industry::Biotechnology => "Biotechnology",
1910                Industry::DiagnosticsAndResearch => "Diagnostics & Research",
1911                Industry::DrugManufacturersGeneral => "Drug Manufacturers - General",
1912                Industry::DrugManufacturersSpecialtyAndGeneric => {
1913                    "Drug Manufacturers - Specialty & Generic"
1914                }
1915                Industry::HealthInformationServices => "Health Information Services",
1916                Industry::HealthcarePlans => "Healthcare Plans",
1917                Industry::MedicalCareFacilities => "Medical Care Facilities",
1918                Industry::MedicalDevices => "Medical Devices",
1919                Industry::MedicalDistribution => "Medical Distribution",
1920                Industry::MedicalInstrumentsAndSupplies => "Medical Instruments & Supplies",
1921                Industry::PharmaceuticalRetailers => "Pharmaceutical Retailers",
1922                Industry::AerospaceAndDefense => "Aerospace & Defense",
1923                Industry::BuildingMaterials => "Building Materials",
1924                Industry::BuildingProductsAndEquipment => "Building Products & Equipment",
1925                Industry::BusinessEquipmentAndSupplies => "Business Equipment & Supplies",
1926                Industry::ChemicalManufacturing => "Chemical Manufacturing",
1927                Industry::Chemicals => "Chemicals",
1928                Industry::Conglomerates => "Conglomerates",
1929                Industry::ConsultingServices => "Consulting Services",
1930                Industry::ElectricalEquipmentAndParts => "Electrical Equipment & Parts",
1931                Industry::EngineeringAndConstruction => "Engineering & Construction",
1932                Industry::FarmAndHeavyConstructionMachinery => {
1933                    "Farm & Heavy Construction Machinery"
1934                }
1935                Industry::IndustrialDistribution => "Industrial Distribution",
1936                Industry::InfrastructureOperations => "Infrastructure Operations",
1937                Industry::IntegratedFreightAndLogistics => "Integrated Freight & Logistics",
1938                Industry::ManufacturingDiversified => "Manufacturing - Diversified",
1939                Industry::MarinePortsAndServices => "Marine Ports & Services",
1940                Industry::MarineShipping => "Marine Shipping",
1941                Industry::MetalFabrication => "Metal Fabrication",
1942                Industry::PaperAndPaperProducts => "Paper & Paper Products",
1943                Industry::PollutionAndTreatmentControls => "Pollution & Treatment Controls",
1944                Industry::Railroads => "Railroads",
1945                Industry::RentalAndLeasingServices => "Rental & Leasing Services",
1946                Industry::SecurityAndProtectionServices => "Security & Protection Services",
1947                Industry::SpecialtyBusinessServices => "Specialty Business Services",
1948                Industry::SpecialtyChemicals => "Specialty Chemicals",
1949                Industry::SpecialtyIndustrialMachinery => "Specialty Industrial Machinery",
1950                Industry::StaffingAndEmploymentServices => "Staffing & Employment Services",
1951                Industry::ToolsAndAccessories => "Tools & Accessories",
1952                Industry::Trucking => "Trucking",
1953                Industry::WasteManagement => "Waste Management",
1954                Industry::RealEstateDevelopment => "Real Estate - Development",
1955                Industry::RealEstateDiversified => "Real Estate - Diversified",
1956                Industry::RealEstateServices => "Real Estate Services",
1957                Industry::ReitDiversified => "REIT - Diversified",
1958                Industry::ReitHealthcareFacilities => "REIT - Healthcare Facilities",
1959                Industry::ReitHotelAndMotel => "REIT - Hotel & Motel",
1960                Industry::ReitIndustrial => "REIT - Industrial",
1961                Industry::ReitMortgage => "REIT - Mortgage",
1962                Industry::ReitOffice => "REIT - Office",
1963                Industry::ReitResidential => "REIT - Residential",
1964                Industry::ReitRetail => "REIT - Retail",
1965                Industry::ReitSpecialty => "REIT - Specialty",
1966                Industry::CommunicationEquipment => "Communication Equipment",
1967                Industry::ComputerHardware => "Computer Hardware",
1968                Industry::ConsumerElectronics => "Consumer Electronics",
1969                Industry::DataAnalytics => "Data Analytics",
1970                Industry::ElectronicComponents => "Electronic Components",
1971                Industry::ElectronicsAndComputerDistribution => {
1972                    "Electronics & Computer Distribution"
1973                }
1974                Industry::HardwareAndSoftwareDistribution => "Hardware & Software Distribution",
1975                Industry::InformationTechnologyServices => "Information Technology Services",
1976                Industry::InternetContentAndInformation => "Internet Content & Information",
1977                Industry::ScientificAndTechnicalInstruments => "Scientific & Technical Instruments",
1978                Industry::SemiconductorEquipmentAndMaterials => {
1979                    "Semiconductor Equipment & Materials"
1980                }
1981                Industry::Semiconductors => "Semiconductors",
1982                Industry::SoftwareApplication => "Software - Application",
1983                Industry::SoftwareInfrastructure => "Software - Infrastructure",
1984                Industry::Broadcasting => "Broadcasting",
1985                Industry::Entertainment => "Entertainment",
1986                Industry::Publishing => "Publishing",
1987                Industry::TelecomServices => "Telecom Services",
1988                Industry::UtilitiesDiversified => "Utilities - Diversified",
1989                Industry::UtilitiesIndependentPowerProducers => {
1990                    "Utilities - Independent Power Producers"
1991                }
1992                Industry::UtilitiesRegulatedElectric => "Utilities - Regulated Electric",
1993                Industry::UtilitiesRegulatedGas => "Utilities - Regulated Gas",
1994                Industry::UtilitiesRegulatedWater => "Utilities - Regulated Water",
1995                Industry::UtilitiesRenewable => "Utilities - Renewable",
1996                Industry::ClosedEndFundDebt => "Closed-End Fund - Debt",
1997                Industry::ClosedEndFundEquity => "Closed-End Fund - Equity",
1998                Industry::ClosedEndFundForeign => "Closed-End Fund - Foreign",
1999                Industry::ExchangeTradedFund => "Exchange Traded Fund",
2000            }
2001        }
2002    }
2003
2004    impl AsRef<str> for Industry {
2005        /// Returns the slug, enabling `finance::industry(Industry::Semiconductors)`.
2006        fn as_ref(&self) -> &str {
2007            self.as_slug()
2008        }
2009    }
2010
2011    impl From<Industry> for String {
2012        /// Returns the screener display name, enabling `EquityField::Industry.eq_str(Industry::Semiconductors)`.
2013        fn from(v: Industry) -> Self {
2014            v.screener_value().to_string()
2015        }
2016    }
2017}
2018
2019/// Typed exchange codes for screener queries.
2020///
2021/// Use with [`EquityField::Exchange`](crate::EquityField::Exchange) or
2022/// [`FundField::Exchange`](crate::FundField::Exchange) and
2023/// [`ScreenerFieldExt::eq_str`](crate::ScreenerFieldExt::eq_str).
2024///
2025/// For mutual fund queries use [`ExchangeCode::Nas`].
2026///
2027/// # Example
2028///
2029/// ```
2030/// use finance_query::{EquityField, EquityScreenerQuery, ScreenerFieldExt, ExchangeCode};
2031///
2032/// let query = EquityScreenerQuery::new()
2033///     .add_condition(EquityField::Exchange.eq_str(ExchangeCode::Nms));
2034/// ```
2035pub mod exchange_codes {
2036    /// Typed exchange code for screener queries.
2037    #[non_exhaustive]
2038    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2039    pub enum ExchangeCode {
2040        // ── US Equity ─────────────────────────────────────────────────────────
2041        /// NYSE American / AMEX ("ASE")
2042        Ase,
2043        /// OTC Bulletin Board ("BTS")
2044        Bts,
2045        /// NASDAQ Capital Market ("NCM")
2046        Ncm,
2047        /// NASDAQ Global Market ("NGM")
2048        Ngm,
2049        /// NASDAQ Global Select Market ("NMS") — primary NASDAQ tier
2050        Nms,
2051        /// New York Stock Exchange ("NYQ")
2052        Nyq,
2053        /// NYSE Arca ("PCX")
2054        Pcx,
2055        /// OTC Pink Sheets / OTC Markets ("PNK")
2056        Pnk,
2057        // ── US Funds ──────────────────────────────────────────────────────────
2058        /// NASDAQ — used for US mutual funds ("NAS")
2059        Nas,
2060        // ── International ─────────────────────────────────────────────────────
2061        /// Australian Securities Exchange ("ASX")
2062        Asx,
2063        /// Bombay Stock Exchange ("BSE")
2064        Bse,
2065        /// Hong Kong Stock Exchange ("HKG")
2066        Hkg,
2067        /// Korea Exchange ("KRX")
2068        Krx,
2069        /// London Stock Exchange ("LSE")
2070        Lse,
2071        /// National Stock Exchange of India ("NSI")
2072        Nsi,
2073        /// Shanghai Stock Exchange ("SHH")
2074        Shh,
2075        /// Shenzhen Stock Exchange ("SHZ")
2076        Shz,
2077        /// Tokyo Stock Exchange ("TYO")
2078        Tyo,
2079        /// Toronto Stock Exchange ("TOR")
2080        Tor,
2081        /// XETRA / Deutsche Börse ("GER")
2082        Ger,
2083    }
2084
2085    impl ExchangeCode {
2086        /// Returns the exchange code string used by Yahoo Finance.
2087        pub fn as_str(self) -> &'static str {
2088            match self {
2089                ExchangeCode::Ase => "ASE",
2090                ExchangeCode::Bts => "BTS",
2091                ExchangeCode::Ncm => "NCM",
2092                ExchangeCode::Ngm => "NGM",
2093                ExchangeCode::Nms => "NMS",
2094                ExchangeCode::Nyq => "NYQ",
2095                ExchangeCode::Pcx => "PCX",
2096                ExchangeCode::Pnk => "PNK",
2097                ExchangeCode::Nas => "NAS",
2098                ExchangeCode::Asx => "ASX",
2099                ExchangeCode::Bse => "BSE",
2100                ExchangeCode::Hkg => "HKG",
2101                ExchangeCode::Krx => "KRX",
2102                ExchangeCode::Lse => "LSE",
2103                ExchangeCode::Nsi => "NSI",
2104                ExchangeCode::Shh => "SHH",
2105                ExchangeCode::Shz => "SHZ",
2106                ExchangeCode::Tyo => "TYO",
2107                ExchangeCode::Tor => "TOR",
2108                ExchangeCode::Ger => "GER",
2109            }
2110        }
2111    }
2112
2113    impl From<ExchangeCode> for String {
2114        fn from(v: ExchangeCode) -> Self {
2115            v.as_str().to_string()
2116        }
2117    }
2118}
2119
2120#[cfg(test)]
2121mod tests {
2122    use super::*;
2123
2124    #[test]
2125    fn test_interval_as_str() {
2126        assert_eq!(Interval::OneMinute.as_str(), "1m");
2127        assert_eq!(Interval::FiveMinutes.as_str(), "5m");
2128        assert_eq!(Interval::OneDay.as_str(), "1d");
2129        assert_eq!(Interval::OneWeek.as_str(), "1wk");
2130    }
2131
2132    #[test]
2133    fn test_time_range_as_str() {
2134        assert_eq!(TimeRange::OneDay.as_str(), "1d");
2135        assert_eq!(TimeRange::OneMonth.as_str(), "1mo");
2136        assert_eq!(TimeRange::OneYear.as_str(), "1y");
2137        assert_eq!(TimeRange::Max.as_str(), "max");
2138    }
2139}