Back to Community
set_universe - tickers changing, positions still opened

I've been playing around with set_universe and it's resulted in positions remaining open and orphaned when the universe changes. I'm monitoring len(data) to see when the list of stocks change. Is there a closeAllPositions() function that I can use to flatten my portfolio?

Also, does the data returned by the history() function change as the universe changes? Having some trouble debugging... I keep seeing my leverage number change to numbers it shouldn't be at. Wondering if it's a result of the universe changing and I'm getting more orphaned positions.

Is there a way to get a random universe of stocks, and then keep that universe the same for the duration of the test?

Update - after some more debugging, it looks like an orphaned order causes the "if get_op_orders() return" line to be stuck. The order never fills and no more trades are ever done for the backtest. All of my orders are market orders. This also explains the leverage numbers being off. Could it be that orders get stuck after a universe change no longer has the stock?

Update 2 - the orphaned order was caused by GDT, which was generated by set_universe, but stops trading after Jun 2006. Might need something which automatically cancels outstanding orders for stocks which have stopped trading.

4 responses

One part of it (as there is no built-in for that):

def closeAllPositions(context):  
    for p in context.portfolio.positions:  
        if context.portfolio.positions[p].amount != 0:  
            order_target(p, 0)  

Also this can be helpful sometimes for the stairstep of when new highs happen, leverage highs in this case:

    c = context   # for brevity  
    if 'max_lvrg' not in c: # init this in initialize() for better efficiency  
        c.max_lvrg = 0  
    if c.account.leverage > c.max_lvrg:  
        c.max_lvrg = c.account.leverage  
        record(MaxLvrg = c.max_lvrg)  

Thanks. I wrote something similar to the closeAllPositions function, but it was still stuck. It looks like it's due to a stuck opened order. I can't figure out what order is still opened. Maybe we need a cancelAllOrders function, or an option to automatically cancel all opened orders at the end of day.

The leverage problem that I had was just due to the stuck order as well. Since the algorithm could not proceed, it became unhedged.

Added code. There's some logging in there, which basically shows that after Jul 2005, all trades just stop due to an opened ordered.

Clone Algorithm
1
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
import numpy as np
import statsmodels.api as smapi

   
def initialize(context):
    set_symbol_lookup_date('2015-07-01')
    set_universe(universe.DollarVolumeUniverse(99, 100.0))
    context.HEDGE = sid(8554)
    context.universecount = 0
    context.uchanged = 0
    context.banned = []
    #context.banned.append(sid(12321))    
    #context.banned.append(sid(12527))

    set_benchmark(context.HEDGE)
    schedule_function(myfunc,date_rule=date_rules.every_day(),time_rule=time_rules.market_close(minutes=30))
    
    log.info(context.HEDGE)

def handle_data(context, data):
    record(l=context.account.leverage)
    pass

def myfunc(context, data):
    if context.universecount != len(data):
        context.uchanged = 1
        log.info(len(data))
        log.info(context.universecount)
        context.universecount = len(data)
        #go through all positions, close them out if not in data
        for s in context.portfolio.positions:
            if s not in data.keys():
                log.info('closing out' + str(s))
                order_target_value(s, 0)
        return
    else:
        context.uchanged = 0
        
    if get_open_orders():
        return
    
    prices = history(20, "1d", "price")
    wsum = 0
    for sid in prices:
        try:
            if sid not in context.banned:
                order_target_value(sid,  500)
            wsum += 500
        except Exception, e:
            log.info("exception")
            log.info(str(e))
            continue 
    
    log.info("done")
    order_target_value(context.HEDGE, -wsum)
There was a runtime error.

Gary, there are 2 options for your algo (and you can do both!):

1) If there are open orders for the stock, skip that stock. Instead of skipping all of the stocks and not running handle_data. To do so, add this to line 45:

if get_open_orders(sid):  
            continue  

2) Remove securities from your universe if the end_date is approaching. This unfortunately suffers from survivorship bis, but it will remove the orphaned positions. Here's an example how to do it (see Seong's reply): https://www.quantopian.com/posts/why-does-the-number-of-positions-and-leverage-creep-up-for-this-algorithm

It's also on our radar to improve the experience with delisting securities. Hope that helps!

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.