BUG: Fix emission of order updates.

The emission of order updates from the blotter were incorrect,
and subsequently, performance.

Previously, only the first action of the order was emitted,
fix so that all status updates are emitted.
This commit is contained in:
fawce
2013-04-18 16:08:44 -04:00
committed by Eddie Hebert
parent fc4d563a02
commit bc95c3a62e
3 changed files with 50 additions and 41 deletions
+1 -2
View File
@@ -551,8 +551,7 @@ class PerformancePeriod(object):
self.period_cash_flow = 0.0
self.pnl = 0.0
self.processed_transactions = []
self.placed_orders = \
[order for order in self.placed_orders if order.open]
self.placed_orders = []
self.cumulative_capital_used = 0.0
self.max_capital_used = 0.0
self.max_leverage = 0.0
+11 -18
View File
@@ -144,9 +144,6 @@ class VolumeShareSlippage(object):
if zp_math.tolerant_equals(open_amount, 0):
continue
# check price limits, continue if the
# order isn't triggered yet
order.check_triggers(event)
if not order.triggered:
continue
@@ -175,19 +172,18 @@ class VolumeShareSlippage(object):
simulated_impact = (volume_share) ** 2 \
* self.price_impact * order.direction * event.price
txn = create_transaction(
event.sid,
cur_amount,
# In the future, we may want to change the next line
# for limit pricing
event.price + simulated_impact,
dt.replace(tzinfo=pytz.utc),
order.id
)
if cur_amount > 0:
txn = create_transaction(
event.sid,
cur_amount,
# In the future, we may want to change the next line
# for limit pricing
event.price + simulated_impact,
dt.replace(tzinfo=pytz.utc),
order.id
)
# mark the last_modified date of the order to match
order.last_modified_dt = event.dt
txns.append(txn)
txns.append(txn)
return txns
@@ -210,9 +206,6 @@ class FixedSlippage(object):
# and one for 100 shares short
# such as in a hedging scenario?
# check price limits, continue if the
# order isn't triggered yet
order.check_triggers(event)
if not order.triggered:
continue
+38 -21
View File
@@ -51,9 +51,6 @@ class Blotter(object):
self.open_orders = defaultdict(list)
# keep a dict of orders by their own id
self.orders = {}
# track transactions by sid and by order
self.txns_by_sid = defaultdict(list)
self.txns_by_order = defaultdict(list)
# holding orders that have come in since the last
# event.
self.new_orders = []
@@ -72,14 +69,32 @@ class Blotter(object):
for date, snapshot in stream_in:
# relay any orders placed in prior snapshot
# handling and reset the internal holding pen
results = self.new_orders
self.new_orders = []
if self.new_orders:
yield date, self.new_orders
self.new_orders = []
results = []
for event in snapshot:
results.append(event)
# We only fill transactions on trade events.
if event.type == DATASOURCE_TYPE.TRADE:
txns = self.process_trade(event)
results.extend(txns)
modified_orders = [order for order
in self.open_orders[event.sid]
if order.last_modified_dt == date]
results.extend(modified_orders)
# update the open orders for the trade_event's sid
self.open_orders[event.sid] = [order for order
in self.open_orders[event.sid]
if order.open]
for order in modified_orders:
if not order.open:
del self.orders[order.id]
yield date, results
def process_trade(self, trade_event):
@@ -98,22 +113,15 @@ class Blotter(object):
else:
return []
for order in current_orders:
# check price limits, continue if the
# order isn't triggered yet
order.check_triggers(trade_event)
txns = self.transact(trade_event, current_orders)
for txn in txns:
self.txns_by_order[txn.order_id].append(txn)
self.txns_by_sid[txn.sid].append(txn)
self.orders[txn.order_id].filled += txn.amount
# update the open orders for the trade_event's sid
self.open_orders[trade_event.sid] = \
[order for order in orders if order.open]
# drop any filled orders.
filled = \
[order.id for order in orders if not order.open]
for order_id in filled:
del self.orders[order_id]
# mark the last_modified date of the order to match
self.orders[txn.order_id].last_modified_dt = txn.dt
return txns
@@ -129,7 +137,7 @@ class Order(object):
@filled - how many shares of the order have been filled so far
"""
# get a string representation of the uuid.
self.id = uuid.uuid4().get_hex()
self.id = self.make_id()
self.dt = dt
self.last_modified_dt = dt
self.sid = sid
@@ -143,6 +151,9 @@ class Order(object):
self.direction = math.copysign(1, self.amount)
self.type = DATASOURCE_TYPE.ORDER
def make_id(self):
return uuid.uuid4().get_hex()
def to_dict(self):
py = copy(self.__dict__)
for field in ['type', 'direction']:
@@ -154,9 +165,13 @@ class Order(object):
Update internal state based on price triggers and the
trade event's price.
"""
self.last_modified_dt = event.dt
self.stop_reached, self.limit_reached = \
stop_reached, limit_reached = \
check_order_triggers(self, event)
if (stop_reached, limit_reached) \
!= (self.stop_reached, self.limit_reached):
self.last_modified_dt = event.dt
self.stop_reached = stop_reached
self.limit_reached = limit_reached
@property
def open(self):
@@ -377,6 +392,8 @@ class AlgorithmSimulator(object):
# receives its next message.
self.blotter.place_order(order)
return order.id
def transform(self, stream_in):
"""
Main generator work loop.