Back to Community
Fading the Gap Algo Bug?

Cannot figure out why my portfolio doubles in size with two short sales in a row.

Log output:

2013-06-07PRINTPrev Hi: 217.93  
2013-06-07PRINTOpen: 219.03  
2013-06-07PRINTBuy Short on 2013-06-07 13:31:00+00:00  
2013-06-07PRINTPortfolio value: 10214.7381812  
2013-06-07PRINTPosition shares: -46.6362515691  
2013-06-07PRINT----  
2013-06-07PRINTPortfolio value: 20314.4238187  
2013-06-07PRINTPosition shares: -46  
2013-06-07PRINTSell- cover short on 2013-06-07 13:36:00+00:00  
2013-06-07PRINTTarget: 217.93  
2013-06-07PRINTCurrent: 217.401  
2013-06-07PRINTPortfolio value: 20314.4238187  
2013-06-07PRINTPosition shares: 46  

My algo should only have one position open at a time. Looks like for some reason a position is not closing out and begins building and borrowing to do so.

What is the best way to ensure no cash is borrowed, and positions are closed out before another position is opened?

Thanks

Clone Algorithm
6
Loading...
Backtest from to with initial capital
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
hold_period = 15 # hold period in days
threshold = 5 # price difference threshold in percent
import pytz
EST = pytz.timezone('US/Eastern')
import datetime


def initialize(context):
    
    context.stocks = [sid(23709)] # NFLX
    
    context.previous_price = 1
    context.previous_hi = 0
    context.previous_lo = 0
    context.initialize = True
    context.event_day = 0
    context.new_day = False
    context.day_counter = 0
    context.bought = False
    context.day_submitted = 0
    context.num_shares = 0
    context.gapup = False
    context.gapdown = False
    context.hi = 0
    context.lo = 0
    context.target = 0
    context.max_notional = 10000.1  
    context.min_notional = -1.0
    
    
def handle_data(context, data):
    event_datetime = data[context.stocks[0]].datetime
    current_price = data[context.stocks[0]].price
    context.hi = data[context.stocks[0]].high
    context.lo = data[context.stocks[0]].low
    
    
    
    
    event_day = data[context.stocks[0]].datetime.day
    
    if context.initialize:
        context.event_day = event_day
        context.initialize = False 
    
    if event_day != context.event_day:
        context.new_day = True
    else:
        context.new_day = False
        
    if context.new_day and not(context.day_counter==1):
        context.day_counter = context.day_counter + 1
        
        if current_price > context.previous_hi:
            context.target = context.previous_hi
            if not (context.bought):
                order(context.stocks[0],-context.portfolio.cash/current_price)
                context.gapup = True
                print '----'
                print 'Prev Hi: ' + str(context.previous_hi)
                print 'Open: ' + str(current_price)
                context.bought = True
                print 'Buy Short on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(-context.portfolio.cash/current_price)
            elif context.gapup == True and context.bought:
                order(context.stocks[0],context.portfolio.positions[context.stocks[0]].amount)
                context.bought = False
                context.gapup = False
                print '----'
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Sell- moving wrong direction on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
        if current_price < context.previous_lo:
            context.target = context.previous_lo
            if not (context.bought):
                order(context.stocks[0],context.portfolio.cash/current_price)
                context.gapdown = True
                print '----'
                print 'Prev Low: ' + str(context.previous_hi)
                print 'Open: ' + str(current_price)
                context.bought = True
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Buy Long on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.cash/current_price)
            elif context.gapdown == True and context.bought:
                order(context.stocks[0],-context.portfolio.positions[context.stocks[0]].amount)
                context.bought = False
                context.gapdown = False
                print '----'
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Sell- moving wrong direction on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
    else:
        context.day_counter = context.day_counter + 1
    
    if (context.bought):
        if (context.gapup) and current_price < context.target:
            order(context.stocks[0],context.portfolio.positions[context.stocks[0]].amount)
            print '----'
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)      
            print 'Sell- cover short on ' +str(event_datetime)
            print 'Target: ' + str(context.target)
            print 'Current: ' + str(current_price)
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(-context.portfolio.positions[context.stocks[0]].amount)
            context.bought = False
            context.gapup = False
        elif (context.gapdown) and current_price > context.target:
            order(context.stocks[0],-context.portfolio.positions[context.stocks[0]].amount)
            print '----'
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
            print 'Sell- cover long on ' +str(event_datetime)
            print 'Target: ' + str(context.target)
            print 'Current: ' + str(current_price)
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
            context.bought = False
            context.gapdown = False
    
    context.previous_price = current_price
    context.previous_hi = context.hi
    context.previous_lo = context.lo
    context.event_day = event_day
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
2 responses

@Chuck, by definition a short position must borrow (stocks, not cash). As a result your "cash" is still there but is tied up as collateral.

I plugged in a quick test of how much capital you are using. It looks like you are borrowing $90k on your starting $10k. Not good.

I would suggest you examine your algorithm logic for how you check for existing positions. The easiest way I know of is from the portfolio object:

qty = context.portfolio.positions[context.stocks[0]].amount  
if qty > 0: print "long"  
if qty < 0: print "short"  
if qty == 0: print "no position"  

I'm wondering about your $10k starting cash. If you are planning to trade in a real account you will need $25k minimum to get a margin account. Otherwise you won't be able to take a short position at all.

Clone Algorithm
10
Loading...
Backtest from to with initial capital
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
hold_period = 15 # hold period in days
threshold = 5 # price difference threshold in percent
import pytz
EST = pytz.timezone('US/Eastern')
import datetime


def initialize(context):
    
    context.stocks = [sid(23709)] # NFLX
    
    context.previous_price = 1
    context.previous_hi = 0
    context.previous_lo = 0
    context.initialize = True
    context.event_day = 0
    context.new_day = False
    context.day_counter = 0
    context.bought = False
    context.day_submitted = 0
    context.num_shares = 0
    context.gapup = False
    context.gapdown = False
    context.hi = 0
    context.lo = 0
    context.target = 0
    context.max_notional = 10000.1  
    context.min_notional = -1.0
    
    
def handle_data(context, data):
    
    
    # calculate capital_used using absolute amount: abs(amount)*cost_basis  
    pos = context.portfolio.positions  
    abs_capital_used = sum(abs(pos[s].amount) * pos[s].cost_basis for s in pos)  
    record(abs_capital_used = abs_capital_used)
    
    # calculate free cash: starting_cash + pnl - capital_used  
    port = context.portfolio  
    abs_cash = port.starting_cash + port.pnl - abs_capital_used  
    record(abs_cash = abs_cash)  
    
    
    event_datetime = data[context.stocks[0]].datetime
    current_price = data[context.stocks[0]].price
    context.hi = data[context.stocks[0]].high
    context.lo = data[context.stocks[0]].low
    
    
    
    
    event_day = data[context.stocks[0]].datetime.day
    
    if context.initialize:
        context.event_day = event_day
        context.initialize = False 
    
    if event_day != context.event_day:
        context.new_day = True
    else:
        context.new_day = False
        
    if context.new_day and not(context.day_counter==1):
        context.day_counter = context.day_counter + 1
        
        if current_price > context.previous_hi:
            context.target = context.previous_hi
            if not (context.bought):
                order(context.stocks[0],-context.portfolio.cash/current_price)
                context.gapup = True
                print '----'
                print 'Prev Hi: ' + str(context.previous_hi)
                print 'Open: ' + str(current_price)
                context.bought = True
                print 'Buy Short on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(-context.portfolio.cash/current_price)
            elif context.gapup == True and context.bought:
                order(context.stocks[0],context.portfolio.positions[context.stocks[0]].amount)
                context.bought = False
                context.gapup = False
                print '----'
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Sell- moving wrong direction on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
        if current_price < context.previous_lo:
            context.target = context.previous_lo
            if not (context.bought):
                order(context.stocks[0],context.portfolio.cash/current_price)
                context.gapdown = True
                print '----'
                print 'Prev Low: ' + str(context.previous_hi)
                print 'Open: ' + str(current_price)
                context.bought = True
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Buy Long on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.cash/current_price)
            elif context.gapdown == True and context.bought:
                order(context.stocks[0],-context.portfolio.positions[context.stocks[0]].amount)
                context.bought = False
                context.gapdown = False
                print '----'
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
                print 'Sell- moving wrong direction on ' +str(event_datetime)
                print 'Portfolio value: ' +str(context.portfolio.cash)
                print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
    else:
        context.day_counter = context.day_counter + 1
    
    if (context.bought):
        if (context.gapup) and current_price < context.target:
            order(context.stocks[0],context.portfolio.positions[context.stocks[0]].amount)
            print '----'
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)      
            print 'Sell- cover short on ' +str(event_datetime)
            print 'Target: ' + str(context.target)
            print 'Current: ' + str(current_price)
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(-context.portfolio.positions[context.stocks[0]].amount)
            context.bought = False
            context.gapup = False
        elif (context.gapdown) and current_price > context.target:
            order(context.stocks[0],-context.portfolio.positions[context.stocks[0]].amount)
            print '----'
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
            print 'Sell- cover long on ' +str(event_datetime)
            print 'Target: ' + str(context.target)
            print 'Current: ' + str(current_price)
            print 'Portfolio value: ' +str(context.portfolio.cash)
            print 'Position shares: ' +str(context.portfolio.positions[context.stocks[0]].amount)
            context.bought = False
            context.gapdown = False
    
    context.previous_price = current_price
    context.previous_hi = context.hi
    context.previous_lo = context.lo
    context.event_day = event_day
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Thanks for the look Dennis.

I will change the initial investment to $25k as that does make more sense.

I will also add the logic you suggested.