Skip to content

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

main
 └── feature/v1.5.1-parity

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, NaN volume, and Inf adjusted 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.lasttwelvemonths and netepsdiluted.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() and Ticker.ValuationMeasures() as compatibility entry points using Python defaults: freq="quarterly" and periods=5.
  • [x] Add a method form, GetValuationMeasures(freq string, periods *int), for callers that need monthly, yearly, trailing, or all periods.
  • [x] Fetch current values from trailing series and period columns from the selected frequency, matching Python's Current plus 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.ValuationMeasures exposed string values. The model now stores nullable raw numeric cells in RawValues, adds FloatValue(), and keeps Value() 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() returning gold, silver, bronze, premium, free, or an empty/none state for not logged in.
  • [x] Revisit SetLoginCookies API compatibility:
  • Python now returns a bool after live validation.
  • Go currently exposes SetLoginCookies(cookieT, cookieY string) with no return. Prefer preserving it and adding SetLoginCookiesAndCheck or a separate CheckLogin call 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] NaN volume or absent volume before volume scaling;
  • [x] adjusted close values that are +Inf or -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 YfData singleton 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 return bool. 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 explicit math.IsNaN and math.IsInf guards where values are parsed, compared, rounded, or converted to integer volume.
  • Python complementary-info fixes now map to Go's Info() path through an additive trailingPegRatio fundamentals-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