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
sectors = Sector()
return pipe

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(
)
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.

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))
return pipe

alphas = context.alphas.fillna(0.0)
constraints = [
opt.MaxGrossExposure(1.0),
opt.DollarNeutral(),
#opt.NetGroupExposure(context.labels, context.minw, context.maxw),
opt.experimental.RiskModelExposure(
),
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.