Back to Community
Percent range slippage model -- USE order.amount - order.filled

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)

Clone Algorithm
3
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
def initialize(context):
    set_slippage(PercentRangeSlippageModel(25, .1))
    context.security = symbol('PCLN')
    #context.security = symbol('ZAGG')
    
def handle_data(context, data):
    record(Leverage = context.account.leverage)
    
    if (get_open_orders(context.security)):
        return
    if (get_datetime().day == 17 and get_datetime().month == 6):
        order_target_percent(context.security, 0)
    else:
        order_target_percent(context.security, 1)
   
        
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
        
        # Limit the quantity to 25% of the total volume
        orderQuantity = int(min(order.amount, this.pctParticipation * trade_bar.volume))
        
        # Calculate any price impact of the order
        priceImpactSlippage =  min(.25, (float(order.amount) / 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)
There was a runtime error.
2 responses

It is not order.amount that should change after an order is filled in full or part, but order.filled. See "Order object" at https://www.quantopian.com/help.

Perhaps you should replace order.amount with order.amount-order.filled, the number of shares not filled yet, in lines 30 and 33.

Edit: I know this is what an order object looks like from within handle_data. I don't know what process_order gets, or is supposed to get, after an order is partially filled. You could print order at the beginning to find out.

If your slippage model doesn't place a transaction for the full amount of the order, the order stays open with an updated amount value, and will be passed to process_order on the next bar. Orders that have limits that have not been reached will not be passed to process_order. Finally, if your transaction has 0 shares or more shares than the original order amount, an exception will be thrown.

The doc is wrong. Andre is right. One must use the following when processing a large order.

remainingQty = order.amount - order.filled