finance_query/models/indices/
mod.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
12#[non_exhaustive]
13pub struct IndexQuote {
14 pub symbol: String,
16 pub name: Option<String>,
18 pub price: Option<f64>,
20 pub change: Option<f64>,
22 pub change_percent: Option<f64>,
24 pub timestamp: Option<i64>,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
33#[non_exhaustive]
34pub enum MajorIndex {
35 Sp500,
37 Nasdaq100,
39 DowJones,
41}
42
43impl MajorIndex {
44 pub fn as_str(self) -> &'static str {
46 match self {
47 Self::Sp500 => "sp500",
48 Self::Nasdaq100 => "nasdaq100",
49 Self::DowJones => "dowjones",
50 }
51 }
52
53 pub fn from_symbol(symbol: &str) -> Option<Self> {
59 let s: String = symbol
60 .trim()
61 .trim_start_matches('^')
62 .chars()
63 .filter(|c| !c.is_whitespace() && *c != '&' && *c != '-')
64 .collect::<String>()
65 .to_ascii_lowercase();
66 match s.as_str() {
67 "gspc" | "spx" | "sp500" => Some(Self::Sp500),
68 "ndx" | "nasdaq100" => Some(Self::Nasdaq100),
69 "dji" | "djia" | "dowjones" | "dow" | "dowjones30" => Some(Self::DowJones),
70 _ => None,
71 }
72 }
73}
74
75impl std::fmt::Display for MajorIndex {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 f.write_str(self.as_str())
78 }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83#[non_exhaustive]
84pub struct IndexConstituent {
85 pub symbol: String,
87 pub name: Option<String>,
89 pub sector: Option<String>,
91 pub sub_sector: Option<String>,
93 pub headquarters: Option<String>,
95 pub date_first_added: Option<String>,
97 pub cik: Option<String>,
99 pub founded: Option<String>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105#[non_exhaustive]
106pub struct IndexConstituentChange {
107 pub date: Option<String>,
109 pub symbol: Option<String>,
111 pub added_security: Option<String>,
113 pub removed_ticker: Option<String>,
115 pub removed_security: Option<String>,
117 pub reason: Option<String>,
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn major_index_maps_common_symbols() {
127 for s in ["^GSPC", "GSPC", "SPX", "sp500", "S&P 500"] {
128 assert_eq!(MajorIndex::from_symbol(s), Some(MajorIndex::Sp500), "{s}");
129 }
130 for s in ["^NDX", "ndx", "NASDAQ 100", "nasdaq100"] {
131 assert_eq!(
132 MajorIndex::from_symbol(s),
133 Some(MajorIndex::Nasdaq100),
134 "{s}"
135 );
136 }
137 for s in ["^DJI", "DJIA", "dow", "Dow Jones"] {
138 assert_eq!(
139 MajorIndex::from_symbol(s),
140 Some(MajorIndex::DowJones),
141 "{s}"
142 );
143 }
144 assert_eq!(MajorIndex::from_symbol("AAPL"), None);
145 assert_eq!(MajorIndex::from_symbol("^IXIC"), None);
146 }
147}