From 8b4e6fc0fecf40a05f801328e83928794791bf92 Mon Sep 17 00:00:00 2001 From: Horizontal42 <75383519+Horizontal42@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:51:40 +0300 Subject: [PATCH] market data: switch to Yahoo v8 chart, drop delisted tickers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src-tauri/src/main.rs | 39 +++++++++++++++++---------------------- src/main.ts | 3 ++- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index aa8c6dd..4fd3982 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -292,29 +292,24 @@ async fn fetch_market_data( .build() .map_err(|e| e.to_string())?; - let joined = symbols.join(","); - let url = format!( - "https://query1.finance.yahoo.com/v7/finance/quote?symbols={}", - 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())?; - + // v7/finance/quote now requires a cookie+crumb pair Yahoo stopped issuing + // to plain API clients (returns 401); v8 chart still answers anonymously, + // one symbol per request. let mut prices = std::collections::HashMap::new(); - if let Some(results) = body["quoteResponse"]["result"].as_array() { - for item in results { - let sym = item["symbol"].as_str().unwrap_or("").to_string(); - // regularMarketPrice is in the quote currency (USD for US stocks) - if let Some(price) = item["regularMarketPrice"].as_f64() { - if price > 0.0 && !sym.is_empty() { - prices.insert(sym, price); - } + for sym in &symbols { + let url = format!( + "https://query1.finance.yahoo.com/v8/finance/chart/{}?range=1d&interval=1d", + sym + ); + let Ok(resp) = client.get(&url).send().await else { + continue; + }; + let Ok(body) = resp.json::().await else { + continue; + }; + if let Some(price) = body["chart"]["result"][0]["meta"]["regularMarketPrice"].as_f64() { + if price > 0.0 { + prices.insert(sym.clone(), price); } } } diff --git a/src/main.ts b/src/main.ts index 71ec438..ba24916 100644 --- a/src/main.ts +++ b/src/main.ts @@ -548,7 +548,8 @@ async function refreshRates(force = false): Promise { // ---------- 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 = {}; let marketFetchedAt = 0;