diff --git a/zipline/finance/order.py b/zipline/finance/order.py index aaefc827..d6ff5ab0 100644 --- a/zipline/finance/order.py +++ b/zipline/finance/order.py @@ -18,7 +18,6 @@ import uuid from six import text_type, iteritems -from zipline.finance.slippage import check_order_triggers import zipline.protocol as zp from zipline.utils.serialization_utils import VERSION_LABEL from zipline.utils.enum import enum @@ -31,6 +30,11 @@ ORDER_STATUS = enum( 'HELD', ) +SELL = 1 << 0 +BUY = 1 << 1 +STOP = 1 << 2 +LIMIT = 1 << 3 + class Order(object): def __init__(self, dt, sid, amount, stop=None, limit=None, filled=0, @@ -81,7 +85,7 @@ class Order(object): trade event's price. """ stop_reached, limit_reached, sl_stop_reached = \ - check_order_triggers(self, event) + self.check_order_triggers(event) if (stop_reached, limit_reached) \ != (self.stop_reached, self.limit_reached): self.dt = event.dt @@ -91,6 +95,65 @@ class Order(object): # Change the STOP LIMIT order into a LIMIT order self.stop = None + def check_order_triggers(self, event): + """ + Given an order and a trade event, return a tuple of + (stop_reached, limit_reached). + For market orders, will return (False, False). + For stop orders, limit_reached will always be False. + For limit orders, stop_reached will always be False. + For stop limit orders a Boolean is returned to flag + that the stop has been reached. + + Orders that have been triggered already (price targets reached), + the order's current values are returned. + """ + if self.triggered: + return (self.stop_reached, self.limit_reached, False) + + stop_reached = False + limit_reached = False + sl_stop_reached = False + + order_type = 0 + + if self.amount > 0: + order_type |= BUY + else: + order_type |= SELL + + if self.stop is not None: + order_type |= STOP + + if self.limit is not None: + order_type |= LIMIT + + if order_type == BUY | STOP | LIMIT: + if event.price >= self.stop: + sl_stop_reached = True + if event.price <= self.limit: + limit_reached = True + elif order_type == SELL | STOP | LIMIT: + if event.price <= self.stop: + sl_stop_reached = True + if event.price >= self.limit: + limit_reached = True + elif order_type == BUY | STOP: + if event.price >= self.stop: + stop_reached = True + elif order_type == SELL | STOP: + if event.price <= self.stop: + stop_reached = True + elif order_type == BUY | LIMIT: + if event.price <= self.limit: + limit_reached = True + elif order_type == SELL | LIMIT: + # This is a SELL LIMIT order + if event.price >= self.limit: + limit_reached = True + + return (stop_reached, limit_reached, sl_stop_reached) + def handle_split(self, split_event): ratio = split_event.ratio diff --git a/zipline/finance/slippage.py b/zipline/finance/slippage.py index 772d9e85..6bea1caf 100644 --- a/zipline/finance/slippage.py +++ b/zipline/finance/slippage.py @@ -34,66 +34,6 @@ STOP = 1 << 2 LIMIT = 1 << 3 -def check_order_triggers(order, event): - """ - Given an order and a trade event, return a tuple of - (stop_reached, limit_reached). - For market orders, will return (False, False). - For stop orders, limit_reached will always be False. - For limit orders, stop_reached will always be False. - For stop limit orders a Boolean is returned to flag - that the stop has been reached. - - Orders that have been triggered already (price targets reached), - the order's current values are returned. - """ - if order.triggered: - return (order.stop_reached, order.limit_reached, False) - - stop_reached = False - limit_reached = False - sl_stop_reached = False - - order_type = 0 - - if order.amount > 0: - order_type |= BUY - else: - order_type |= SELL - - if order.stop is not None: - order_type |= STOP - - if order.limit is not None: - order_type |= LIMIT - - if order_type == BUY | STOP | LIMIT: - if event.price >= order.stop: - sl_stop_reached = True - if event.price <= order.limit: - limit_reached = True - elif order_type == SELL | STOP | LIMIT: - if event.price <= order.stop: - sl_stop_reached = True - if event.price >= order.limit: - limit_reached = True - elif order_type == BUY | STOP: - if event.price >= order.stop: - stop_reached = True - elif order_type == SELL | STOP: - if event.price <= order.stop: - stop_reached = True - elif order_type == BUY | LIMIT: - if event.price <= order.limit: - limit_reached = True - elif order_type == SELL | LIMIT: - # This is a SELL LIMIT order - if event.price >= order.limit: - limit_reached = True - - return (stop_reached, limit_reached, sl_stop_reached) - - def transact_stub(slippage, commission, event, open_orders): """ This is intended to be wrapped in a partial, so that the