docstr: :Parameters:
      period : str
          Valid periods: 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
          Either Use period parameter or use start and end
      interval : str
          Valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
          Intraday data cannot extend last 60 days
      start: str
          Download start date string (YYYY-MM-DD) or _datetime, inclusive.
          Default is 99 years ago
          E.g. for start="2020-01-01", the first data point will be on "2020-01-01"
      end: str
          Download end date string (YYYY-MM-DD) or _datetime, exclusive.
          Default is now
          E.g. for end="2023-01-01", the last data point will be on "2022-12-31"
      prepost : bool
          Include Pre and Post market data in results?
          Default is False
      auto_adjust: bool
          Adjust all OHLC automatically? Default is True
      back_adjust: bool
          Back-adjusted data to mimic true historical prices
      repair: bool
          Detect currency unit 100x mixups and attempt repair.
          Default is False
      keepna: bool
          Keep NaN rows returned by Yahoo?
          Default is False
      proxy: str
          Optional. Proxy server URL scheme. Default is None
      rounding: bool
          Round values to 2 decimal places?
          Optional. Default is False = precision suggested by Yahoo!
      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)
          Default is 10 seconds.
      raise_errors: bool
          If True, then raise errors as Exceptions instead of logging.
docstr_tok: [":","Parameters",":","period",":","str","Valid","periods",":","1d,5d,1mo,3mo,6mo,1y,2y,5y,10y",",","ytd",",","max","Either","Use","period","parameter","or","use","start","and","end","interval",":","str","Valid","intervals",":","1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo","Intraday","data","can","not","extend","last","60","days","start",":","str","Download","start","date","string","(","YYYY-MM-DD",")","or","_datetime",",","inclusive",".","Default","is","99","years","ago","E.g",".","for","start=","''","2020-01-01","''",",","the","first","data","point","will","be","on","``","2020-01-01","''","end",":","str","Download","end","date","string","(","YYYY-MM-DD",")","or","_datetime",",","exclusive",".","Default","is","now","E.g",".","for","end=","''","2023-01-01","''",",","the","last","data","point","will","be","on","``","2022-12-31","''","prepost",":","bool","Include","Pre","and","Post","market","data","in","results","?","Default","is","False","auto_adjust",":","bool","Adjust","all","OHLC","automatically","?","Default","is","True","back_adjust",":","bool","Back-adjusted","data","to","mimic","true","historical","prices","repair",":","bool","Detect","currency","unit","100x","mixups","and","attempt","repair",".","Default","is","False","keepna",":","bool","Keep","NaN","rows","returned","by","Yahoo","?","Default","is","False","proxy",":","str","Optional",".","Proxy","server","URL","scheme",".","Default","is","None","rounding",":","bool","Round","values","to","2","decimal","places","?","Optional",".","Default","is","False","=","precision","suggested","by","Yahoo","!","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",")","Default","is","10","seconds",".","raise_errors",":","bool","If","True",",","then","raise","errors","as","Exceptions","instead","of","logging","."]
code: 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:
      """
      :Parameters:
          period : str
              Valid periods: 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
              Either Use period parameter or use start and end
          interval : str
              Valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
              Intraday data cannot extend last 60 days
          start: str
              Download start date string (YYYY-MM-DD) or _datetime, inclusive.
              Default is 99 years ago
              E.g. for start="2020-01-01", the first data point will be on "2020-01-01"
          end: str
              Download end date string (YYYY-MM-DD) or _datetime, exclusive.
              Default is now
              E.g. for end="2023-01-01", the last data point will be on "2022-12-31"
          prepost : bool
              Include Pre and Post market data in results?
              Default is False
          auto_adjust: bool
              Adjust all OHLC automatically? Default is True
          back_adjust: bool
              Back-adjusted data to mimic true historical prices
          repair: bool
              Detect currency unit 100x mixups and attempt repair.
              Default is False
          keepna: bool
              Keep NaN rows returned by Yahoo?
              Default is False
          proxy: str
              Optional. Proxy server URL scheme. Default is None
          rounding: bool
              Round values to 2 decimal places?
              Optional. Default is False = precision suggested by Yahoo!
          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)
              Default is 10 seconds.
          raise_errors: bool
              If True, then raise errors as Exceptions instead of logging.
      """
      logger = utils.get_yf_logger()
      proxy = proxy or self.proxy
  
      start_user = start
      end_user = end
      if start or period is None or period.lower() == "max":
          # Check can get TZ. Fail => probably delisted
          tz = self._get_ticker_tz(proxy, timeout)
          if tz is None:
              # Every valid ticker has a timezone. Missing = problem
              err_msg = "No timezone found, symbol may be delisted"
              shared._DFS[self.ticker] = utils.empty_df()
              shared._ERRORS[self.ticker] = err_msg
              if raise_errors:
                  raise Exception(f"{self.ticker}: {err_msg}")
              else:
                  logger.error(f"{self.ticker}: {err_msg}")
              return utils.empty_df()
  
          if end is None:
              end = int(_time.time())
          else:
              end = utils._parse_user_dt(end, tz)
          if start is None:
              if interval == "1m":
                  start = end - 604800  # Subtract 7 days
              else:
                  max_start_datetime = pd.Timestamp.utcnow().floor(
                      "D"
                  ) - _datetime.timedelta(days=99 * 365)
                  start = int(max_start_datetime.timestamp())
          else:
              start = utils._parse_user_dt(start, tz)
          params = {"period1": start, "period2": end}
      else:
          period = period.lower()
          params = {"range": period}
  
      params["interval"] = interval.lower()
      params["includePrePost"] = prepost
  
      # 1) fix weired bug with Yahoo! - returning 60m for 30m bars
      if params["interval"] == "30m":
          params["interval"] = "15m"
  
      # if the ticker is MUTUALFUND or ETF, then get capitalGains events
      params["events"] = "div,splits,capitalGains"
  
      params_pretty = dict(params)
      tz = self._get_ticker_tz(proxy, timeout)
      for k in ["period1", "period2"]:
          if k in params_pretty:
              params_pretty[k] = str(
                  pd.Timestamp(params[k], unit="s")
                  .tz_localize("UTC")
                  .tz_convert(tz)
              )
      logger.debug(
          f"{self.ticker}: Yahoo GET parameters: {str(params_pretty)}"
      )
  
      # Getting data from json
      url = f"{self._base_url}/v8/finance/chart/{self.ticker}"
      data = None
      get_fn = self._data.get
      if end is not None:
          end_dt = pd.Timestamp(end, unit="s").tz_localize("UTC")
          dt_now = pd.Timestamp.utcnow()
          data_delay = _datetime.timedelta(minutes=30)
          if end_dt + data_delay <= dt_now:
              # Date range in past so safe to fetch through cache:
              get_fn = self._data.cache_get
      try:
          data = get_fn(
              url=url, params=params, proxy=proxy, timeout=timeout
          )
          if "Will be right back" in data.text or data is None:
              raise RuntimeError(
                  "*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n"
                  "Our engineers are working quickly to resolve "
                  "the issue. Thank you for your patience."
              )
  
          data = data.json()
      except Exception:
          if raise_errors:
              raise
  
      # Store the meta data that gets retrieved simultaneously
      try:
          self._history_metadata = data["chart"]["result"][0]["meta"]
      except Exception:
          self._history_metadata = {}
  
      intraday = params["interval"][-1] in ("m", "h")
      err_msg = "No price data found, symbol may be delisted"
      if start or period is None or period.lower() == "max":
          err_msg += f' ({params["interval"]} '
          if start_user is not None:
              err_msg += f"{start_user}"
          elif not intraday:
              err_msg += f'{pd.Timestamp(start, unit="s").tz_localize("UTC").tz_convert(tz).date()}'
          else:
              err_msg += f'{pd.Timestamp(start, unit="s").tz_localize("UTC").tz_convert(tz)}'
          err_msg += " -> "
          if end_user is not None:
              err_msg += f"{end_user})"
          elif not intraday:
              err_msg += f'{pd.Timestamp(end, unit="s").tz_localize("UTC").tz_convert(tz).date()})'
          else:
              err_msg += f'{pd.Timestamp(end, unit="s").tz_localize("UTC").tz_convert(tz)})'
      else:
          err_msg += f" (period={period})"
  
      fail = False
      if data is None or not isinstance(data, dict):
          fail = True
      elif isinstance(data, dict) and "status_code" in data:
          err_msg += f"(Yahoo status_code = {data['status_code']})"
          fail = True
      elif "chart" in data and data["chart"]["error"]:
          err_msg = data["chart"]["error"]["description"]
          fail = True
      elif (
          "chart" not in data
          or data["chart"]["result"] is None
          or not data["chart"]["result"]
      ):
          fail = True
      elif (
          period is not None
          and "timestamp" not in data["chart"]["result"][0]
          and period not in self._history_metadata["validRanges"]
      ):
          # User provided a bad period. The minimum should be '1d', but sometimes Yahoo accepts '1h'.
          err_msg = f"Period '{period}' is invalid, must be one of {self._history_metadata['validRanges']}"
          fail = True
      if fail:
          shared._DFS[self.ticker] = utils.empty_df()
          shared._ERRORS[self.ticker] = err_msg
          if raise_errors:
              raise Exception(f"{self.ticker}: {err_msg}")
          else:
              logger.error(f"{self.ticker}: {err_msg}")
          if (
              self._reconstruct_start_interval is not None
              and self._reconstruct_start_interval == interval
          ):
              self._reconstruct_start_interval = None
          return utils.empty_df()
  
      # parse quotes
      try:
          quotes = utils.parse_quotes(data["chart"]["result"][0])
          # Yahoo bug fix - it often appends latest price even if after end date
          if end and not quotes.empty:
              endDt = pd.to_datetime(
                  _datetime.datetime.utcfromtimestamp(end)
              )
              if quotes.index[quotes.shape[0] - 1] >= endDt:
                  quotes = quotes.iloc[0 : quotes.shape[0] - 1]
      except Exception:
          shared._DFS[self.ticker] = utils.empty_df()
          shared._ERRORS[self.ticker] = err_msg
          if raise_errors:
              raise Exception(f"{self.ticker}: {err_msg}")
          else:
              logger.error(f"{self.ticker}: {err_msg}")
          if (
              self._reconstruct_start_interval is not None
              and self._reconstruct_start_interval == interval
          ):
              self._reconstruct_start_interval = None
          return shared._DFS[self.ticker]
      logger.debug(
          f"{self.ticker}: yfinance received OHLC data: {quotes.index[0]} -> {quotes.index[-1]}"
      )
  
      # 2) fix weired bug with Yahoo! - returning 60m for 30m bars
      if interval.lower() == "30m":
          logger.debug(f"{self.ticker}: resampling 30m OHLC from 15m")
          quotes2 = quotes.resample("30T")
          quotes = pd.DataFrame(
              index=quotes2.last().index,
              data={
                  "Open": quotes2["Open"].first(),
                  "High": quotes2["High"].max(),
                  "Low": quotes2["Low"].min(),
                  "Close": quotes2["Close"].last(),
                  "Adj Close": quotes2["Adj Close"].last(),
                  "Volume": quotes2["Volume"].sum(),
              },
          )
          try:
              quotes["Dividends"] = quotes2["Dividends"].max()
              quotes["Stock Splits"] = quotes2["Stock Splits"].max()
          except Exception:
              pass
  
      # Select useful info from metadata
      quote_type = self._history_metadata["instrumentType"]
      expect_capital_gains = quote_type in ("MUTUALFUND", "ETF")
      tz_exchange = self._history_metadata["exchangeTimezoneName"]
  
      # Note: ordering is important. If you change order, run the tests!
      quotes = utils.set_df_tz(quotes, params["interval"], tz_exchange)
      quotes = utils.fix_Yahoo_dst_issue(quotes, params["interval"])
      quotes = utils.fix_Yahoo_returning_live_separate(
          quotes, params["interval"], tz_exchange
      )
      intraday = params["interval"][-1] in ("m", "h")
      if (
          not prepost
          and intraday
          and "tradingPeriods" in self._history_metadata
      ):
          tps = self._history_metadata["tradingPeriods"]
          if not isinstance(tps, pd.DataFrame):
              self._history_metadata = utils.format_history_metadata(
                  self._history_metadata, tradingPeriodsOnly=True
              )
              tps = self._history_metadata["tradingPeriods"]
          quotes = utils.fix_Yahoo_returning_prepost_unrequested(
              quotes, params["interval"], tps
          )
      logger.debug(
          f"{self.ticker}: OHLC after cleaning: {quotes.index[0]} -> {quotes.index[-1]}"
      )
  
      # actions
      dividends, splits, capital_gains = utils.parse_actions(
          data["chart"]["result"][0]
      )
      if not expect_capital_gains:
          capital_gains = None
  
      if splits is not None:
          splits = utils.set_df_tz(splits, interval, tz_exchange)
      if dividends is not None:
          dividends = utils.set_df_tz(dividends, interval, tz_exchange)
      if capital_gains is not None:
          capital_gains = utils.set_df_tz(
              capital_gains, interval, tz_exchange
          )
      if start is not None:
          if not quotes.empty:
              startDt = quotes.index[0].floor("D")
              if dividends is not None:
                  dividends = dividends.loc[startDt:]
              if capital_gains is not None:
                  capital_gains = capital_gains.loc[startDt:]
              if splits is not None:
                  splits = splits.loc[startDt:]
      if end is not None:
          endDt = pd.Timestamp(end, unit="s").tz_localize(tz)
          if dividends is not None:
              dividends = dividends[dividends.index < endDt]
          if capital_gains is not None:
              capital_gains = capital_gains[capital_gains.index < endDt]
          if splits is not None:
              splits = splits[splits.index < endDt]
  
      # Prepare for combine
      intraday = params["interval"][-1] in ("m", "h")
      if not intraday:
          # If localizing a midnight during DST transition hour when clocks roll back,
          # meaning clock hits midnight twice, then use the 2nd (ambiguous=True)
          quotes.index = pd.to_datetime(quotes.index.date).tz_localize(
              tz_exchange, ambiguous=True, nonexistent="shift_forward"
          )
          if dividends.shape[0] > 0:
              dividends.index = pd.to_datetime(
                  dividends.index.date
              ).tz_localize(
                  tz_exchange,
                  ambiguous=True,
                  nonexistent="shift_forward",
              )
          if splits.shape[0] > 0:
              splits.index = pd.to_datetime(
                  splits.index.date
              ).tz_localize(
                  tz_exchange,
                  ambiguous=True,
                  nonexistent="shift_forward",
              )
  
      # Combine
      df = quotes.sort_index()
      if dividends.shape[0] > 0:
          df = utils.safe_merge_dfs(df, dividends, interval)
      if "Dividends" in df.columns:
          df.loc[df["Dividends"].isna(), "Dividends"] = 0
      else:
          df["Dividends"] = 0.0
      if splits.shape[0] > 0:
          df = utils.safe_merge_dfs(df, splits, interval)
      if "Stock Splits" in df.columns:
          df.loc[df["Stock Splits"].isna(), "Stock Splits"] = 0
      else:
          df["Stock Splits"] = 0.0
      if expect_capital_gains:
          if capital_gains.shape[0] > 0:
              df = utils.safe_merge_dfs(df, capital_gains, interval)
          if "Capital Gains" in df.columns:
              df.loc[df["Capital Gains"].isna(), "Capital Gains"] = 0
          else:
              df["Capital Gains"] = 0.0
      logger.debug(
          f"{self.ticker}: OHLC after combining events: {quotes.index[0]} -> {quotes.index[-1]}"
      )
  
      df = df[
          ~df.index.duplicated(keep="first")
      ]  # must do before repair
  
      if repair:
          # Do this before auto/back adjust
          logger.debug(f"{self.ticker}: checking OHLC for repairs ...")
          df = self._fix_unit_mixups(df, interval, tz_exchange, prepost)
          df = self._fix_bad_stock_split(df, interval, tz_exchange)
          # Must repair 100x and split errors before price reconstruction
          df = self._fix_zeroes(df, interval, tz_exchange, prepost)
          df = self._fix_missing_div_adjust(df, interval, tz_exchange)
          df = df.sort_index()
  
      # Auto/back adjust
      try:
          if auto_adjust:
              df = utils.auto_adjust(df)
          elif back_adjust:
              df = utils.back_adjust(df)
      except Exception as e:
          if auto_adjust:
              err_msg = "auto_adjust failed with %s" % e
          else:
              err_msg = "back_adjust failed with %s" % e
          shared._DFS[self.ticker] = utils.empty_df()
          shared._ERRORS[self.ticker] = err_msg
          if raise_errors:
              raise Exception("%s: %s" % (self.ticker, err_msg))
          else:
              logger.error("%s: %s" % (self.ticker, err_msg))
  
      if rounding:
          df = np.round(
              df, data["chart"]["result"][0]["meta"]["priceHint"]
          )
      df["Volume"] = df["Volume"].fillna(0).astype(np.int64)
  
      if intraday:
          df.index.name = "Datetime"
      else:
          df.index.name = "Date"
  
      self._history = df.copy()
  
      # missing rows cleanup
      if not actions:
          df = df.drop(
              columns=["Dividends", "Stock Splits", "Capital Gains"],
              errors="ignore",
          )
      if not keepna:
          mask_nan_or_zero = (df.isna() | (df == 0)).all(axis=1)
          df = df.drop(mask_nan_or_zero.index[mask_nan_or_zero])
  
      logger.debug(
          f"{self.ticker}: yfinance returning OHLC: {df.index[0]} -> {df.index[-1]}"
      )
  
      if (
          self._reconstruct_start_interval is not None
          and self._reconstruct_start_interval == interval
      ):
          self._reconstruct_start_interval = None
      return df
  
imports: from __future__ import print_function
  import datetime
  from io import StringIO
  import json
  import logging
  import time
  import warnings
  from typing import Optional
  from urllib.parse import quote
  import dateutil
  import numpy
  import pandas
  import requests
  from .None import shared, utils, cache
  from .data import YfData
  from .scrapers.analysis import Analysis
  from .scrapers.fundamentals import Fundamentals
  from .scrapers.holders import Holders
  from .scrapers.quote import Quote, FastInfo
  from .const import _BASE_URL_, _ROOT_URL_
label_desc: Use image node_id 2 for calling the TickerBase obj's underlying member method code with example usage: obj.history(period, interval, start, end, prepost, actions, auto_adjust, back_adjust, repair, keepna, proxy, rounding, timeout, raise_errors) and returns: df, utils, utils, shared