ENH: Add style parameters to order API helper methods.

Add `style` parameter to order_value, order_percent, order_target,
order_target_percent, and order_target_value methods.  The style parameter is
forwarded to the underlying call to `order`.
This commit is contained in:
Scott Sanderson
2014-04-17 14:26:36 -04:00
parent 119a1a4cda
commit f1fafc34ce
3 changed files with 89 additions and 14 deletions
+19
View File
@@ -26,6 +26,7 @@ import zipline.utils.simfactory as simfactory
from zipline.test_algorithms import (TestRegisterTransformAlgorithm,
RecordAlgorithm,
TestOrderAlgorithm,
TestOrderStyleForwardingAlgorithm,
TestOrderInstantAlgorithm,
TestOrderValueAlgorithm,
TestTargetAlgorithm,
@@ -211,6 +212,24 @@ class TestTransformAlgorithm(TestCase):
)
algo.run(self.df)
def test_order_method_style_forwarding(self):
method_names_to_test = ['order',
'order_value',
'order_percent',
'order_target',
'order_target_percent',
'order_target_value']
for name in method_names_to_test:
algo = TestOrderStyleForwardingAlgorithm(
sim_params=self.sim_params,
data_frequency='daily',
instant_fill=False,
method_name=name
)
algo.run(self.df)
def test_order_instant(self):
algo = TestOrderInstantAlgorithm(sim_params=self.sim_params,
data_frequency='daily',
+38 -14
View File
@@ -537,7 +537,8 @@ class TradingAlgorithm(object):
return MarketOrder()
@api_method
def order_value(self, sid, value, limit_price=None, stop_price=None):
def order_value(self, sid, value,
limit_price=None, stop_price=None, style=None):
"""
Place an order by desired value rather than desired number of shares.
If the requested sid is found in the universe, the requested value is
@@ -561,7 +562,10 @@ class TradingAlgorithm(object):
return
else:
amount = value / last_price
return self.order(sid, amount, limit_price, stop_price)
return self.order(sid, amount,
limit_price=limit_price,
stop_price=stop_price,
style=style)
@property
def recorded_vars(self):
@@ -639,7 +643,8 @@ class TradingAlgorithm(object):
self.annualizer = ANNUALIZER[self.data_frequency]
@api_method
def order_percent(self, sid, percent, limit_price=None, stop_price=None):
def order_percent(self, sid, percent,
limit_price=None, stop_price=None, style=None):
"""
Place an order in the specified security corresponding to the given
percent of the current portfolio value.
@@ -647,10 +652,14 @@ class TradingAlgorithm(object):
Note that percent must expressed as a decimal (0.50 means 50\%).
"""
value = self.portfolio.portfolio_value * percent
return self.order_value(sid, value, limit_price, stop_price)
return self.order_value(sid, value,
limit_price=limit_price,
stop_price=stop_price,
style=style)
@api_method
def order_target(self, sid, target, limit_price=None, stop_price=None):
def order_target(self, sid, target,
limit_price=None, stop_price=None, style=None):
"""
Place an order to adjust a position to a target number of shares. If
the position doesn't already exist, this is equivalent to placing a new
@@ -661,13 +670,19 @@ class TradingAlgorithm(object):
if sid in self.portfolio.positions:
current_position = self.portfolio.positions[sid].amount
req_shares = target - current_position
return self.order(sid, req_shares, limit_price, stop_price)
return self.order(sid, req_shares,
limit_price=limit_price,
stop_price=stop_price,
style=style)
else:
return self.order(sid, target, limit_price, stop_price)
return self.order(sid, target,
limit_price=limit_price,
stop_price=stop_price,
style=style)
@api_method
def order_target_value(self, sid, target, limit_price=None,
stop_price=None):
def order_target_value(self, sid, target,
limit_price=None, stop_price=None, style=None):
"""
Place an order to adjust a position to a target value. If
the position doesn't already exist, this is equivalent to placing a new
@@ -680,13 +695,19 @@ class TradingAlgorithm(object):
current_price = self.trading_client.current_data[sid].price
current_value = current_position * current_price
req_value = target - current_value
return self.order_value(sid, req_value, limit_price, stop_price)
return self.order_value(sid, req_value,
limit_price=limit_price,
stop_price=stop_price,
style=style)
else:
return self.order_value(sid, target, limit_price, stop_price)
return self.order_value(sid, target,
limit_price=limit_price,
stop_price=stop_price,
style=style)
@api_method
def order_target_percent(self, sid, target, limit_price=None,
stop_price=None):
def order_target_percent(self, sid, target,
limit_price=None, stop_price=None, style=None):
"""
Place an order to adjust a position to a target percent of the
current portfolio value. If the position doesn't already exist, this is
@@ -705,7 +726,10 @@ class TradingAlgorithm(object):
target_value = self.portfolio.portfolio_value * target
req_value = target_value - current_value
return self.order_value(sid, req_value, limit_price, stop_price)
return self.order_value(sid, req_value,
limit_price=limit_price,
stop_price=stop_price,
style=style)
@api_method
def get_open_orders(self, sid=None):
+32
View File
@@ -79,6 +79,7 @@ from six import itervalues
from zipline.algorithm import TradingAlgorithm
from zipline.api import FixedSlippage
from zipline.finance.execution import StopLimitOrder
class TestAlgorithm(TradingAlgorithm):
@@ -261,6 +262,37 @@ class TestOrderInstantAlgorithm(TradingAlgorithm):
self.last_price = data[0].price
class TestOrderStyleForwardingAlgorithm(TradingAlgorithm):
"""
Test Algorithm for verifying that ExecutionStyles are properly forwarded by
order API helper methods. Pass the name of the method to be tested as a
string parameter to this algorithm's constructor.
"""
def __init__(self, *args, **kwargs):
self.method_name = kwargs.pop('method_name')
super(TestOrderStyleForwardingAlgorithm, self)\
.__init__(*args, **kwargs)
def initialize(self):
self.incr = 0
self.last_price = None
def handle_data(self, data):
if self.incr == 0:
assert len(self.portfolio.positions.keys()) == 0
method_to_check = getattr(self, self.method_name)
method_to_check(0, data[0].price, style=StopLimitOrder(10, 10))
assert len(self.blotter.open_orders[0]) == 1
result = self.blotter.open_orders[0][0]
assert result.limit == 10
assert result.stop == 10
self.incr += 1
class TestOrderValueAlgorithm(TradingAlgorithm):
def initialize(self):
self.incr = 0