From 57ff9aa66be969c465e293261ad22fb647e9b7fd Mon Sep 17 00:00:00 2001 From: R5dan Date: Mon, 6 Jan 2025 14:54:24 +0000 Subject: [PATCH] Make download and history work --- yfinance/base.py | 4 ++-- yfinance/config.py | 3 ++- yfinance/data.py | 11 +++++----- yfinance/multi.py | 42 ++++++++++++++++-------------------- yfinance/scrapers/history.py | 17 +++++++-------- yfinance/ticker.py | 10 ++++++--- 6 files changed, 44 insertions(+), 43 deletions(-) diff --git a/yfinance/base.py b/yfinance/base.py index 088b16a9..24860578 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -49,7 +49,7 @@ class TickerBase: def __init__(self, ticker, config:'_Config'=None): self.ticker = ticker.upper() - self.config = config or Config.current + self.config = config self._tz = None self._isin = None @@ -85,7 +85,7 @@ def history(self, *args, **kwargs) -> pd.DataFrame: def _lazy_load_price_history(self): if self._price_history is None: - self._price_history = PriceHistory(self._data, self.ticker, self._get_ticker_tz(self.proxy, timeout=10)) + self._price_history = PriceHistory(self._data, self.ticker, self._get_ticker_tz(self.config), self.config) return self._price_history def _get_ticker_tz(self, config:'_Config'=None): diff --git a/yfinance/config.py b/yfinance/config.py index ada70f6d..0085e687 100644 --- a/yfinance/config.py +++ b/yfinance/config.py @@ -62,7 +62,7 @@ def set_session(self, session: 'requests.Session') -> 'Config': """ self.session = session return self - + def set_proxy(self, proxy: 'str') -> 'Config': """ Set the proxy for the yfinance package. @@ -104,6 +104,7 @@ def set_timeout(self, timeout: 'int') -> 'Config': self.timeout = timeout return self + class CurrentConfig(Config): def set_new_config(self, config:'Config') -> 'CurrentConfig': """ diff --git a/yfinance/data.py b/yfinance/data.py index e71204e4..8d6e3742 100644 --- a/yfinance/data.py +++ b/yfinance/data.py @@ -44,13 +44,14 @@ class SingletonMeta(type): _instances = {} _lock = threading.Lock() - def __call__(cls, *args, **kwargs): + def __call__(cls, config:'_Config'=None, *args, **kwargs): + config = config or Config.current with cls._lock: if cls not in cls._instances: instance = super().__call__(*args, **kwargs) cls._instances[cls] = instance else: - cls._instances[cls]._set_session(*args, **kwargs) + cls._instances[cls]._set_session(config.session) return cls._instances[cls] @@ -73,8 +74,7 @@ def __init__(self, config:'_Config'=None): self._cookie_lock = threading.Lock() - self.config = config or _Config().from_dict(Config.config) - + self.config = config or Config.current self._set_session(self.config.session or requests.Session()) def _set_session(self, session): @@ -361,6 +361,7 @@ def _make_request(self, url, request_method, user_agent_headers=None, body=None, else: utils.get_yf_logger().debug(f'url={url}') utils.get_yf_logger().debug(f'params={params}') + utils.get_yf_logger().debug(f"{user_agent_headers=} {body=} {config=}, {request_method=}") proxy = self._get_proxy(config.proxy) if params is None: @@ -393,7 +394,7 @@ def _make_request(self, url, request_method, user_agent_headers=None, body=None, if body: request_args['json'] = body - + response = request_method(**request_args) utils.get_yf_logger().debug(f'response code={response.status_code}') if response.status_code >= 400: diff --git a/yfinance/multi.py b/yfinance/multi.py index 490189f1..f49ccf42 100644 --- a/yfinance/multi.py +++ b/yfinance/multi.py @@ -31,14 +31,14 @@ from . import Ticker, utils from .data import YfData -from . import shared +from . import shared, Config @utils.log_indent_decorator def download(tickers, start=None, end=None, actions=False, threads=True, ignore_tz=None, group_by='column', auto_adjust=True, back_adjust=False, repair=False, keepna=False, progress=True, period="max", interval="1d", - prepost=False, proxy=None, rounding=False, timeout=10, session=None, + prepost=False, rounding=False, config=None, multi_level_index=True) -> Union[_pd.DataFrame, None]: """ Download yahoo tickers @@ -79,20 +79,15 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_tz: bool When combining from different timezones, ignore that part of datetime. Default depends on interval. Intraday = False. Day+ = True. - proxy: str - Optional. Proxy server URL scheme. Default is None rounding: bool Optional. Round values to 2 decimal places? - timeout: None or float - If not None stops waiting for a response after given number of - seconds. (Can also be a fraction of a second e.g. 0.01) - session: None or Session - Optional. Pass your own session object to be used for all requests multi_level_index: bool Optional. Always return a MultiIndex DataFrame? Default is True """ logger = utils.get_yf_logger() + config = config or Config.current + if logger.isEnabledFor(logging.DEBUG): if threads: # With DEBUG, each thread generates a lot of log messages. @@ -122,7 +117,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, for ticker in tickers: if utils.is_isin(ticker): isin = ticker - ticker = utils.get_ticker_by_isin(ticker, proxy, session=session) + ticker = utils.get_ticker_by_isin(ticker, config) shared._ISINS[ticker] = isin _tickers_.append(ticker) @@ -139,7 +134,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, shared._TRACEBACKS = {} # Ensure data initialised with session. - YfData(session=session) + YfData(config) # download using threads if threads: @@ -151,8 +146,9 @@ def download(tickers, start=None, end=None, actions=False, threads=True, start=start, end=end, prepost=prepost, actions=actions, auto_adjust=auto_adjust, back_adjust=back_adjust, repair=repair, keepna=keepna, - progress=(progress and i > 0), proxy=proxy, - rounding=rounding, timeout=timeout) + progress=(progress and i > 0), + config=config, + rounding=rounding) while len(shared._DFS) < len(tickers): _time.sleep(0.01) # download synchronously @@ -162,8 +158,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, start=start, end=end, prepost=prepost, actions=actions, auto_adjust=auto_adjust, back_adjust=back_adjust, repair=repair, keepna=keepna, - proxy=proxy, - rounding=rounding, timeout=timeout) + rounding=rounding, config=config) if progress: shared._PROGRESS_BAR.animate() @@ -253,11 +248,12 @@ def _realign_dfs(): def _download_one_threaded(ticker, start=None, end=None, auto_adjust=False, back_adjust=False, repair=False, actions=False, progress=True, period="max", - interval="1d", prepost=False, proxy=None, - keepna=False, rounding=False, timeout=10): + interval="1d", prepost=False, + keepna=False, rounding=False, config=None): + config = config or Config.current _download_one(ticker, start, end, auto_adjust, back_adjust, repair, - actions, period, interval, prepost, proxy, rounding, - keepna, timeout) + actions, period, interval, prepost, rounding, + keepna, config) if progress: shared._PROGRESS_BAR.animate() @@ -265,16 +261,16 @@ def _download_one_threaded(ticker, start=None, end=None, def _download_one(ticker, start=None, end=None, auto_adjust=False, back_adjust=False, repair=False, actions=False, period="max", interval="1d", - prepost=False, proxy=None, rounding=False, - keepna=False, timeout=10): + prepost=False, rounding=False, + keepna=False, config=None): data = None try: data = Ticker(ticker).history( period=period, interval=interval, start=start, end=end, prepost=prepost, actions=actions, auto_adjust=auto_adjust, - back_adjust=back_adjust, repair=repair, proxy=proxy, - rounding=rounding, keepna=keepna, timeout=timeout, + back_adjust=back_adjust, repair=repair, + rounding=rounding, keepna=keepna, config=config, raise_errors=True ) except Exception as e: diff --git a/yfinance/scrapers/history.py b/yfinance/scrapers/history.py index e94a16bd..8167c17b 100644 --- a/yfinance/scrapers/history.py +++ b/yfinance/scrapers/history.py @@ -7,17 +7,16 @@ import time as _time import bisect -from yfinance import shared, utils +from yfinance import shared, utils, Config from yfinance.const import _BASE_URL_, _PRICE_COLNAMES_ from yfinance.exceptions import YFInvalidPeriodError, YFPricesMissingError, YFTzMissingError, YFRateLimitError class PriceHistory: - def __init__(self, data, ticker, tz, session=None, proxy=None): + def __init__(self, data, ticker, tz, config): + self.config = config or Config.current self._data = data self.ticker = ticker.upper() self.tz = tz - self.proxy = proxy - self.session = session self._history = None self._history_metadata = None @@ -30,8 +29,8 @@ def __init__(self, data, ticker, tz, session=None, proxy=None): def history(self, period="1mo", interval="1d", start=None, end=None, prepost=False, actions=True, auto_adjust=True, back_adjust=False, repair=False, keepna=False, - proxy=None, rounding=False, timeout=10, - raise_errors=False) -> pd.DataFrame: + proxy=None, rounding=False, + raise_errors=False, config=None) -> pd.DataFrame: """ :Parameters: period : str @@ -74,7 +73,8 @@ def history(self, period="1mo", interval="1d", If True, then raise errors as Exceptions instead of logging. """ logger = utils.get_yf_logger() - proxy = proxy or self.proxy + proxy = proxy or self.config.proxy + config = config or self.config interval_user = interval period_user = period @@ -175,8 +175,7 @@ def history(self, period="1mo", interval="1d", data = get_fn( url=url, params=params, - proxy=proxy, - timeout=timeout + config=config ) if "Will be right back" in data.text or data is None: raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" diff --git a/yfinance/ticker.py b/yfinance/ticker.py index a10c7980..7dfbbab2 100644 --- a/yfinance/ticker.py +++ b/yfinance/ticker.py @@ -23,6 +23,8 @@ from collections import namedtuple as _namedtuple from .scrapers.funds import FundsData +from .config import Config as _Config +from . import Config import pandas as _pd @@ -30,9 +32,11 @@ from .const import _BASE_URL_ + class Ticker(TickerBase): - def __init__(self, ticker, session=None, proxy=None): - super(Ticker, self).__init__(ticker, session=session, proxy=proxy) + def __init__(self, ticker, config:'_Config'=None): + self.config = config or Config.current + super(Ticker, self).__init__(ticker, config=config) self._expirations = {} self._underlying = {} @@ -45,7 +49,7 @@ def _download_options(self, date=None): else: url = f"{_BASE_URL_}/v7/finance/options/{self.ticker}?date={date}" - r = self._data.get(url=url, proxy=self.proxy).json() + r = self._data.get(url=url, config=self.config).json() if len(r.get('optionChain', {}).get('result', [])) > 0: for exp in r['optionChain']['result'][0]['expirationDates']: self._expirations[_pd.Timestamp(exp, unit='s').strftime('%Y-%m-%d')] = exp