Skip to content

Commit 7432d29

Browse files
authored
Merge pull request #1711 from rickturner2001/refactor/ticker-proxy
Refactor/ticker proxy
2 parents 7da64b6 + d607c43 commit 7432d29

File tree

3 files changed

+41
-152
lines changed

3 files changed

+41
-152
lines changed

tests/ticker.py

Lines changed: 7 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -126,132 +126,18 @@ def test_goodTicker(self):
126126
for attribute_name, attribute_type in ticker_attributes:
127127
assert_attribute_type(self, dat, attribute_name, attribute_type)
128128

129-
#TODO:: Refactor with `assert_attribute` once proxy is accepted as a parameter of `Ticker`
130129
def test_goodTicker_withProxy(self):
131-
# that yfinance works when full api is called on same instance of ticker
132-
133130
tkr = "IBM"
134-
dat = yf.Ticker(tkr, session=self.session)
135-
136-
dat._fetch_ticker_tz(proxy=self.proxy, timeout=5)
137-
dat._get_ticker_tz(proxy=self.proxy, timeout=5)
138-
dat.history(period="1wk", proxy=self.proxy)
139-
140-
v = dat.get_major_holders(proxy=self.proxy)
141-
self.assertIsNotNone(v)
142-
self.assertFalse(v.empty)
143-
144-
v = dat.get_institutional_holders(proxy=self.proxy)
145-
self.assertIsNotNone(v)
146-
self.assertFalse(v.empty)
147-
148-
v = dat.get_mutualfund_holders(proxy=self.proxy)
149-
self.assertIsNotNone(v)
150-
self.assertFalse(v.empty)
151-
152-
v = dat.get_info(proxy=self.proxy)
153-
self.assertIsNotNone(v)
154-
self.assertTrue(len(v) > 0)
155-
156-
v = dat.get_income_stmt(proxy=self.proxy)
157-
self.assertIsNotNone(v)
158-
self.assertFalse(v.empty)
159-
160-
v = dat.get_incomestmt(proxy=self.proxy)
161-
self.assertIsNotNone(v)
162-
self.assertFalse(v.empty)
163-
164-
v = dat.get_financials(proxy=self.proxy)
165-
self.assertIsNotNone(v)
166-
self.assertFalse(v.empty)
167-
168-
v = dat.get_balance_sheet(proxy=self.proxy)
169-
self.assertIsNotNone(v)
170-
self.assertFalse(v.empty)
171-
172-
v = dat.get_balancesheet(proxy=self.proxy)
173-
self.assertIsNotNone(v)
174-
self.assertFalse(v.empty)
175-
176-
v = dat.get_cash_flow(proxy=self.proxy)
177-
self.assertIsNotNone(v)
178-
self.assertFalse(v.empty)
179-
180-
v = dat.get_cashflow(proxy=self.proxy)
181-
self.assertIsNotNone(v)
182-
self.assertFalse(v.empty)
183-
184-
v = dat.get_shares_full(proxy=self.proxy)
185-
self.assertIsNotNone(v)
186-
self.assertFalse(v.empty)
187-
188-
v = dat.get_isin(proxy=self.proxy)
189-
self.assertIsNotNone(v)
190-
self.assertTrue(v != "")
191-
192-
v = dat.get_news(proxy=self.proxy)
193-
self.assertIsNotNone(v)
194-
self.assertTrue(len(v) > 0)
131+
dat = yf.Ticker(tkr, session=self.session, proxy=self.proxy)
195132

196-
v = dat.get_earnings_dates(proxy=self.proxy)
197-
self.assertIsNotNone(v)
198-
self.assertFalse(v.empty)
199-
200-
dat.get_history_metadata(proxy=self.proxy)
201-
self.assertIsNotNone(v)
202-
self.assertTrue(len(v) > 0)
203-
204-
# Below will fail because not ported to Yahoo API
205-
206-
# v = dat.stats(proxy=self.proxy)
207-
# self.assertIsNotNone(v)
208-
# self.assertTrue(len(v) > 0)
209-
210-
# v = dat.get_recommendations(proxy=self.proxy)
211-
# self.assertIsNotNone(v)
212-
# self.assertFalse(v.empty)
213-
214-
# v = dat.get_calendar(proxy=self.proxy)
215-
# self.assertIsNotNone(v)
216-
# self.assertFalse(v.empty)
217-
218-
# v = dat.get_sustainability(proxy=self.proxy)
219-
# self.assertIsNotNone(v)
220-
# self.assertFalse(v.empty)
221-
222-
# v = dat.get_recommendations_summary(proxy=self.proxy)
223-
# self.assertIsNotNone(v)
224-
# self.assertFalse(v.empty)
225-
226-
# v = dat.get_analyst_price_target(proxy=self.proxy)
227-
# self.assertIsNotNone(v)
228-
# self.assertFalse(v.empty)
229-
230-
# v = dat.get_rev_forecast(proxy=self.proxy)
231-
# self.assertIsNotNone(v)
232-
# self.assertFalse(v.empty)
233-
234-
# v = dat.get_earnings_forecast(proxy=self.proxy)
235-
# self.assertIsNotNone(v)
236-
# self.assertFalse(v.empty)
237-
238-
# v = dat.get_trend_details(proxy=self.proxy)
239-
# self.assertIsNotNone(v)
240-
# self.assertFalse(v.empty)
241-
242-
# v = dat.get_earnings_trend(proxy=self.proxy)
243-
# self.assertIsNotNone(v)
244-
# self.assertFalse(v.empty)
245-
246-
# v = dat.get_earnings(proxy=self.proxy)
247-
# self.assertIsNotNone(v)
248-
# self.assertFalse(v.empty)
249-
250-
# v = dat.get_shares(proxy=self.proxy)
251-
# self.assertIsNotNone(v)
252-
# self.assertFalse(v.empty)
133+
dat._fetch_ticker_tz(timeout=5)
134+
dat._get_ticker_tz(timeout=5)
135+
dat.history(period="1wk")
253136

137+
for attribute_name, attribute_type in ticker_attributes:
138+
assert_attribute_type(self, dat, attribute_name, attribute_type)
254139

140+
255141
class TestTickerHistory(unittest.TestCase):
256142
session = None
257143

yfinance/base.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@
4646

4747

4848
class TickerBase:
49-
def __init__(self, ticker, session=None):
49+
def __init__(self, ticker, session=None, proxy=None):
5050
self.ticker = ticker.upper()
51+
self.proxy = proxy
5152
self.session = session
5253
self._history = None
5354
self._history_metadata = None
@@ -132,6 +133,7 @@ def history(self, period="1mo", interval="1d",
132133
If True, then raise errors as Exceptions instead of logging.
133134
"""
134135
logger = utils.get_yf_logger()
136+
proxy = proxy or self.proxy
135137

136138
if debug is not None:
137139
if debug:
@@ -1638,7 +1640,8 @@ def map_signals_to_ranges(f, f_up, f_down):
16381640

16391641
return df2
16401642

1641-
def _get_ticker_tz(self, proxy, timeout):
1643+
def _get_ticker_tz(self,timeout, proxy=None):
1644+
proxy = proxy or self.proxy
16421645
if self._tz is not None:
16431646
return self._tz
16441647
cache = utils.get_tz_cache()
@@ -1662,9 +1665,9 @@ def _get_ticker_tz(self, proxy, timeout):
16621665
return tz
16631666

16641667
@utils.log_indent_decorator
1665-
def _fetch_ticker_tz(self, proxy, timeout):
1668+
def _fetch_ticker_tz(self, timeout, proxy=None):
16661669
# Query Yahoo for fast price data just to get returned timezone
1667-
1670+
proxy = proxy or self.proxy
16681671
logger = utils.get_yf_logger()
16691672

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

16971700
def get_recommendations(self, proxy=None, as_dict=False):
1698-
self._quote.proxy = proxy
1701+
self._quote.proxy = proxy or self.proxy
16991702
data = self._quote.recommendations
17001703
if as_dict:
17011704
return data.to_dict()
17021705
return data
17031706

17041707
def get_calendar(self, proxy=None, as_dict=False):
1705-
self._quote.proxy = proxy
1708+
self._quote.proxy = proxy or self.proxy
17061709
data = self._quote.calendar
17071710
if as_dict:
17081711
return data.to_dict()
17091712
return data
17101713

17111714
def get_major_holders(self, proxy=None, as_dict=False):
1712-
self._holders.proxy = proxy
1715+
self._holders.proxy = proxy or self.proxy
17131716
data = self._holders.major
17141717
if as_dict:
17151718
return data.to_dict()
17161719
return data
17171720

17181721
def get_institutional_holders(self, proxy=None, as_dict=False):
1719-
self._holders.proxy = proxy
1722+
self._holders.proxy = proxy or self.proxy
17201723
data = self._holders.institutional
17211724
if data is not None:
17221725
if as_dict:
17231726
return data.to_dict()
17241727
return data
17251728

17261729
def get_mutualfund_holders(self, proxy=None, as_dict=False):
1727-
self._holders.proxy = proxy
1730+
self._holders.proxy = proxy or self.proxy
17281731
data = self._holders.mutualfund
17291732
if data is not None:
17301733
if as_dict:
17311734
return data.to_dict()
17321735
return data
17331736

17341737
def get_info(self, proxy=None) -> dict:
1735-
self._quote.proxy = proxy
1738+
self._quote.proxy = proxy or self.proxy
17361739
data = self._quote.info
17371740
return data
17381741

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

17491752
def get_sustainability(self, proxy=None, as_dict=False):
1750-
self._quote.proxy = proxy
1753+
self._quote.proxy = proxy or self.proxy
17511754
data = self._quote.sustainability
17521755
if as_dict:
17531756
return data.to_dict()
17541757
return data
17551758

17561759
def get_recommendations_summary(self, proxy=None, as_dict=False):
1757-
self._quote.proxy = proxy
1760+
self._quote.proxy = proxy or self.proxy
17581761
data = self._quote.recommendations
17591762
if as_dict:
17601763
return data.to_dict()
17611764
return data
17621765

17631766
def get_analyst_price_target(self, proxy=None, as_dict=False):
1764-
self._analysis.proxy = proxy
1767+
self._analysis.proxy = proxy or self.proxy
17651768
data = self._analysis.analyst_price_target
17661769
if as_dict:
17671770
return data.to_dict()
17681771
return data
17691772

17701773
def get_rev_forecast(self, proxy=None, as_dict=False):
1771-
self._analysis.proxy = proxy
1774+
self._analysis.proxy = proxy or self.proxy
17721775
data = self._analysis.rev_est
17731776
if as_dict:
17741777
return data.to_dict()
17751778
return data
17761779

17771780
def get_earnings_forecast(self, proxy=None, as_dict=False):
1778-
self._analysis.proxy = proxy
1781+
self._analysis.proxy = proxy or self.proxy
17791782
data = self._analysis.eps_est
17801783
if as_dict:
17811784
return data.to_dict()
17821785
return data
17831786

17841787
def get_trend_details(self, proxy=None, as_dict=False):
1785-
self._analysis.proxy = proxy
1788+
self._analysis.proxy = proxy or self.proxy
17861789
data = self._analysis.analyst_trend_details
17871790
if as_dict:
17881791
return data.to_dict()
17891792
return data
17901793

17911794
def get_earnings_trend(self, proxy=None, as_dict=False):
1792-
self._analysis.proxy = proxy
1795+
self._analysis.proxy = proxy or self.proxy
17931796
data = self._analysis.earnings_trend
17941797
if as_dict:
17951798
return data.to_dict()
@@ -1808,7 +1811,7 @@ def get_earnings(self, proxy=None, as_dict=False, freq="yearly"):
18081811
Optional. Proxy server URL scheme
18091812
Default is None
18101813
"""
1811-
self._fundamentals.proxy = proxy
1814+
self._fundamentals.proxy = proxy or self.proxy
18121815
data = self._fundamentals.earnings[freq]
18131816
if as_dict:
18141817
dict_data = data.to_dict()
@@ -1833,7 +1836,7 @@ def get_income_stmt(self, proxy=None, as_dict=False, pretty=False, freq="yearly"
18331836
Optional. Proxy server URL scheme
18341837
Default is None
18351838
"""
1836-
self._fundamentals.proxy = proxy
1839+
self._fundamentals.proxy = proxy or self.proxy
18371840

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

@@ -1866,7 +1869,7 @@ def get_balance_sheet(self, proxy=None, as_dict=False, pretty=False, freq="yearl
18661869
Optional. Proxy server URL scheme
18671870
Default is None
18681871
"""
1869-
self._fundamentals.proxy = proxy
1872+
self._fundamentals.proxy = proxy or self.proxy
18701873

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

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

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

@@ -1946,7 +1949,7 @@ def get_actions(self, proxy=None):
19461949
return []
19471950

19481951
def get_shares(self, proxy=None, as_dict=False):
1949-
self._fundamentals.proxy = proxy
1952+
self._fundamentals.proxy = proxy or self.proxy
19501953
data = self._fundamentals.shares
19511954
if as_dict:
19521955
return data.to_dict()
@@ -2020,7 +2023,7 @@ def get_isin(self, proxy=None) -> Optional[str]:
20202023

20212024
q = ticker
20222025

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

yfinance/ticker.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@
3030

3131

3232
class Ticker(TickerBase):
33-
def __init__(self, ticker, session=None):
34-
super(Ticker, self).__init__(ticker, session=session)
33+
def __init__(self, ticker, session=None, proxy=None):
34+
super(Ticker, self).__init__(ticker, session=session, proxy=proxy)
3535
self._expirations = {}
3636
self._underlying = {}
3737

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

41-
def _download_options(self, date=None, proxy=None):
41+
def _download_options(self, date=None):
4242
if date is None:
4343
url = f"{self._base_url}/v7/finance/options/{self.ticker}"
4444
else:
4545
url = f"{self._base_url}/v7/finance/options/{self.ticker}?date={date}"
4646

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

83-
def option_chain(self, date=None, proxy=None, tz=None):
83+
def option_chain(self, date=None, tz=None):
8484
if date is None:
85-
options = self._download_options(proxy=proxy)
85+
options = self._download_options()
8686
else:
8787
if not self._expirations:
8888
self._download_options()
@@ -91,7 +91,7 @@ def option_chain(self, date=None, proxy=None, tz=None):
9191
f"Expiration `{date}` cannot be found. "
9292
f"Available expirations are: [{', '.join(self._expirations)}]")
9393
date = self._expirations[date]
94-
options = self._download_options(date, proxy=proxy)
94+
options = self._download_options(date)
9595

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

0 commit comments

Comments
 (0)