Back to Community
What is wrong with my optimization for contest? -- please help

I am doing the following in my algorithm and following all guidelines but it still fails the criteria. Why?

def make_pipeline():  
    minprice = USEquityPricing.close.latest > 10  
    pipe = Pipeline(screen=QTradableStocksUS() & minprice)  
    sectors = Sector()  
    pipe.add(sectors, 'sector')  
    return pipe


def trade_sectors(context, data):  
    todays_universe = context.stocks  
    alphas = pd.Series(context.alphas, index=todays_universe)  
    alphas = alphas.fillna(0.)  
    objective = opt.MaximizeAlpha(alphas)  
    constraints = []

    constraints.append(opt.MaxGrossExposure(1.0))  
    constraints.append(opt.DollarNeutral(0.01))  
    constraints.append(opt.NetGroupExposure(context.labels, context.minw, context.maxw))  
    constraint_sector_style_risk = opt.experimental.RiskModelExposure(  
        context.risk_loading_pipeline,  
        version=opt.Newest,  
    )  
    constraints.append(constraint_sector_style_risk)  
    constraints.append(  
        opt.PositionConcentration.with_equal_bounds(  
            min=-1. / (context.label * 5),  
            max=1. / (context.label * 5)))  
    constraints.append(opt.MaxTurnover(0.6))  
    try:  
        algo.order_optimal_portfolio(objective=objective, constraints=constraints)  
        record(e=0)  
    except:  
        record(e=1)  

It fails on the following:

Checking leverage limits...
FAIL: Minimum leverage of 0.63x is below 0.7x

Checking style exposure limits...
FAIL: 98th percentile short_term_reversal exposure of 0.525 (absolute value) is greater than 0.40.

Checking investment in tradable universe...
FAIL: Investment in QTradableStocksUS (2nd percentile) of 92.42% is < 95.0%.

5 responses

Hi Pravin,

I would start with checking why leverage constraint is being violated. Might want to check a day's positions (long and short book) and (compare totals to the required end of day leverage 70% of account value). Not sure what context.label is. Maybe that is causing position sizes too small?

-Leo

Hi Leo,

Thanks for your feedback. I looked at position sizes and long short notional. The issue arises because turnover is set to 60%. The very first day, optimizer only trades 60% of the portfolio. Could someone from Q explain how to avoid this problem?

Also why do the other constraints break when I have the right constraints?

Best regards,
Pravin

That's a nice chart indicator when errors. Logging them can also be helpful sometimes.

except Exception as e:  
    log.info(e)

I came from the world of Perl years ago where laziness was considered a good thing in programming, I think, this style might make for fewer keystrokes in making changes, too lazy to find out for sure but some things to discard or try.

def make_pipeline():  
    pipe = Pipeline(screen=QTradableStocksUS() & (USEquityPricing.close.latest > 10minprice))  
    pipe.add(Sector(), 'sector')  
    return pipe

def trade_sectors(context, data):  
    alphas = context.alphas.fillna(0.0)  
    constraints = [  
        opt.MaxGrossExposure(1.0),  
        opt.DollarNeutral(),  
        #opt.NetGroupExposure(context.labels, context.minw, context.maxw),  
        opt.experimental.RiskModelExposure(  
            context.risk_loading_pipeline,  
            version=opt.Newest,  
        ),  
        opt.PositionConcentration.with_equal_bounds(  
            min = -.045,  
            max =  .045,  
        #    min = -1.0 / (context.label * 5),  
        #    max =  1.0 / (context.label * 5),  
        ),  
    ]  
    if context.account.leverage > .9:  
        constraints.append(opt.MaxTurnover(0.6))  
    try:  
        algo.order_optimal_portfolio(  
            objective   = opt.MaximizeAlpha(alphas),  
            constraints = constraints,  
        )  
        record(e=0)  
    except Exception as e:  
        record(e=10000)  
        log.info(e)  

Hi Pravin,

Here's what I'm current using for the turnover constraint:

    turnover = np.linspace(0.06,0.65,num=100)  
    for max_turnover in turnover:  
        constraints.append(opt.MaxTurnover(max_turnover))  
        if context.init:  
            constraints = constraints[:-1]  
            context.init = False  
        try:  
            order_optimal_portfolio(  
                objective=objective,  
                constraints=constraints,  
                )  
            record(max_turnover = max_turnover)  
            return  
        except:  
            constraints = constraints[:-1]  

Note that I drop the turnover constraint for the first order. For subsequent orders, I start at a minimum turnover and iterate.

Thanks, Karl and Grant. That has fixed my issues.