use crate::client::AkShareClient;
use crate::error::{Error, Result};
use crate::types::FundScaleChangeItem;
impl AkShareClient {
pub async fn fund_scale_change_em(&self) -> Result<Vec<FundScaleChangeItem>> {
let response = self
.get("https://fund.eastmoney.com/data/FundDataPortfolio_Interface.aspx")
.query(&[
("dt", "9"),
("pi", "1"),
("pn", "50"),
("mc", "hypzDetail"),
("st", "desc"),
("sc", "reportdate"),
])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let text = response.text().await.map_err(Error::from)?;
let json_start = text.find('{').unwrap_or(0);
let json_end = text.rfind('}').map_or(text.len(), |i| i + 1);
let json_str = &text[json_start..json_end];
let root: serde_json::Value = serde_json::from_str(json_str)
.map_err(|e| Error::decode(format!("scale change JSON parse: {e}")))?;
let data = root
.get("data")
.and_then(|d| d.as_array())
.ok_or_else(|| Error::not_found("no scale change data"))?;
let mut result = Vec::new();
for (i, item) in data.iter().enumerate() {
let Some(arr) = item.as_array() else { continue };
if arr.len() < 7 {
continue;
}
result.push(FundScaleChangeItem {
rank: (i + 1) as i32,
report_date: arr[0].as_str().unwrap_or("").to_string(),
fund_count: arr[1].as_str().unwrap_or("0").parse().unwrap_or(0),
subscribe: arr[2]
.as_str()
.unwrap_or("0")
.replace(',', "")
.parse()
.unwrap_or(0.0),
redeem: arr[3]
.as_str()
.unwrap_or("0")
.replace(',', "")
.parse()
.unwrap_or(0.0),
end_shares: arr[4]
.as_str()
.unwrap_or("0")
.replace(',', "")
.parse()
.unwrap_or(0.0),
end_net_assets: arr[5]
.as_str()
.unwrap_or("0")
.replace(',', "")
.parse()
.unwrap_or(0.0),
});
}
if result.is_empty() {
return Err(Error::not_found("no scale change data"));
}
Ok(result)
}
}