Skip to main content

stock_rust/stocks/transforms/
sina.rs

1use anyhow::{anyhow, Result};
2
3use crate::stocks::base::{COMMON_HK, COMMON_SH, COMMON_SZ, COMMON_US};
4
5use super::base::{ApiCodeTransform, CommonCodeTransform};
6
7const SINA_SZ: &str = "sz";
8const SINA_SH: &str = "sh";
9const SINA_HK: &str = "hk";
10const SINA_US: &str = "gb_";
11
12pub struct SinaCommonCodeTransform;
13
14impl CommonCodeTransform for SinaCommonCodeTransform {
15    fn transform(&self, code: &str) -> Result<String> {
16        if code.starts_with(COMMON_SH) {
17            return self.sh_transform(code);
18        }
19        if code.starts_with(COMMON_SZ) {
20            return self.sz_transform(code);
21        }
22        if code.starts_with(COMMON_HK) {
23            return self.hk_transform(code);
24        }
25        if code.starts_with(COMMON_US) {
26            return self.us_transform(code);
27        }
28
29        Err(anyhow!("请检查统一代码是否正确"))
30    }
31
32    fn sz_transform(&self, code: &str) -> Result<String> {
33        if !code.starts_with(COMMON_SZ) {
34            return Err(anyhow!("请检查统一代码是否正确"));
35        }
36        Ok(format!("{}{}", SINA_SZ, code.replacen(COMMON_SZ, "", 1)))
37    }
38
39    fn sh_transform(&self, code: &str) -> Result<String> {
40        if !code.starts_with(COMMON_SH) {
41            return Err(anyhow!("请检查统一代码是否正确"));
42        }
43        Ok(format!("{}{}", SINA_SH, code.replacen(COMMON_SH, "", 1)))
44    }
45
46    fn hk_transform(&self, code: &str) -> Result<String> {
47        if !code.starts_with(COMMON_HK) {
48            return Err(anyhow!("请检查统一代码是否正确"));
49        }
50        Ok(format!("{}{}", SINA_HK, code.replacen(COMMON_HK, "", 1)))
51    }
52
53    fn us_transform(&self, code: &str) -> Result<String> {
54        if !code.starts_with(COMMON_US) {
55            return Err(anyhow!("请检查统一代码是否正确"));
56        }
57        Ok(format!(
58            "{}{}",
59            SINA_US,
60            code.replacen(COMMON_US, "", 1).to_lowercase()
61        ))
62    }
63}
64
65pub struct SinaApiCodeTransform;
66
67impl ApiCodeTransform for SinaApiCodeTransform {
68    fn transform(&self, code: &str) -> Result<String> {
69        if code.starts_with(SINA_SZ) {
70            return self.sz_transform(code);
71        }
72        if code.starts_with(SINA_SH) {
73            return self.sh_transform(code);
74        }
75        if code.starts_with(SINA_HK) {
76            return self.hk_transform(code);
77        }
78        if code.starts_with(SINA_US) {
79            return self.us_transform(code);
80        }
81
82        Err(anyhow!("请检查股票代码是否正确"))
83    }
84
85    fn sz_transform(&self, code: &str) -> Result<String> {
86        if !code.starts_with(SINA_SZ) {
87            return Err(anyhow!("请检查股票代码是否正确"));
88        }
89        Ok(format!("{}{}", COMMON_SZ, code.replacen(SINA_SZ, "", 1)))
90    }
91
92    fn sh_transform(&self, code: &str) -> Result<String> {
93        if !code.starts_with(SINA_SH) {
94            return Err(anyhow!("请检查股票代码是否正确"));
95        }
96        Ok(format!("{}{}", COMMON_SH, code.replacen(SINA_SH, "", 1)))
97    }
98
99    fn hk_transform(&self, code: &str) -> Result<String> {
100        if !code.starts_with(SINA_HK) {
101            return Err(anyhow!("请检查股票代码是否正确"));
102        }
103        Ok(format!("{}{}", COMMON_HK, code.replacen(SINA_HK, "", 1)))
104    }
105
106    fn us_transform(&self, code: &str) -> Result<String> {
107        if !code.starts_with(SINA_US) {
108            return Err(anyhow!("请检查股票代码是否正确"));
109        }
110        Ok(format!(
111            "{}{}",
112            COMMON_US,
113            code.replacen(SINA_US, "", 1).to_lowercase()
114        ))
115    }
116}
117
118pub struct SinaSearchCodeTransform;
119
120impl SinaSearchCodeTransform {
121    pub fn transform(&self, code: &str) -> Vec<String> {
122        if let Some(raw) = code.strip_prefix("us") {
123            return vec![format!("{}{}", COMMON_US, raw)];
124        }
125        if let Some(raw) = code.strip_prefix("sz") {
126            return vec![format!("{}{}", COMMON_SZ, raw)];
127        }
128        if let Some(raw) = code.strip_prefix("sh") {
129            return vec![format!("{}{}", COMMON_SH, raw)];
130        }
131        if let Some(raw) = code.strip_prefix("hk") {
132            return vec![format!("{}{}", COMMON_HK, raw)];
133        }
134        if let Some(raw) = code.strip_prefix("of") {
135            return vec![format!("{}{}", COMMON_SZ, raw), format!("{}{}", COMMON_SH, raw)];
136        }
137
138        Vec::new()
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_common_code_transform() {
148        let t = SinaCommonCodeTransform;
149        assert_eq!(t.transform("SH510500").unwrap(), "sh510500");
150        assert_eq!(t.transform("SZ399001").unwrap(), "sz399001");
151        assert_eq!(t.transform("HKHSI").unwrap(), "hkHSI");
152        assert_eq!(t.transform("USDJI").unwrap(), "gb_dji");
153    }
154
155    #[test]
156    fn test_api_code_transform() {
157        let t = SinaApiCodeTransform;
158        assert_eq!(t.transform("sh510500").unwrap(), "SH510500");
159        assert_eq!(t.transform("sz399001").unwrap(), "SZ399001");
160        assert_eq!(t.transform("hkHSI").unwrap(), "HKHSI");
161        assert_eq!(t.transform("gb_dji").unwrap(), "USdji");
162    }
163
164    #[test]
165    fn test_search_code_transform() {
166        let t = SinaSearchCodeTransform;
167        assert_eq!(t.transform("usdji"), vec!["USdji"]);
168        assert_eq!(t.transform("sz399001"), vec!["SZ399001"]);
169        assert_eq!(t.transform("sh510500"), vec!["SH510500"]);
170        assert_eq!(t.transform("hkHSI"), vec!["HKHSI"]);
171        assert_eq!(t.transform("of510500"), vec!["SZ510500", "SH510500"]);
172    }
173}