Your algorithm must be less than 20% exposed to each sector as defined in the
Quantopian risk model. There are 11 sectors in the risk model:
-
Basic Materials
-
Technology
-
Real Estate
-
Energy
-
Communication Services
-
Health Care
-
Financial Services
-
Consumer Cyclical
-
Industrials
-
Consumer Defensive
-
Utilities
Your algorithm must also be less than 40% exposed to each style factor in the Quantopian risk model. There are 5 style factors in the risk model:
-
Size
-
Value
-
Momentum
-
Short-Term Reversal
-
Volatility
Exposure to risk factors in the Quantopian risk model is measured as the mean net exposure over a 63-trading-day rolling window. Each day, the rolling mean net exposure to each sector must be between -20% and 20%, while the rolling mean net exposure to each style factor must be between -40% and 40%. If your algorithm is overexposed to any of the sector or style factors, it won’t be eligible to run in the contest.
The definition of a risk model codifies a particular view of the market. The Quantopian Risk Model is designed to identify the particular risk exposures that are desired by Quantopian’s investor clients. One of the goals of the contest is to incentivize the construction of algorithms that could be considered for an
allocation. Keeping low exposure to the factors in the risk model aligns your algorithm with Quantopian's allocation process.
There are two ways to limit your exposure to the terms in the Quantopian Risk Model. The first way is to construct an alpha factor that is independent of any of the sector or style factors. This is typically done in the research step when analyzing the properties of your alpha factor.
The other way to limit your exposure to the risk factors in the Quantopian Risk Model is by supplying constraints to
order_optimal_portfolio. You can use the
risk_loading_pipeline to get historical risk factor exposures for each asset. Then you can constrain your portfolio based on these historical exposures by supplying a
RiskModelExposure constraint to
order_optimal_portfolio.
Here’s an example algorithm that constrains the portfolio to the default exposure limits (18% for each sector, 36% for each style):
import quantopian.algorithm as algo
import quantopian.optimize as opt
from quantopian.pipeline.experimental import risk_loading_pipeline
def initialize(context):
# Attach the risk loading pipeline to our algorithm.
algo.attach_pipeline(risk_loading_pipeline(), 'risk_loading_pipeline')
def before_trading_start(context, data):
# Get the risk loading data every day.
context.risk_loading_pipeline = pipeline_output('risk_loading_pipeline')
def place_orders(context, data):
# Constrain our risk exposures. We're using version 0 of the default bounds
# which constrain our portfolio to 18% exposure to each sector and 36% to
# each style factor.
constrain_sector_style_risk = opt.experimental.RiskModelExposure(
risk_model_loadings=context.risk_loading_pipeline,
version=0,
)
# Supply the constraint to order_optimal_portfolio.
algo.order_optimal_portfolio(
objective=my_objective, #Fill in with your objective function.
constraints=[constrain_sector_style_risk],
)
The default exposures are constrained to 18% for each sector, and 36% for each style. These constraints are below the respective limits of 20% and 40% because we are using historical exposures to constrain our portfolio for the next day. Tomorrow’s exposures can vary from their past exposures, so the buffer leaves you with a bit of room to stay under the contest limits.
Some of the risk exposures are more stable than others. For example, the per-asset sector exposures don’t tend to change as much over time as some of the style factors. The short-term reversal risk factor tends to change the most since it is computed over a 14 day trailing window. If you are having trouble controlling your exposure to this factor, you can try overriding the default constraint of 36% historical exposure. To do this, you can modify the constraint you pass to order_optimal_portfolio to look like this:
constrain_sector_style_risk = opt.experimental.RiskModelExposure(
risk_model_loadings=context.risk_loading_pipeline,
version=0,
min_momentum=-0.1,
max_momentum=0.1,
)
Finally, you can set the version of your RiskModelExposure to be a specific version (version=0 above), or you can set it to version=opt.Newest so that your algorithm always uses the newest version of the defaults. For the contest, you should pick a specific version to use since you don’t know how your algorithm will be affected by a change to the default.
Here are some example that meet the risk exposure criteria: