def test_get_datetime(self, name, tz): algo = dedent(""" import pandas as pd from zipline.api import get_datetime def initialize(context): context.tz = {tz} or 'UTC' context.first_bar = True def handle_data(context, data): if context.first_bar: dt = get_datetime({tz}) if dt.tz.zone != context.tz: raise ValueError("Mismatched Zone") elif dt.tz_convert("US/Eastern").hour != 9: raise ValueError("Mismatched Hour") elif dt.tz_convert("US/Eastern").minute != 31: raise ValueError("Mismatched Minute") context.first_bar = False """.format(tz=repr(tz))) start = to_utc('2014-01-02 9:31') end = to_utc('2014-01-03 9:31') source = RandomWalkSource( start=start, end=end, ) sim_params = factory.create_simulation_parameters( data_frequency='minute') algo = TradingAlgorithm(script=algo, sim_params=sim_params, identifiers=[1]) algo.run(source) self.assertFalse(algo.first_bar)
def test_history_daily_data_1m_window(self): algo_text = """ from zipline.api import history, add_history def initialize(context): add_history(bar_count=1, frequency='1m', field='price') def handle_data(context, data): prices = history(bar_count=3, frequency='1d', field='price') """.strip() start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-30', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end) with self.assertRaises(IncompatibleHistoryFrequency): algo = TradingAlgorithm( script=algo_text, data_frequency='daily', sim_params=sim_params ) source = RandomWalkSource(start=start, end=end) algo.run(source)
def test_day(self): np.random.seed(123) start_prices = {0: 100, 1: 500} start = pd.Timestamp('1990-01-01', tz='UTC') end = pd.Timestamp('1992-01-01', tz='UTC') source = RandomWalkSource(start_prices=start_prices, calendar=calendar_nyse, start=start, end=end, freq='day') self.assertIsInstance(source.start, pd.lib.Timestamp) self.assertIsInstance(source.end, pd.lib.Timestamp) for event in source: self.assertIn(event.sid, start_prices.keys()) self.assertIn(event.dt.replace(minute=0, hour=0), calendar_nyse.trading_days) self.assertGreater(event.dt, start) self.assertLess(event.dt, end) self.assertGreater(event.price, 0, "price should never go negative.") self.assertTrue( 13 <= event.dt.hour <= 21, "event.dt.hour == %i, not during market \ hours." % event.dt.hour)
def test_minute_data(self): source = RandomWalkSource(freq='minute', start=pd.Timestamp('2000-1-3', tz='UTC'), end=pd.Timestamp('2000-1-4', tz='UTC')) self.sim_params.data_frequency = 'minute' algo = TestOrderInstantAlgorithm(sim_params=self.sim_params, instant_fill=True) algo.run(source)
def test_history_passed_to_talib(self): """ Had an issue where MagicMock was causing errors during validation with talib. We don't officially support a talib integration, yet. But using talib directly should work. """ algo_text = """ import talib import numpy as np from zipline.api import history, add_history, record def initialize(context): add_history(2, '1d', 'price') def handle_data(context, data): prices = history(2, '1d', 'price') ma_result = talib.MA(np.asarray(prices[0]), timeperiod=2) record(ma=ma_result[-1]) """.strip() # April 2007 # Su Mo Tu We Th Fr Sa # 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 # 15 16 17 18 19 20 21 # 22 23 24 25 26 27 28 # 29 30 # Eddie: this was set to 04-10 but I don't see how that makes # sense as it does not generate enough data to get at -2 index # below. start = pd.Timestamp('2007-04-05', tz='UTC') end = pd.Timestamp('2007-04-10', tz='UTC') sim_params = SimulationParameters(period_start=start, period_end=end, capital_base=float("1.0e5"), data_frequency='minute', emission_rate='daily') test_algo = TradingAlgorithm(script=algo_text, data_frequency='minute', sim_params=sim_params) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) # At this point, just ensure that there is no crash. self.assertIsNotNone(output) recorded_ma = output.ix[-2, 'ma'] self.assertFalse(pd.isnull(recorded_ma)) # Depends on seed np.testing.assert_almost_equal(recorded_ma, 159.76304468946876)
def test_history_container_constructed_at_runtime(self): algo_text = dedent("""\ from zipline.api import history def handle_data(context, data): context.prices = history(2, '1d', 'price') """) start = pd.Timestamp('2007-04-05', tz='UTC') end = pd.Timestamp('2007-04-10', tz='UTC') sim_params = SimulationParameters(period_start=start, period_end=end, capital_base=float("1.0e5"), data_frequency='minute', emission_rate='daily') test_algo = TradingAlgorithm(script=algo_text, data_frequency='minute', sim_params=sim_params) source = RandomWalkSource(start=start, end=end) self.assertIsNone(test_algo.history_container) test_algo.run(source) self.assertIsNotNone( test_algo.history_container, msg='HistoryContainer was not constructed at runtime', ) container = test_algo.history_container self.assertEqual( container.buffer_panel.window_length, Frequency.MAX_MINUTES['d'], msg='HistoryContainer.buffer_panel was not large enough to service' ' the given HistorySpec', ) self.assertEqual( len(container.digest_panels), 1, msg='The HistoryContainer created too many digest panels', ) freq, digest = list(container.digest_panels.items())[0] self.assertEqual( freq.unit_str, 'd', ) self.assertEqual( digest.window_length, 1, msg='The digest panel is not large enough to service the given' ' HistorySpec', )
def test_basic_history_positional_args(self): """ Ensure that positional args work. """ algo_text = """ import copy from zipline.api import history, add_history def initialize(context): add_history(2, '1d', 'price') def handle_data(context, data): prices = history(2, '1d', 'price') context.last_prices = copy.deepcopy(prices) """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-21', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) self.assertIsNotNone(output) last_prices = test_algo.last_prices[0] oldest_dt = pd.Timestamp( '2006-03-20 4:00 PM', tz='US/Eastern').tz_convert('UTC') newest_dt = pd.Timestamp( '2006-03-21 4:00 PM', tz='US/Eastern').tz_convert('UTC') self.assertEquals(oldest_dt, last_prices.index[0]) self.assertEquals(newest_dt, last_prices.index[-1]) self.assertEquals(139.36946942498648, last_prices[oldest_dt]) self.assertEquals(180.15661995395106, last_prices[newest_dt])
def test_basic_history_one_day(self): algo_text = """ from zipline.api import history, add_history def initialize(context): add_history(bar_count=1, frequency='1d', field='price') def handle_data(context, data): prices = history(bar_count=1, frequency='1d', field='price') context.last_prices = prices """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-21', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) self.assertIsNotNone(output) last_prices = test_algo.last_prices[0] # oldest and newest should be the same if there is only 1 bar oldest_dt = pd.Timestamp( '2006-03-21 4:00 PM', tz='US/Eastern').tz_convert('UTC') newest_dt = pd.Timestamp( '2006-03-21 4:00 PM', tz='US/Eastern').tz_convert('UTC') self.assertEquals(oldest_dt, last_prices.index[0]) self.assertEquals(newest_dt, last_prices.index[-1]) # Random, depends on seed self.assertEquals(180.15661995395106, last_prices[oldest_dt]) self.assertEquals(180.15661995395106, last_prices[newest_dt])
def test_history_passed_to_func(self): """ Had an issue where MagicMock was causing errors during validation with rolling mean. """ algo_text = """ from zipline.api import history, add_history import pandas as pd def initialize(context): add_history(2, '1d', 'price') def handle_data(context, data): prices = history(2, '1d', 'price') pd.rolling_mean(prices, 2) """.strip() # April 2007 # Su Mo Tu We Th Fr Sa # 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 # 15 16 17 18 19 20 21 # 22 23 24 25 26 27 28 # 29 30 start = pd.Timestamp('2007-04-10', tz='UTC') end = pd.Timestamp('2007-04-10', tz='UTC') sim_params = SimulationParameters( period_start=start, period_end=end, capital_base=float("1.0e5"), data_frequency='minute', emission_rate='minute' ) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) # At this point, just ensure that there is no crash. self.assertIsNotNone(output)
def test_history(self): history_algo = """ from zipline.api import history, add_history def initialize(context): add_history(10, '1d', 'price') def handle_data(context, data): df = history(10, '1d', 'price') """ start = pd.Timestamp('1991-01-01', tz='UTC') end = pd.Timestamp('1991-01-15', tz='UTC') source = RandomWalkSource(start=start, end=end) algo = TradingAlgorithm(script=history_algo, data_frequency='minute') output = algo.run(source) self.assertIsNot(output, None)
def test_history_grow_length_intra_bar(self, incr): """ Tests growing the length of a digest panel with different date_buf deltas in a single bar. """ algo_text = dedent( """\ from zipline.api import history def initialize(context): context.bar_count = 1 def handle_data(context, data): prices = history(context.bar_count, '1d', 'price') context.test_case.assertEqual(len(prices), context.bar_count) context.bar_count += {incr} prices = history(context.bar_count, '1d', 'price') context.test_case.assertEqual(len(prices), context.bar_count) """ ).format(incr=incr) start = pd.Timestamp('2007-04-05', tz='UTC') end = pd.Timestamp('2007-04-10', tz='UTC') sim_params = SimulationParameters( period_start=start, period_end=end, capital_base=float("1.0e5"), data_frequency='minute', emission_rate='daily', env=self.env, ) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=self.env, ) test_algo.test_case = self source = RandomWalkSource(start=start, end=end) self.assertIsNone(test_algo.history_container) test_algo.run(source)
def test_history_with_volume(self): algo_text = """ from zipline.api import history, add_history, record def initialize(context): add_history(3, '1d', 'volume') def handle_data(context, data): volume = history(3, '1d', 'volume') record(current_volume=volume[0].ix[-1]) """.strip() # April 2007 # Su Mo Tu We Th Fr Sa # 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 # 15 16 17 18 19 20 21 # 22 23 24 25 26 27 28 # 29 30 start = pd.Timestamp('2007-04-10', tz='UTC') end = pd.Timestamp('2007-04-10', tz='UTC') sim_params = SimulationParameters( period_start=start, period_end=end, capital_base=float("1.0e5"), data_frequency='minute', emission_rate='minute' ) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) np.testing.assert_equal(output.ix[0, 'current_volume'], 212218404.0)
def source(self): return RandomWalkSource(start=self._start, end=self._end)
def test_history_in_bts_price_days(self, data_freq): """ Test calling history() in before_trading_start() with daily price bars. """ algo_text = """ from zipline.api import history def initialize(context): context.first_bts_call = True def before_trading_start(context, data): if not context.first_bts_call: prices_bts = history(bar_count=3, frequency='1d', field='price') context.prices_bts = prices_bts context.first_bts_call = False def handle_data(context, data): prices_hd = history(bar_count=3, frequency='1d', field='price') context.prices_hd = prices_hd """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-22', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end, data_frequency=data_freq) test_algo = TradingAlgorithm( script=algo_text, data_frequency=data_freq, sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end, freq=data_freq) output = test_algo.run(source) self.assertIsNotNone(output) # Get the prices recorded by history() within handle_data() prices_hd = test_algo.prices_hd[0] # Get the prices recorded by history() within BTS prices_bts = test_algo.prices_bts[0] # before_trading_start() is timestamp'd to midnight prior to # the day's trading. Since no equity trades occur at midnight, # the price recorded for this time is forward filled from the # last trade - typically ~4pm the previous day. This results # in the OHLCV data recorded by history() in BTS lagging # that recorded by history in handle_data(). # The trace of the pricing data from history() called within # handle_data() vs. BTS in the above algo is as follows: # When called within handle_data() # --------------------------------- # 2006-03-20 21:00:00 139.369469 # 2006-03-21 21:00:00 180.156620 # 2006-03-22 21:00:00 221.344654 # When called within BTS # --------------------------------- # 2006-03-17 21:00:00 NaN # 2006-03-20 21:00:00 139.369469 # 2006-03-22 00:00:00 180.156620 # Get relevant Timestamps for the history() call within handle_data() oldest_hd_dt = pd.Timestamp( '2006-03-20 4:00 PM', tz='US/Eastern').tz_convert('UTC') penultimate_hd_dt = pd.Timestamp( '2006-03-21 4:00 PM', tz='US/Eastern').tz_convert('UTC') # Get relevant Timestamps for the history() call within BTS penultimate_bts_dt = pd.Timestamp( '2006-03-20 4:00 PM', tz='US/Eastern').tz_convert('UTC') newest_bts_dt = normalize_date(pd.Timestamp( '2006-03-22 04:00 PM', tz='US/Eastern').tz_convert('UTC')) if data_freq == 'daily': # If we're dealing with daily data, then we record # canonicalized timestamps, so make conversion here: oldest_hd_dt = normalize_date(oldest_hd_dt) penultimate_hd_dt = normalize_date(penultimate_hd_dt) penultimate_bts_dt = normalize_date(penultimate_bts_dt) self.assertEquals(prices_hd[oldest_hd_dt], prices_bts[penultimate_bts_dt]) self.assertEquals(prices_hd[penultimate_hd_dt], prices_bts[newest_bts_dt])
def test_history_in_bts_price_minutes(self): """ Test calling history() in before_trading_start() with minutely price bars. """ algo_text = """ from zipline.api import history def initialize(context): context.first_bts_call = True def before_trading_start(context, data): if not context.first_bts_call: price_bts = history(bar_count=1, frequency='1m', field='price') context.price_bts = price_bts context.first_bts_call = False def handle_data(context, data): pass """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-22', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) self.assertIsNotNone(output) # Get the prices recorded by history() within BTS price_bts_0 = test_algo.price_bts[0] price_bts_1 = test_algo.price_bts[1] # The prices recorded by history() in BTS should # be the closing price of the previous day, which are: # # sid | close on 2006-03-21 # ---------------------------- # 0 | 180.15661995395106 # 1 | 578.41665003444723 # These are not 'real' price values. They are the product of # RandonWalkSource, which produces random walk OHLCV timeseries. For a # given seed these values are deterministc. self.assertEquals(180.15661995395106, price_bts_0.ix[0]) self.assertEquals(578.41665003444723, price_bts_1.ix[0])
def test_history_in_bts_volume_days(self, data_freq): """ Test calling history() in before_trading_start() with daily volume bars. """ algo_text = """ from zipline.api import history def initialize(context): context.first_bts_call = True def before_trading_start(context, data): if not context.first_bts_call: volume_bts = history(bar_count=2, frequency='1d', field='volume') context.volume_bts = volume_bts context.first_bts_call = False def handle_data(context, data): volume_hd = history(bar_count=2, frequency='1d', field='volume') context.volume_hd = volume_hd """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-22', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end, data_frequency=data_freq) test_algo = TradingAlgorithm( script=algo_text, data_frequency=data_freq, sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end, freq=data_freq) output = test_algo.run(source) self.assertIsNotNone(output) # Get the volume recorded by history() within handle_data() volume_hd_0 = test_algo.volume_hd[0] volume_hd_1 = test_algo.volume_hd[1] # Get the volume recorded by history() within BTS volume_bts_0 = test_algo.volume_bts[0] volume_bts_1 = test_algo.volume_bts[1] penultimate_hd_dt = pd.Timestamp( '2006-03-21 4:00 PM', tz='US/Eastern').tz_convert('UTC') # Midnight of the day on which BTS is invoked. newest_bts_dt = normalize_date(pd.Timestamp( '2006-03-22 04:00 PM', tz='US/Eastern').tz_convert('UTC')) if data_freq == 'daily': # If we're dealing with daily data, then we record # canonicalized timestamps, so make conversion here: penultimate_hd_dt = normalize_date(penultimate_hd_dt) # When history() is called in BTS, its 'current' volume value # should equal the sum of the previous day. self.assertEquals(volume_hd_0[penultimate_hd_dt], volume_bts_0[newest_bts_dt]) self.assertEquals(volume_hd_1[penultimate_hd_dt], volume_bts_1[newest_bts_dt])
def test_history_in_bts_volume_minutes(self): """ Test calling history() in before_trading_start() with minutely volume bars. """ algo_text = """ from zipline.api import history def initialize(context): context.first_bts_call = True def before_trading_start(context, data): if not context.first_bts_call: volume_bts = history(bar_count=2, frequency='1m', field='volume') context.volume_bts = volume_bts context.first_bts_call = False def handle_data(context, data): pass """.strip() # March 2006 # Su Mo Tu We Th Fr Sa # 1 2 3 4 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30 31 start = pd.Timestamp('2006-03-20', tz='UTC') end = pd.Timestamp('2006-03-22', tz='UTC') sim_params = factory.create_simulation_parameters( start=start, end=end) test_algo = TradingAlgorithm( script=algo_text, data_frequency='minute', sim_params=sim_params, env=TestHistoryAlgo.env, ) source = RandomWalkSource(start=start, end=end) output = test_algo.run(source) self.assertIsNotNone(output) # Get the volumes recorded for sid 0 by history() within BTS volume_bts_0 = test_algo.volume_bts[0] # Get the volumes recorded for sid 1 by history() within BTS volume_bts_1 = test_algo.volume_bts[1] # The values recorded on 2006-03-22 by history() in BTS # should equal the final volume values for the trading # day 2006-03-21: # 0 1 # 2006-03-21 20:59:00 215548 439908 # 2006-03-21 21:00:00 985645 664313 # # Note: These are not 'real' volume values. They are the product of # RandonWalkSource, which produces random walk OHLCV timeseries. For a # given seed these values are deterministc. self.assertEquals(215548, volume_bts_0.ix[0]) self.assertEquals(985645, volume_bts_0.ix[1]) self.assertEquals(439908, volume_bts_1.ix[0]) self.assertEquals(664313, volume_bts_1.ix[1])