Back to Community
Run multiple order_optimal_portfolio's?

Hi Qsters,

I want to go long pipline-A and go short pipeline-B in a contest Algo. Simple enough! Is this even possible?

I tried to split out an algo that had previously met all contest constraints . . . into) 1 long pipeline-A and 1 short pipeline-B and then push those to 1 short order_optimal_portfolio and 1 long order_optimal_portfolio - each with their own set of constraints. When I tried this inside the same rebalance it did manage to go long/short kind of (dollar neutral went out of balance), but it didn't meet constraints anymore and most puzzling of all, in backtest it failed to meet Tradable Universe constraint even though of course QTradableStocksUS was used by both pipeline screeners. All I had changed was running 2 order_optimal_portfolio's instead of 1. I also tried to accomplish this goal by doing 2 schedulers - 1 scheduler rebalanceShort and 1 scheduler rebalanceLong, but only 1of the 2 schedulers seemed to run.

Thanks in advance,
Your pal Stephan

5 responses

To clear out those no longer in QTradableStocksUS, maybe try:

def initialize(context):  
    attach_pipeline(make_pipeline2(context), 'qtu_only')

def make_pipeline2(context):  
    return Pipeline(  
        columns = {},  
        screen  = QTradableStocksUS()  
    )

def trade(context, data):  
    weight = pd.Series({}) 

    qtu = algo.pipeline_output('qtu_only').index

    for s in context.pipe_out.index:  
        if s not in qtu:  
            weight[s] = 0.0  
            continue  
        weight[s] = .....  

Let us know how that goes.

You might have been referring to criteria met. rather than ...
When order_optimal_portfolio was complaining of impossible constraints, this was making it through those days by relaxing them with retry.

Flexible constraints to keep optimize happy

def trade(context, data):  
    .....  

    if context.account.leverage < .9:  #  0.85:  
        turnover = opt.MaxTurnover(1.0)  
    else:  
        turnover = opt.MaxTurnover(0.3)

    # With weights normalized, and using TargetWeights, PositionConcentration should already be fine, could remove maybe?

    count   = 0  
    betaval = .05  
    expval  = .01  
    conc    = 1.0 / len(weight)

    while count < 5:  
        count += 1

        constraints = [  
            turnover,  
            opt.MaxGrossExposure(1.0),  
            opt.DollarNeutral(),  
            opt.FactorExposure(                 # beta_neutral  
                context.output[['beta']],  
                min_exposures = {'beta': -betaval},  
                max_exposures = {'beta':  betaval},  
            ),  
            opt.NetGroupExposure.with_equal_bounds(  
                labels=context.output.sector,  
                min = -expval,  
                max =  expval,  
            ),  
            opt.PositionConcentration.with_equal_bounds(-conc, conc),  
        ]

        try:  
            order_optimal_portfolio(  
                objective   = opt.TargetWeights(weight),  
                constraints = constraints,  
            )  
            break  
        except Exception as e:  
            betaval *= 2.0  
            expval  *= 2.0  
            conc    *= 0.8  
            print('    count {}\n{}'.format(count, e))  

did you mean to comment on my post? I don't understand the pertinence of your reply.

did you mean to comment on my post? I don't understand

Absolutely.
The first is for failed to meet Tradable Universe.
The second for didn't meet constraints anymore.

On another, only 1of the 2 schedulers seemed to run, I doubt that it would be reasonable for you to remove any secret sauce to then attach a backtest, might be too time-consuming if it is even possible to come up with a generic version still exhibiting all of those problems. From the forum side, it would be the fastest way to traction and replies addressing all issues.

In the meantime I'd suggest clicking line numbers in the margin to set breakpoints. The https://www.google.com/search?q=debugger+site:quantopian.com is not just for bugs anymore, it's also an incredible learning tool.

I've got a workaround at the moment, I appreciate the code blocks though. If and when I have to go back to this, I'll update. thanks.