market data: switch to Yahoo v8 chart, drop delisted tickers

v7/finance/quote returns 401 now — Yahoo stopped issuing anonymous
clients the cookie+crumb pair it requires. v8 chart still answers
without auth, one symbol per request instead of one bulk call.
Also dropped SBER/GAZP from the tracked symbols; Yahoo delisted
Russian tickers in 2022, so those two always missed anyway.
This commit is contained in:
Horizontal42 2026-07-03 11:51:40 +03:00
parent d0d13ec1c0
commit 8b4e6fc0fe
2 changed files with 19 additions and 23 deletions

View file

@ -292,29 +292,24 @@ async fn fetch_market_data(
.build() .build()
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let joined = symbols.join(","); // v7/finance/quote now requires a cookie+crumb pair Yahoo stopped issuing
let url = format!( // to plain API clients (returns 401); v8 chart still answers anonymously,
"https://query1.finance.yahoo.com/v7/finance/quote?symbols={}", // one symbol per request.
joined
);
let body: serde_json::Value = client
.get(&url)
.send()
.await
.map_err(|e| e.to_string())?
.json()
.await
.map_err(|e| e.to_string())?;
let mut prices = std::collections::HashMap::new(); let mut prices = std::collections::HashMap::new();
if let Some(results) = body["quoteResponse"]["result"].as_array() { for sym in &symbols {
for item in results { let url = format!(
let sym = item["symbol"].as_str().unwrap_or("").to_string(); "https://query1.finance.yahoo.com/v8/finance/chart/{}?range=1d&interval=1d",
// regularMarketPrice is in the quote currency (USD for US stocks) sym
if let Some(price) = item["regularMarketPrice"].as_f64() { );
if price > 0.0 && !sym.is_empty() { let Ok(resp) = client.get(&url).send().await else {
prices.insert(sym, price); continue;
} };
let Ok(body) = resp.json::<serde_json::Value>().await else {
continue;
};
if let Some(price) = body["chart"]["result"][0]["meta"]["regularMarketPrice"].as_f64() {
if price > 0.0 {
prices.insert(sym.clone(), price);
} }
} }
} }

View file

@ -548,7 +548,8 @@ async function refreshRates(force = false): Promise<void> {
// ---------- market data // ---------- market data
const MARKET_SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META", "SBER", "GAZP"]; // Yahoo delisted Russian tickers (SBER/GAZP) in 2022 — dropped, they always miss.
const MARKET_SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META"];
let marketPrices: Record<string, number> = {}; let marketPrices: Record<string, number> = {};
let marketFetchedAt = 0; let marketFetchedAt = 0;