BLD: completed unit tests for validating bundles against OHLCV data on each exchange

This commit is contained in:
Frederic Fortier
2017-12-20 16:04:01 -05:00
parent 55262eeb46
commit 3b16bf7538
3 changed files with 79 additions and 33 deletions
+2
View File
@@ -19,6 +19,7 @@ from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
NoDataAvailableOnExchange, NoValueForField, LastCandleTooEarlyError
from catalyst.exchange.exchange_utils import get_exchange_symbols, \
get_frequency, resample_history_df, has_bundle
from catalyst.utils.deprecate import deprecated
log = Logger('Exchange', level=LOG_LEVEL)
@@ -407,6 +408,7 @@ class Exchange:
return value
@deprecated
def get_series_from_candles(self, candles, start_dt, end_dt,
data_frequency, field, previous_value=None):
"""
+24
View File
@@ -705,3 +705,27 @@ def save_asset_data(folder, df, decimals=8):
header=print_headers,
float_format='%.{}f'.format(decimals),
)
def get_candles_df(candles, field, freq, bar_count, end_dt,
previous_value=None):
all_series = dict()
for asset in candles:
periods = pd.date_range(end=end_dt, periods=bar_count, freq=freq)
dates = [candle['last_traded'] for candle in candles[asset]]
values = [candle[field] for candle in candles[asset]]
series = pd.Series(values, index=dates)
series = series.reindex(
periods,
method='ffill',
fill_value=previous_value,
)
series.sort_index(inplace=True)
all_series[asset] = series
df = pd.DataFrame(all_series)
df.dropna(inplace=True)
return df
+53 -33
View File
@@ -1,4 +1,5 @@
import random
from datetime import timedelta
from logbook import Logger
from pandas.util.testing import assert_frame_equal
@@ -8,11 +9,18 @@ import pandas as pd
from catalyst import get_calendar
from catalyst.exchange.asset_finder_exchange import AssetFinderExchange
from catalyst.exchange.exchange_data_portal import DataPortalExchangeBacktest
from catalyst.exchange.exchange_utils import get_candles_df
from catalyst.exchange.factory import get_exchange
from catalyst.exchange.test_utils import select_random_exchanges, output_df, \
select_random_assets
log = Logger('TestSuiteExchange')
pd.set_option('display.expand_frame_repr', False)
pd.set_option('precision', 8)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
class TestSuiteBundle:
@staticmethod
@@ -29,7 +37,7 @@ class TestSuiteBundle:
return data_portal
def compare_bundle_with_exchange(self, exchange, assets, end_dt, bar_count,
freq, data_portal):
freq, data_frequency, data_portal):
"""
Creates DataFrames from the bundle and exchange for the specified
data set.
@@ -46,18 +54,19 @@ class TestSuiteBundle:
-------
"""
data = dict()
log.info('creating data sample from bundle')
df1 = data_portal.get_history_window(
data['bundle'] = data_portal.get_history_window(
assets=assets,
end_dt=end_dt,
bar_count=bar_count,
frequency=freq,
field='close',
data_frequency='minute'
data_frequency=data_frequency,
)
path = output_df(df1, assets, '{}_resampled'.format(freq))
log.info('saved resampled bundle candles: {}\n{}'.format(
path, df1.tail(10))
log.info('bundle data:\n{}'.format(
data['bundle'].tail(10))
)
log.info('creating data sample from exchange api')
@@ -65,28 +74,29 @@ class TestSuiteBundle:
end_dt=end_dt,
freq=freq,
assets=assets,
bar_count=bar_count
bar_count=bar_count,
)
series = dict()
for asset in assets:
series[asset] = pd.Series(
data=[candle['close'] for candle in candles[asset]],
index=[candle['last_traded'] for candle in candles[asset]]
)
df2 = pd.DataFrame(series)
path = output_df(df2, assets, '{}_api'.format(freq))
log.info('saved exchange api candles: {}\n{}'.format(
path, df2.tail(10))
data['exchange'] = get_candles_df(
candles=candles,
field='close',
freq=freq,
bar_count=bar_count,
end_dt=end_dt,
)
log.info('exchange data:\n{}'.format(
data['exchange'].tail(10))
)
for source in data:
df = data[source]
path = output_df(df, assets, '{}_{}'.format(freq, source))
log.info('saved {}:\n{}'.format(source, path))
try:
assert_frame_equal(df1, df2)
return True
except:
log.warn('differences found in dataframes')
return False
assert_frame_equal(
right=data['bundle'],
left=data['exchange'],
check_less_precise=True
)
pass
def test_validate_bundles(self):
exchange_population = 3
@@ -94,10 +104,11 @@ class TestSuiteBundle:
data_frequency = random.choice(['minute', 'daily'])
bundle = 'dailyBundle' if data_frequency == 'daily' else 'minuteBundle'
exchanges = select_random_exchanges(
population=exchange_population,
features=[bundle],
) # Type: list[Exchange]
# exchanges = select_random_exchanges(
# population=exchange_population,
# features=[bundle],
# ) # Type: list[Exchange]
exchanges = [get_exchange('bitfinex', skip_init=True)]
data_portal = TestSuiteBundle.get_data_portal(
[exchange.name for exchange in exchanges]
@@ -109,18 +120,27 @@ class TestSuiteBundle:
freq = random.sample(frequencies, 1)[0]
bar_count = random.randint(1, 10)
end_dt = pd.Timestamp.utcnow().floor('1T')
dt_range = pd.date_range(
end=end_dt, periods=bar_count, freq=freq
)
assets = select_random_assets(
exchange.assets, asset_population
)
end_dt = None
for asset in assets:
attribute = 'end_{}'.format(data_frequency)
asset_end_dt = getattr(asset, attribute)
if end_dt is None or asset_end_dt < end_dt:
end_dt = asset_end_dt
dt_range = pd.date_range(
end=end_dt, periods=bar_count, freq=freq
)
self.compare_bundle_with_exchange(
exchange=exchange,
assets=assets,
end_dt=dt_range[-1],
bar_count=bar_count,
freq=freq,
data_frequency=data_frequency,
data_portal=data_portal,
)