use crate::client::AkShareClient;
use crate::error::{Error, Result};
use crate::types::*;
impl AkShareClient {
pub async fn us_quote(&self, symbol: &str) -> Result<QuoteSnapshot> {
let mut candles = self.us_candles(symbol, 2).await?;
let last = candles
.pop()
.ok_or_else(|| Error::upstream("no US quote data"))?;
Ok(QuoteSnapshot {
symbol: symbol.to_uppercase(),
date: last.trade_date,
open: last.open,
high: last.high,
low: last.low,
close: last.close,
volume: last.volume,
})
}
pub async fn us_candles(&self, symbol: &str, limit: usize) -> Result<Vec<CandlePoint>> {
match self.sina_us_daily(symbol, limit).await {
Ok(items) if !items.is_empty() => return Ok(items),
_ => {}
}
match self.yahoo_candles(symbol, limit).await {
Ok(items) if !items.is_empty() => return Ok(items),
_ => {}
}
self.stooq_candles(symbol, limit).await
}
pub async fn get_us_stock_name(&self) -> Result<Vec<serde_json::Value>> {
let mut all_stocks = Vec::new();
for page in 1..=5 {
let url = format!(
"https://stock.finance.sina.com.cn/usstock/api/jsonp.php/callback/US_CategoryService.getList?page={}&num=20&sort=&asc=0&market=&id=",
page
);
let resp = self
.get(&url)
.header("User-Agent", "Mozilla/5.0")
.send()
.await?
.text()
.await?;
if let Some(start) = resp.find("({") {
if let Some(end) = resp.rfind(");") {
let json_str = &resp[start + 1..end + 1];
if let Ok(data) = serde_json::from_str::<serde_json::Value>(json_str) {
if let Some(arr) = data.get("data").and_then(|d| d.as_array()) {
if arr.is_empty() {
break;
}
all_stocks.extend(arr.clone());
}
}
}
}
}
Ok(all_stocks)
}
}