Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
New Challenge: Build Smart Beta Factors

About the Challenge:

While most of us are (hopefully) sitting in our home-offices, we thought we'd post a new challenge to give you something to pass the time. To keep things interesting we are again trying something new for this challenge: we’re asking you to build and submit your best long-only, smart beta portfolios. This is part of our effort to widen our range of investment products and demonstrate to third parties what the Quantopian community is capable of.

Though in the past our focus was on long-short high-alpha factors, they are obviously not the only class of investment products out there. In fact, smart beta products accounted for $880 billion in total cumulative assets in 2019.

In addition, we ask you to fill out the following mandatory questionnaire classifying your smart beta factor.

To find out more about smart beta, see this article.


  • Long-only
  • All stocks must be in the QTU
  • Must hold at least 250 assets
  • Maximum position concentration 5%
  • Turnover <= 10% per month (this will be challenging)
  • Leverage = 1 at all times
  • Provide a description of what smart beta you’re trying to capture through our questionnaire

Selection Criteria:

  • Alpha to market (higher is better), however, we will not say over which time-period(s)
  • Universe size (larger is better)


Top 5 factors receive $500 each.

Important Upcoming Dates:
The submission deadline for this challenge is Apr 27, 2020 at 9pm CET.

I hope to see your submission on the list!

Thomas Wiecki,
VP of Data Science at Quantopian


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.

254 responses

Algorithm template:

Factor NB template:

I like the long only strats idea because after the coronavirus blows over, there is no where but up for the market - just as it was after 2008. Citadel went on a hiring spree in 2009 to build out their teams because anything you could throw your money at would go up in that period of time. Also, the questionare is currently blocked and one cannot submit their answers to it


Regarding turnover less than 10% monthly, are we allowed to use the MaxTurnover constraint in the optimizer to control this if needed?

@ Thomas,

why are the total returns in backtester and alpha decay analysis notebook so different?

@Vladimir: In the example I posted? I might have used a different backtest ID.

@ Thomas,
Look at my notebook above.
This is my backtest and my notebook on that backtest.

@Vladimir, @Thomas,

I have the same observations as Vladimir. I originally thought that the returns on the notebook were annualized but appparently not. It is the same for other metrics such as turnover and Sharpe (IR), they are different from what the full tearsheet in Backtest IDE shows.

Oh yeah, that looks wrong. Let me investigate.

@Vladimir @James: Could you try with this NB?

@Thomas, seems like cummulative returns and IR is now consistent with backtest results. I'm not sure about monthly turnover . My backtest shows a daily turnover of 0.785% (or 0.785 x 21days = 16.485%), the graph on the NB shows much higher monthly turnover.

Here's my revised Model 1:

First Entry ever :-) - Model 1
Pure Smart Beta.

Just to confirm, the turnover graph is monthly turnover (rather than daily) and is written as a decimal, correct? So 0.10 on the graph = 10% monthly turnover, not 0.1% monthly turnover, yes?

@ Thomas,

I have tried new notebook.
The returns and sharpe metrics very consistent with backtest results.

Model #1

Model #2

Model #3

@All: I just updated the above alpha-decay NB as it contained a bug and gave you wrong results that did not match those with what your backtester showed (the backtest results were more accurate). I also relabeled the lower-left plot as that is showing Monthly turnover to make it easier to spot whether you breach the 10% monthly turnover limit.

Model 1

@James, @Thomas,

I have the same observations as James:
My backtest shows a daily turnover of 0.785% (or 0.785% x 21days = 16.485%),
the graph on the NB shows much higher monthly turnover.

With scheduled rebalance once a year I see in my notebook monthly turnover at 25% level between trades
which may be translated as 350% a year and not realistic.
Backtest shows 0.15% daily turnover which may be translated as 3.15% a month or 37.8% a year what is more likely correct.

May be we need to change this line

monthly_turnover = factor_stats['turnover'].resample('1M').sum()  

@Thomas, I’ve observed the same as James and Vladimir.

I'm seeing the same thing too

Model #4

Model #5

Model #6

Model 1

My first submission :)

I'm investigating the turnover questions that came up. Here is a NB. The difference is that the alpha decay analysis uses the positions to compute turnover while pyfolio uses transactions. The two should come out in a similar way, and they do (although I'm not sure if in my NB the difference is still larger than expected). Could someone try if the difference is much larger for them?

Model 2

@Thomas, here's the result of the monthly turnover test based on my Model 4. In this case, I see substantial difference between pyfolio and position based monthly turnover. If transactions based pyfolio monthly turnover was used, it would have probably made the below 10% threshold.

@ Thomas,

Here is 13 years backtest of simple buy and hold strategy.
Turnover in backtaster 0%.

@ Thomas,

Here's your last notebook of the same backtest.
The positions change sometimes reaches 40% and never reaches 0%.

@Thomas, @Vladimir,

I think the disconnect between pyfolio which is transactions based vs. Thomas' NB which is positions based is the actual execution of trades based on rebalancing schedule. Positions can change on a daily basis but when you schedule to rebalance on a monthly or quarterly basis, actual execution of trades takes place as scheduled. Therefore, the NB is overstating turnover as it is recording turnover as positions change but not actually executed. Makes sense?

Great demonstration of the turnover problem @Vladimir!

@James Yes, you're right, just the regular stock movements due to price shifts will increase the position-based turnover calculation. I suppose the easiest fix would be to change the alpha decay NB here to compute turnover based on transactions, we do have that data available anyhow. Anyone can think of a better solution?

@Thomas, I concur. I think it is the most straight forward fix.

@all: I updated the top NB to use a more accurate turnover calculation. It should now be lower than what you've seen before.

I'm also attaching a version of the template algorithm that uses downsample() to only update a factor monthly.

Model 1

Model 2 Revised

Model 3 - Revised

Still very much a work in progress. The turnover graph looks accurate now, but it's still difficult to determine if the strategy meets the monthly max turnover criterion. Maybe add a line showing mean monthly turnover as well?

It beats the SPY over this period, though you can't really tell from this tear sheet. Instead of using 'Specific Returns' (based on the Q Risk model), I'd suggest to use excess returns over the market, i.e SPY assuming that's the benchmark. Possibly volatility adjusted.

Model #1 with latest NB

Model #7

Model #8

Model #9 (using optimizer)

Model #10

Model #11

Model #12

Model 2

Model 4


Long Backtest of Model 4

Model 5

Model 3

Model 2

Model 4

Model 2

Model 3

Model 6!

Model 5

Model #13

Model #14

Model #15

Model 4

Smart Beta 1

Smart Beta 2

Smart Beta 3

Model 5

Model 6. Turnover still higher than required.

Model 3

Model 7

Algo 1

Model 6

Model 8

Baseline entry.

Algo 2

Algo 3

Model 7

Model 9


Model 4

Algo 4



Model 10

Model 5

Model 6

Model 7

Model 8

Model 8

Smart Beta - Model 1

Can I use a list of costraints to meet the challange's requirements?



How do I check that my factor is positive?

Something like

    screen = factor.top(300, mask=(qtu & ~factor.isnull() & factor.isfinite() & factor.ispositive()))  

does not work

This way I can force the fact that I can go only long

Model 1.1

My first challenge - Model #1

Model 9

Model 1.2

My first challenge - Model #2

Model 1

Model 1.3

Model 1.4

Model 1.1

Model 10

Model 1.2

My first challenge - Model #3

Model 1.3

Model 1.4

Model 2

Model 2.1

My first challenge - Model #4


Model 2.2

Model 2.3

My first challenge - Model #5_1

My first challenge - Model #5_2

Smart Beta 4

Model V3

Model 3

Model 11

My first challenge - Model #6

Model 4.1

My first challenge - Model #7

Model 4.2

Model 4.3

My first challenge - Model #8

Model 1.1

Smart Beta 5

Model 11

Smart Beta 5.1

Model 12.1

Model 5 combined factors

Model 5 combined factors number 2

My first challenge - Model #9

My first challenge - Model #10

Model 1

Smart Beta 6

Model 5

Model 6.1

Model 6.2

Model 6.3

Model 7






Model 7



Smart Beta 7

Smart Beta 7.1

Model 13

Model #16

Model 14 V1

Model 14 V2

Model 3

Model 3.1

Smart Beta 8

Smart Beta 8.1

Smart Beta 9

Smart Beta 8.2

Smart Beta 9.1

Smart Beta 9.2

Smart Beta 9.3

Model 15 V1




Model 9

version 1

Smart Beta 10

Model 4


Model 4.1

Model 4.2


Model 4.3



Model 6.2

Model 16 V1

model 1.1

model 1.2

model 1.3

model 2.1

model 3

model 4

model 4.2

model 5


Model 8

model 5.2

model 5.3

Submission 1

Submission 2

Version 2


Model 17 V1






Model 9

Model 17 V2

Model 10

Here my model

Model 11

Model 12

Model 8 V2

model 5.4

model 6

model 7

Model #17

Model #1.

This is... not good. But I wanted to partecipate to a contest for once, and so here's my submission. I might try to slightly improve it tomorrow, but probably not :)

Actualy, I think it's over the monthly turnover limit, so technically not even a valid entry. Might be the first thing to fix...

Model 4 V2

Model 16 V2

Model 9 V2

New Multifactor Model

Attempt 2. Now this both bad and WEIRD. Why does IC increase over time? I have absolutely no idea.

Model 4 V3 (Longer time window)

VSB_Q600US bottom to bottom

VSSB_Q600US top to top

Model 8 V3 (Longer time window)

Model 13-Pure Technical

New Multifactor Model V2

New Multifactor Model V3

MicroSegment #1

New Multifactor Model V4

Model 14-Pure Technical

Final model

version 3

Model 2

Model 3

Model 4

Micro Segment #2




Model 1

EZ2 bt8

FM fw

FE3 fw

Model # 1

Model 1


FM bt2






Thanks for submitting to the challenge everyone, submissions are closed now.

We didn't quite know what to expect with this curve ball we've been throwing you but there never was a doubt that the community would rise to the task!

Rene will analyze all submissions as we did before and we'll announce when we'll do the webinar, probably in 2-3 weeks.

Hi! Any updates? Thanks

Thanks for attending the smart beta challenge! It is the first challenge we hold for long-only trading strategies. There are 223 valid backtest submissions from our community users -- great job! Unfortunately we won't be able to do a webinar this time and instead will describe the methodology that Rene came up with to rank the submissions here.

The methodology we used to select the winners for the smart-beta challenge is similar to the one we used for the previous challenge, but there are a couple of changes. First, instead of using correlation to cluster trading strategies, we clustered them using their absolute max risk style factor exposures. Second, we involved a new metric to measure how well a trading strategy could time the style factors using its long term average style factor exposure as a benchmark. This new metric is defined by the ratio between the mean of style timing returns and the volatility of the style timing returns, where the style timing returns are the total style factor returns minus the tilt style factor returns. Please see here for a more detailed definition of timing returns and tilt returns.

The winners we select are Leo M, Antony Jackson, James Villa, Indigo Monkey, and Neeraj Salodia. Congratulations!