Skip to main content

stock_rust/stocks/transforms/
xueqiu.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 XUEQIU_SZ: &str = "SZ";
8const XUEQIU_SH: &str = "SH";
9const XUEQIU_HK: &str = "HK";
10const XUEQIU_US: &str = "";
11
12pub struct XueqiuCommonCodeTransform;
13
14impl CommonCodeTransform for XueqiuCommonCodeTransform {
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.contains(COMMON_SZ) {
34            return Err(anyhow!("请检查统一代码是否正确"));
35        }
36        Ok(format!("{}{}", XUEQIU_SZ, code.replacen(COMMON_SZ, "", 1)))
37    }
38
39    fn sh_transform(&self, code: &str) -> Result<String> {
40        if !code.contains(COMMON_SH) {
41            return Err(anyhow!("请检查统一代码是否正确"));
42        }
43        Ok(format!("{}{}", XUEQIU_SH, code.replacen(COMMON_SH, "", 1)))
44    }
45
46    fn hk_transform(&self, code: &str) -> Result<String> {
47        if !code.contains(COMMON_HK) {
48            return Err(anyhow!("请检查统一代码是否正确"));
49        }
50        Ok(format!("{}{}", XUEQIU_HK, code.replacen(COMMON_HK, "", 1)))
51    }
52
53    fn us_transform(&self, code: &str) -> Result<String> {
54        if !code.contains(COMMON_US) {
55            return Err(anyhow!("请检查统一代码是否正确"));
56        }
57        Ok(format!("{}{}", XUEQIU_US, code.replacen(COMMON_US, "", 1)))
58    }
59}
60
61pub struct XueqiuApiCodeTransform;
62
63impl ApiCodeTransform for XueqiuApiCodeTransform {
64    fn transform(&self, code: &str) -> Result<String> {
65        if code.contains(XUEQIU_SZ) {
66            return self.sz_transform(code);
67        }
68        if code.contains(XUEQIU_SH) {
69            return self.sh_transform(code);
70        }
71        if code.contains(XUEQIU_HK) {
72            return self.hk_transform(code);
73        }
74
75        self.us_transform(code)
76    }
77
78    fn sz_transform(&self, code: &str) -> Result<String> {
79        if !code.contains(XUEQIU_SZ) {
80            return Err(anyhow!("请检查股票代码是否正确"));
81        }
82        Ok(format!("{}{}", COMMON_SZ, code.replacen(XUEQIU_SZ, "", 1)))
83    }
84
85    fn sh_transform(&self, code: &str) -> Result<String> {
86        if !code.contains(XUEQIU_SH) {
87            return Err(anyhow!("请检查股票代码是否正确"));
88        }
89        Ok(format!("{}{}", COMMON_SH, code.replacen(XUEQIU_SH, "", 1)))
90    }
91
92    fn hk_transform(&self, code: &str) -> Result<String> {
93        if !code.contains(XUEQIU_HK) {
94            return Err(anyhow!("请检查股票代码是否正确"));
95        }
96        Ok(format!("{}{}", COMMON_HK, code.replacen(XUEQIU_HK, "", 1)))
97    }
98
99    fn us_transform(&self, code: &str) -> Result<String> {
100        if code.contains(XUEQIU_SZ) || code.contains(XUEQIU_SH) || code.contains(XUEQIU_HK) {
101            return Err(anyhow!("请检查股票代码是否正确"));
102        }
103        Ok(format!("{}{}", COMMON_US, code.replacen(XUEQIU_US, "", 1)))
104    }
105}
106
107pub struct XueqiuSearchCodeTransform;
108
109impl XueqiuSearchCodeTransform {
110    pub fn transform(&self, code: &str) -> Vec<String> {
111        if let Some(raw) = code.strip_prefix("SZ") {
112            return vec![format!("{}{}", COMMON_SZ, raw)];
113        }
114        if let Some(raw) = code.strip_prefix("SH") {
115            return vec![format!("{}{}", COMMON_SH, raw)];
116        }
117
118        vec![format!("{}{}", COMMON_HK, code), format!("{}{}", COMMON_US, code)]
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_common_code_transform() {
128        let t = XueqiuCommonCodeTransform;
129        assert_eq!(t.transform("SH510500").unwrap(), "SH510500");
130        assert_eq!(t.transform("SZ399001").unwrap(), "SZ399001");
131        assert_eq!(t.transform("HKHSI").unwrap(), "HKHSI");
132        assert_eq!(t.transform("USDJI").unwrap(), "DJI");
133    }
134
135    #[test]
136    fn test_api_code_transform() {
137        let t = XueqiuApiCodeTransform;
138        assert_eq!(t.transform("SH510500").unwrap(), "SH510500");
139        assert_eq!(t.transform("SZ399001").unwrap(), "SZ399001");
140        assert_eq!(t.transform("HKHSI").unwrap(), "HKHSI");
141        assert_eq!(t.transform("DJI").unwrap(), "USDJI");
142    }
143
144    #[test]
145    fn test_search_code_transform() {
146        let t = XueqiuSearchCodeTransform;
147        assert_eq!(t.transform("SZ399001"), vec!["SZ399001"]);
148        assert_eq!(t.transform("SH510500"), vec!["SH510500"]);
149        assert_eq!(t.transform("HSI"), vec!["HKHSI", "USHSI"]);
150    }
151}