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.

Requirements:

  • 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)

Prizes:

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

Loading notebook preview...
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.

254 responses

Algorithm template:

Clone Algorithm
217
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Template algorithm for the smart-beta challenge. Market-cap weighted top 500 QTU long-only strategy.

from quantopian.algorithm import attach_pipeline, pipeline_output

import quantopian.optimize as opt
from quantopian.pipeline import Pipeline
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.domain import US_EQUITIES
from quantopian.pipeline.data.factset import Fundamentals

import pandas as pd
import numpy as np

def initialize(context):
    """
    Called once at the start of the algorithm.
    """
    # Normally a contest algo uses the default commission and slippage
    # This is unique and only required for this 'mini-contest'
    set_commission(commission.PerShare(cost=0.000, min_trade_cost=0))   
    set_slippage(slippage.FixedSlippage(spread=0))
    
    # Rebalance every day, 1 hour after market open.
    schedule_function(
        rebalance,
        date_rules.every_day(),
        time_rules.market_close(hours=2),
    )
    # Create our dynamic stock selector.
    attach_pipeline(make_pipeline(context), 'pipeline') 
    
    # Record any custom data at the end of each day    
    schedule_function(record_positions, 
                      date_rules.every_day(),
                      time_rules.market_close())
    
    
def create_factor():
    # Base universe set to the QTradableStocksUS
    qtu = QTradableStocksUS()
    
    factor = Fundamentals.mkt_val.latest
    
    screen = factor.top(500, mask=(qtu & ~factor.isnull() & factor.isfinite()))
    
    return factor, screen

def make_pipeline(context):  
    factor, screen = create_factor()
    
    return Pipeline(columns={'factor': factor}, 
                    screen=screen, domain=US_EQUITIES)
    

def rebalance(context, data): 
    # Get the alpha factor data from the pipeline output
    output = pipeline_output('pipeline')
    factor = output.factor
    log.info(factor)
    # Weight securities by their factor
    # Divide by the abs of total weight to create a leverage of 1
    weights = factor / factor.abs().sum() 
    
    # Must use TargetWeights as an objective
    order_optimal_portfolio(
        objective=opt.TargetWeights(weights),
        constraints=[],
    )

    
def record_positions(context, data):
    pos = pd.Series()
    for position in context.portfolio.positions.values():
        pos.loc[position.sid] = position.amount
        
    pos /= pos.abs().sum()
    record(max_conc_perc=np.max(np.abs(pos)) * 100)
    record(pos_count_div_100=len(pos) / 100)
There was a runtime error.

Factor NB template:

Click to load notebook preview

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

@Thomas,

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?

Click to load notebook preview

@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?

Click to load notebook preview

@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:

Click to load notebook preview

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

Click to load notebook preview

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.

Click to load notebook preview

Model #1

Click to load notebook preview

Model #2

Click to load notebook preview

Model #3

Click to load notebook preview

@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

Click to load notebook preview

@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

Click to load notebook preview

Model #5

Click to load notebook preview

Model #6

Click to load notebook preview

Model 1

My first submission :)

Click to load notebook preview

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?

Click to load notebook preview

Model 2

Click to load notebook preview

@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.

Click to load notebook preview

@ Thomas,

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

Clone Algorithm
25
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# B&H
# ----------------------------------------------------------
ASSETS = symbols('QQQ', 'TLT');  WT =  [0.5, 0.5]; LEV = 1.0
# ----------------------------------------------------------
def initialize(context):
    schedule_function(trade, date_rules.month_start(),time_rules.market_open(minutes = 65))
    schedule_function(record_positions, date_rules.every_day(), time_rules.market_close()) 
    context.invested = 0
    
def trade(context, data):
    if context.invested: 
        return
    
    for i in range(len(ASSETS)):        
        order_target_percent(ASSETS[i], LEV*WT[i])
        record(**{ASSETS[i].symbol: LEV*WT[i]})
        
        
def record_positions(context, data):            
    record(Leverage = context.account.leverage) 
    context.invested = 1
    
There was a runtime error.

@ Thomas,

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

Click to load notebook preview

@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.

Clone Algorithm
31
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Template algorithm for the smart-beta challenge. Market-cap weighted top 500 QTU long-only strategy.

from quantopian.algorithm import attach_pipeline, pipeline_output

import quantopian.optimize as opt
from quantopian.pipeline import Pipeline
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.domain import US_EQUITIES
from quantopian.pipeline.data.factset import Fundamentals

import pandas as pd
import numpy as np

def initialize(context):
    """
    Called once at the start of the algorithm.
    """
    # Normally a contest algo uses the default commission and slippage
    # This is unique and only required for this 'mini-contest'
    set_commission(commission.PerShare(cost=0.000, min_trade_cost=0))   
    set_slippage(slippage.FixedSlippage(spread=0))
    
    # Rebalance every day, 1 hour after market open.
    schedule_function(
        rebalance,
        date_rules.every_day(),
        time_rules.market_close(hours=2),
    )
    # Create our dynamic stock selector.
    attach_pipeline(make_pipeline(context), 'pipeline') 
    
    # Record any custom data at the end of each day    
    schedule_function(record_positions, 
                      date_rules.every_day(),
                      time_rules.market_close())
    
    
def create_factor():
    # Base universe set to the QTradableStocksUS
    qtu = QTradableStocksUS()
    
    factor = Fundamentals.mkt_val.latest
    
    screen = factor.top(500, mask=(qtu & ~factor.isnull() & factor.isfinite()))
    
    return factor, screen

def make_pipeline(context):  
    factor, screen = create_factor()
    factor = factor.downsample('month_start')
    return Pipeline(columns={'factor': factor}, 
                    screen=screen, domain=US_EQUITIES)
    

def rebalance(context, data): 
    # Get the alpha factor data from the pipeline output
    output = pipeline_output('pipeline')
    factor = output.factor
    log.info(factor)
    # Weight securities by their factor
    # Divide by the abs of total weight to create a leverage of 1
    weights = factor / factor.abs().sum() 
    weights = weights.dropna()
    # Must use TargetWeights as an objective
    order_optimal_portfolio(
        objective=opt.TargetWeights(weights),
        constraints=[],
    )

    
def record_positions(context, data):
    pos = pd.Series()
    for position in context.portfolio.positions.values():
        pos.loc[position.sid] = position.amount
        
    pos /= pos.abs().sum()
    record(max_conc_perc=np.max(np.abs(pos)) * 100)
    record(pos_count_div_100=len(pos) / 100)
There was a runtime error.

Model 1

Click to load notebook preview

Model 2 Revised

Click to load notebook preview

Model 3 - Revised

Click to load notebook preview

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.

Click to load notebook preview

Model #1 with latest NB

Click to load notebook preview

Model #7

Click to load notebook preview

Model #8

Click to load notebook preview

Model #9 (using optimizer)

Click to load notebook preview

Model #10

Click to load notebook preview

Model #11

Click to load notebook preview

Model #12

Click to load notebook preview

Model 2

Click to load notebook preview

Model 4

Click to load notebook preview

Model1

Click to load notebook preview

Long Backtest of Model 4

Click to load notebook preview

Model 5

Click to load notebook preview

Model 3

Click to load notebook preview

Model 2

Click to load notebook preview

Model 4

Click to load notebook preview

Model 2

Click to load notebook preview

Model 3

Click to load notebook preview

Model 6!

Click to load notebook preview

Model 5

Click to load notebook preview

Model #13

Click to load notebook preview

Model #14

Click to load notebook preview

Model #15

Click to load notebook preview

Model 4

Click to load notebook preview

Smart Beta 1

Click to load notebook preview

Smart Beta 2

Click to load notebook preview

Smart Beta 3

Click to load notebook preview

Model 5

Click to load notebook preview

Model 6. Turnover still higher than required.

Click to load notebook preview

Model 3

Click to load notebook preview

Model 7

Click to load notebook preview

Algo 1

Click to load notebook preview

Model 6

Click to load notebook preview

Model 8

Click to load notebook preview

Baseline entry.

Click to load notebook preview

Algo 2

Click to load notebook preview

Algo 3

Click to load notebook preview

Model 7

Click to load notebook preview

Model 9

Click to load notebook preview

Entry.

Click to load notebook preview

Model 4

Click to load notebook preview

Algo 4

Click to load notebook preview

5

Click to load notebook preview

6

Click to load notebook preview

Model 10

Click to load notebook preview

Model 5

Click to load notebook preview

Model 6

Click to load notebook preview

Model 7

Click to load notebook preview

Model 8

Click to load notebook preview

Model 8

Click to load notebook preview

Smart Beta - Model 1

Click to load notebook preview

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

Like

order_optimal_portfolio(  
        objective=objective,  
        constraints=[  
            max_leverage,  
            dollar_neutral,  
            constrain_pos_size,  
            max_turnover,  
            factor_risk_constraints,  
        ]  
    )  

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

Click to load notebook preview

My first challenge - Model #1

Click to load notebook preview

Model 9

Click to load notebook preview

Model 1.2

Click to load notebook preview

My first challenge - Model #2

Click to load notebook preview

Model 1

Click to load notebook preview

Model 1.3

Click to load notebook preview

Model 1.4

Click to load notebook preview

Model 1.1

Click to load notebook preview

Model 10

Click to load notebook preview

Model 1.2

Click to load notebook preview

My first challenge - Model #3

Click to load notebook preview

Model 1.3

Click to load notebook preview

Model 1.4

Click to load notebook preview

Model 2

Click to load notebook preview

Model 2.1

Click to load notebook preview

My first challenge - Model #4

Click to load notebook preview

7

Click to load notebook preview

Model 2.2

Click to load notebook preview

Model 2.3

Click to load notebook preview

My first challenge - Model #5_1

Click to load notebook preview

My first challenge - Model #5_2

Click to load notebook preview

Smart Beta 4

Click to load notebook preview

Model V3

Click to load notebook preview

Model 3

Click to load notebook preview

Model 11

Click to load notebook preview

My first challenge - Model #6

Click to load notebook preview

Model 4.1

Click to load notebook preview

My first challenge - Model #7

Click to load notebook preview

Model 4.2

Click to load notebook preview

Model 4.3

Click to load notebook preview

My first challenge - Model #8

Click to load notebook preview

Model 1.1

Click to load notebook preview

Smart Beta 5

Click to load notebook preview

Model 11

Click to load notebook preview

Smart Beta 5.1

Click to load notebook preview

Model 12.1

Click to load notebook preview

Model 5 combined factors

Click to load notebook preview

Model 5 combined factors number 2

Click to load notebook preview

My first challenge - Model #9

Click to load notebook preview

My first challenge - Model #10

Click to load notebook preview

Model 1

Click to load notebook preview

Smart Beta 6

Click to load notebook preview

Model 5

Click to load notebook preview

Model 6.1

Click to load notebook preview

Model 6.2

Click to load notebook preview

Model 6.3

Click to load notebook preview

Model 7

Click to load notebook preview

S1

Click to load notebook preview

S2

Click to load notebook preview

S3

Click to load notebook preview

S4

Click to load notebook preview

S5

Click to load notebook preview

Model 7

Click to load notebook preview

S6

Click to load notebook preview

S7

Click to load notebook preview

Smart Beta 7

Click to load notebook preview

Smart Beta 7.1

Click to load notebook preview

Model 13

Click to load notebook preview

Model #16

Click to load notebook preview

Model 14 V1

Click to load notebook preview

Model 14 V2

Click to load notebook preview

Model 3

Click to load notebook preview

Model 3.1

Click to load notebook preview

Smart Beta 8

Click to load notebook preview

Smart Beta 8.1

Click to load notebook preview

Smart Beta 9

Click to load notebook preview

Smart Beta 8.2

Click to load notebook preview

Smart Beta 9.1

Click to load notebook preview

Smart Beta 9.2

Click to load notebook preview

Smart Beta 9.3

Click to load notebook preview

Model 15 V1

Click to load notebook preview

R1

Click to load notebook preview

R2

Click to load notebook preview

R3

Click to load notebook preview

Model 9

Click to load notebook preview

version 1

Click to load notebook preview

Smart Beta 10

Click to load notebook preview

Model 4

Click to load notebook preview

R4

Click to load notebook preview

Model 4.1

Click to load notebook preview

Model 4.2

Click to load notebook preview

R5

Click to load notebook preview

Model 4.3

Click to load notebook preview

R6

Click to load notebook preview

R7

Click to load notebook preview

Model 6.2

Click to load notebook preview

Model 16 V1

Click to load notebook preview

model 1.1

Click to load notebook preview

model 1.2

Click to load notebook preview

model 1.3

Click to load notebook preview

model 2.1

Click to load notebook preview

model 3

Click to load notebook preview

model 4

Click to load notebook preview

model 4.2

Click to load notebook preview

model 5

Click to load notebook preview

R8

Click to load notebook preview

Model 8

Click to load notebook preview

model 5.2

Click to load notebook preview

model 5.3

Click to load notebook preview

Submission 1

Click to load notebook preview

Submission 2

Click to load notebook preview

Version 2

Click to load notebook preview

R9

Click to load notebook preview

Model 17 V1

Click to load notebook preview

R10

Click to load notebook preview

R11

Click to load notebook preview

C1

Click to load notebook preview

C2

Click to load notebook preview

C3

Click to load notebook preview

Model 9

Click to load notebook preview

Model 17 V2

Click to load notebook preview

Model 10

Click to load notebook preview

Here my model

Click to load notebook preview

Model 11

Click to load notebook preview

Model 12

Click to load notebook preview

Model 8 V2

Click to load notebook preview

model 5.4

Click to load notebook preview

model 6

Click to load notebook preview

model 7

Click to load notebook preview

Model #17

Click to load notebook preview

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

Click to load notebook preview

Model 4 V2

Click to load notebook preview

Model 16 V2

Click to load notebook preview

Model 9 V2

Click to load notebook preview

New Multifactor Model

Click to load notebook preview

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

Click to load notebook preview

Model 4 V3 (Longer time window)

Click to load notebook preview

VSB_Q600US bottom to bottom

Click to load notebook preview

VSSB_Q600US top to top

Click to load notebook preview

Model 8 V3 (Longer time window)

Click to load notebook preview

Model 13-Pure Technical

Click to load notebook preview

New Multifactor Model V2

Click to load notebook preview

New Multifactor Model V3

Click to load notebook preview

MicroSegment #1

Click to load notebook preview

New Multifactor Model V4

Click to load notebook preview

Model 14-Pure Technical

Click to load notebook preview

Final model

Click to load notebook preview

version 3

Click to load notebook preview

Model 2

Click to load notebook preview

Model 3

Click to load notebook preview

Model 4

Click to load notebook preview

Micro Segment #2

Click to load notebook preview

SP1

Click to load notebook preview

SP2

Click to load notebook preview

SP3

Click to load notebook preview

Model 1

Click to load notebook preview

EZ2 bt8

Click to load notebook preview

FM fw

Click to load notebook preview

FE3 fw

Click to load notebook preview

Model # 1

Clone Algorithm
12
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Numero de dias atras para Vender
NUMBER_OF_DAYS_AGO = 5

# Tasa de crecimiento, para comprar
GROWTH_RATE = 0.05

def initialize(context):

    context.tesla = sid(39840) # TSLA Tesla Motors

    
def handle_data(context, data):
    # Valor promedio del Stock en los ultimos NUMBER_OF_DAYS_AGO dias
    average_price = data[context.tesla].mavg(NUMBER_OF_DAYS_AGO)
    
    # Valor actual del Stock
    current_price = data[context.tesla].price
    
    cash = context.portfolio.cash
    
    factor(
        context=context,
        price=current_price,
        average=average_price,
        cash=cash
    )
    # Mostrar el precio del Stock
    record(stock_price=data[context.tesla].price)

def factor(context, price, average, cash):
    # Si el precio acual es mayor que el 5% de los 5 Dias anteriores entonces compro
    # en otras palabras, si el stock en los ultimos 5 dias crecio mas del 5%
    # y tengo plata, entonces compro  todo lo que puedo
    if price > (1 + GROWTH_RATE) * average and cash > price:
        buy(context, cash, price)
    
    # Si la acción cayó en los ultimos 5 dias, entonces vendo
    elif price < average:
        sell(context)
    
def get_shares(cash, price):
    # Numero de Stock que puedo a comprar, teniendo en cuenta
    # el dinero que tengo
    return abs(int(cash/price))

def buy(context, cash, price):
    # Comprar todas las acciones que pueda, teniendo en cuenta 
    # El dinero que tengo
    number_of_shares = get_shares(cash, price)    
    order(context.tesla, abs(number_of_shares))

def sell(context):
    # Vender todas las acciones
    order_target(context.tesla, 0)
There was a runtime error.

Model 1

Click to load notebook preview

FL

Click to load notebook preview

FM bt2

Click to load notebook preview

FJ

Click to load notebook preview

FH

Click to load notebook preview

FO

Click to load notebook preview

FR

Click to load notebook preview

FQ

Click to load notebook preview

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!