Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 7 additions & 121 deletions tests/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,132 +126,18 @@ def test_goodTicker(self):
for attribute_name, attribute_type in ticker_attributes:
assert_attribute_type(self, dat, attribute_name, attribute_type)

#TODO:: Refactor with `assert_attribute` once proxy is accepted as a parameter of `Ticker`
def test_goodTicker_withProxy(self):
# that yfinance works when full api is called on same instance of ticker

tkr = "IBM"
dat = yf.Ticker(tkr, session=self.session)

dat._fetch_ticker_tz(proxy=self.proxy, timeout=5)
dat._get_ticker_tz(proxy=self.proxy, timeout=5)
dat.history(period="1wk", proxy=self.proxy)

v = dat.get_major_holders(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_institutional_holders(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_mutualfund_holders(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_info(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertTrue(len(v) > 0)

v = dat.get_income_stmt(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_incomestmt(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_financials(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_balance_sheet(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_balancesheet(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_cash_flow(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_cashflow(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_shares_full(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

v = dat.get_isin(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertTrue(v != "")

v = dat.get_news(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertTrue(len(v) > 0)
dat = yf.Ticker(tkr, session=self.session, proxy=self.proxy)

v = dat.get_earnings_dates(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertFalse(v.empty)

dat.get_history_metadata(proxy=self.proxy)
self.assertIsNotNone(v)
self.assertTrue(len(v) > 0)

# Below will fail because not ported to Yahoo API

# v = dat.stats(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertTrue(len(v) > 0)

# v = dat.get_recommendations(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_calendar(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_sustainability(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_recommendations_summary(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_analyst_price_target(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_rev_forecast(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_earnings_forecast(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_trend_details(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_earnings_trend(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_earnings(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)

# v = dat.get_shares(proxy=self.proxy)
# self.assertIsNotNone(v)
# self.assertFalse(v.empty)
dat._fetch_ticker_tz(timeout=5)
dat._get_ticker_tz(timeout=5)
dat.history(period="1wk")

for attribute_name, attribute_type in ticker_attributes:
assert_attribute_type(self, dat, attribute_name, attribute_type)


class TestTickerHistory(unittest.TestCase):
session = None

Expand Down
51 changes: 27 additions & 24 deletions yfinance/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@


class TickerBase:
def __init__(self, ticker, session=None):
def __init__(self, ticker, session=None, proxy=None):
self.ticker = ticker.upper()
self.proxy = proxy
self.session = session
self._history = None
self._history_metadata = None
Expand Down Expand Up @@ -132,6 +133,7 @@ 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

if debug is not None:
if debug:
Expand Down Expand Up @@ -1638,7 +1640,8 @@ def map_signals_to_ranges(f, f_up, f_down):

return df2

def _get_ticker_tz(self, proxy, timeout):
def _get_ticker_tz(self,timeout, proxy=None):
proxy = proxy or self.proxy
if self._tz is not None:
return self._tz
cache = utils.get_tz_cache()
Expand All @@ -1662,9 +1665,9 @@ def _get_ticker_tz(self, proxy, timeout):
return tz

@utils.log_indent_decorator
def _fetch_ticker_tz(self, proxy, timeout):
def _fetch_ticker_tz(self, timeout, proxy=None):
# Query Yahoo for fast price data just to get returned timezone

proxy = proxy or self.proxy
logger = utils.get_yf_logger()

params = {"range": "1d", "interval": "1d"}
Expand Down Expand Up @@ -1695,44 +1698,44 @@ def _fetch_ticker_tz(self, proxy, timeout):
return None

def get_recommendations(self, proxy=None, as_dict=False):
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
data = self._quote.recommendations
if as_dict:
return data.to_dict()
return data

def get_calendar(self, proxy=None, as_dict=False):
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
data = self._quote.calendar
if as_dict:
return data.to_dict()
return data

def get_major_holders(self, proxy=None, as_dict=False):
self._holders.proxy = proxy
self._holders.proxy = proxy or self.proxy
data = self._holders.major
if as_dict:
return data.to_dict()
return data

def get_institutional_holders(self, proxy=None, as_dict=False):
self._holders.proxy = proxy
self._holders.proxy = proxy or self.proxy
data = self._holders.institutional
if data is not None:
if as_dict:
return data.to_dict()
return data

def get_mutualfund_holders(self, proxy=None, as_dict=False):
self._holders.proxy = proxy
self._holders.proxy = proxy or self.proxy
data = self._holders.mutualfund
if data is not None:
if as_dict:
return data.to_dict()
return data

def get_info(self, proxy=None) -> dict:
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
data = self._quote.info
return data

Expand All @@ -1747,49 +1750,49 @@ def basic_info(self):
return self.fast_info

def get_sustainability(self, proxy=None, as_dict=False):
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
data = self._quote.sustainability
if as_dict:
return data.to_dict()
return data

def get_recommendations_summary(self, proxy=None, as_dict=False):
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
data = self._quote.recommendations
if as_dict:
return data.to_dict()
return data

def get_analyst_price_target(self, proxy=None, as_dict=False):
self._analysis.proxy = proxy
self._analysis.proxy = proxy or self.proxy
data = self._analysis.analyst_price_target
if as_dict:
return data.to_dict()
return data

def get_rev_forecast(self, proxy=None, as_dict=False):
self._analysis.proxy = proxy
self._analysis.proxy = proxy or self.proxy
data = self._analysis.rev_est
if as_dict:
return data.to_dict()
return data

def get_earnings_forecast(self, proxy=None, as_dict=False):
self._analysis.proxy = proxy
self._analysis.proxy = proxy or self.proxy
data = self._analysis.eps_est
if as_dict:
return data.to_dict()
return data

def get_trend_details(self, proxy=None, as_dict=False):
self._analysis.proxy = proxy
self._analysis.proxy = proxy or self.proxy
data = self._analysis.analyst_trend_details
if as_dict:
return data.to_dict()
return data

def get_earnings_trend(self, proxy=None, as_dict=False):
self._analysis.proxy = proxy
self._analysis.proxy = proxy or self.proxy
data = self._analysis.earnings_trend
if as_dict:
return data.to_dict()
Expand All @@ -1808,7 +1811,7 @@ def get_earnings(self, proxy=None, as_dict=False, freq="yearly"):
Optional. Proxy server URL scheme
Default is None
"""
self._fundamentals.proxy = proxy
self._fundamentals.proxy = proxy or self.proxy
data = self._fundamentals.earnings[freq]
if as_dict:
dict_data = data.to_dict()
Expand All @@ -1833,7 +1836,7 @@ def get_income_stmt(self, proxy=None, as_dict=False, pretty=False, freq="yearly"
Optional. Proxy server URL scheme
Default is None
"""
self._fundamentals.proxy = proxy
self._fundamentals.proxy = proxy or self.proxy

data = self._fundamentals.financials.get_income_time_series(freq=freq, proxy=proxy)

Expand Down Expand Up @@ -1866,7 +1869,7 @@ def get_balance_sheet(self, proxy=None, as_dict=False, pretty=False, freq="yearl
Optional. Proxy server URL scheme
Default is None
"""
self._fundamentals.proxy = proxy
self._fundamentals.proxy = proxy or self.proxy

data = self._fundamentals.financials.get_balance_sheet_time_series(freq=freq, proxy=proxy)

Expand Down Expand Up @@ -1896,7 +1899,7 @@ def get_cash_flow(self, proxy=None, as_dict=False, pretty=False, freq="yearly"):
Optional. Proxy server URL scheme
Default is None
"""
self._fundamentals.proxy = proxy
self._fundamentals.proxy = proxy or self.proxy

data = self._fundamentals.financials.get_cash_flow_time_series(freq=freq, proxy=proxy)

Expand Down Expand Up @@ -1946,7 +1949,7 @@ def get_actions(self, proxy=None):
return []

def get_shares(self, proxy=None, as_dict=False):
self._fundamentals.proxy = proxy
self._fundamentals.proxy = proxy or self.proxy
data = self._fundamentals.shares
if as_dict:
return data.to_dict()
Expand Down Expand Up @@ -2020,7 +2023,7 @@ def get_isin(self, proxy=None) -> Optional[str]:

q = ticker

self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
if self._quote.info is None:
# Don't print error message cause self._quote.info will print one
return None
Expand Down Expand Up @@ -2141,7 +2144,7 @@ def get_earnings_dates(self, limit=12, proxy=None) -> Optional[pd.DataFrame]:
dates[cn] = dates[cn] + ' ' + tzinfo["AM/PM"]
dates[cn] = pd.to_datetime(dates[cn], format="%b %d, %Y, %I %p")
# - instead of attempting decoding of ambiguous timezone abbreviation, just use 'info':
self._quote.proxy = proxy
self._quote.proxy = proxy or self.proxy
tz = self._get_ticker_tz(proxy=proxy, timeout=30)
dates[cn] = dates[cn].dt.tz_localize(tz)

Expand Down
14 changes: 7 additions & 7 deletions yfinance/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@


class Ticker(TickerBase):
def __init__(self, ticker, session=None):
super(Ticker, self).__init__(ticker, session=session)
def __init__(self, ticker, session=None, proxy=None):
super(Ticker, self).__init__(ticker, session=session, proxy=proxy)
self._expirations = {}
self._underlying = {}

def __repr__(self):
return f'yfinance.Ticker object <{self.ticker}>'

def _download_options(self, date=None, proxy=None):
def _download_options(self, date=None):
if date is None:
url = f"{self._base_url}/v7/finance/options/{self.ticker}"
else:
url = f"{self._base_url}/v7/finance/options/{self.ticker}?date={date}"

r = self._data.get(url=url, proxy=proxy).json()
r = self._data.get(url=url, proxy=self.proxy).json()
if len(r.get('optionChain', {}).get('result', [])) > 0:
for exp in r['optionChain']['result'][0]['expirationDates']:
self._expirations[_datetime.datetime.utcfromtimestamp(
Expand Down Expand Up @@ -80,9 +80,9 @@ def _options2df(self, opt, tz=None):
data['lastTradeDate'] = data['lastTradeDate'].dt.tz_convert(tz)
return data

def option_chain(self, date=None, proxy=None, tz=None):
def option_chain(self, date=None, tz=None):
if date is None:
options = self._download_options(proxy=proxy)
options = self._download_options()
else:
if not self._expirations:
self._download_options()
Expand All @@ -91,7 +91,7 @@ def option_chain(self, date=None, proxy=None, tz=None):
f"Expiration `{date}` cannot be found. "
f"Available expirations are: [{', '.join(self._expirations)}]")
date = self._expirations[date]
options = self._download_options(date, proxy=proxy)
options = self._download_options(date)

return _namedtuple('Options', ['calls', 'puts', 'underlying'])(**{
"calls": self._options2df(options['calls'], tz=tz),
Expand Down