Back to Community
Beta in backtest seems above bounds set in algorithm for brief periods

Hi, I am using this beta computation code from (https://www.quantopian.com/lectures/example-long-short-equity-algorithm)

beta = 0.66*RollingLinearRegressionOfReturns(
target=sid(8554),
returns_length=5,
regression_length=260,
mask=long_short_screen
).beta + 0.33*1.0

I noticed that in backtest periods for short durations the beta is much higher than the bounds I set in the order_optimal_portfolio that takes beta bounds from the above code in the pipeline.

For instance, beta is like 0.6 to 0.8 when the bounds of beta are [-0.25 .. 0.25] if I run it for a month or two. Over long periods (6months+) beta ultimately seems to settle within the bounds that was set in the constraint.

I am wondering if I can continue to use the beta calculation code in that lecture for all my algorithms for limiting beta to the bound that is necessary for Quantopian requirements or do I need to do some calculations on my own or use a different piece of code?

4 responses

Hi @Leo,

in backtest periods for short durations the beta is much higher than the bounds I set in the order_optimal_portfolio

Which "beta" are you looking at in backtest? Can you post a pyfolio tearsheet?

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.

Hi @jonathan,

I'm getting error pyfolio tearsheet "TearSheetNotAvailable: Algorithm with id '...' lacks sufficient data to create a tear sheet. Please make sure it has run for at least 6 months before creating tear sheets". I am looking at the regular "Run full backtest" from algorithm page, just for different time periods.
From a beta of -1.06 in the last two weeks, I went down to beta of -0.25 in last six weeks and further down to -0.04 over last two years. I am wondering if the wide changes are a result of the algorithm entering positions on day 1 that get averaged out over longer time periods.

From 2017-07-20 to 2017-08-03 with $10,000,000 initial capital

Beta
-1.06

Same algo (no code change)

From 2017-06-20 to 2017-08-03 with $10,000,000 initial capital

Beta
-0.25

Seems to get really low over a 2 year backtest and in general all multi year backtests.
From 2015-06-01 to 2017-07-19 with $10,000,000 initial capital

Beta
-0.04

My constraint is as follows:
MAX_BETA_EXPOSURE = 0.25

beta_default = 0.66*RollingLinearRegressionOfReturns(
target=sid(8554),
returns_length=5,
regression_length=260,
mask=long_short_screen_default
).beta + 0.33*1.0

pipe = Pipeline(columns = {  

....
'market_beta_default':beta_default,
....
}

risk_factor_exposures = pd.DataFrame({
'market_beta_default':pipeline_data.market_beta_default.fillna(1.0)
})
neutralize_risk_factors = opt.WeightedExposure(
loadings=risk_factor_exposures,
min_exposures={'market_beta_default':-MAX_BETA_EXPOSURE},
max_exposures={'market_beta_default':MAX_BETA_EXPOSURE}
)

@Leo, a stock's beta is an estimated value. In the pipeline expression, you are calculating a regression beta per stock. This is the historical beta of the stock. What we really care about, of course, is the future actual beta of the stock. The weighting of 2/3 and 1/3 is called Blume's Adjustment from Betas and Their Regression Tendencies. It basically posits that the historical regression is noisy and tends to overestimate or underestimate beta; over time betas should revert to 1.0. A more modern interpretation is that we have a prior belief that betas are all "1.0" and we shrink the regression estimate toward this value.

In your optimization constraints, you are constraining the portfolio to a weighted sum of this predicted beta. The reality could be something different.

The beta in the backtester is a regression of your algo's return stream versus the SPY. You can think of this as what actually happened. Your portfolio is constrained in the optimizer to what you are predicting the betas will be, and what actually happened in the future is what is reported as the beta in the backtester (and pyfolio). However, this backtester regression beta is also an estimate. Like any regression coefficient, you need a sufficiently long time series to get a good estimate. This reported beta is an estimated value and has a standard error. In your examples, you can see that with a very short period of time you get a very noisy estimate, but that the estimates converge to a reasonable value as you add more time.

Thanks a lot @jonathan for the detailed explanation.