Skip to main content

finance_query/constants/
indices.rs

1/// Region categories for world indices
2///
3/// The `alias`es mirror the shorthands [`FromStr`](std::str::FromStr) accepts, so
4/// deserializing (axum query extraction, JSON) takes the same spellings parsing does.
5#[non_exhaustive]
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
7#[serde(rename_all = "kebab-case")]
8pub enum Region {
9    /// North and South America
10    #[serde(alias = "america", alias = "am")]
11    Americas,
12    /// European markets
13    #[serde(alias = "eu")]
14    Europe,
15    /// Asia and Pacific markets
16    #[serde(alias = "asia", alias = "apac", alias = "asia_pacific")]
17    AsiaPacific,
18    /// Middle East and Africa
19    #[serde(alias = "mea", alias = "emea", alias = "middle_east_africa")]
20    MiddleEastAfrica,
21    /// Currency indices
22    #[serde(alias = "currency", alias = "fx")]
23    Currencies,
24}
25
26impl std::str::FromStr for Region {
27    type Err = ();
28
29    fn from_str(s: &str) -> Result<Self, Self::Err> {
30        match s.to_lowercase().replace(['-', '_'], "").as_str() {
31            "americas" | "america" | "am" => Ok(Region::Americas),
32            "europe" | "eu" => Ok(Region::Europe),
33            "asiapacific" | "asia" | "apac" => Ok(Region::AsiaPacific),
34            "middleeastafrica" | "mea" | "emea" => Ok(Region::MiddleEastAfrica),
35            "currencies" | "currency" | "fx" => Ok(Region::Currencies),
36            _ => Err(()),
37        }
38    }
39}
40
41impl Region {
42    /// Parse from string, returns None on invalid input
43    pub fn parse(s: &str) -> Option<Self> {
44        s.parse().ok()
45    }
46
47    /// Get the symbols for this region
48    pub fn symbols(&self) -> &'static [&'static str] {
49        match self {
50            Region::Americas => AMERICAS,
51            Region::Europe => EUROPE,
52            Region::AsiaPacific => ASIA_PACIFIC,
53            Region::MiddleEastAfrica => MIDDLE_EAST_AFRICA,
54            Region::Currencies => CURRENCIES,
55        }
56    }
57
58    /// Convert to string representation
59    pub fn as_str(&self) -> &'static str {
60        match self {
61            Region::Americas => "americas",
62            Region::Europe => "europe",
63            Region::AsiaPacific => "asia-pacific",
64            Region::MiddleEastAfrica => "middle-east-africa",
65            Region::Currencies => "currencies",
66        }
67    }
68
69    /// All region variants
70    pub fn all() -> &'static [Region] {
71        &[
72            Region::Americas,
73            Region::Europe,
74            Region::AsiaPacific,
75            Region::MiddleEastAfrica,
76            Region::Currencies,
77        ]
78    }
79}
80
81/// Americas indices
82pub const AMERICAS: &[&str] = &[
83    "^GSPC",   // S&P 500
84    "^DJI",    // Dow Jones Industrial Average
85    "^IXIC",   // NASDAQ Composite
86    "^NYA",    // NYSE Composite Index
87    "^XAX",    // NYSE American Composite Index
88    "^RUT",    // Russell 2000 Index
89    "^VIX",    // CBOE Volatility Index
90    "^GSPTSE", // S&P/TSX Composite (Canada)
91    "^BVSP",   // IBOVESPA (Brazil)
92    "^MXX",    // IPC MEXICO
93    "^IPSA",   // S&P IPSA (Chile)
94    "^MERV",   // MERVAL (Argentina)
95];
96
97/// Europe indices
98pub const EUROPE: &[&str] = &[
99    "^FTSE",            // FTSE 100 (UK)
100    "^GDAXI",           // DAX (Germany)
101    "^FCHI",            // CAC 40 (France)
102    "^STOXX50E",        // EURO STOXX 50
103    "^N100",            // Euronext 100 Index
104    "^BFX",             // BEL 20 (Belgium)
105    "^BUK100P",         // Cboe UK 100
106    "MOEX.ME",          // Moscow Exchange
107    "^125904-USD-STRD", // MSCI EUROPE
108];
109
110/// Asia Pacific indices
111pub const ASIA_PACIFIC: &[&str] = &[
112    "^N225",     // Nikkei 225 (Japan)
113    "^HSI",      // Hang Seng Index (Hong Kong)
114    "000001.SS", // SSE Composite Index (China)
115    "^KS11",     // KOSPI (South Korea)
116    "^TWII",     // Taiwan Weighted Index
117    "^STI",      // STI Index (Singapore)
118    "^AXJO",     // S&P/ASX 200 (Australia)
119    "^AORD",     // All Ordinaries (Australia)
120    "^NZ50",     // S&P/NZX 50 (New Zealand)
121    "^BSESN",    // S&P BSE SENSEX (India)
122    "^JKSE",     // IDX Composite (Indonesia)
123    "^KLSE",     // FTSE Bursa Malaysia KLCI
124];
125
126/// Middle East & Africa indices
127pub const MIDDLE_EAST_AFRICA: &[&str] = &[
128    "^TA125.TA", // TA-125 (Israel)
129    "^CASE30",   // EGX 30 (Egypt)
130    "^JN0U.JO",  // Top 40 USD Net TRI (South Africa)
131];
132
133/// Currency indices
134pub const CURRENCIES: &[&str] = &[
135    "DX-Y.NYB", // US Dollar Index
136    "^XDB",     // British Pound Currency Index
137    "^XDE",     // Euro Currency Index
138    "^XDN",     // Japanese Yen Currency Index
139    "^XDA",     // Australian Dollar Currency Index
140];
141
142/// All world indices (all regions combined)
143pub fn all_symbols() -> Vec<&'static str> {
144    Region::all()
145        .iter()
146        .flat_map(|r| r.symbols().iter().copied())
147        .collect()
148}