From 45844bac31b12fd32a8d99d9ff05d93300e6cc1f Mon Sep 17 00:00:00 2001 From: Jamie Kirkpatrick Date: Tue, 31 Dec 2013 19:11:40 +0000 Subject: [PATCH 1/3] BUG: adjust benchmark events to match market hours Previously benchmark events were emitted at 0:00 on the day the benchmark related to: in 'minute' emission mode this meant that the benchmarks were emitted before any intra-day trades were processed. See: https://github.com/quantopian/zipline/issues/241 --- tests/test_algorithm_gen.py | 14 ++++++++++++++ zipline/algorithm.py | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/test_algorithm_gen.py b/tests/test_algorithm_gen.py index c878d3a5..dac9b0ae 100644 --- a/tests/test_algorithm_gen.py +++ b/tests/test_algorithm_gen.py @@ -159,3 +159,17 @@ class AlgorithmGeneratorTestCase(TestCase): gen = algo.get_generator() results = list(gen) self.assertEqual(results[-2]['progress'], 1.0) + + def test_benchmark_times_match_market_close_for_minutely_data(self): + """ + Benchmark dates should be adjusted so that benchmark events are + emitted at the end of each trading day when working with minutely + data. + Verification relies on the fact that there are no trades so + algo.datetime should be equal to the last benchmark time. + See https://github.com/quantopian/zipline/issues/241 + """ + sim_params = factory.create_simulation_parameters(num_days=1) + algo = TestAlgo(self, sim_params=sim_params, data_frequency='minute') + algo.run(source=[]) + self.assertEqual(algo.datetime, sim_params.last_close) diff --git a/zipline/algorithm.py b/zipline/algorithm.py index 01b1fc54..14f27431 100644 --- a/zipline/algorithm.py +++ b/zipline/algorithm.py @@ -227,8 +227,13 @@ class TradingAlgorithm(object): skipped. """ if self.benchmark_return_source is None: + env = trading.environment + if self.data_frequency == 'minute': + update_time = lambda date: env.get_open_and_close(date)[1] + else: + update_time = lambda date: date benchmark_return_source = [ - Event({'dt': dt, + Event({'dt': update_time(dt), 'returns': ret, 'type': zipline.protocol.DATASOURCE_TYPE.BENCHMARK, 'source_id': 'benchmarks'}) From 147242339da7663da2b7d9df219aa536e2bff852 Mon Sep 17 00:00:00 2001 From: Jamie Kirkpatrick Date: Thu, 2 Jan 2014 13:30:31 +0000 Subject: [PATCH 2/3] BUG: ensure perf stats are generated for all days When running with minutely emissions the simulator would report to the user that it simulated 'n - 1' days (where n is the number of days specified in the simulation params). Now the correct number of trading days are reported as being simulated. --- tests/test_tradesimulation.py | 28 ++++++++++++++++++++++++++++ zipline/algorithm.py | 5 ++++- zipline/gens/tradesimulation.py | 2 +- zipline/test_algorithms.py | 3 +++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/test_tradesimulation.py diff --git a/tests/test_tradesimulation.py b/tests/test_tradesimulation.py new file mode 100644 index 00000000..24dcf006 --- /dev/null +++ b/tests/test_tradesimulation.py @@ -0,0 +1,28 @@ +# +# Copyright 2014 Quantopian, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import TestCase +from zipline.test_algorithms import NoopAlgorithm +from zipline.utils import factory + + +class TestTradeSimulation(TestCase): + + def test_minutely_emissions_generate_performance_stats_for_last_day(self): + params = factory.create_simulation_parameters(num_days=1) + params.emission_rate = 'minute' + algo = NoopAlgorithm() + algo.run(source=[], sim_params=params) + self.assertEqual(algo.perf_tracker.day_count, 1.0) diff --git a/zipline/algorithm.py b/zipline/algorithm.py index 14f27431..829d5f0b 100644 --- a/zipline/algorithm.py +++ b/zipline/algorithm.py @@ -59,6 +59,7 @@ DEFAULT_CAPITAL_BASE = float("1.0e5") class TradingAlgorithm(object): + """ Base class for trading algorithms. Inherit and overload initialize() and handle_data(data). @@ -83,6 +84,7 @@ class TradingAlgorithm(object): stats = my_algo.run(data) """ + def __init__(self, *args, **kwargs): """Initialize sids and other state variables. @@ -228,7 +230,8 @@ class TradingAlgorithm(object): """ if self.benchmark_return_source is None: env = trading.environment - if self.data_frequency == 'minute': + if (self.data_frequency == 'minute' + or sim_params.emission_rate == 'minute'): update_time = lambda date: env.get_open_and_close(date)[1] else: update_time = lambda date: date diff --git a/zipline/gens/tradesimulation.py b/zipline/gens/tradesimulation.py index 715ec468..c95b63de 100644 --- a/zipline/gens/tradesimulation.py +++ b/zipline/gens/tradesimulation.py @@ -188,7 +188,7 @@ class AlgorithmSimulator(object): yield daily_rollup tp = self.algo.perf_tracker.todays_performance tp.rollover() - if mkt_close < self.algo.perf_tracker.last_close: + if mkt_close <= self.algo.perf_tracker.last_close: _, mkt_close = \ trading.environment.next_open_and_close( mkt_close diff --git a/zipline/test_algorithms.py b/zipline/test_algorithms.py index 614476ea..00f62304 100644 --- a/zipline/test_algorithms.py +++ b/zipline/test_algorithms.py @@ -134,6 +134,9 @@ class NoopAlgorithm(TradingAlgorithm): def set_transact_setter(self, txn_sim_callable): pass + def handle_data(self, data): + pass + class ExceptionAlgorithm(TradingAlgorithm): """ From 734abb2800038c1122e61a5cc21d4f929b5d2fbe Mon Sep 17 00:00:00 2001 From: twiecki Date: Thu, 30 Jan 2014 16:33:49 -0500 Subject: [PATCH 3/3] BUG: NoopAlgorithm requires initialize(). --- zipline/test_algorithms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zipline/test_algorithms.py b/zipline/test_algorithms.py index 00f62304..3b74d70f 100644 --- a/zipline/test_algorithms.py +++ b/zipline/test_algorithms.py @@ -131,6 +131,9 @@ class NoopAlgorithm(TradingAlgorithm): def get_sid_filter(self): return [] + def initialize(self): + pass + def set_transact_setter(self, txn_sim_callable): pass