Actually you were right. I dug a bit more into the Zipline code and noticed there's a volume check in simulate()
. I'm using this code for a custom NoSlippage
class:
class NoSlippage(SlippageModel):
# Copied from slippage.NoSlippage.process_order()
@staticmethod
def process_order(data, order):
return (
data.current(order.asset, "close"),
order.amount,
)
# Original code from slippage.SlippageModel.simulate()
def simulate(self, data, asset, orders_for_asset):
self._volume_for_bar = 0
volume = data.current(asset, "volume")
# !!! IGNORE
# if volume == 0:
# return
# can use the close price, since we verified there's volume in this
# bar.
price = data.current(asset, "close")
# BEGIN
#
# Remove this block after fixing data to ensure volume always has
# corresponding price.
if pd.isnull(price):
return
# END
dt = data.current_dt
for order in orders_for_asset:
if order.open_amount == 0:
continue
order.check_triggers(price, dt)
if not order.triggered:
continue
txn = None
try:
execution_price, execution_volume = self.process_order(data, order)
if execution_price is not None:
txn = create_transaction(
order, data.current_dt, execution_price, execution_volume
)
except LiquidityExceeded:
break
if txn:
self._volume_for_bar += abs(txn.amount)
yield order, txn