Skip to content

Commit be7fc39

Browse files
committed
Merge pull request #7665 from dstephens99/master
TST/CLN: Refactor io.data.options class to improve testing
2 parents 83a7d77 + 836e760 commit be7fc39

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed

pandas/io/data.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -661,31 +661,35 @@ def get_options_data(self, month=None, year=None, expiry=None):
661661

662662
_OPTIONS_BASE_URL = 'http://finance.yahoo.com/q/op?s={sym}'
663663

664-
def _get_option_tables(self, month, year, expiry):
664+
def _get_option_tables(self, expiry):
665+
root = self._get_option_page_from_yahoo(expiry)
666+
tables = self._parse_option_page_from_yahoo(root)
667+
m1 = _two_char_month(expiry.month)
668+
table_name = '_tables' + m1 + str(expiry.year)[-2:]
669+
setattr(self, table_name, tables)
670+
return tables
665671

666-
year, month, expiry = self._try_parse_dates(year, month, expiry)
672+
def _get_option_page_from_yahoo(self, expiry):
667673

668674
url = self._OPTIONS_BASE_URL.format(sym=self.symbol)
669675

670-
if month and year: # try to get specified month from yahoo finance
671-
m1 = _two_char_month(month)
676+
m1 = _two_char_month(expiry.month)
672677

673-
# if this month use other url
674-
if month == CUR_MONTH and year == CUR_YEAR:
675-
url += '+Options'
676-
else:
677-
url += '&m={year}-{m1}'.format(year=year, m1=m1)
678-
else: # Default to current month
678+
# if this month use other url
679+
if expiry.month == CUR_MONTH and expiry.year == CUR_YEAR:
679680
url += '+Options'
681+
else:
682+
url += '&m={year}-{m1}'.format(year=expiry.year, m1=m1)
680683

681684
root = self._parse_url(url)
685+
return root
686+
687+
def _parse_option_page_from_yahoo(self, root):
688+
682689
tables = root.xpath('.//table')
683690
ntables = len(tables)
684691
if ntables == 0:
685-
raise RemoteDataError("No tables found at {0!r}".format(url))
686-
687-
table_name = '_tables' + m1 + str(year)[-2:]
688-
setattr(self, table_name, tables)
692+
raise RemoteDataError("No tables found")
689693

690694
try:
691695
self.underlying_price, self.quote_time = self._get_underlying_price(root)
@@ -723,7 +727,7 @@ def _get_option_data(self, month, year, expiry, name):
723727
try:
724728
tables = getattr(self, table_name)
725729
except AttributeError:
726-
tables = self._get_option_tables(month, year, expiry)
730+
tables = self._get_option_tables(expiry)
727731

728732
ntables = len(tables)
729733
table_loc = self._TABLE_LOC[name]
@@ -903,13 +907,14 @@ def get_near_stock_price(self, above_below=2, call=True, put=False,
903907
meth_name = 'get_{0}_data'.format(nam[:-1])
904908
df = getattr(self, meth_name)(expiry=expiry)
905909

906-
start_index = np.where(df.index.get_level_values('Strike')
910+
if self.underlying_price:
911+
start_index = np.where(df.index.get_level_values('Strike')
907912
> self.underlying_price)[0][0]
908913

909-
get_range = slice(start_index - above_below,
914+
get_range = slice(start_index - above_below,
910915
start_index + above_below + 1)
911-
chop = df[get_range].dropna(how='all')
912-
data[nam] = chop
916+
chop = df[get_range].dropna(how='all')
917+
data[nam] = chop
913918

914919
return concat([data[nam] for nam in to_ret]).sortlevel()
915920

@@ -948,6 +953,8 @@ def _try_parse_dates(year, month, expiry):
948953
year = CUR_YEAR
949954
month = CUR_MONTH
950955
expiry = dt.date(year, month, 1)
956+
else:
957+
expiry = dt.date(year, month, 1)
951958

952959
return year, month, expiry
953960

@@ -1127,7 +1134,11 @@ def _get_expiry_months(self):
11271134
url = 'http://finance.yahoo.com/q/op?s={sym}'.format(sym=self.symbol)
11281135
root = self._parse_url(url)
11291136

1130-
links = root.xpath('.//*[@id="yfncsumtab"]')[0].xpath('.//a')
1137+
try:
1138+
links = root.xpath('.//*[@id="yfncsumtab"]')[0].xpath('.//a')
1139+
except IndexError:
1140+
return RemoteDataError('Expiry months not available')
1141+
11311142
month_gen = (element.attrib['href'].split('=')[-1]
11321143
for element in links
11331144
if '/q/op?s=' in element.attrib['href']

pandas/io/tests/test_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def test_sample_page_price_quote_time2(self):
334334
@network
335335
def test_sample_page_chg_float(self):
336336
#Tests that numeric columns with comma's are appropriately dealt with
337-
tables = self.root1.xpath('.//table')
337+
tables = self.aapl._parse_option_page_from_yahoo(self.root1)
338338
data = web._parse_options_data(tables[self.aapl._TABLE_LOC['puts']])
339339
option_data = self.aapl._process_data(data)
340340
self.assertEqual(option_data['Chg'].dtype, 'float64')

0 commit comments

Comments
 (0)