From 83d70f4a7081eff694ca445d8b3f8795d21be16b Mon Sep 17 00:00:00 2001 From: Jean Bredeche Date: Tue, 10 May 2016 09:14:38 -0400 Subject: [PATCH] DEV: pull remove-open-orders logic into its own method And test it. --- tests/test_blotter.py | 34 ++++++++++++++++++++++++++++++--- tests/test_finance.py | 4 +++- zipline/finance/blotter.py | 24 ++++++++++++++++++----- zipline/gens/tradesimulation.py | 4 +++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/tests/test_blotter.py b/tests/test_blotter.py index f1576b1b..a42c5ef9 100644 --- a/tests/test_blotter.py +++ b/tests/test_blotter.py @@ -17,7 +17,7 @@ from nose_parameterized import parameterized import pandas as pd from zipline.finance.blotter import Blotter -from zipline.finance.order import ORDER_STATUS +from zipline.finance.order import ORDER_STATUS, Order from zipline.finance.execution import ( LimitOrder, MarketOrder, @@ -224,9 +224,10 @@ class BlotterTestCase(WithLogger, lambda: self.sim_params.trading_days[-1], self.sim_params.data_frequency, ) - txns, _ = blotter.get_transactions(bar_data) + txns, _, closed_orders = blotter.get_transactions(bar_data) for txn in txns: filled_order = blotter.orders[txn.order_id] + blotter.prune_orders(closed_orders) self.assertEqual(filled_order.id, filled_id) self.assertIn(filled_order, blotter.new_orders) @@ -298,7 +299,7 @@ class BlotterTestCase(WithLogger, lambda: dt, self.sim_params.data_frequency, ) - txns, _ = blotter.get_transactions(bar_data) + txns, _, _ = blotter.get_transactions(bar_data) for txn in txns: filled_order = blotter.orders[txn.order_id] @@ -306,3 +307,30 @@ class BlotterTestCase(WithLogger, self.assertEqual(filled_order.status, expected_status) self.assertEqual(filled_order.filled, expected_filled) self.assertEqual(filled_order.open_amount, expected_open) + + def test_prune_orders(self): + blotter = Blotter(self.sim_params.data_frequency, + self.env.asset_finder) + + asset_24 = blotter.asset_finder.retrieve_asset(24) + asset_25 = blotter.asset_finder.retrieve_asset(25) + + blotter.order(asset_24, 100, MarketOrder()) + open_order = blotter.open_orders[asset_24][0] + + blotter.prune_orders([]) + self.assertEqual(1, len(blotter.open_orders[asset_24])) + + blotter.prune_orders([open_order]) + self.assertEqual(0, len(blotter.open_orders[asset_24])) + + # prune an order that isn't in our our open orders list, make sure + # nothing blows up + + other_order = Order( + dt=blotter.current_dt, + sid=asset_25, + amount=1 + ) + + blotter.prune_orders([other_order]) diff --git a/tests/test_finance.py b/tests/test_finance.py index fc32934c..2e6095ab 100644 --- a/tests/test_finance.py +++ b/tests/test_finance.py @@ -309,11 +309,13 @@ class FinanceTestCase(WithLogger, lambda: tick, sim_params.data_frequency ) - txns, _ = blotter.get_transactions(bar_data) + txns, _, closed_orders = blotter.get_transactions(bar_data) for txn in txns: tracker.process_transaction(txn) transactions.append(txn) + blotter.prune_orders(closed_orders) + for i in range(order_count): order = order_list[i] self.assertEqual(order.sid, sid) diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index 52c06be5..057fb9d6 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -296,6 +296,9 @@ class Blotter(object): parameters. If there are no commission events (because, for example, Zipline models the commission cost into the fill price of the transaction), then this is None. + + closed_orders: List + closed_orders: list of all the orders that have filled. """ closed_orders = [] @@ -329,13 +332,27 @@ class Blotter(object): if not order.open: closed_orders.append(order) + return transactions, None, closed_orders + + def prune_orders(self, closed_orders): + """ + Removes all given orders from the blotter's open_orders list. + + Parameters + ---------- + closed_orders: iterable of orders that are closed. + + Returns + ------- + None + """ # remove all closed orders from our open_orders dict for order in closed_orders: sid = order.sid + sid_orders = self.open_orders[sid] try: - sid_orders = self.open_orders[sid] sid_orders.remove(order) - except KeyError: + except ValueError: continue # now clear out the sids from our open_orders dict that have @@ -343,6 +360,3 @@ class Blotter(object): for sid in list(self.open_orders.keys()): if len(self.open_orders[sid]) == 0: del self.open_orders[sid] - - # FIXME this API doesn't feel right (returning two things here) - return transactions, None diff --git a/zipline/gens/tradesimulation.py b/zipline/gens/tradesimulation.py index 431350a2..44e7e0f1 100644 --- a/zipline/gens/tradesimulation.py +++ b/zipline/gens/tradesimulation.py @@ -110,9 +110,11 @@ class AlgorithmSimulator(object): # handle any transactions and commissions coming out new orders # placed in the last bar - new_transactions, new_commissions = \ + new_transactions, new_commissions, closed_orders = \ blotter.get_transactions(current_data) + blotter.prune_orders(closed_orders) + for transaction in new_transactions: perf_tracker.process_transaction(transaction)