From 8e39af906f05ee3b90151b42d5f4064f2523cf7e Mon Sep 17 00:00:00 2001 From: Thomas Wiecki Date: Thu, 27 Jun 2013 10:36:57 -0400 Subject: [PATCH] ENH: Move blotter call to after handle_data() and add fill_delay option. --- zipline/finance/blotter.py | 9 +++++++-- zipline/gens/tradesimulation.py | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/zipline/finance/blotter.py b/zipline/finance/blotter.py index 29ac0094..fe9112bd 100644 --- a/zipline/finance/blotter.py +++ b/zipline/finance/blotter.py @@ -18,6 +18,7 @@ import uuid from copy import copy from logbook import Logger from collections import defaultdict +from datetime import timedelta import zipline.errors import zipline.protocol as zp @@ -43,7 +44,7 @@ ORDER_STATUS = Enum( class Blotter(object): - def __init__(self): + def __init__(self, fill_delay=timedelta(minutes=1)): self.transact = transact_partial(VolumeShareSlippage(), PerShare()) # these orders are aggregated by sid self.open_orders = defaultdict(list) @@ -55,6 +56,8 @@ class Blotter(object): self.current_dt = None self.max_shares = int(1e+11) + self.fill_delay = fill_delay + def __repr__(self): return """ {class_name}( @@ -155,8 +158,10 @@ class Blotter(object): orders = self.open_orders[trade_event.sid] orders = sorted(orders, key=lambda o: o.dt) # Only use orders for the current day or before + # Since orders generally do not get filled immediately, + # we allow for a delay here. current_orders = filter( - lambda o: o.dt <= trade_event.dt, + lambda o: o.dt + self.fill_delay <= trade_event.dt, orders) else: return diff --git a/zipline/gens/tradesimulation.py b/zipline/gens/tradesimulation.py index 167e73c3..80a697f9 100644 --- a/zipline/gens/tradesimulation.py +++ b/zipline/gens/tradesimulation.py @@ -110,7 +110,7 @@ class AlgorithmSimulator(object): self.algo.perf_tracker.process_event(event) else: - + events = [] for event in snapshot: if event.type in (DATASOURCE_TYPE.TRADE, DATASOURCE_TYPE.CUSTOM): @@ -120,11 +120,9 @@ class AlgorithmSimulator(object): self.algo.set_datetime(event.dt) bm_updated = True - process_trade = self.algo.blotter.process_trade - for txn, order in process_trade(event): - self.algo.perf_tracker.process_event(txn) - self.algo.perf_tracker.process_event(order) - self.algo.perf_tracker.process_event(event) + # Save events to stream through blotter below. + events.append(event) + # Update our portfolio. self.algo.set_portfolio( @@ -145,6 +143,17 @@ class AlgorithmSimulator(object): self.algo.perf_tracker.process_event(order) self.algo.blotter.new_orders = [] + # Fill orders + for event in events: + process_trade = self.algo.blotter.process_trade + for txn, order in process_trade(event): + + self.algo.perf_tracker.process_event(txn) + self.algo.perf_tracker.process_event(order) + + self.algo.perf_tracker.process_event(event) + + # The benchmark is our internal clock. When it # updates, we need to emit a performance message. if bm_updated: