ccxt_exchanges/binance/parser/
ohlcv.rs1use ccxt_core::{
2 Result,
3 error::{Error, ParseError},
4 types::OHLCV,
5};
6use serde_json::Value;
7
8pub fn parse_ohlcv(data: &Value) -> Result<ccxt_core::types::OHLCV> {
10 if let Some(array) = data.as_array() {
11 if array.len() < 6 {
12 return Err(Error::from(ParseError::invalid_format(
13 "data",
14 "OHLCV array length insufficient",
15 )));
16 }
17
18 let timestamp = array[0]
19 .as_i64()
20 .ok_or_else(|| Error::from(ParseError::invalid_format("data", "无效的时间戳")))?;
21
22 let open = array[1]
23 .as_str()
24 .and_then(|s| s.parse::<f64>().ok())
25 .or_else(|| array[1].as_f64())
26 .ok_or_else(|| Error::from(ParseError::invalid_format("data", "Invalid open price")))?;
27
28 let high = array[2]
29 .as_str()
30 .and_then(|s| s.parse::<f64>().ok())
31 .or_else(|| array[2].as_f64())
32 .ok_or_else(|| Error::from(ParseError::invalid_format("data", "Invalid high price")))?;
33
34 let low = array[3]
35 .as_str()
36 .and_then(|s| s.parse::<f64>().ok())
37 .or_else(|| array[3].as_f64())
38 .ok_or_else(|| Error::from(ParseError::invalid_format("data", "Invalid low price")))?;
39
40 let close = array[4]
41 .as_str()
42 .and_then(|s| s.parse::<f64>().ok())
43 .or_else(|| array[4].as_f64())
44 .ok_or_else(|| {
45 Error::from(ParseError::invalid_format("data", "Invalid close price"))
46 })?;
47
48 let volume = array[5]
49 .as_str()
50 .and_then(|s| s.parse::<f64>().ok())
51 .or_else(|| array[5].as_f64())
52 .ok_or_else(|| Error::from(ParseError::invalid_format("data", "Invalid volume")))?;
53
54 Ok(OHLCV::new(timestamp, open, high, low, close, volume))
55 } else {
56 Err(Error::from(ParseError::invalid_format(
57 "data",
58 "OHLCV data must be in array format",
59 )))
60 }
61}
62
63pub fn parse_ohlcvs(data: &Value) -> Result<Vec<ccxt_core::types::OHLCV>> {
65 if let Some(array) = data.as_array() {
66 array.iter().map(|item| parse_ohlcv(item)).collect()
67 } else {
68 Err(Error::from(ParseError::invalid_format(
69 "data",
70 "OHLCV data list must be in array format",
71 )))
72 }
73}
74
75pub fn parse_ws_ohlcv(data: &Value) -> Result<OHLCV> {
77 let kline = data["k"]
78 .as_object()
79 .ok_or_else(|| Error::from(ParseError::missing_field("k")))?;
80
81 let timestamp = kline
82 .get("t")
83 .and_then(serde_json::Value::as_i64)
84 .ok_or_else(|| Error::from(ParseError::missing_field("t")))?;
85
86 let open = kline
87 .get("o")
88 .and_then(serde_json::Value::as_str)
89 .and_then(|s| s.parse::<f64>().ok())
90 .ok_or_else(|| Error::from(ParseError::missing_field("o")))?;
91
92 let high = kline
93 .get("h")
94 .and_then(serde_json::Value::as_str)
95 .and_then(|s| s.parse::<f64>().ok())
96 .ok_or_else(|| Error::from(ParseError::missing_field("h")))?;
97
98 let low = kline
99 .get("l")
100 .and_then(serde_json::Value::as_str)
101 .and_then(|s| s.parse::<f64>().ok())
102 .ok_or_else(|| Error::from(ParseError::missing_field("l")))?;
103
104 let close = kline
105 .get("c")
106 .and_then(serde_json::Value::as_str)
107 .and_then(|s| s.parse::<f64>().ok())
108 .ok_or_else(|| Error::from(ParseError::missing_field("c")))?;
109
110 let volume = kline
111 .get("v")
112 .and_then(serde_json::Value::as_str)
113 .and_then(|s| s.parse::<f64>().ok())
114 .ok_or_else(|| Error::from(ParseError::missing_field("v")))?;
115
116 Ok(OHLCV {
117 timestamp,
118 open,
119 high,
120 low,
121 close,
122 volume,
123 })
124}