Skip to content

Commit

Permalink
adding tests for prices functions
Browse files Browse the repository at this point in the history
  • Loading branch information
lockefox committed Aug 3, 2017
1 parent bf0bc33 commit c347dd5
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 8 deletions.
17 changes: 9 additions & 8 deletions prosper/datareader/stocks/prices.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""datareader.news.py: tools for fetching stock news"""
from datetime import datetime
from datetime import datetime, timezone
import dateutil.parser
from os import path

Expand Down Expand Up @@ -148,10 +148,7 @@ def fetch_instruments_rh(

return data

def market_is_open(
market_uri,
logger=LOGGER
):
def market_is_open(market_uri, logger=LOGGER): #pragma: no cover
"""checks if market is open right now
Args:
Expand All @@ -163,6 +160,7 @@ def market_is_open(
"""
#TODO: cache me
#TODO: test me
market_name = market_uri.split('/')[-1]
logger.info('fetching market info for %s -- Robinhood', market_name)

Expand All @@ -179,7 +177,7 @@ def market_is_open(
return False

close_datetime = dateutil.parser.parse(hours_data['extended_opens_at'])
now = datetime.utcnow()
now = datetime.now(timezone.utc)

if close_datetime > now:
return False
Expand Down Expand Up @@ -217,7 +215,7 @@ def get_quote_rh(
stock_info = {**quote, **fundamentals, **instruments} #join all data together
stock_info['is_open'] = market_is_open(instruments['market'])

if stock_info['is_open']:
if stock_info['is_open']: #pragma: no cover
stock_info['current_price'] = stock_info['last_trade_price']
else:
stock_info['current_price'] = stock_info['last_extended_hours_trade_price']
Expand All @@ -229,4 +227,7 @@ def get_quote_rh(

summary_df['pct_change'] = (summary_df['current_price'] - summary_df['previous_close']) / summary_df['previous_close'] * 100

return summary_df[keys]
if keys:
return summary_df[keys]
else:
return summary_df
104 changes: 104 additions & 0 deletions tests/test_stocks_prices.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""test_stocks_news.py: validate behavior for datareader.stocks.prices"""
from datetime import datetime
from os import path
import re

import pytest
import requests
import helpers
import pandas as pd
import numpy

import prosper.datareader.stocks.prices as prices
import prosper.datareader.exceptions as exceptions
Expand Down Expand Up @@ -60,3 +63,104 @@ def test_validate_market_hours(self):
hours = hours_req.json()

helpers.validate_schema(hours, 'stocks/rh_markets_hours.schema')

def test_ticker_list_to_str():
"""make sure ticker_list_to_str returns as expected"""
no_caps_pattern = re.compile('[a-z]+')

single_stock = prices.ticker_list_to_str('MU')
assert not no_caps_pattern.match(single_stock)
assert single_stock == 'MU'

lower_stock = prices.ticker_list_to_str('mu')
assert not no_caps_pattern.match(lower_stock)
assert lower_stock == 'MU'

multi_stock = prices.ticker_list_to_str(['MU', 'INTC', 'BA'])
assert not no_caps_pattern.match(multi_stock)
assert multi_stock == 'MU,INTC,BA'

lower_multi_stock = prices.ticker_list_to_str(['MU', 'intc', 'BA'])
assert not no_caps_pattern.match(lower_multi_stock)
assert lower_multi_stock == 'MU,INTC,BA'

with pytest.raises(TypeError):
bad_stock = prices.ticker_list_to_str({'butts':1})

def test_cast_str_to_int():
"""validate behavior for cast_str_to_int"""
demo_json = [
{
"string_value": "butts",
"int_value": "12",
"float_value": "10.50"
},
{
"string_value": "otherbutts",
"int_value": "-99",
"float_value": "-5.00"
}
]

demo_df = pd.DataFrame(demo_json)
assert demo_df['string_value'].dtype == object
assert demo_df['int_value'].dtype == object
assert demo_df['float_value'].dtype == object

with pytest.raises(TypeError):
demo_df['diff'] = demo_df['int_value'] - demo_df['float_value']

updated_df = prices.cast_str_to_int(demo_df)

assert updated_df['string_value'].dtype == object
assert updated_df['int_value'].dtype == numpy.int64
assert updated_df['float_value'].dtype == numpy.float64

updated_df['diff'] = updated_df['int_value'] - updated_df['float_value']
assert updated_df['diff'].dtype == numpy.float64

class TestGetQuoteRH:
"""validate behavior for prices.get_quote_rh()"""
good_ticker = helpers.CONFIG.get('STOCKS', 'good_ticker')
ticker_list = helpers.CONFIG.get('STOCKS', 'ticker_list').split(',')

def test_get_quote_rh_default(self):
"""validate expected default behavior for get_quote_rh()"""
single_quote = prices.get_quote_rh(self.good_ticker)

assert isinstance(single_quote, pd.DataFrame)
assert len(single_quote) == 1

assert set(list(single_quote.columns.values)) == set(prices.SUMMARY_KEYS)

def test_get_quote_rh_multi(self):
"""validate expected behavior with list of stocks"""
multi_quote = prices.get_quote_rh(self.ticker_list)

assert isinstance(multi_quote, pd.DataFrame)
assert len(multi_quote) == len(self.ticker_list)

assert set(list(multi_quote.columns.values)) == set(prices.SUMMARY_KEYS)

def test_get_quote_rh_no_filter(self):
"""look at all possible summary keys"""
no_filter = prices.get_quote_rh(self.good_ticker, keys=None)

assert isinstance(no_filter, pd.DataFrame)
assert len(no_filter) == 1

all_keys = [
'adjusted_previous_close', 'ask_price', 'ask_size', 'average_volume',
'bid_price', 'bid_size', 'bloomberg_unique', 'ceo', 'country',
'current_price', 'day_trade_ratio', 'description', 'dividend_yield',
'fundamentals', 'has_traded', 'headquarters_city', 'headquarters_state',
'high', 'high_52_weeks', 'id', 'instrument', 'is_open',
'last_extended_hours_trade_price', 'last_trade_price',
'last_trade_price_source', 'list_date', 'low', 'low_52_weeks',
'maintenance_ratio', 'margin_initial_ratio', 'market', 'market_cap',
'min_tick_size', 'name', 'num_employees', 'open', 'pe_ratio',
'previous_close', 'previous_close_date', 'quote', 'simple_name',
'splits', 'state', 'symbol', 'tradeable', 'trading_halted', 'type',
'updated_at', 'url', 'volume', 'year_founded', 'pct_change'
]
assert set(list(no_filter.columns.values)) == set(all_keys)

0 comments on commit c347dd5

Please sign in to comment.