From 999650257362cbd23c1b983e6aca4d9a93924f08 Mon Sep 17 00:00:00 2001 From: jfkirk Date: Thu, 28 May 2015 10:43:36 -0400 Subject: [PATCH] DEP: Removes use of 'count'-defined test sources Test sources are now defined by the sim_params period_start and period_end, rather than by the period_start and a defined 'count' of bars. This allows us to consider the sim_params.period_end as the canonical definition of the end of a simulation. --- tests/test_algorithm.py | 1 - tests/test_algorithm_gen.py | 2 -- tests/test_finance.py | 1 - tests/test_transforms.py | 6 ++-- zipline/sources/test_source.py | 64 +++++++++++++--------------------- zipline/utils/factory.py | 32 +++++++---------- zipline/utils/simfactory.py | 8 ----- 7 files changed, 41 insertions(+), 73 deletions(-) diff --git a/tests/test_algorithm.py b/tests/test_algorithm.py index d1541e70..2fee8382 100644 --- a/tests/test_algorithm.py +++ b/tests/test_algorithm.py @@ -135,7 +135,6 @@ class TestMiscellaneousAPI(TestCase): ) self.source = factory.create_minutely_trade_source( sids, - trade_count=100, sim_params=self.sim_params, concurrent=True, ) diff --git a/tests/test_algorithm_gen.py b/tests/test_algorithm_gen.py index 8df72bc8..03d3c625 100644 --- a/tests/test_algorithm_gen.py +++ b/tests/test_algorithm_gen.py @@ -134,7 +134,6 @@ class AlgorithmGeneratorTestCase(TestCase): algo = TestAlgo(self, sim_params=sim_params) trade_source = factory.create_daily_trade_source( [8229], - 200, sim_params ) algo.set_sources([trade_source]) @@ -205,7 +204,6 @@ class AlgorithmGeneratorTestCase(TestCase): algo = TestAlgo(self, sim_params=sim_params) trade_source = factory.create_daily_trade_source( [8229], - 3, sim_params ) algo.set_sources([trade_source]) diff --git a/tests/test_finance.py b/tests/test_finance.py index 4f796521..0cb5c8cd 100644 --- a/tests/test_finance.py +++ b/tests/test_finance.py @@ -72,7 +72,6 @@ class FinanceTestCase(TestCase): sim_params = factory.create_simulation_parameters() trade_source = factory.create_daily_trade_source( [133], - 200, sim_params ) prev = None diff --git a/tests/test_transforms.py b/tests/test_transforms.py index d1b1739d..8346612d 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -41,6 +41,7 @@ def handle_data_wrapper(f): else: context.mins_for_days[-1] += 1 + hist = context.history(2, '1d', 'close_price') for n in (1, 2, 3): if n in data: if data[n].dt == dt: @@ -53,7 +54,7 @@ def handle_data_wrapper(f): context.price_bars[n].append(np.nan) context.vol_bars[n].append(0) - context.last_close_prices[n] = context.price_bars[n][-2] + context.last_close_prices[n] = hist[n][0] if context.warmup < 0: return f(context, data) @@ -101,6 +102,7 @@ def with_algo(f): initialize=initialize_with(self, tfm_name, days), handle_data=handle_data_wrapper(f), sim_params=sim_params, + identifiers=[1, 2, 3] ) algo.run(source) @@ -131,12 +133,10 @@ class TransformTestCase(TestCase): cls.sim_and_source = { 'minute': (minute_sim_ps, factory.create_minutely_trade_source( cls.sids, - trade_count=45, sim_params=minute_sim_ps, )), 'daily': (daily_sim_ps, factory.create_trade_source( cls.sids, - trade_count=90, trade_time_increment=timedelta(days=1), sim_params=daily_sim_ps, )), diff --git a/zipline/sources/test_source.py b/zipline/sources/test_source.py index 06579910..5e64a320 100644 --- a/zipline/sources/test_source.py +++ b/zipline/sources/test_source.py @@ -19,9 +19,9 @@ A source to be used in testing. import pytz -from itertools import cycle -from six.moves import filter, zip +from six.moves import filter from datetime import datetime, timedelta +import itertools import numpy as np from six.moves import range @@ -53,9 +53,9 @@ def create_trade(sid, price, amount, datetime, source_id="test_factory"): @with_environment() -def date_gen(start=datetime(2006, 6, 6, 12, tzinfo=pytz.utc), +def date_gen(start, + end, delta=timedelta(minutes=1), - count=100, repeats=None, env=None): """ @@ -88,7 +88,7 @@ def date_gen(start=datetime(2006, 6, 6, 12, tzinfo=pytz.utc), # yield count trade events, all on trading days, and # during trading hours. - for i in range(count): + while cur < end: if repeats: for j in range(repeats): yield cur @@ -98,22 +98,6 @@ def date_gen(start=datetime(2006, 6, 6, 12, tzinfo=pytz.utc), cur = advance_current(cur) -def mock_prices(count): - """ - Utility to generate a stream of mock prices. By default - cycles through values from 0.0 to 10.0, n times. - """ - return (float(i % 10) + 1.0 for i in range(count)) - - -def mock_volumes(count): - """ - Utility to generate a set of volumes. By default cycles - through values from 100 to 1000, incrementing by 50. - """ - return ((i * 50) % 900 + 100 for i in range(count)) - - class SpecificEquityTrades(object): """ Yields all events in event_list that match the given sid_filter. @@ -136,18 +120,16 @@ class SpecificEquityTrades(object): # Default to None for event_list and filter. self.event_list = kwargs.get('event_list') self.filter = kwargs.get('filter') - if self.event_list is not None: # If event_list is provided, extract parameters from there # This isn't really clean and ultimately I think this # class should serve a single purpose (either take an # event_list or autocreate events). - self.count = kwargs.get('count', len(self.event_list)) self.sids = kwargs.get( 'sids', np.unique([event.sid for event in self.event_list]).tolist()) self.start = kwargs.get('start', self.event_list[0].dt) - self.end = kwargs.get('start', self.event_list[-1].dt) + self.end = kwargs.get('end', self.event_list[-1].dt) self.delta = kwargs.get( 'delta', self.event_list[1].dt - self.event_list[0].dt) @@ -155,11 +137,13 @@ class SpecificEquityTrades(object): else: # Unpack config dictionary with default values. - self.count = kwargs.get('count', 500) self.sids = kwargs.get('sids', [1, 2]) self.start = kwargs.get( 'start', datetime(2008, 6, 6, 15, tzinfo=pytz.utc)) + self.end = kwargs.get( + 'end', + datetime(2008, 6, 6, 15, tzinfo=pytz.utc)) self.delta = kwargs.get( 'delta', timedelta(minutes=1)) @@ -201,30 +185,32 @@ class SpecificEquityTrades(object): if self.concurrent: # in this context the count is the number of # trades per sid, not the total. - dates = date_gen( - count=self.count, + date_generator = date_gen( start=self.start, + end=self.end, delta=self.delta, repeats=len(self.sids), ) else: - dates = date_gen( - count=self.count, + date_generator = date_gen( start=self.start, + end=self.end, delta=self.delta ) - prices = mock_prices(self.count) - volumes = mock_volumes(self.count) + source_id = self.get_hash() - sids = cycle(self.sids) - - # Combine the iterators into a single iterator of arguments - arg_gen = zip(sids, prices, volumes, dates) - - # Convert argument packages into events. - unfiltered = (create_trade(*args, source_id=self.get_hash()) - for args in arg_gen) + unfiltered = ( + create_trade( + sid=sid, + price=float(i % 10) + 1.0, + amount=(i * 50) % 900 + 100, + datetime=date, + source_id=source_id, + ) for (i, date), sid in itertools.product( + enumerate(date_generator), self.sids + ) + ) # If we specified a sid filter, filter out elements that don't # match the filter. diff --git a/zipline/utils/factory.py b/zipline/utils/factory.py index d55d9281..03da1231 100644 --- a/zipline/utils/factory.py +++ b/zipline/utils/factory.py @@ -224,65 +224,59 @@ def create_returns_from_list(returns, sim_params): data=returns) -def create_daily_trade_source(sids, trade_count, sim_params, - concurrent=False): +def create_daily_trade_source(sids, sim_params, concurrent=False): """ creates trade_count trades for each sid in sids list. first trade will be on sim_params.period_start, and daily thereafter for each sid. Thus, two sids should result in two trades per day. - - Important side-effect: sim_params.period_end will be modified - to match the day of the final trade. """ return create_trade_source( sids, - trade_count, timedelta(days=1), sim_params, concurrent=concurrent ) -def create_minutely_trade_source(sids, trade_count, sim_params, - concurrent=False): +def create_minutely_trade_source(sids, sim_params, concurrent=False): """ creates trade_count trades for each sid in sids list. first trade will be on sim_params.period_start, and every minute thereafter for each sid. Thus, two sids should result in two trades per minute. - - Important side-effect: sim_params.period_end will be modified - to match the day of the final trade. """ return create_trade_source( sids, - trade_count, timedelta(minutes=1), sim_params, concurrent=concurrent ) -def create_trade_source(sids, trade_count, - trade_time_increment, sim_params, +def create_trade_source(sids, trade_time_increment, sim_params, concurrent=False): + # If the sim_params define an end that is during market hours, that will be + # used as the end of the data source + if trading.environment.is_market_hours(sim_params.period_end): + end = sim_params.period_end + # Otherwise, the last_close after the period_end is used as the end of the + # data source + else: + end = sim_params.last_close + args = tuple() kwargs = { - 'count': trade_count, 'sids': sids, 'start': sim_params.first_open, + 'end': end, 'delta': trade_time_increment, 'filter': sids, 'concurrent': concurrent } source = SpecificEquityTrades(*args, **kwargs) - # TODO: do we need to set the trading environment's end to same dt as - # the last trade in the history? - # sim_params.period_end = trade_history[-1].dt - return source diff --git a/zipline/utils/simfactory.py b/zipline/utils/simfactory.py index b7137007..cce56ab7 100644 --- a/zipline/utils/simfactory.py +++ b/zipline/utils/simfactory.py @@ -42,13 +42,6 @@ def create_test_zipline(**config): else: order_amount = 100 - if 'trade_count' in config: - trade_count = config['trade_count'] - else: - # to ensure all orders are filled, we provide one more - # trade than order - trade_count = 101 - # ------------------- # Create the Algo # ------------------- @@ -72,7 +65,6 @@ def create_test_zipline(**config): else: trade_source = factory.create_daily_trade_source( sid_list, - trade_count, test_algo.sim_params, concurrent=concurrent_trades )