Back to Community
long only, choose 6 among the major 12 stocks, rebalance every 1month, with the target annualized volatility of 0.10, since 2006, with sharpe 0.93

long only, choose 6 among the major 12 stocks, rebalance every 1month, with the target annualized volatility of 0.10, since 2006, with sharpe 0.93

Clone Algorithm
19
Loading...
Backtest from to with initial capital
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
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import Fundamentals
from quantopian.pipeline.filters import QTradableStocksUS, StaticAssets
from quantopian.pipeline.factors import AverageDollarVolume, Returns, SimpleMovingAverage, RollingLinearRegressionOfReturns, AnnualizedVolatility
from quantopian.pipeline.classifiers.fundamentals import Sector
import quantopian.optimize as opt
import numpy as np
from collections import defaultdict

_NUM_HOLINGS = 6
_WEEK = 5
_MONTH = 22 # 22 days = 1 month
_TARGET_VOLATILITY = 0.10

def factor_pipeline():
    columns = {
        'r0': Returns(window_length=_WEEK),
        'r': Returns(window_length=_MONTH),
        'r2': Returns(window_length=2*_MONTH),
        'volatility': AnnualizedVolatility(annualization_factor = _MONTH),
        }

    #stock_filter = StaticAssets(symbols('AAPL', 'AMZN', 'GOOG', 'MSFT', 'NFLX', 'FB', 'TSLA', 'BABA'))
    stock_filter = StaticAssets(symbols('AAPL', 'AMZN', 'GOOG', 'MSFT', 'NFLX', 'FB', 'TSLA', 'BABA', 'GE', 'MU', 'SQ', 'CHK'))
    total_filter = (QTradableStocksUS() & stock_filter)

    pipe = Pipeline(
        columns = columns,
        screen = total_filter)

    return pipe

def initialize(context):
    attach_pipeline(factor_pipeline(), 'factor_pipeline')
    schedule_function(clear, date_rules.month_start(), time_rules.market_open())
    schedule_function(rebalance, date_rules.month_start(), time_rules.market_close(hours=2))
    set_benchmark(symbol('SPY'))
    #set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    #set_slippage(slippage.FixedSlippage(spread=0))
    context.days_cnt = 0
    context.clear_cnt = 0
    context.rebalance_cnt = 0

def before_trading_start(context, data):
    '''called every day'''
    context.days_cnt += 1

def clear(context, data):
    context.clear_cnt += 1
    
    log.info(get_datetime())
    log.info("clearing")
    for s in context.portfolio.positions:
        order_target_percent(s, 0)

def rebalance(context, data):    
    context.rebalance_cnt += 1
    
    safe = symbol('TLT')
    safe_hist = data.history(safe, 'price', _MONTH + 1, '1d')
    safe_mom = (safe_hist[-1]/safe_hist[0]) - 1.0

    spy = symbol('SPY')
    spy_hist = data.history(spy, 'price', _MONTH + 1, '1d')
    spy_mom = (spy_hist[-1]/spy_hist[0]) - 1.0

    factors = pipeline_output('factor_pipeline').dropna()

    factors['r_sum'] = factors.r + factors.r0 + factors.r2
    top_assets = factors.sort_values('r_sum').index[-_NUM_HOLINGS:]
    top_mom = factors.r[top_assets]

    n_picks = len(top_assets)
    
    target_weights = {}

    picks = 0
    weight_unit = 1.0 / _NUM_HOLINGS
    for i in range(n_picks):
        a = top_assets[i]
        m = top_mom[i]
        max_m = max(m, spy_mom, safe_mom)
        if m == max_m and m > 0:
            if data.can_trade(a):
                volatility = factors.volatility[a]
                volatility_multiplier = min(1.0, _TARGET_VOLATILITY / volatility)

                target_weights[a] = weight_unit * volatility_multiplier
                picks += 1

    more_picks = _NUM_HOLINGS - picks
    if more_picks > 0:
        if spy_mom == max_m and spy_mom > 0:
            target_weights[spy] = weight_unit * more_picks
        elif safe_mom > 0:
            target_weights[safe] = weight_unit * more_picks
        
    execute(context, target_weights)
    
    non_safe_weight = sum(map(lambda p: target_weights[p] if (p != safe and p != spy) else 0, target_weights))
    record(
        leverage = context.account.leverage,
        non_safe_weight = non_safe_weight,
        safe_weight = target_weights[safe] if safe in target_weights else 0,
        spy_weight = target_weights[spy] if spy in target_weights else 0,
    )
    
def execute(context, target_weights):   
    log.info("after rebalance, holdings: %s" % (str(target_weights)))
    for a, p in target_weights.items():
        order_target_percent(a, p)
There was a runtime error.