stock_rust/stocks/base/
mod.rs1use anyhow::{anyhow, Result};
2use async_trait::async_trait;
3
4use crate::types::{Stock, StockApi};
5
6pub const COMMON_SZ: &str = "SZ";
7pub const COMMON_SH: &str = "SH";
8pub const COMMON_HK: &str = "HK";
9pub const COMMON_US: &str = "US";
10
11#[derive(Clone, Copy)]
12pub struct BaseApi;
13
14#[async_trait]
15impl StockApi for BaseApi {
16 async fn get_stock(&self, _code: &str) -> Result<Stock> {
17 Err(anyhow!("未实现获取股票数据"))
18 }
19
20 async fn get_stocks(&self, _codes: &[String]) -> Result<Vec<Stock>> {
21 Err(anyhow!("未实现获取股票数据组"))
22 }
23
24 async fn search_stocks(&self, _key: &str) -> Result<Vec<Stock>> {
25 Err(anyhow!("未实现搜索股票代码"))
26 }
27}
28
29pub fn dedup_codes(codes: &[String]) -> Vec<String> {
30 let mut out: Vec<String> = Vec::new();
31 for code in codes {
32 if !code.is_empty() && !out.contains(code) {
33 out.push(code.clone());
34 }
35 }
36 out
37}
38
39pub fn code_market(code: &str) -> &str {
40 if code.len() >= 2 {
41 &code[..2]
42 } else {
43 ""
44 }
45}
46
47pub fn parse_num(s: Option<&str>) -> f64 {
48 s.unwrap_or("0").parse::<f64>().unwrap_or(0.0)
49}
50
51pub fn as_f64(v: Option<&serde_json::Value>) -> f64 {
52 match v {
53 Some(serde_json::Value::Number(n)) => n.as_f64().unwrap_or(0.0),
54 Some(serde_json::Value::String(s)) => s.parse::<f64>().unwrap_or(0.0),
55 _ => 0.0,
56 }
57}
58
59pub fn as_string(v: Option<&serde_json::Value>) -> String {
60 match v {
61 Some(serde_json::Value::String(s)) => s.clone(),
62 Some(other) => other.to_string(),
63 None => "---".to_string(),
64 }
65}
66
67pub fn percent(now: f64, yesterday: f64) -> f64 {
68 if now == 0.0 || yesterday == 0.0 {
69 0.0
70 } else {
71 now / yesterday - 1.0
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_dedup_codes() {
81 let codes = vec![
82 "SH510500".to_string(),
83 "".to_string(),
84 "SH510500".to_string(),
85 "SZ000001".to_string(),
86 ];
87 assert_eq!(dedup_codes(&codes), vec!["SH510500", "SZ000001"]);
88 }
89
90 #[test]
91 fn test_percent() {
92 let p = percent(7.224, 7.149);
93 assert!((p - (7.224 / 7.149 - 1.0)).abs() < 1e-12);
94 assert_eq!(percent(0.0, 7.149), 0.0);
95 }
96}