go-yfinance v1.5.1 Development Progress
Last Updated: 2026-06-29
Overview
Implementation plan and progress tracking for Python yfinance v1.5.1 parity. Python yfinance v1.5.0 was retracted, so this work targets the corrected v1.5.1 release line. The release combines two user-visible data-path changes with several defensive fixes around Yahoo response shape, authentication, and price repair edge cases.
This document records the implementation plan before code changes so that each upstream item can be tracked as implemented, intentionally skipped, or verified as not applicable to Go.
Branch Structure
Upstream Release Scope
| Upstream Item | Python Change | Initial Go Assessment |
|---|---|---|
| Release 1.5.0 | Retracted release | Do not target directly; use v1.5.1 as the parity baseline |
| Release 1.5.1 | Re-published 1.5.x changes after merging dev branch | Target release for this branch |
| #2811 | Fall back to chunked requests when single-URL fundamentals fetch fails or times out | Done: Go financials retries failed/empty/malformed single requests with 60-key chunks and keeps sticky chunked mode on success |
| #2845 | Determine login state and subscription tier from Yahoo subscriptions API | Done: CheckLogin() now uses the subscriptions API and SubscriptionTier() exposes Yahoo tier names |
| #2850 | Preserve login cookies across cookie-strategy switches | Done: Go merges named cookies, preserves existing jar entries when login cookies are set, and invalidates only the stale crumb |
| #2851 | Replace valuation-measures HTML scrape with fundamentals-timeseries API; add freq and periods |
Done: Go now fetches fundamentals-timeseries, supports freq-specific cache and periods slicing, and exposes raw numeric cells |
| #2853 | Normalize configured proxy strings | Done for Go shape: CycleTLS accepts a single proxy string, so config/client now trim and pass the string through request options |
| #2863 / #2877 | Guard complementary info parsing against empty, missing, or malformed timeseries result | Done: Info() now fetches trailingPegRatio from fundamentals-timeseries and treats sparse/malformed cells as missing |
Commit 974fac8 |
Fix _fetch_info handling of None responses |
Done for analogous quoteSummary path: added parser tests for empty, missing, and null result payloads |
| #2867 | Fix missing comma between two screener EPS fields | Done: split the Go constants and added regression coverage |
| #2842 | Fix price-repair unit-switch sometimes applying twice | Done for Go shape: unit-switch correction stops after the first detected switch, preventing overlapping prefix re-correction |
| #2843 | Avoid premarket false-positive bad-dividend repair | Done for Go shape: intraday pre/post dividend too-small detection now suppresses recovered low-price drops |
| #2859 | Price repair: handle NaN volume |
Reviewed for Go shape: parsed volume is int64, so direct NaN volume is not representable; added non-finite correction guards around repair factors |
| #2860 | Dividend repair: handle Adj Close going to infinity |
Done for Go shape: non-finite adjusted close is normalized on parse and guarded in auto-adjust/dividend repair |
Commit df54d12 |
Ensure parsed OHLC/Adj Close columns are float when Adj Close contains infinity |
Done for Go shape: added value-level Inf guards and regression tests |
| Docs-only patches | CONTRIBUTING typo/link updates | Not applicable unless local docs copy equivalent text |
Implementation Plan
Phase 0: Audit and Regression Scaffold
- Create a per-upstream-item checklist from the table above and update statuses as code lands.
- Add or adjust tests before behavior changes where practical:
- screener EPS field validation;
Info()nil, empty, and missing-result response handling;- valuation API parser with missing measures and missing cells;
- financials chunk fallback success, sticky mode, and rollback on chunk failure;
- price repair fixtures for premarket false positives,
NaNvolume, andInfadjusted close. - Preserve existing user work in unrelated files. At branch creation, the
worktree already had a pre-existing modification in
pkg/repair/CLAUDE.md.
Phase 1: Low-Risk Correctness Fixes
- [x] Split the concatenated screener fields into
netepsbasic.lasttwelvemonthsandnetepsdiluted.lasttwelvemonths. - [x] Add regression coverage proving both fields validate and the concatenated key is absent.
- [x] Review proxy configuration flow. CycleTLS accepts a single proxy string,
so Go does not need Python's
{"http": proxy, "https": proxy}mapping. The configured string is now trimmed and passed to CycleTLS request options. - [x] Harden
Info()parsing for empty/missing Yahoo result payloads without changing successful response behavior.
Phase 2: Valuation Measures API Migration
- [x] Replace key-statistics HTML scraping with the fundamentals-timeseries API.
- [x] Keep
Ticker.Valuation()andTicker.ValuationMeasures()as compatibility entry points using Python defaults:freq="quarterly"andperiods=5. - [x] Add a method form,
GetValuationMeasures(freq string, periods *int), for callers that needmonthly,yearly,trailing, or all periods. - [x] Fetch current values from trailing series and period columns from the selected
frequency, matching Python's
Currentplus newest-first date columns shape. - [x] Emit all nine valuation measure rows even when individual cells are missing.
- [x] Decide model compatibility carefully:
- Python v1.5.1 returns raw numeric cells with missing values represented as null/NaN in DataFrame form.
- Existing Go
models.ValuationMeasuresexposed string values. The model now stores nullable raw numeric cells inRawValues, addsFloatValue(), and keepsValue()as a compatibility string helper. - [x] Retire HTML parser tests and replace them with timeseries parser, periods, invalid-input, and freq tests.
Phase 3: Fundamentals Chunked Fallback
- [x] Add a small, shared state flag for fundamentals-timeseries chunked mode. The state should live with the ticker/client data path rather than as a package global.
- [x] Keep the fast path as a single request when the flag is false.
- [x] On timeout, transport failure, empty result, or malformed result from the single request, retry using chunks of 60 keys.
- [x] If chunked retry succeeds, keep chunked mode for later fundamentals fetches on the same data path to avoid repeated long-request timeouts.
- [x] If chunked retry also fails, revert the flag so future calls can retry the fast path.
- [x] Add mock tests for chunk fallback, sticky mode, rollback behavior, and the 60-key chunk boundary.
Phase 4: Authentication Parity
- [x] Add the Yahoo subscriptions endpoint:
https://query1.finance.yahoo.com/ws/obi-integration/v1/subscriptions. - [x] Change login checking to use the subscriptions response instead of parsing the Yahoo Finance home page.
- [x] Add
SubscriptionTier()returninggold,silver,bronze,premium,free, or an empty/none state for not logged in. - [x] Revisit
SetLoginCookiesAPI compatibility: - Python now returns a bool after live validation.
- Go currently exposes
SetLoginCookies(cookieT, cookieY string)with no return. Prefer preserving it and addingSetLoginCookiesAndCheckor a separateCheckLogincall unless a breaking change is explicitly chosen. - [x] Ensure manually supplied login cookies merge into the existing cookie jar and invalidate the cached crumb so the next request remints it under the login cookies.
Phase 5: Price Repair Hardening
- [x] Compare Go repair behavior against Python changes before editing algorithms.
- [x] Add targeted fixtures/tests first, especially around:
- [x] premarket dividend false positives;
- [x]
NaNvolume or absent volume before volume scaling; - [x] adjusted close values that are
+Infor-Inf; - [x] unit-switch repair that may run after currency standardization.
- [x] Apply the smallest algorithm changes needed to match Python behavior without expanding repair scope.
- [x] Update repair docs if behavior or caveats change.
Phase 6: Documentation and Verification
- [x] Update release notes under
docs/releases/. - [x] Update README/API docs only when public APIs change.
- [x] Run targeted package tests while developing.
- [x] Run the full verification set before completion:
- [x]
go test ./... - [x]
go vet ./... - [x]
golangci-lint run ./...if available locally - [x]
go test -v -race -coverprofile=coverage.out ./... - [x]
make docs - [x]
cp README.md docs/index.md - [x]
make docs-build
Verification Plan
| Check | Status |
|---|---|
| Screener EPS field regression tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/screener |
Info() nil/empty/malformed response tests |
PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/ticker, including sparse complementary trailingPegRatio timeseries |
| Client proxy config pass-through tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/client |
| Valuation fundamentals-timeseries parser tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/ticker |
| Valuation public API compatibility tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/models ./pkg/ticker |
| Financials chunk fallback tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/ticker |
| Auth subscriptions and subscription-tier tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/client |
| Login cookie preservation tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/client |
| Price repair edge-case tests | PASS: GOCACHE=/tmp/go-build-cache go test ./pkg/repair ./pkg/ticker for non-finite adjusted close, repair correction guards, intraday pre/post dividend false-positive suppression, and unit-switch single-application |
go test ./... |
PASS: GOCACHE=/tmp/go-build-cache go test ./... |
| CI race/coverage test | PASS: GOCACHE=/tmp/go-build-cache go test -v -race -coverprofile=coverage.out ./... with network-enabled integration tests |
| Broader lint/vet checks | PASS: GOCACHE=/tmp/go-build-cache go vet ./...; PASS: GOLANGCI_LINT_CACHE=/tmp/golangci-lint-cache golangci-lint run ./...; PASS: make lint after updating the lint target for golangci-lint v2 package discovery |
| GoDoc/API docs generation | PASS: GOMARKDOC=/tmp/gobin/gomarkdoc make docs |
| MkDocs site build | PASS: make docs-build; README was synced to docs/index.md before build |
Python vs Go Call Structure Notes
- Python uses a process-wide
YfDatasingleton and stores the sticky fundamentals chunked flag there. Go should keep equivalent state scoped to the client/ticker data path so callers can control sharing through object reuse. - Python's valuation result is a pandas DataFrame. Go should preserve a structured model with stable JSON tags and helper methods rather than expose a DataFrame-like abstraction.
- Python changed
Auth.set_login_cookies()to validate and returnbool. Go's existing method does not return a value, so a non-breaking additive API is preferable unless this branch intentionally introduces a breaking release. - Python repair code uses pandas/NumPy behavior around
NaN, dtype, and infinity. Go needs explicitmath.IsNaNandmath.IsInfguards where values are parsed, compared, rounded, or converted to integer volume. - Python complementary-info fixes now map to Go's
Info()path through an additivetrailingPegRatiofundamentals-timeseries fetch. Sparse or malformed values are treated as missing, matching Python v1.5.1's guarded parse.
Change History
| Date | Description |
|---|---|
| 2026-06-29 | Branch created and Python yfinance v1.5.1 release scope reviewed |
| 2026-06-29 | Added implementation plan before code changes |
| 2026-06-29 | Completed Phase 1 low-risk fixes: screener EPS fields, Info sparse-response guards, and client proxy pass-through |
| 2026-06-29 | Completed Phase 2 valuation migration from HTML scraping to fundamentals-timeseries API |
| 2026-06-29 | Completed Phase 3 fundamentals chunked fallback with sticky/rollback behavior and chunk-size regression tests |
| 2026-06-29 | Completed Phase 4 authentication parity using Yahoo subscriptions API, additive login-cookie validation, and tier mapping tests |
| 2026-06-29 | Started Phase 5 price repair hardening with non-finite adjusted-close parsing, auto-adjust, dividend, zero, and unit-correction guards |
| 2026-06-29 | Added Phase 5 intraday pre/post dividend false-positive guard matching Python's recovered-price behavior |
| 2026-06-29 | Completed Phase 5 unit-switch overlap guard so sudden-change correction applies once per repair pass |
| 2026-06-29 | Completed Phase 6 release notes, README update, regenerated API docs, and full test/vet/lint verification |
| 2026-06-29 | Added final complementary-info parity for Info().TrailingPegRatio and sparse timeseries guards |
| 2026-06-29 | Re-ran release checks including race/coverage integration tests, API docs generation, README-to-docs index sync, MkDocs build, vet, and lint |