Back to Community
Smart Beta ETF correlation algo

Questions/comments/improvements/criticisms welcome.

Clone Algorithm
7
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
# https://www.quantopian.com/posts/new-challenge-build-smart-beta-factors

from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.factors import RollingPearsonOfReturns
import pandas as pd

N_STOCKS = 250

def normalize(x):
    
    return x/x.abs().sum()
    
def factor_pipeline():
    
    QTU = QTradableStocksUS()
    
    pipeline_columns = {}

# https://etfdb.com/themes/smart-beta-etfs/#complete-list&sort_name=assets_under_management&sort_order=desc&page=1
    
    ETFs = [sid(25909), # VTV
            sid(21518), # IWF
            sid(25910), # VUG
            sid(28364), # VIG
            sid(21517), # IWD
            sid(42039), # USMV
            sid(32888), # VYM
            sid(21514), # IVW
            sid(45104), # QUAL
            sid(21512), # IVE
            sid(27806), # SDY
            sid(25647), # DVY
            sid(42041), # EFAV
            sid(24744), # RSP
            sid(42043), # SCHD
            sid(25901), # VBR
            sid(22907), # IWP
            sid(41382), # SPLV
            sid(47109), # DGRO
            sid(22909), # IWS
            sid(44542), # MTUM
            sid(39065), # SCHG
            sid(25425), # FVD
            sid(25900), # VBK
            sid(32521), # VOE
           ]
            
    for ETF in ETFs:
        r = RollingPearsonOfReturns(target=ETF,returns_length=2,correlation_length=260,mask=QTU)
        pipeline_columns['alpha_'+str(ETF)] = r.zscore(mask=QTU)
        
    pipe = Pipeline(columns = pipeline_columns, screen = QTU)
    
    return pipe
    
def initialize(context):    
    
    attach_pipeline(factor_pipeline(), 'factor_pipeline')
    
    # Schedule my rebalance function
    schedule_function(func=rebalance,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_close(),
                      half_days=True)
    # record my portfolio variables at the end of day
    schedule_function(func=recording_statements,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_close(),
                      half_days=True)
    
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))

def recording_statements(context, data):
 
    record(num_positions=len(context.portfolio.positions))
    record(leverage=context.account.leverage) 
    
def rebalance(context, data):
    
    alpha = pipeline_output('factor_pipeline').sum(axis=1).dropna()
    
    alpha = pd.Series().append(alpha.nlargest(N_STOCKS))
    alpha = normalize(alpha.replace(alpha,1.0))
    
    objective = opt.TargetWeights(alpha)
    
    order_optimal_portfolio(objective=objective,
                            constraints=[]
                           )
There was a runtime error.
2 responses

Smart Beta Challenge notebook

Loading notebook preview...

Here's a variant. I just changed from equal weights to ranks. I'm not sure if it's any "smarter" or not, and I'm still not clear on the definition of Smart Beta and how one would measure Smart-Beta-ness of an investment portfolio.

def rebalance(context, data):  
    alpha = pipeline_output('factor_pipeline').sum(axis=1).dropna()  
    alpha = normalize(pd.Series().append(alpha.nlargest(N_STOCKS)).rank())  
    objective = opt.TargetWeights(alpha)  
    order_optimal_portfolio(objective=objective,  
                            constraints=[]  
                           )  
Clone Algorithm
3
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
# https://www.quantopian.com/posts/new-challenge-build-smart-beta-factors

from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.factors import RollingPearsonOfReturns
import pandas as pd

N_STOCKS = 250

def normalize(x):
    
    return x/x.abs().sum()
    
def factor_pipeline():
    
    QTU = QTradableStocksUS()
    
    pipeline_columns = {}

# https://etfdb.com/themes/smart-beta-etfs/#complete-list&sort_name=assets_under_management&sort_order=desc&page=1
    
    ETFs = [sid(25909), # VTV
            sid(21518), # IWF
            sid(25910), # VUG
            sid(28364), # VIG
            sid(21517), # IWD
            sid(42039), # USMV
            sid(32888), # VYM
            sid(21514), # IVW
            sid(45104), # QUAL
            sid(21512), # IVE
            sid(27806), # SDY
            sid(25647), # DVY
            sid(42041), # EFAV
            sid(24744), # RSP
            sid(42043), # SCHD
            sid(25901), # VBR
            sid(22907), # IWP
            sid(41382), # SPLV
            sid(47109), # DGRO
            sid(22909), # IWS
            sid(44542), # MTUM
            sid(39065), # SCHG
            sid(25425), # FVD
            sid(25900), # VBK
            sid(32521), # VOE
           ]
            
    for ETF in ETFs:
        r = RollingPearsonOfReturns(target=ETF,returns_length=2,correlation_length=260,mask=QTU)
        pipeline_columns['alpha_'+str(ETF)] = r.zscore(mask=QTU)
        
    pipe = Pipeline(columns = pipeline_columns, screen = QTU)
    
    return pipe
    
def initialize(context):    
    
    attach_pipeline(factor_pipeline(), 'factor_pipeline')
    
    # Schedule my rebalance function
    schedule_function(func=rebalance,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_close(),
                      half_days=True)
    # record my portfolio variables at the end of day
    schedule_function(func=recording_statements,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_close(),
                      half_days=True)
    
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))

def recording_statements(context, data):
 
    record(num_positions=len(context.portfolio.positions))
    record(leverage=context.account.leverage) 
    
def rebalance(context, data):
    
    alpha = pipeline_output('factor_pipeline').sum(axis=1).dropna()
    
    alpha = normalize(pd.Series().append(alpha.nlargest(N_STOCKS)).rank())
    
    objective = opt.TargetWeights(alpha)
    
    order_optimal_portfolio(objective=objective,
                            constraints=[]
                           )
There was a runtime error.