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