From 2700b0845d9e008b53cdd9252fb569a8dfa47342 Mon Sep 17 00:00:00 2001 From: Harwinder Date: Tue, 5 May 2026 20:01:35 -0400 Subject: [PATCH] Disable SSL verify for yfinance via curl_cffi session Live server sits behind a TLS-inspecting proxy that re-signs HTTPS with an untrusted root CA, breaking yfinance HTTPS calls. yfinance >= 0.2.40 requires a curl_cffi session (rejects requests.Session), so we build one with verify=False and impersonate=chrome. Trade-off: yfinance traffic is no longer authenticated against MITM. Acceptable because the data is public market quotes and an attacker can at worst inject bad prices. Session is yfinance-only and not reused for any authenticated traffic. Co-Authored-By: Claude Opus 4.7 --- data_provider.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/data_provider.py b/data_provider.py index b460058..77460d7 100644 --- a/data_provider.py +++ b/data_provider.py @@ -24,6 +24,17 @@ except ImportError: yf = None _YF_AVAILABLE = False +# Insecure HTTPS session for yfinance — disables SSL verification. +# Needed on servers behind a TLS-inspecting proxy that re-signs certs with +# an untrusted root. yfinance requires a curl_cffi session, not requests. +# Security trade-off: man-in-the-middle attacks on yfinance traffic are +# possible. Acceptable here because the data is public market quotes. +try: + from curl_cffi import requests as _curl_cffi_requests + _YF_SESSION = _curl_cffi_requests.Session(impersonate="chrome", verify=False) +except ImportError: + _YF_SESSION = None + from config import PlatformConfig, Timeframe, SYMBOL_DISPLAY, PIP_VALUES logger = logging.getLogger(__name__) @@ -304,10 +315,13 @@ class ForexDataProvider: period = "2y" try: - df = yf.download( - yf_symbol, interval=yf_interval, period=period, + yf_kwargs = dict( + interval=yf_interval, period=period, progress=False, auto_adjust=False, threads=False, ) + if _YF_SESSION is not None: + yf_kwargs["session"] = _YF_SESSION + df = yf.download(yf_symbol, **yf_kwargs) if df is None or df.empty: return None