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.
This commit is contained in:
Eddie Hebert
2013-06-19 16:35:05 -04:00
parent 2aa038c2a7
commit afdb6c99af
3 changed files with 68 additions and 70 deletions
+58 -58
View File
@@ -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),
+7 -4
View File
@@ -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]
+3 -8
View File
@@ -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)