Back to Community
Financials tearsheet challenge entry

Here's my Financials tearsheet challenge entry. I will post the tearsheet next.

Clone Algorithm
42
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import RollingLinearRegressionOfReturns
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
import numpy as np
from quantopian.pipeline.data.factset import RBICSFocus

def normalize(x):
    
    r = x - x.mean()
    
    return r/r.abs().sum()

def regression_pipeline():
    
    QTU = QTradableStocksUS()
    sector = RBICSFocus.l1_name.latest
    
    universe = QTU & sector.eq('Finance')
    
    regression = RollingLinearRegressionOfReturns(
        target=symbol('SPY'),
        returns_length=2,
        regression_length=8,
        mask=universe,
    )
    
    alpha = regression.alpha
    beta = regression.beta
    correlation = regression.r_value
    
    pipe = Pipeline(columns = {
        'alpha':alpha,
        'beta':beta,
        'correlation':correlation,
    },
    screen = universe)
    return pipe

def initialize(context):    
    
    attach_pipeline(regression_pipeline(), 'regression_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 = normalize(-pipeline_output('regression_pipeline')['alpha']).dropna()
    
    objective = opt.TargetWeights(alpha)
         
    order_optimal_portfolio(objective=objective,
                            constraints=[]
                           )
There was a runtime error.
8 responses

Here's the tearsheet.

Loading notebook preview...

Alpha factor as THE alpha over SPY? Seems a little bit data mining to me. But thanks for sharing as always.

Financial sector is a tough one to work on.

@ Xiaochen Lin -

Presumably this is not a viable factor, since it is based mostly on common returns. However, I suspect that alpha over SPY is a measure of an individual stock to short-term mean revert to the market.

@Grant Kiehne -

I was wrong, as it is not the same period alpha over SPY. So it is a mean-reversion strategy. Interesting that this factor may work for REITs.

@ Xiaochen Lin -

Yes, I suspect that there are similarities between the financial and real estate sectors. You can see the rolling correlation between XLF & IYR here:

https://www.portfoliovisualizer.com/asset-correlations?s=y&symbols=XLF%2CIYR&timePeriod=1&tradingDays=20&months=36

It's pretty interesting how much inertia there is in markets...the real estate bubble ramped up and ramped down over the last 20 years!

Here's an update. I'll post the tearsheet next.

I changed to:

regression = RollingLinearRegressionOfReturns(  
        target=symbol('SPY'),  
        returns_length=4,  
        regression_length=8,  
        mask=universe,  
    )  

and

    alpha = normalize(-pipeline_output('regression_pipeline')['alpha']*pipeline_output('regression_pipeline')['correlation'].abs()).dropna()  
Clone Algorithm
42
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import RollingLinearRegressionOfReturns
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
import numpy as np
import pandas as pd
from quantopian.pipeline.data.factset import RBICSFocus

def normalize(x):
    
    # r = x.rank()
    # r = r/r.max()
    # r = r - 0.5
    
    r = x - x.mean()
    
    return r/r.abs().sum()

def regression_pipeline():
    
    QTU = QTradableStocksUS()
    sector = RBICSFocus.l1_name.latest
    
    universe = QTU & sector.eq('Finance')
    
    regression = RollingLinearRegressionOfReturns(
        target=symbol('SPY'),
        returns_length=4,
        regression_length=8,
        mask=universe,
    )
    
    alpha = regression.alpha
    beta = regression.beta
    correlation = regression.r_value
    
    pipe = Pipeline(columns = {
        'alpha':alpha,
        'beta':beta,
        'correlation':correlation,
    },
    screen = universe)
    return pipe

def initialize(context):    
    
    attach_pipeline(regression_pipeline(), 'regression_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 = normalize(-pipeline_output('regression_pipeline')['alpha']*pipeline_output('regression_pipeline')['correlation'].abs()).dropna()
    
    objective = opt.TargetWeights(alpha)
         
    order_optimal_portfolio(objective=objective,
                            constraints=[]
                           )
There was a runtime error.

Notebook for backtest immediately above.

Loading notebook preview...

Here's a longer run of the backtest above (5ded570bc829b957452d5741).

Clone Algorithm
0
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import RollingLinearRegressionOfReturns
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
import numpy as np
import pandas as pd
from quantopian.pipeline.data.factset import RBICSFocus

def normalize(x):
    
    # r = x.rank()
    # r = r/r.max()
    # r = r - 0.5
    
    r = x - x.mean()
    
    return r/r.abs().sum()

def regression_pipeline():
    
    QTU = QTradableStocksUS()
    sector = RBICSFocus.l1_name.latest
    
    universe = QTU & sector.eq('Finance')
    
    regression = RollingLinearRegressionOfReturns(
        target=symbol('SPY'),
        returns_length=4,
        regression_length=8,
        mask=universe,
    )
    
    alpha = regression.alpha
    beta = regression.beta
    correlation = regression.r_value
    
    pipe = Pipeline(columns = {
        'alpha':alpha,
        'beta':beta,
        'correlation':correlation,
    },
    screen = universe)
    return pipe

def initialize(context):    
    
    attach_pipeline(regression_pipeline(), 'regression_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 = normalize(-pipeline_output('regression_pipeline')['alpha']*pipeline_output('regression_pipeline')['correlation'].abs()).dropna()
    
    objective = opt.TargetWeights(alpha)
         
    order_optimal_portfolio(objective=objective,
                            constraints=[]
                           )
There was a runtime error.