use crate::client::AkShareClient;
use crate::error::Result;
use crate::types::MacroDataPoint;
use super::shared::{fetch_em_industry_index, fetch_em_report, fetch_jin10_report};
fn extract_html_text(html: &str) -> String {
let mut result = String::new();
let mut in_tag = false;
for ch in html.chars() {
match ch {
'<' => in_tag = true,
'>' => in_tag = false,
_ if !in_tag => result.push(ch),
_ => {}
}
}
result.trim().to_string()
}
async fn fetch_sina_macro(
client: &AkShareClient,
cate: &str,
event: &str,
name_label: &str,
) -> Result<Vec<MacroDataPoint>> {
let url = "https://quotes.sina.cn/mac/api/jsonp_v3.php/SINAREMOTECALLCALLBACK/MacPage_Service.get_pagedata";
let resp_text = client
.get(url)
.query(&[
("cate", cate),
("event", event),
("from", "0"),
("num", "500"),
("condition", ""),
])
.send()
.await?
.text()
.await?;
let json_start = resp_text.find('{').unwrap_or(0);
let json_end = resp_text.rfind('}').unwrap_or(resp_text.len());
if json_start >= json_end {
return Ok(Vec::new());
}
let json_str = &resp_text[json_start..=json_end];
let data: serde_json::Value = serde_json::from_str(json_str)?;
let mut items = Vec::new();
if let Some(data_arr) = data.get("data").and_then(|d| d.as_array()) {
for row in data_arr {
if let Some(row_obj) = row.as_object() {
let mut date = String::new();
let mut value = 0.0f64;
for (key, val) in row_obj {
if key.contains("时间") || key.contains("月份") || key.contains("统计") {
date = val.as_str().unwrap_or("").to_string();
}
}
for (_key, val) in row_obj {
if let Some(v) = val.as_str().and_then(|s| s.parse::<f64>().ok()) {
value = v;
break;
} else if let Some(v) = val.as_f64() {
value = v;
break;
}
}
if !date.is_empty() {
items.push(MacroDataPoint {
date: date.get(..10).unwrap_or(&date).to_string(),
value,
name: name_label.to_string(),
});
}
}
}
} else if let Some(data_obj) = data.get("data").and_then(|d| d.as_object()) {
if let Some(arr) = data_obj.get("非累计").and_then(|v| v.as_array()) {
for row in arr {
if let Some(row_obj) = row.as_object() {
let mut date = String::new();
let mut value = 0.0f64;
for (key, val) in row_obj {
if key.contains("时间") || key.contains("月份") || key.contains("统计")
{
date = val.as_str().unwrap_or("").to_string();
}
}
for (_key, val) in row_obj {
if let Some(v) = val.as_str().and_then(|s| s.parse::<f64>().ok()) {
value = v;
break;
} else if let Some(v) = val.as_f64() {
value = v;
break;
}
}
if !date.is_empty() {
items.push(MacroDataPoint {
date: date.get(..10).unwrap_or(&date).to_string(),
value,
name: name_label.to_string(),
});
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
impl AkShareClient {
pub async fn china_gdp(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_GDP", "REPORT_DATE", "China GDP").await
}
pub async fn china_cpi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_CPI", "REPORT_DATE", "China CPI").await
}
pub async fn china_ppi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_PPI", "REPORT_DATE", "China PPI").await
}
pub async fn china_pmi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_PMI", "REPORT_DATE", "China PMI").await
}
pub async fn china_money_supply(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_CURRENCY_SUPPLY",
"REPORT_DATE",
"China Money Supply",
)
.await
}
pub async fn china_trade(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_CUSTOMS", "REPORT_DATE", "China Trade").await
}
pub async fn china_goods_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_GOODS_INDEX",
"REPORT_DATE",
"China Goods Index",
)
.await
}
pub async fn china_fdi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_FDI", "REPORT_DATE", "China FDI").await
}
pub async fn china_lpr(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPTA_WEB_RATE", "REPORT_DATE", "China LPR").await
}
pub async fn china_new_house_price(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_HOUSE_PRICE",
"REPORT_DATE",
"China New House Price",
)
.await
}
pub async fn china_enterprise_boom_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_BOOM_INDEX",
"REPORT_DATE",
"China Enterprise Boom Index",
)
.await
}
pub async fn china_national_tax_receipts(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(self, "RPT_ECONOMY_TAX", "REPORT_DATE", "China Tax Receipts").await
}
pub async fn china_new_financial_credit(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_RMB_LOAN",
"REPORT_DATE",
"China New Credit",
)
.await
}
pub async fn china_fx_gold(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_GOLD_CURRENCY",
"REPORT_DATE",
"China FX Gold",
)
.await
}
pub async fn china_stock_market_cap(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_STOCK_STATISTICS",
"REPORT_DATE",
"China Stock Market Cap",
)
.await
}
pub async fn china_fixed_asset_investment(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_ASSET_INVEST",
"REPORT_DATE",
"China Fixed Asset Investment",
)
.await
}
pub async fn china_fiscal_revenue(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_INCOME",
"REPORT_DATE",
"China Fiscal Revenue",
)
.await
}
pub async fn china_fx_loans(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_FOREX_LOAN",
"REPORT_DATE",
"China FX Loans",
)
.await
}
pub async fn china_fx_deposits(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_FOREX_DEPOSIT",
"REPORT_DATE",
"China FX Deposits",
)
.await
}
pub async fn china_consumer_confidence(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_FAITH_INDEX",
"REPORT_DATE",
"China Consumer Confidence",
)
.await
}
pub async fn china_industrial_growth(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_INDUS_GROW",
"REPORT_DATE",
"China Industrial Growth",
)
.await
}
pub async fn china_reserve_requirement_ratio(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_DEPOSIT_RESERVE",
"REPORT_DATE",
"China RRR",
)
.await
}
pub async fn china_consumer_goods_retail(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_report(
self,
"RPT_ECONOMY_TOTAL_RETAIL",
"REPORT_DATE",
"China Consumer Goods Retail",
)
.await
}
}
impl AkShareClient {
pub async fn china_bank_financing(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI01516267", "China Bank Financing").await
}
pub async fn china_insurance_income(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMM00088870", "China Insurance Income").await
}
pub async fn china_mobile_number(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00225823", "China Mobile Shipments").await
}
pub async fn china_vegetable_basket(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00009275", "China Vegetable Basket").await
}
pub async fn china_agricultural_product(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00009274", "China Agricultural Product").await
}
pub async fn china_agricultural_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00662543", "China Agricultural Index").await
}
pub async fn china_energy_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00662539", "China Energy Index").await
}
pub async fn china_commodity_price_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00662535", "China Commodity Price Index").await
}
pub async fn china_yw_electronic_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00055551", "China Yiwu Index").await
}
pub async fn china_construction_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00662541", "China Construction Index").await
}
pub async fn china_construction_price_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00237146", "China Construction Price Index").await
}
pub async fn china_lpi_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00352262", "China LPI Index").await
}
pub async fn china_bdti_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00107668", "China BDTI Index").await
}
pub async fn china_bsi_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMI00107667", "China BSI Index").await
}
pub async fn china_real_estate(&self) -> Result<Vec<MacroDataPoint>> {
fetch_em_industry_index(self, "EMM00121987", "China Real Estate").await
}
}
impl AkShareClient {
pub async fn china_gdp_yearly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "57", "China GDP Yearly").await
}
pub async fn china_cpi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "56", "China CPI Yearly").await
}
pub async fn china_cpi_monthly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "72", "China CPI Monthly").await
}
pub async fn china_ppi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "60", "China PPI Yearly").await
}
pub async fn china_exports_yoy(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "66", "China Exports YoY").await
}
pub async fn china_imports_yoy(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "77", "China Imports YoY").await
}
pub async fn china_trade_balance_jin10(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "61", "China Trade Balance").await
}
pub async fn china_industrial_production_yoy(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "58", "China Industrial Production YoY").await
}
pub async fn china_pmi_jin10(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "65", "China Official PMI").await
}
pub async fn china_caixin_pmi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "73", "China Caixin PMI").await
}
pub async fn china_caixin_services_pmi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "67", "China Caixin Services PMI").await
}
pub async fn china_non_man_pmi(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "75", "China Non-Man PMI").await
}
pub async fn china_fx_reserves_yearly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "76", "China FX Reserves").await
}
pub async fn china_m2_yearly(&self) -> Result<Vec<MacroDataPoint>> {
fetch_jin10_report(self, "59", "China M2 Yearly").await
}
}
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Jin10CdnCdnResp {
values: Option<serde_json::Value>,
}
impl AkShareClient {
pub async fn china_shibor(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/il_1.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(cols) = row.as_object() {
for (tenor, col_data) in cols {
if let Some(arr) = col_data.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: format!("Shibor {}", tenor),
});
}
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn china_hibor(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/il_2.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(cols) = row.as_object() {
for (tenor, col_data) in cols {
if let Some(arr) = col_data.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: format!("HIBOR {}", tenor),
});
}
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn china_rmb_central_parity(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/exchange_rate.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(cols) = row.as_object() {
for (pair, col_data) in cols {
if let Some(arr) = col_data.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: format!("RMB {}", pair),
});
}
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn china_margin_sz(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/fs_2.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(arr) = row.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: "SZ Margin Buy".to_string(),
});
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn china_margin_sh(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/fs_1.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(arr) = row.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: "SH Margin Buy".to_string(),
});
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn china_sge_report(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/sge.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, products) in obj {
if let Some(arr) = products.as_array() {
for product in arr {
if let Some(parr) = product.as_array() {
let name = parr.first().and_then(|v| v.as_str()).unwrap_or("unknown");
let volume = parr.get(8).and_then(|v| v.as_f64()).unwrap_or(0.0);
items.push(MacroDataPoint {
date: date.clone(),
value: volume,
name: format!("SGE {}", name),
});
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
}
impl AkShareClient {
pub async fn macro_china_agricultural_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_agricultural_index().await
}
pub async fn macro_china_agricultural_product(&self) -> Result<Vec<MacroDataPoint>> {
self.china_agricultural_product().await
}
pub async fn macro_china_bank_financing(&self) -> Result<Vec<MacroDataPoint>> {
self.china_bank_financing().await
}
pub async fn macro_china_bdti_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_bdti_index().await
}
pub async fn macro_china_bsi_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_bsi_index().await
}
pub async fn macro_china_commodity_price_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_commodity_price_index().await
}
pub async fn macro_china_construction_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_construction_index().await
}
pub async fn macro_china_construction_price_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_construction_price_index().await
}
pub async fn macro_china_consumer_goods_retail(&self) -> Result<Vec<MacroDataPoint>> {
self.china_consumer_goods_retail().await
}
pub async fn macro_china_cpi(&self) -> Result<Vec<MacroDataPoint>> {
self.china_cpi().await
}
pub async fn macro_china_cpi_monthly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_cpi_monthly().await
}
pub async fn macro_china_cpi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_cpi_yearly().await
}
pub async fn macro_china_energy_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_energy_index().await
}
pub async fn macro_china_enterprise_boom_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_enterprise_boom_index().await
}
pub async fn macro_china_exports_yoy(&self) -> Result<Vec<MacroDataPoint>> {
self.china_exports_yoy().await
}
pub async fn macro_china_fdi(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fdi().await
}
pub async fn macro_china_fx_gold(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fx_gold().await
}
pub async fn macro_china_fx_reserves_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fx_reserves_yearly().await
}
pub async fn macro_china_gdp(&self) -> Result<Vec<MacroDataPoint>> {
self.china_gdp().await
}
pub async fn macro_china_gdp_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_gdp_yearly().await
}
pub async fn macro_china_imports_yoy(&self) -> Result<Vec<MacroDataPoint>> {
self.china_imports_yoy().await
}
pub async fn macro_china_industrial_production_yoy(&self) -> Result<Vec<MacroDataPoint>> {
self.china_industrial_production_yoy().await
}
pub async fn macro_china_insurance_income(&self) -> Result<Vec<MacroDataPoint>> {
self.china_insurance_income().await
}
pub async fn macro_china_lpi_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_lpi_index().await
}
pub async fn macro_china_lpr(&self) -> Result<Vec<MacroDataPoint>> {
self.china_lpr().await
}
pub async fn macro_china_m2_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_m2_yearly().await
}
pub async fn macro_china_mobile_number(&self) -> Result<Vec<MacroDataPoint>> {
self.china_mobile_number().await
}
pub async fn macro_china_money_supply(&self) -> Result<Vec<MacroDataPoint>> {
self.china_money_supply().await
}
pub async fn macro_china_national_tax_receipts(&self) -> Result<Vec<MacroDataPoint>> {
self.china_national_tax_receipts().await
}
pub async fn macro_china_new_financial_credit(&self) -> Result<Vec<MacroDataPoint>> {
self.china_new_financial_credit().await
}
pub async fn macro_china_new_house_price(&self) -> Result<Vec<MacroDataPoint>> {
self.china_new_house_price().await
}
pub async fn macro_china_non_man_pmi(&self) -> Result<Vec<MacroDataPoint>> {
self.china_non_man_pmi().await
}
pub async fn macro_china_pmi(&self) -> Result<Vec<MacroDataPoint>> {
self.china_pmi().await
}
pub async fn macro_china_ppi(&self) -> Result<Vec<MacroDataPoint>> {
self.china_ppi().await
}
pub async fn macro_china_ppi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_ppi_yearly().await
}
pub async fn macro_china_real_estate(&self) -> Result<Vec<MacroDataPoint>> {
self.china_real_estate().await
}
pub async fn macro_china_reserve_requirement_ratio(&self) -> Result<Vec<MacroDataPoint>> {
self.china_reserve_requirement_ratio().await
}
pub async fn macro_china_stock_market_cap(&self) -> Result<Vec<MacroDataPoint>> {
self.china_stock_market_cap().await
}
pub async fn macro_china_vegetable_basket(&self) -> Result<Vec<MacroDataPoint>> {
self.china_vegetable_basket().await
}
pub async fn macro_china_yw_electronic_index(&self) -> Result<Vec<MacroDataPoint>> {
self.china_yw_electronic_index().await
}
pub async fn macro_china_au_report(&self) -> Result<Vec<MacroDataPoint>> {
self.china_sge_report().await
}
pub async fn macro_china_shibor_all(&self) -> Result<Vec<MacroDataPoint>> {
self.china_shibor().await
}
pub async fn macro_china_hk_market_info(&self) -> Result<Vec<MacroDataPoint>> {
self.china_hibor().await
}
pub async fn macro_china_rmb(&self) -> Result<Vec<MacroDataPoint>> {
self.china_rmb_central_parity().await
}
pub async fn macro_china_market_margin_sz(&self) -> Result<Vec<MacroDataPoint>> {
self.china_margin_sz().await
}
pub async fn macro_china_market_margin_sh(&self) -> Result<Vec<MacroDataPoint>> {
self.china_margin_sh().await
}
pub async fn macro_china_trade_balance(&self) -> Result<Vec<MacroDataPoint>> {
self.china_trade_balance_jin10().await
}
pub async fn macro_china_pmi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_pmi_jin10().await
}
pub async fn macro_china_cx_pmi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_caixin_pmi().await
}
pub async fn macro_china_cx_services_pmi_yearly(&self) -> Result<Vec<MacroDataPoint>> {
self.china_caixin_services_pmi().await
}
pub async fn macro_china_czsr(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fiscal_revenue().await
}
pub async fn macro_china_gdzctz(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fixed_asset_investment().await
}
pub async fn macro_china_gyzjz(&self) -> Result<Vec<MacroDataPoint>> {
self.china_industrial_growth().await
}
pub async fn macro_china_hgjck(&self) -> Result<Vec<MacroDataPoint>> {
self.china_trade().await
}
pub async fn macro_china_whxd(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fx_loans().await
}
pub async fn macro_china_wbck(&self) -> Result<Vec<MacroDataPoint>> {
self.china_fx_deposits().await
}
pub async fn macro_china_xfzxx(&self) -> Result<Vec<MacroDataPoint>> {
self.china_consumer_confidence().await
}
pub async fn macro_china_qyspjg(&self) -> Result<Vec<MacroDataPoint>> {
self.china_goods_index().await
}
pub async fn macro_cnbs(&self) -> Result<Vec<MacroDataPoint>> {
Ok(Vec::new())
}
pub async fn macro_china_central_bank_balance(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "fininfo", "8", "China Central Bank Balance").await
}
pub async fn macro_china_insurance(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "fininfo", "19", "China Insurance").await
}
pub async fn macro_china_supply_of_money(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "fininfo", "1", "China Supply of Money").await
}
pub async fn macro_china_foreign_exchange_gold(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "fininfo", "5", "China FX Gold Sina").await
}
pub async fn macro_china_retail_price_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "price", "12", "China Retail Price Index").await
}
pub async fn macro_china_society_electricity(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "6", "China Society Electricity").await
}
pub async fn macro_china_society_traffic_volume(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "10", "China Society Traffic").await
}
pub async fn macro_china_postal_telecommunicational(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "11", "China Postal Telecom").await
}
pub async fn macro_china_international_tourism_fx(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "15", "China Intl Tourism FX").await
}
pub async fn macro_china_passenger_load_factor(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "20", "China Passenger Load Factor").await
}
pub async fn macro_china_freight_index(&self) -> Result<Vec<MacroDataPoint>> {
fetch_sina_macro(self, "industry", "22", "China Freight Index").await
}
pub async fn macro_china_shrzgm(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://data.mofcom.gov.cn/datamofcom/front/gnmy/shrzgmQuery";
let resp: serde_json::Value = self.post(url).send().await?.json().await?;
let mut items = Vec::new();
if let Some(arr) = resp.as_array() {
for row in arr {
if let Some(arr_inner) = row.as_array() {
if arr_inner.len() < 2 {
continue;
}
let date = arr_inner[0].as_str().unwrap_or("").to_string();
if date.is_empty() {
continue;
}
if let Some(val) = arr_inner[6].as_f64() {
items.push(MacroDataPoint {
date,
value: val,
name: "Social Financing".to_string(),
});
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn macro_rmb_loan(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://data.10jqka.com.cn/macro/loan/";
let body = self
.get(url)
.header("User-Agent", "Mozilla/5.0 (compatible; akshare-rust/0.1)")
.send()
.await?
.text()
.await?;
let mut items = Vec::new();
for line in body.lines() {
let trimmed = line.trim();
if trimmed.contains("<td") && trimmed.contains("-") {
let text = extract_html_text(trimmed);
if text.contains("-") && text.len() <= 10 {
}
}
}
let re_rows: Vec<&str> = body.split("<tr").collect();
for row in &re_rows[1..] {
let cells: Vec<&str> = row.split("<td").collect();
if cells.len() >= 3 {
let date_cell = extract_html_text(cells[1]);
let val_cell = extract_html_text(cells[2]);
if date_cell.contains("-") {
if let Ok(val) = val_cell.replace(',', "").parse::<f64>() {
items.push(MacroDataPoint {
date: date_cell,
value: val,
name: "RMB Loan".to_string(),
});
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn macro_rmb_deposit(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://data.10jqka.com.cn/macro/rmb/";
let body = self
.get(url)
.header("User-Agent", "Mozilla/5.0 (compatible; akshare-rust/0.1)")
.send()
.await?
.text()
.await?;
let mut items = Vec::new();
let re_rows: Vec<&str> = body.split("<tr").collect();
for row in &re_rows[1..] {
let cells: Vec<&str> = row.split("<td").collect();
if cells.len() >= 3 {
let date_cell = extract_html_text(cells[1]);
let val_cell = extract_html_text(cells[2]);
if date_cell.contains("-") {
if let Ok(val) = val_cell.replace(',', "").parse::<f64>() {
items.push(MacroDataPoint {
date: date_cell,
value: val,
name: "RMB Deposit".to_string(),
});
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn macro_china_daily_energy(&self) -> Result<Vec<MacroDataPoint>> {
let url = "https://cdn.jin10.com/data_center/reports/energy.json";
let resp: Jin10CdnCdnResp = self.get(url).send().await?.json().await?;
let values = resp.values.unwrap_or_default();
let mut items = Vec::new();
if let Some(obj) = values.as_object() {
for (date, row) in obj {
if let Some(cols) = row.as_object() {
for (col_name, col_data) in cols {
if let Some(arr) = col_data.as_array() {
if let Some(val) = arr.first().and_then(|v| v.as_f64()) {
items.push(MacroDataPoint {
date: date.clone(),
value: val,
name: format!("Energy {}", col_name),
});
}
}
}
}
}
}
items.sort_by(|a, b| a.date.cmp(&b.date));
Ok(items)
}
pub async fn macro_china_nbs_nation(
&self,
kind: &str,
path: &str,
period: &str,
) -> Result<Vec<MacroDataPoint>> {
let dbcode = match kind {
"月度数据" => "hgyd",
"季度数据" => "hgjd",
"年度数据" => "hgnd",
_ => {
return Err(crate::error::Error::invalid_input(format!(
"invalid kind: {kind}"
)));
}
};
let url = "https://data.stats.gov.cn/easyquery.htm";
let resp = self
.post(url)
.form(&[
("m", "QueryData"),
("dbcode", dbcode),
("rowcode", "zb"),
("colcode", "sj"),
("wds", "[]"),
(
"dfwds",
format!("[{{\"wdcode\":\"zb\",\"valuecode\":\"{}\"}}]", path).as_str(),
),
("k1", period),
])
.header("User-Agent", "Mozilla/5.0")
.send()
.await?
.error_for_status()?
.json::<serde_json::Value>()
.await?;
let items = resp
.get("returndata")
.and_then(|r| r.get("datanodes"))
.and_then(|d| d.as_array())
.cloned()
.unwrap_or_default();
Ok(items
.iter()
.map(|v| {
let date = v
.get("wds")
.and_then(|w| w.as_array())
.and_then(|a| a.get(2))
.and_then(|w| w.get("valuecode"))
.and_then(|v| v.as_str())
.unwrap_or("");
let value = v
.get("data")
.and_then(|d| d.get("data"))
.and_then(|d| d.as_f64())
.unwrap_or(0.0);
MacroDataPoint {
date: date.to_string(),
value,
name: path.to_string(),
}
})
.collect())
}
pub async fn macro_china_nbs_region(
&self,
kind: &str,
path: &str,
indicator: &str,
period: &str,
) -> Result<Vec<MacroDataPoint>> {
let dbcode = match kind {
"分省月度数据" => "fsyd",
"分省季度数据" => "fsjd",
"分省年度数据" => "fsnd",
_ => {
return Err(crate::error::Error::invalid_input(format!(
"invalid kind: {kind}"
)));
}
};
let url = "https://data.stats.gov.cn/easyquery.htm";
let dfwds = format!(
"[{{\"wdcode\":\"zb\",\"valuecode\":\"{}\"}},{{\"wdcode\":\"reg\",\"valuecode\":\"{}\"}}]",
path, indicator
);
let resp = self
.post(url)
.form(&[
("m", "QueryData"),
("dbcode", dbcode),
("rowcode", "reg"),
("colcode", "sj"),
("wds", "[]"),
("dfwds", dfwds.as_str()),
("k1", period),
])
.header("User-Agent", "Mozilla/5.0")
.send()
.await?
.error_for_status()?
.json::<serde_json::Value>()
.await?;
let items = resp
.get("returndata")
.and_then(|r| r.get("datanodes"))
.and_then(|d| d.as_array())
.cloned()
.unwrap_or_default();
Ok(items
.iter()
.map(|v| {
let date = v
.get("wds")
.and_then(|w| w.as_array())
.and_then(|a| a.get(2))
.and_then(|w| w.get("valuecode"))
.and_then(|v| v.as_str())
.unwrap_or("");
let value = v
.get("data")
.and_then(|d| d.get("data"))
.and_then(|d| d.as_f64())
.unwrap_or(0.0);
MacroDataPoint {
date: date.to_string(),
value,
name: path.to_string(),
}
})
.collect())
}
pub async fn macro_china_urban_unemployment(&self) -> Result<Vec<MacroDataPoint>> {
let url =
"https://data.stats.gov.cn/dg/website/publicrelease/web/external/getEsDataByCidAndDt";
let payload = serde_json::json!({
"cid": "ee3b7046b390415b9b7745e3d16f6052",
"indicatorIds": [
"3888eac6062945a79c8a27e5f13d4953",
"1d550f3ec77a463bb607d4a3427e1465",
"1c1b2d9ab24048bfadc5c7d9510dc663"
],
"daCatalogId": "",
"das": [{"text": "全国", "value": "000000000000"}],
"dt": "LAST60"
});
let resp = self
.post(url)
.json(&payload)
.header("User-Agent", "Mozilla/5.0")
.send()
.await?
.error_for_status()?
.json::<serde_json::Value>()
.await?;
let items = resp
.get("data")
.and_then(|d| d.as_array())
.cloned()
.unwrap_or_default();
Ok(items
.iter()
.map(|v| {
let date = v
.get("date")
.and_then(|d| d.as_str())
.unwrap_or("")
.to_string();
let value = v.get("value").and_then(|d| d.as_f64()).unwrap_or(0.0);
MacroDataPoint {
date,
value,
name: "城镇调查失业率".to_string(),
}
})
.collect())
}
}