fix: two yfinance segfaults (option_chain pandas path, VIX .history()) - #534
Open
essentialbit wants to merge 8 commits into
Open
fix: two yfinance segfaults (option_chain pandas path, VIX .history())#534essentialbit wants to merge 8 commits into
essentialbit wants to merge 8 commits into
Conversation
added 2 commits
July 31, 2026 12:59
Ticker.option_chain() builds its DataFrame via _options2df(), which calls pd.to_datetime() on lastTradeDate -- the exact same numpy/pandas ABI mismatch already worked around in correlation_engine.py (PR #474), except here it's a SIGSEGV (exit 139, uncatchable) rather than a raised exception. fetch_options_snapshot() is wired into a daily APScheduler cron job (job_options_refresh, main.py:5515) running inside the main Flask process, so this would crash the whole server, not just fail one job. Live-confirmed the segfault (bare 3-line option_chain() repro) and the fix: switched to yfinance's own already-tested _download_options() (raw JSON dicts, same fetch/auth path, no DataFrame construction), computing the put/call ratios and ATM IV in pure Python instead of pandas. Verified end to end against SPY, AAPL, and a no-coverage ticker (BTC-USD).
Ticker.history() reliably segfaults (exit 139) even on non-dividend VIX index tickers (^VIX confirmed via bare repro) -- the "dividend-paying tickers only" framing in project memory for this crash class was too narrow, and this module's own per-ticker try/except never actually protected against it since SIGSEGV isn't catchable. Switches to portfolio_risk._daily_closes -- the same cross-module reuse divergence_radar.py already uses for these exact ^VIX9D/^VIX/^VIX3M/^VIX6M tickers, itself built on market_data.fetch_history()'s pure-JSON _chart() path (no pandas). Verified compute_vix_term_structure()'s spread/regime logic against a synthetic _daily_closes fixture (live network hit an active Yahoo rate-limit mid-cycle from prior verification calls, so this avoids adding to it) -- contango/backwardation classification and all four tenor values come through correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related SIGSEGV bugs found and fixed this cycle, same numpy 2.5.1/pandas 2.2.2 ABI-mismatch root cause already documented for
pd.to_datetime(correlation_engine.py, PR #474):options_data_client.fetch_options_snapshot()calledyfinance.Ticker.option_chain(), which builds a DataFrame via_options2df()->pd.to_datetime(lastTradeDate, ...)-> segfault (exit 139). Scheduled daily (job_options_refresh,main.py:5515) inside the main Flask/APScheduler process, so this would crash the whole server. Fixed by switching to yfinance's own private_download_options()(raw JSON dicts, same fetch/auth path, no DataFrame step) and computing ratios/IV in pure Python.vix_term_structure._latest_close()calledyfinance.Ticker.history(), which also reliably segfaults — confirmed live even on non-dividend index tickers (^VIX), which narrows/corrects the "dividend-paying tickers only" framing previously in project memory for this crash class. Fixed by switching toportfolio_risk._daily_closes(already the established cross-module patterndivergence_radar.pyuses for these exact VIX tenor tickers).Test plan
option_chain()and.history()confirmed segfault (exit 139) before the fixfetch_options_snapshot()verified end-to-end post-fix against SPY, AAPL (real ratios/IV, exit 0) and BTC-USD (gracefulNonefor no options coverage)compute_vix_term_structure()verified against a synthetic_daily_closesfixture (spread calc + contango/backwardation regime classification correct) — live end-to-end re-verification deferred to next cycle since this session hit an active Yahoo rate-limit from the options verification calls abovefrom main import *still imports cleanly after both changes🤖 Generated with Claude Code