Thanks to Andre P., and although the docs say to use "amount" on order, the actual remaining is order.amount - order.filled.
This works:
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class PercentRangeSlippageModel(slippage.SlippageModel):
'''
Daily slippage model only
'''
def __init__(this, basisPointsDrift, pctParticipation):
this.basisPointsDrift = basisPointsDrift * .0001
this.pctParticipation = pctParticipation * .01
def process_order(this, trade_bar, order):
close = trade_bar.close_price
remainingQty = order.amount - order.filled
# Limit the quantity to 25% of the total volume
orderQuantity = int(min(remainingQty, this.pctParticipation * trade_bar.volume))
# Calculate any price impact of the order
priceImpactSlippage = min(.25, (float(remainingQty) / float(trade_bar.volume))) **2 * .1
# Calculate a rough mid point of the day's trading range
rangeMid = trade_bar.close_price * .35 \
+ trade_bar.open_price * .35 \
+ trade_bar.high * .15 \
+ trade_bar.low * .15
# Calculate a conservative price drift from the day's mid point price
drift = this.basisPointsDrift + (this.basisPointsDrift * priceImpactSlippage)
executionPrice = rangeMid + (rangeMid * drift * order.direction)
direction = "BUY" if order.direction > 0 else "SELL"
print(" {0:<4} {1:>7} @ {2:>7.2f} midPrice:{3:>7.2f} close:{4:>7.2f} barVol:{5:>10}".format(
direction, orderQuantity, executionPrice, rangeMid, close, trade_bar.volume))
return slippage.create_transaction(trade_bar, order, executionPrice, orderQuantity)