Skip to content

Commit

Permalink
Merge pull request #1337 from ranaroussi/dev
Browse files Browse the repository at this point in the history
dev -> main
  • Loading branch information
ValueRaider authored Jan 25, 2023
2 parents ab6214d + af77206 commit 66a1c1a
Show file tree
Hide file tree
Showing 7 changed files with 528 additions and 9 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ import yfinance as yf

msft = yf.Ticker("MSFT")

# get stock info
# fast access to subset of stock info
msft.basic_info
# slow access to all stock info
msft.info

# get historical market data
Expand Down
107 changes: 105 additions & 2 deletions tests/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""
import pandas as pd
import numpy as np

from .context import yfinance as yf

Expand Down Expand Up @@ -660,14 +661,116 @@ def test_shares_full(self):
self.assertIsInstance(data, pd.Series, "data has wrong type")
self.assertFalse(data.empty, "data is empty")

def test_bad_freq_value_raises_exception(self):
self.assertRaises(ValueError, lambda: self.ticker.get_cashflow(freq="badarg"))


class TestTickerInfo(unittest.TestCase):
session = None

@classmethod
def setUpClass(cls):
cls.session = requests_cache.CachedSession(backend='memory')

@classmethod
def tearDownClass(cls):
if cls.session is not None:
cls.session.close()

def setUp(self):
tkrs = ["ESLT.TA", "BP.L", "GOOGL"]
self.tickers = [yf.Ticker(tkr, session=self.session) for tkr in tkrs]

def tearDown(self):
self.ticker = None

def test_info(self):
data = self.ticker.info
self.assertIsInstance(data, dict, "data has wrong type")
self.assertIn("symbol", data.keys(), "Did not find expected key in info dict")
self.assertEqual("GOOGL", data["symbol"], "Wrong symbol value in info dict")

def test_bad_freq_value_raises_exception(self):
self.assertRaises(ValueError, lambda: self.ticker.get_cashflow(freq="badarg"))
def test_basic_info(self):
yf.scrapers.quote.PRUNE_INFO = False

# basic_info_keys = self.ticker.basic_info.keys()
basic_info_keys = set()
for ticker in self.tickers:
basic_info_keys.update(set(ticker.basic_info.keys()))
basic_info_keys = sorted(list(basic_info_keys))

key_rename_map = {}
key_rename_map["last_price"] = ["currentPrice", "regularMarketPrice"]
key_rename_map["open"] = ["open", "regularMarketOpen"]
key_rename_map["day_high"] = ["dayHigh", "regularMarketDayHigh"]
key_rename_map["day_low"] = ["dayLow", "regularMarketDayLow"]
key_rename_map["previous_close"] = ["previousClose", "regularMarketPreviousClose"]

# preMarketPrice

key_rename_map["fifty_day_average"] = "fiftyDayAverage"
key_rename_map["two_hundred_day_average"] = "twoHundredDayAverage"
key_rename_map["year_change"] = "52WeekChange"
key_rename_map["year_high"] = "fiftyTwoWeekHigh"
key_rename_map["year_low"] = "fiftyTwoWeekLow"

key_rename_map["last_volume"] = ["volume", "regularMarketVolume"]
key_rename_map["ten_day_average_volume"] = ["averageVolume10days", "averageDailyVolume10Day"]
key_rename_map["three_month_average_volume"] = "averageVolume"

key_rename_map["market_cap"] = "marketCap"
key_rename_map["shares"] = "floatShares"
key_rename_map["timezone"] = "exchangeTimezoneName"

approximate_keys = {"fifty_day_average", "ten_day_average_volume"}
approximate_keys.update({"market_cap"})

# bad_keys = []
bad_keys = {"shares"}

# Loose tolerance for averages, no idea why don't match info[]. Is info wrong?
custom_tolerances = {}
# custom_tolerances["ten_day_average_volume"] = 1e-3
custom_tolerances["ten_day_average_volume"] = 1e-1
# custom_tolerances["three_month_average_volume"] = 1e-2
custom_tolerances["three_month_average_volume"] = 5e-1
custom_tolerances["fifty_day_average"] = 1e-2
custom_tolerances["two_hundred_day_average"] = 1e-2

for k in basic_info_keys:
if k in key_rename_map:
k2 = key_rename_map[k]
else:
k2 = k

if not isinstance(k2, list):
k2 = [k2]

for m in k2:
for ticker in self.tickers:
if not m in ticker.info:
print(sorted(list(ticker.info.keys())))
raise Exception("Need to add/fix mapping for basic_info key", k)

if k in bad_keys:
# Doesn't match, investigate why
continue

if k in custom_tolerances:
rtol = custom_tolerances[k]
else:
rtol = 5e-3
# rtol = 1e-4

print(f"Testing key {m} -> {k} ticker={ticker.ticker}")
# if k in approximate_keys:
v1 = ticker.basic_info[k]
v2 = ticker.info[m]
if isinstance(v1, float) or isinstance(v2, int):
self.assertTrue(np.isclose(v1, v2, rtol=rtol), f"{k}: {v1} != {v2}")
else:
self.assertEqual(v1, v2, f"{k}: {v1} != {v2}")



def suite():
Expand Down
Loading

0 comments on commit 66a1c1a

Please sign in to comment.