stock_rust/stocks/transforms/
xueqiu.rs1use 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}