Pull Yahoo Finance quote snapshots and historical OHLCV candles for any list of tickers — equities, ETFs, indices, crypto, FX. We handle the retries, fingerprint rotation, and proxy routing so the data lands. One typed row per symbol, JSON or CSV export.
Fix: previous_close was empty on every single row in production
(30-day field-fill audit, run gDqSDDtW3424IRvjX). Root cause: the parser
read meta.previousClose, but a live probe against
query1.finance.yahoo.com/v8/finance/chart/{symbol} on 2026-09-12 showed
Yahoo only populates that key when the request's range=1d. For every
other range — including 1mo, this Actor's default — the key is simply
absent from the response. meta.chartPreviousClose looked like an obvious
substitute but is a different number entirely: the reference price from
before the requested chart window (e.g. ~1 month old for range=1mo,
~1 year old for range=1y), not yesterday's close.
The fix does not cost an extra request. When the interval is daily,
the true previous session close is already sitting in the same response —
it's the second-to-last close in the candle series that was fetched
anyway. Verified this equals the direct meta.previousClose value exactly
when both are available (range=1d). For non-daily intervals (1wk,
1mo) there is no way to recover a genuine daily previous-close from that
response, so the field now returns null honestly instead of guessing —
same behaviour as before for that narrower case, just no longer silently
wrong for the common daily case.
Added 3 regression tests (tests/test_parser.py) against realistic
Yahoo response shapes (no meta.previousClose, only chartPreviousClose)
that fail against the pre-fix parser and pass against the fix.
Checked the other 13 dataset fields against a fresh local run
(AAPL/^GSPC/BTC-USD, default range=1mo/interval=1d) and against six
live symbol classes (equity, index, ETF, crypto, FX) — all populated with
no unexpected nulls at the default configuration.
0.1.0 — 2026-09-10
Initial local-green build: real per-symbol quote + OHLCV candle
fetch against query1.finance.yahoo.com/v8/finance/chart/{symbol}
via curl-cffi browser impersonation (rotating
chrome131/chrome124/firefox147/safari180), exponential
backoff on 408/429/5xx/network errors (2s→30s, max 5 attempts),
immediate fail on 404.
Per-symbol fault isolation: one bad/delisted ticker is logged and
skipped, the rest of the run continues; the run fails loud only if
every requested symbol fails.
One dataset row per symbol (snapshot fields + nested candles list),
never one row per candle. result PPE event fires once per row.
45 unit tests across models/parser/client/main against
synthetic fixtures (equity, index, empty-candles, chart.error,
malformed body); ruff/pyright clean.