Skip to content

fix: two yfinance segfaults (option_chain pandas path, VIX .history()) - #534

Open
essentialbit wants to merge 8 commits into
mainfrom
fix/options-chain-segfault-workaround
Open

fix: two yfinance segfaults (option_chain pandas path, VIX .history())#534
essentialbit wants to merge 8 commits into
mainfrom
fix/options-chain-segfault-workaround

Conversation

@essentialbit

@essentialbit essentialbit commented Jul 31, 2026

Copy link
Copy Markdown
Owner

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):

  1. options_data_client.fetch_options_snapshot() called yfinance.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.
  2. vix_term_structure._latest_close() called yfinance.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 to portfolio_risk._daily_closes (already the established cross-module pattern divergence_radar.py uses for these exact VIX tenor tickers).

Test plan

  • Bare repro of both option_chain() and .history() confirmed segfault (exit 139) before the fix
  • fetch_options_snapshot() verified end-to-end post-fix against SPY, AAPL (real ratios/IV, exit 0) and BTC-USD (graceful None for no options coverage)
  • compute_vix_term_structure() verified against a synthetic _daily_closes fixture (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 above
  • from main import * still imports cleanly after both changes

🤖 Generated with Claude Code

Saifodius 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.
@essentialbit essentialbit changed the title fix: bypass yfinance option_chain() pandas path to avoid segfault fix: two yfinance segfaults (option_chain pandas path, VIX .history()) Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant