From f3cfc9623d67bc4160039c2088dd748a79cd6a67 Mon Sep 17 00:00:00 2001 From: fawce Date: Fri, 26 Apr 2013 14:21:55 -0400 Subject: [PATCH] ENH: new order management methods: - get_open_orders - get_order - cancel --- zipline/algorithm.py | 2 +- zipline/finance/blotter.py | 45 +++++++++++++++++++++++--------------- zipline/protocol.py | 4 ++++ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/zipline/algorithm.py b/zipline/algorithm.py index 33cbca38..9f8b325f 100644 --- a/zipline/algorithm.py +++ b/zipline/algorithm.py @@ -321,7 +321,7 @@ class TradingAlgorithm(object): self._recorded_vars[name] = value def order(self, sid, amount, limit_price=None, stop_price=None): - self.blotter.order(sid, amount, limit_price, stop_price) + return self.blotter.order(sid, amount, limit_price, stop_price) @property def recorded_vars(self): diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index d327219b..af4d5ad2 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -20,6 +20,7 @@ from logbook import Logger from collections import defaultdict from zipline.protocol import DATASOURCE_TYPE +from zipline.protocol import Order as zpOrder from zipline.finance.slippage import ( VolumeShareSlippage, @@ -35,7 +36,8 @@ from zipline.utils.protocol_utils import Enum ORDER_STATUS = Enum( 'OPEN', - 'FILLED' + 'FILLED', + 'CANCELLED' ) @@ -52,12 +54,6 @@ class Blotter(object): self.new_orders = [] self.current_dt = None - def cancel_order(self, order_id): - order = self.orders[order_id] - if order.open: - order_list = self.open_orders[order.sid] - order_list.remove(order) - def set_date(self, dt): self.current_dt = dt @@ -103,6 +99,21 @@ class Blotter(object): return order.id + def cancel(self, order_id): + cur_order = self.orders[order_id] + if cur_order.open: + order_list = self.open_orders[cur_order.sid] + if cur_order in order_list: + order_list.remove(cur_order) + + if cur_order in self.new_orders: + self.new_orders.remove(cur_order) + cur_order.status = ORDER_STATUS.CANCELLED + cur_order.dt = self.current_dt + # we want this order's new status to be relayed out + # along with newly placed orders. + self.new_orders.append(cur_order) + def process_trade(self, trade_event): if trade_event.type != DATASOURCE_TYPE.TRADE: return [], [] @@ -133,13 +144,6 @@ class Blotter(object): in self.open_orders[trade_event.sid] if order.dt == trade_event.dt] - # TODO: without this limit, orders can grow in memory - # unchecked. Taking it out so that it is easy to find - # orders by id during a running test. - # for order in modified_orders: - # if not order.open: - # del self.orders[order.id] - # update the open orders for the trade_event's sid self.open_orders[trade_event.sid] = \ [order for order @@ -183,6 +187,11 @@ class Order(object): del py[field] return py + def to_api_obj(self): + pydict = self.to_dict() + obj = zpOrder(initial_values=pydict) + return obj + def check_triggers(self, event): """ Update internal state based on price triggers and the @@ -198,6 +207,9 @@ class Order(object): @property def open(self): + if self.status == ORDER_STATUS.CANCELLED: + return False + remainder = self.amount - self.filled if remainder != 0: self.status = ORDER_STATUS.OPEN @@ -212,7 +224,7 @@ class Order(object): For a market order, True. For a stop order, True IFF stop_reached. For a limit order, True IFF limit_reached. - For a stop-limit order, True IFF (stp_reached AND limit_reached) + For a stop-limit order, True IFF (stop_reached AND limit_reached) """ if self.stop and not self.stop_reached: return False @@ -221,6 +233,3 @@ class Order(object): return False return True - - def __getitem__(self, name): - return self.__dict__[name] diff --git a/zipline/protocol.py b/zipline/protocol.py index f0e79244..ec052721 100644 --- a/zipline/protocol.py +++ b/zipline/protocol.py @@ -62,6 +62,10 @@ class Event(object): return "Event({0})".format(self.__dict__) +class Order(Event): + pass + + class Portfolio(object): def __init__(self, initial_values=None):