From afdb6c99afad10e7d678749798125c6785b6d898 Mon Sep 17 00:00:00 2001 From: Eddie Hebert Date: Wed, 19 Jun 2013 16:35:05 -0400 Subject: [PATCH] MAINT: Return orders alongside transactions from slippage simulate. So that blotter.process_trade doesn't need to reindex the dictionary of open orders, yield a tuple of (order, transaction) from simulate. Also, update corresponding unit tests now that the method returns a generator instead of a list. --- tests/finance/test_slippage.py | 116 ++++++++++++++++----------------- zipline/finance/blotter.py | 11 ++-- zipline/finance/slippage.py | 11 +--- 3 files changed, 68 insertions(+), 70 deletions(-) diff --git a/tests/finance/test_slippage.py b/tests/finance/test_slippage.py index 193deebd..241b874d 100644 --- a/tests/finance/test_slippage.py +++ b/tests/finance/test_slippage.py @@ -57,13 +57,13 @@ class SlippageTestCase(TestCase): 'sid': 133}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( event, open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.01875), @@ -99,11 +99,11 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[2], open_orders - ) - self.assertEquals(len(txns), 0) + )) + self.assertEquals(len(orders_txns), 0) # long, does trade open_orders = [ @@ -115,13 +115,13 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[3], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + txn = orders_txns[0][1] expected_txn = { 'price': float(3.500875), @@ -148,14 +148,14 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[0], open_orders - ) + )) expected_txn = {} - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) # short, does trade @@ -168,13 +168,13 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[1], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.499125), @@ -205,12 +205,12 @@ class SlippageTestCase(TestCase): 'stop': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[2], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) # long, does trade @@ -224,13 +224,13 @@ class SlippageTestCase(TestCase): }) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[3], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.500875), @@ -255,12 +255,12 @@ class SlippageTestCase(TestCase): 'stop': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[0], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) # short, does trade @@ -273,13 +273,13 @@ class SlippageTestCase(TestCase): 'stop': 3.4}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[1], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.499125), @@ -309,19 +309,19 @@ class SlippageTestCase(TestCase): 'limit': 3.0}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[2], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[3], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) # long, does trade @@ -335,20 +335,20 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[2], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[3], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.500875), @@ -373,19 +373,19 @@ class SlippageTestCase(TestCase): 'limit': 4.0}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[0], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[1], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) # short, does trade @@ -399,20 +399,20 @@ class SlippageTestCase(TestCase): 'limit': 3.5}) ] - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[0], open_orders - ) + )) - self.assertEquals(len(txns), 0) + self.assertEquals(len(orders_txns), 0) - txns = slippage_model.simulate( + orders_txns = list(slippage_model.simulate( events[1], open_orders - ) + )) - self.assertEquals(len(txns), 1) - txn = txns[0] + self.assertEquals(len(orders_txns), 1) + _, txn = orders_txns[0] expected_txn = { 'price': float(3.499125), diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index 6f4bcfd2..bdefba40 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -160,12 +160,15 @@ class Blotter(object): else: return [], [] - txns = self.transact(trade_event, current_orders) - for txn in txns: - self.orders[txn.order_id].filled += txn.amount + txns = [] + + for order, txn in self.transact(trade_event, current_orders): + order.filled += txn.amount # mark the date of the order to match the transaction # that is filling it. - self.orders[txn.order_id].dt = txn.dt + order.dt = txn.dt + + txns.append(txn) modified_orders = [order for order in self.open_orders[trade_event.sid] diff --git a/zipline/finance/slippage.py b/zipline/finance/slippage.py index d28cded4..b4c2895a 100644 --- a/zipline/finance/slippage.py +++ b/zipline/finance/slippage.py @@ -62,9 +62,7 @@ def transact_stub(slippage, commission, event, open_orders): This is intended to be wrapped in a partial, so that the slippage and commission models can be enclosed. """ - transactions = slippage(event, open_orders) - - for transaction in transactions: + for order, transaction in slippage(event, open_orders): if ( transaction and not @@ -74,7 +72,7 @@ def transact_stub(slippage, commission, event, open_orders): per_share, total_commission = commission.calculate(transaction) transaction.price = transaction.price + (per_share * direction) transaction.commission = total_commission - return transactions + yield order, transaction def transact_partial(slippage, commission): @@ -139,7 +137,6 @@ class SlippageModel(object): self._volume_for_bar = 0 - txns = [] for order in current_orders: open_amount = order.amount - order.filled @@ -154,10 +151,8 @@ class SlippageModel(object): txn = self.process_order(event, order) if txn: - txns.append(txn) self._volume_for_bar += abs(txn.amount) - - return txns + yield order, txn def __call__(self, event, current_orders, **kwargs): return self.simulate(event, current_orders, **kwargs)