ENH: Added informative message for calling order in init.

Previously, calling order() in initalize resulted in a weird
stack trace. It now returns a well formulated error that is
readable to the user through the API. Adding a slippage
kwarg to test_algorithm and simfactor was necessary because
slippage can only be called during init. Previously initaliazed
was never set to true and calls to init-only function were sprinkled
around the code in non-init sections. Code changes were to enforce
init-only rules.
This commit is contained in:
Delaney Granizo-Mackenzie
2014-07-08 14:03:53 -04:00
parent 6baabc5975
commit 3521a11ed4
5 changed files with 54 additions and 12 deletions
+16 -1
View File
@@ -29,6 +29,7 @@ import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
from zipline.errors import (
OrderDuringInitialize,
RegisterTradingControlPostInit,
TradingControlViolation,
)
@@ -53,6 +54,7 @@ from zipline.test_algorithms import (
api_algo,
api_symbol_algo,
call_all_order_methods,
call_order_in_init,
handle_data_api,
handle_data_noop,
initialize_api,
@@ -585,7 +587,8 @@ def handle_data(context, data):
self._algo_record_float_magic_should_pass('nan')
def test_order_methods(self):
"""Only test that order methods can be called without error.
"""
Only test that order methods can be called without error.
Correct filling of orders is tested in zipline.
"""
test_algo = TradingAlgorithm(
@@ -602,6 +605,18 @@ def handle_data(context, data):
output, _ = drain_zipline(self, zipline)
def test_order_in_init(self):
"""
Test that calling order in initialize
will return an error
"""
with self.assertRaises(OrderDuringInitialize):
test_algo = TradingAlgorithm(
script=call_order_in_init,
sim_params=self.sim_params,
)
set_algo_instance(test_algo)
class TestHistory(TestCase):
def test_history(self):
+8 -1
View File
@@ -27,6 +27,7 @@ from six import iteritems, exec_
from operator import attrgetter
from zipline.errors import (
OrderDuringInitialize,
OverrideCommissionPostInit,
OverrideSlippagePostInit,
RegisterTradingControlPostInit,
@@ -76,7 +77,6 @@ DEFAULT_CAPITAL_BASE = float("1.0e5")
class TradingAlgorithm(object):
"""
Base class for trading algorithms. Inherit and overload
initialize() and handle_data(data).
@@ -531,6 +531,13 @@ class TradingAlgorithm(object):
Raises an UnsupportedOrderParameters if invalid arguments are found.
"""
# Make sure we're not in init before we order.
if not self.initialized:
raise OrderDuringInitialize(
msg="order() can only be called from within handle_data()"
)
if style:
if limit_price:
raise UnsupportedOrderParameters(
+7
View File
@@ -137,6 +137,13 @@ class UnsupportedOrderParameters(ZiplineError):
msg = "{msg}"
class OrderDuringInitialize(ZiplineError):
"""
Raised if order is called during initialize()
"""
msg = "{msg}"
class TradingControlViolation(ZiplineError):
"""
Raised if an order would violate a constraint set by a TradingControl.
+21 -2
View File
@@ -97,7 +97,12 @@ class TestAlgorithm(TradingAlgorithm):
at the close of a simulation.
"""
def initialize(self, sid, amount, order_count, sid_filter=None):
def initialize(self,
sid,
amount,
order_count,
sid_filter=None,
slippage=None):
self.count = order_count
self.sid = sid
self.amount = amount
@@ -108,6 +113,9 @@ class TestAlgorithm(TradingAlgorithm):
else:
self.sid_filter = [self.sid]
if slippage is not None:
self.set_slippage(slippage)
def handle_data(self, data):
# place an order for amount shares of sid
if self.incr < self.count:
@@ -241,7 +249,6 @@ class RecordAlgorithm(TradingAlgorithm):
class TestOrderAlgorithm(TradingAlgorithm):
def initialize(self):
self.incr = 0
self.sale_price = None
def handle_data(self, data):
if self.incr == 0:
@@ -633,6 +640,7 @@ class BatchTransformAlgorithm(TradingAlgorithm):
self.iter = 0
self.set_slippage(FixedSlippage())
self.initialized = True
def handle_data(self, data):
self.history_return_price_class.append(
@@ -943,6 +951,17 @@ def handle_data(context, data):
order(symbol(0), 1)
"""
call_order_in_init = """
from zipline.api import (order)
def initialize(context):
order(0, 10)
pass
def handle_data(context, data):
pass
"""
call_all_order_methods = """
from zipline.api import (order,
order_value,
+2 -8
View File
@@ -62,7 +62,8 @@ def create_test_zipline(**config):
order_amount,
order_count,
sim_params=config.get('sim_params',
factory.create_simulation_parameters())
factory.create_simulation_parameters()),
slippage=config.get('slippage'),
)
# -------------------
@@ -94,13 +95,6 @@ def create_test_zipline(**config):
if transforms is not None:
test_algo.set_transforms(transforms)
# -------------------
# Slippage
# ------------------
slippage = config.get('slippage', None)
if slippage is not None:
test_algo.set_slippage(slippage)
# ------------------
# generator/simulator
sim = test_algo.get_generator()