use serde::Deserialize;
use crate::client::AkShareClient;
use crate::error::{Error, Result};
use crate::types::CxIndexPoint;
#[derive(Debug, Deserialize)]
struct CxEnvelope {
data: Option<Vec<CxRow>>,
}
#[derive(Debug, Deserialize)]
struct CxRow {
#[serde(default)]
v: Option<f64>, #[serde(default)]
s: Option<f64>, #[serde(default)]
t: Option<i64>, #[serde(default)]
value: Option<f64>,
#[serde(default)]
change: Option<f64>,
#[serde(default)]
date: Option<i64>,
}
async fn fetch_cx_index(
client: &AkShareClient,
cx_type: &str,
extra: &[(&str, &str)],
) -> Result<Vec<CxIndexPoint>> {
let mut params = vec![("type", cx_type)];
params.extend(extra.iter().map(|(k, v)| (*k, *v)));
let response = client
.get("https://yun.ccxe.com.cn/api/index/pro/cxIndexTrendInfo")
.query(¶ms)
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let payload: CxEnvelope = response.json().await.map_err(Error::from)?;
let rows = payload.data.unwrap_or_default();
let points: Vec<CxIndexPoint> = rows
.into_iter()
.filter_map(|r| {
let ts = r.t.or(r.date)?;
let val = r.v.or(r.value)?;
let chg = r.s.or(r.change).unwrap_or(0.0);
let dt = chrono::DateTime::from_timestamp_millis(ts)?;
let date = dt
.with_timezone(&chrono::FixedOffset::east_opt(8 * 3600)?)
.format("%Y-%m-%d")
.to_string();
Some(CxIndexPoint {
date,
value: val,
change: chg,
})
})
.collect();
if points.is_empty() {
return Err(Error::not_found("cx returned no data points"));
}
Ok(points)
}
impl AkShareClient {
pub async fn index_pmi_com_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "com", &[]).await
}
pub async fn index_pmi_man_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "man", &[]).await
}
pub async fn index_pmi_ser_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ser", &[]).await
}
pub async fn index_dei_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "dei", &[]).await
}
pub async fn index_ii_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ii", &[]).await
}
pub async fn index_si_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "si", &[]).await
}
pub async fn index_fi_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "fi", &[]).await
}
pub async fn index_bi_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "bi", &[]).await
}
pub async fn index_nei_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "nei", &[]).await
}
pub async fn index_li_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "li", &[]).await
}
pub async fn index_ci_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ci", &[]).await
}
pub async fn index_ti_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ti", &[]).await
}
pub async fn index_neaw_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "neaw", &[]).await
}
pub async fn index_awpr_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "awpr", &[]).await
}
pub async fn index_cci_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "cci", &[("code", "1000050"), ("month", "-1")]).await
}
pub async fn index_qli_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "qli", &[("code", "1000050"), ("month", "-1")]).await
}
pub async fn index_ai_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ai", &[("code", "1000050"), ("month", "-1")]).await
}
pub async fn index_bei_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ind", &[("code", "930927"), ("month", "-1")]).await
}
pub async fn index_neei_cx(&self) -> Result<Vec<CxIndexPoint>> {
fetch_cx_index(self, "ind", &[("code", "930928"), ("month", "1")]).await
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_placeholder() {
}
}