From 7a5af8a09812daba75f330f763011e1f0886ad15 Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Tue, 24 Feb 2015 22:51:20 -0500 Subject: [PATCH 1/4] ENH/PRF: Allow SlippageModels to alert that no more liquidity exists and to stop processing orders --- zipline/finance/slippage.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/zipline/finance/slippage.py b/zipline/finance/slippage.py index 7ee191a4..cedcab21 100644 --- a/zipline/finance/slippage.py +++ b/zipline/finance/slippage.py @@ -150,6 +150,10 @@ def create_transaction(event, order, price, amount): return transaction +class LiquidityExceeded(Exception): + pass + + class SlippageModel(with_metaclass(abc.ABCMeta)): @property @@ -173,7 +177,10 @@ class SlippageModel(with_metaclass(abc.ABCMeta)): if not order.triggered: continue - txn = self.process_order(event, order) + try: + txn = self.process_order(event, order) + except LiquidityExceeded: + break if txn: self._volume_for_bar += abs(txn.amount) @@ -210,7 +217,7 @@ class VolumeShareSlippage(SlippageModel): remaining_volume = max_volume - self.volume_for_bar if remaining_volume < 1: # we can't fill any more transactions - return + raise LiquidityExceeded() # the current order amount will be the min of the # volume available in the bar or the open amount. From 4c5f38d7b1dac377565ec088d1fbd90b5b29fb5e Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Tue, 24 Feb 2015 23:18:55 -0500 Subject: [PATCH 2/4] MAINT: There is no place where orders are put in out of place --- zipline/finance/blotter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index a3d2a5c3..98e91420 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -20,6 +20,7 @@ from logbook import Logger from collections import defaultdict from six import text_type +from six.moves import filter import zipline.errors import zipline.protocol as zp @@ -199,7 +200,6 @@ class Blotter(object): return orders = self.open_orders[trade_event.sid] - orders = sorted(orders, key=lambda o: o.dt) # Only use orders for the current day or before current_orders = filter( lambda o: o.dt <= trade_event.dt, From 69815d1695286887a8f74f44389af1682437042d Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Tue, 24 Feb 2015 23:32:28 -0500 Subject: [PATCH 3/4] PRF: limit the subset of orders we check for bookkeeping --- zipline/finance/blotter.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index 98e91420..807e8495 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -205,19 +205,20 @@ class Blotter(object): lambda o: o.dt <= trade_event.dt, orders) + processed_orders = [] for txn, order in self.process_transactions(trade_event, current_orders): + processed_orders.append(order) yield txn, order - # update the open orders for the trade_event's sid - updated_orders = \ - [order for order - in self.open_orders[trade_event.sid] - if order.open] + # remove closed orders. we should only have to check + # processed orders + not_open = lambda order: not order.open + closed_orders = filter(not_open, processed_orders) + for order in closed_orders: + orders.remove(order) - if updated_orders: - self.open_orders[trade_event.sid] = updated_orders - else: + if len(orders) == 0: del self.open_orders[trade_event.sid] def process_transactions(self, trade_event, current_orders): From 29aab7755ff46fb643484f2c957fb7e77550a9f0 Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Wed, 25 Feb 2015 00:05:34 -0500 Subject: [PATCH 4/4] TST: updated test to the fact that we aren't creating new lists to store orders --- tests/test_finance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_finance.py b/tests/test_finance.py index 5d9eabca..3dd32c8b 100644 --- a/tests/test_finance.py +++ b/tests/test_finance.py @@ -253,7 +253,7 @@ class FinanceTestCase(TestCase): oo = blotter.open_orders self.assertEqual(len(oo), 1) self.assertTrue(sid in oo) - order_list = oo[sid] + order_list = oo[sid][:] # make copy self.assertEqual(order_count, len(order_list)) for i in range(order_count):