use super::helpers::{fmt_date, json_f64, json_f64_opt, json_i64, json_str, json_str_opt};
use super::types::{
LhbDetail, LhbHyyyb, LhbJgmmtj, LhbJgstatistic, LhbSinaDetail, LhbSinaGgtj, LhbSinaJgmx,
LhbSinaJgzz, LhbSinaYytj, LhbStockDetail, LhbStockDetailDate, LhbStockStatistic,
LhbTraderStatistic, LhbYybDetail, LhbYybph,
};
use crate::client::AkShareClient;
use crate::error::{Error, Result};
fn fmt_date_range(start: &str, end: &str) -> (String, String) {
(fmt_date(start), fmt_date(end))
}
impl AkShareClient {
pub async fn stock_lhb_detail_em(
&self,
start_date: &str,
end_date: &str,
) -> Result<Vec<LhbDetail>> {
let (sd, ed) = fmt_date_range(start_date, end_date);
let filter = format!("(TRADE_DATE<='{ed}')(TRADE_DATE>='{sd}')");
let data = self
.dc_fetch_all(
"RPT_DAILYBILLBOARD_DETAILSNEW",
"ALL",
&filter,
"SECURITY_CODE,TRADE_DATE",
"1,-1",
500,
10,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbDetail {
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
trade_date: json_str(v, "TRADE_DATE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
billboard_net_amount: json_f64(v, "BILLBOARD_NET_AMT"),
billboard_buy_amount: json_f64(v, "BILLBOARD_BUY_AMT"),
billboard_sell_amount: json_f64(v, "BILLBOARD_SELL_AMT"),
billboard_deal_amount: json_f64(v, "BILLBOARD_DEAL_AMT"),
total_amount: json_f64(v, "ACCUM_AMOUNT"),
net_ratio: json_f64(v, "DEAL_NET_RATIO"),
deal_ratio: json_f64(v, "DEAL_AMOUNT_RATIO"),
turnover_rate: json_f64(v, "TURNOVERRATE"),
circulating_market_cap: json_f64(v, "FREE_MARKET_CAP"),
reason: json_str(v, "EXPLANATION"),
explanation: json_str_opt(v, "EXPLAIN"),
d1_change: json_f64_opt(v, "D1_CLOSE_ADJCHRATE"),
d2_change: json_f64_opt(v, "D2_CLOSE_ADJCHRATE"),
d5_change: json_f64_opt(v, "D5_CLOSE_ADJCHRATE"),
d10_change: json_f64_opt(v, "D10_CLOSE_ADJCHRATE"),
})
.collect())
}
pub async fn stock_lhb_stock_statistic_em(
&self,
symbol: &str,
) -> Result<Vec<LhbStockStatistic>> {
let cycle = match symbol {
"近三月" => "02",
"近六月" => "03",
"近一年" => "04",
_ => "01",
};
let filter = format!("(STATISTICS_CYCLE=\"{cycle}\")");
let data = self
.dc_fetch_all(
"RPT_BILLBOARD_TRADEALL",
"ALL",
&filter,
"BILLBOARD_TIMES,LATEST_TDATE,SECURITY_CODE",
"-1,-1,1",
5000,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbStockStatistic {
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
latest_trade_date: json_str(v, "LATEST_TDATE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
billboard_times: json_i64(v, "BILLBOARD_TIMES"),
billboard_net_amount: json_f64(v, "BILLBOARD_NET_AMT"),
billboard_buy_amount: json_f64(v, "BILLBOARD_BUY_AMT"),
billboard_sell_amount: json_f64(v, "BILLBOARD_SELL_AMT"),
billboard_total_amount: json_f64(v, "AMOUNT"),
org_buy_times: json_i64(v, "BUY_TIMES"),
org_sell_times: json_i64(v, "SELL_TIMES"),
org_net_buy_amount: json_f64(v, "ORG_BUY_NET_AMT"),
org_buy_amount: json_f64(v, "ORG_BUY_AMT"),
org_sell_amount: json_f64(v, "ORG_SELL_AMT"),
m1_change: json_f64_opt(v, "M1_CLOSE_ADJCHRATE"),
m3_change: json_f64_opt(v, "M3_CLOSE_ADJCHRATE"),
m6_change: json_f64_opt(v, "M6_CLOSE_ADJCHRATE"),
y1_change: json_f64_opt(v, "Y1_CLOSE_ADJCHRATE"),
})
.collect())
}
pub async fn stock_lhb_jgmmtj_em(
&self,
start_date: &str,
end_date: &str,
) -> Result<Vec<LhbJgmmtj>> {
let (sd, ed) = fmt_date_range(start_date, end_date);
let filter = format!("(TRADE_DATE>='{sd}')(TRADE_DATE<='{ed}')");
let data = self
.dc_fetch_all(
"RPT_ORGANIZATION_TRADE_DETAILS",
"ALL",
&filter,
"NET_BUY_AMT,TRADE_DATE,SECURITY_CODE",
"-1,-1,1",
500,
10,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbJgmmtj {
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
trade_date: json_str(v, "TRADE_DATE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
buy_org_count: json_i64(v, "BUY_ORG_NUM"),
sell_org_count: json_i64(v, "SELL_ORG_NUM"),
org_buy_amount: json_f64(v, "ORG_BUY_AMT"),
org_sell_amount: json_f64(v, "ORG_SELL_AMT"),
org_net_buy_amount: json_f64(v, "NET_BUY_AMT"),
total_amount: json_f64(v, "ACCUM_AMOUNT"),
org_net_ratio: json_f64(v, "NET_BUY_RATIO"),
turnover_rate: json_f64(v, "TURNOVERRATE"),
circulating_market_cap: json_f64(v, "FREE_MARKET_CAP"),
reason: json_str(v, "EXPLANATION"),
})
.collect())
}
pub async fn stock_lhb_jgstatistic_em(&self, symbol: &str) -> Result<Vec<LhbJgstatistic>> {
let cycle = match symbol {
"近三月" => "02",
"近六月" => "03",
"近一年" => "04",
_ => "01",
};
let filter = format!("(STATISTICSCYCLE=\"{cycle}\")");
let data = self
.dc_fetch_all(
"RPT_ORGANIZATION_SEATNEW",
"ALL",
&filter,
"ONLIST_TIMES,SECURITY_CODE",
"-1,1",
5000,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbJgstatistic {
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
billboard_amount: json_f64(v, "AMOUNT"),
billboard_times: json_i64(v, "ONLIST_TIMES"),
org_buy_amount: json_f64(v, "BUY_AMT"),
org_buy_times: json_i64(v, "BUY_TIMES"),
org_sell_amount: json_f64(v, "SELL_AMT"),
org_sell_times: json_i64(v, "SELL_TIMES"),
org_net_buy_amount: json_f64(v, "NET_BUY_AMT"),
m1_change: json_f64_opt(v, "M1_CLOSE_ADJCHRATE"),
m3_change: json_f64_opt(v, "M3_CLOSE_ADJCHRATE"),
m6_change: json_f64_opt(v, "M6_CLOSE_ADJCHRATE"),
y1_change: json_f64_opt(v, "Y1_CLOSE_ADJCHRATE"),
})
.collect())
}
pub async fn stock_lhb_hyyyb_em(
&self,
start_date: &str,
end_date: &str,
) -> Result<Vec<LhbHyyyb>> {
let (sd, ed) = fmt_date_range(start_date, end_date);
let filter = format!("(ONLIST_DATE>='{sd}')(ONLIST_DATE<='{ed}')");
let data = self
.dc_fetch_all(
"RPT_OPERATEDEPT_ACTIVE",
"ALL",
&filter,
"TOTAL_NETAMT,ONLIST_DATE,OPERATEDEPT_CODE",
"-1,-1,1",
5000,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbHyyyb {
dept_name: json_str(v, "OPERATEDEPT_NAME"),
trade_date: json_str(v, "ONLIST_DATE"),
buy_stock_count: json_i64(v, "BUY_NUM"),
sell_stock_count: json_i64(v, "SELL_NUM"),
buy_amount: json_f64(v, "BUY_AMT"),
sell_amount: json_f64(v, "SELL_AMT"),
net_amount: json_f64(v, "TOTAL_NETAMT"),
buy_stocks: json_str_opt(v, "BUY_SECURITIES"),
dept_code: json_str(v, "OPERATEDEPT_CODE"),
})
.collect())
}
pub async fn stock_lhb_yybph_em(&self, symbol: &str) -> Result<Vec<LhbYybph>> {
let cycle = match symbol {
"近三月" => "02",
"近六月" => "03",
"近一年" => "04",
_ => "01",
};
let filter = format!("(STATISTICSCYCLE=\"{cycle}\")");
let data = self
.dc_fetch_all(
"RPT_OPERATEDEPT_RANK",
"ALL",
&filter,
"ONLIST_TIMES,OPERATEDEPT_CODE",
"-1,1",
5000,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbYybph {
dept_name: json_str(v, "OPERATEDEPT_NAME"),
dept_code: json_str(v, "OPERATEDEPT_CODE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
billboard_amount: json_f64(v, "AMOUNT"),
billboard_times: json_i64(v, "ONLIST_TIMES"),
buy_amount: json_f64(v, "BUY_AMT"),
buy_times: json_i64(v, "BUY_TIMES"),
sell_amount: json_f64(v, "SELL_AMT"),
sell_times: json_i64(v, "SELL_TIMES"),
net_buy_amount: json_f64(v, "NET_BUY_AMT"),
m1_change: json_f64_opt(v, "M1_CLOSE_ADJCHRATE"),
m3_change: json_f64_opt(v, "M3_CLOSE_ADJCHRATE"),
m6_change: json_f64_opt(v, "M6_CLOSE_ADJCHRATE"),
y1_change: json_f64_opt(v, "Y1_CLOSE_ADJCHRATE"),
})
.collect())
}
pub async fn stock_lhb_traderstatistic_em(
&self,
symbol: &str,
) -> Result<Vec<LhbTraderStatistic>> {
let cycle = match symbol {
"近三月" => "02",
"近六月" => "03",
"近一年" => "04",
_ => "01",
};
let filter = format!("(STATISTICSCYCLE=\"{cycle}\")");
let data = self
.dc_fetch_all(
"RPT_BILLBOARD_DAILYDETAILS_TRADER",
"ALL",
&filter,
"ONLIST_TIMES,OPERATEDEPT_CODE",
"-1,1",
5000,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbTraderStatistic {
trader_name: json_str(v, "OPERATEDEPT_NAME"),
trader_code: json_str(v, "OPERATEDEPT_CODE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
billboard_amount: json_f64(v, "AMOUNT"),
billboard_times: json_i64(v, "ONLIST_TIMES"),
buy_amount: json_f64(v, "BUY_AMT"),
buy_times: json_i64(v, "BUY_TIMES"),
sell_amount: json_f64(v, "SELL_AMT"),
sell_times: json_i64(v, "SELL_TIMES"),
net_buy_amount: json_f64(v, "NET_BUY_AMT"),
m1_change: json_f64_opt(v, "M1_CLOSE_ADJCHRATE"),
m3_change: json_f64_opt(v, "M3_CLOSE_ADJCHRATE"),
m6_change: json_f64_opt(v, "M6_CLOSE_ADJCHRATE"),
y1_change: json_f64_opt(v, "Y1_CLOSE_ADJCHRATE"),
})
.collect())
}
pub async fn stock_lhb_stock_detail_date_em(
&self,
symbol: &str,
) -> Result<Vec<LhbStockDetailDate>> {
let filter = format!("(SECURITY_CODE=\"{symbol}\")");
let data = self
.dc_fetch_all(
"RPT_DAILYBILLBOARD_DETAILSNEW",
"ALL",
&filter,
"TRADE_DATE",
"-1",
500,
1,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbStockDetailDate {
trade_date: json_str(v, "TRADE_DATE"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
reason: json_str(v, "EXPLANATION"),
billboard_net_amount: json_f64(v, "BILLBOARD_NET_AMT"),
billboard_buy_amount: json_f64(v, "BILLBOARD_BUY_AMT"),
billboard_sell_amount: json_f64(v, "BILLBOARD_SELL_AMT"),
})
.collect())
}
pub async fn stock_lhb_stock_detail_em(
&self,
symbol: &str,
date: &str,
flag: &str,
) -> Result<Vec<LhbStockDetail>> {
let report = match flag {
"卖出" => "RPT_BILLBOARD_DAILYDETAILSSELL",
_ => "RPT_BILLBOARD_DAILYDETAILSBUY",
};
let filter = format!(
"(TRADE_DATE='{}')(SECURITY_CODE=\"{symbol}\")",
fmt_date(date)
);
let data = self
.dc_fetch_all(report, "ALL", &filter, "TRADE_DATE", "-1", 500, 1, &[])
.await?;
Ok(data
.iter()
.map(|v| LhbStockDetail {
trade_date: json_str(v, "TRADE_DATE"),
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
dept_name: json_str(v, "OPERATEDEPT_NAME"),
buy_amount: json_f64(v, "BUY"),
sell_amount: json_f64(v, "SELL"),
net_amount: json_f64(v, "NET"),
reason: json_str(v, "EXPLANATION"),
side: flag.to_string(),
})
.collect())
}
pub async fn stock_lhb_yyb_detail_em(&self, symbol: &str) -> Result<Vec<LhbYybDetail>> {
let filter = format!("(OPERATEDEPT_CODE=\"{symbol}\")");
let data = self
.dc_fetch_all(
"RPT_BILLBOARD_DAILYDETAILSBUY",
"ALL",
&filter,
"TRADE_DATE",
"-1",
500,
10,
&[],
)
.await?;
Ok(data
.iter()
.map(|v| LhbYybDetail {
trade_date: json_str(v, "TRADE_DATE"),
code: json_str(v, "SECURITY_CODE"),
name: json_str(v, "SECURITY_NAME_ABBR"),
close_price: json_f64(v, "CLOSE_PRICE"),
change_pct: json_f64(v, "CHANGE_RATE"),
buy_amount: json_f64(v, "BUY"),
sell_amount: json_f64(v, "SELL"),
net_amount: json_f64(v, "NET"),
reason: json_str(v, "EXPLANATION"),
})
.collect())
}
pub async fn stock_lhb_detail_daily_sina(&self, date: &str) -> Result<Vec<LhbSinaDetail>> {
let formatted = fmt_date(date);
let url =
"https://vip.stock.finance.sina.com.cn/q/go.php/vInvestConsult/kind/lhb/index.phtml";
let resp = self
.get(url)
.query(&[("tradedate", formatted.as_str())])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let _text = resp.text().await.map_err(Error::from)?;
Ok(vec![])
}
pub async fn stock_lhb_ggtj_sina(&self) -> Result<Vec<LhbSinaGgtj>> {
let url = "https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml";
let resp = self
.get(url)
.query(&[("last", "5"), ("p", "1")])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let _text = resp.text().await.map_err(Error::from)?;
Ok(vec![])
}
pub async fn stock_lhb_jgmx_sina(&self) -> Result<Vec<LhbSinaJgmx>> {
let url = "https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgmx/index.phtml";
let resp = self
.get(url)
.query(&[("p", "1")])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let _text = resp.text().await.map_err(Error::from)?;
Ok(vec![])
}
pub async fn stock_lhb_jgzz_sina(&self, symbol: &str) -> Result<Vec<LhbSinaJgzz>> {
let url = "https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgzz/index.phtml";
let resp = self
.get(url)
.query(&[("last", symbol), ("p", "1")])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let _text = resp.text().await.map_err(Error::from)?;
Ok(vec![])
}
pub async fn stock_lhb_yytj_sina(&self, symbol: &str) -> Result<Vec<LhbSinaYytj>> {
let url = "https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/yytj/index.phtml";
let resp = self
.get(url)
.query(&[("last", symbol), ("p", "1")])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let _text = resp.text().await.map_err(Error::from)?;
Ok(vec![])
}
}