For anyone interested I believe this slight adaptation follows the original slightly more accurately. Can't load back test so I'm posting code:
# Original Strategy: https://quantstrattrader.wordpress.com/2015/04/06/the-logical-invest-hell-on-fire-replication-attempt/
import pandas as pd
import datetime as dt
import numpy as np
import math
# The original strategy used any weight from 0% to 100% in increments of 10%
# I changed this to 20% to 80% in increments of 1%
ratios = []
for weight in np.arange(0.0, 1.10, 0.1):
ratios.append([weight, 1 - weight])
lookback = 73
sd_power = 2.5
leverage = 1 # Change to 3 if using the SPY / TLT appromimation method
def initialize(context):
set_commission(commission.PerShare(cost=0.0001, min_trade_cost=0.00))
set_slippage(slippage.FixedSlippage(spread=0.00001))
# ETFs from blog post
#context.symbols = [sid(37514), # SPXL(DIREXION DAILY S&P 500 BULL 3X)
# sid(38294)] # TMF(DIREXION DAILY 20 YEAR PLUS TR)
# Use these if you want to do an approximate backtest using more history
context.symbols = [sid(8554), # SPY
sid(23921)] # TLT
# Rebalance every month
schedule_function(
reallocate,
date_rules.month_start(),
time_rules.market_close(minutes = 5)
)
# set_benchmark(sid(37514))
def handle_data(context, data):
record(leverage = context.portfolio.positions_value / context.portfolio.portfolio_value)
def reallocate(context, data):
price_history = data.history(context.symbols, fields="price", bar_count=lookback, frequency="1d")
#history(bar_count = lookback, frequency='1d', field='price')
returns = (price_history - price_history.shift(1)) / price_history.shift(1)
# Random initial values
ratio = [0, 1]
max_sharpe = -1000
# Loop through each ratio
for c in range(len(ratios)):
temp_returns = returns.ix[:, 0] * ratios[c][0] + returns.ix[:, 1] * ratios[c][1]
# Use this if using the SPY / TLT approximation method
#temp_returns = 3 * returns.ix[:, 0] * ratios[c][0] + 3 * returns.ix[:, 1] * ratios[c][1]
cum_return = np.prod(1 + temp_returns) - 1
ann_return = cum_return ** (252 / lookback)
ann_sd = temp_returns.std() * math.sqrt(252)
#sharpe = ann_return / (ann_sd ** sd_power)
sharpe = temp_returns.mean() / (temp_returns.std() ** sd_power)
if sharpe > max_sharpe:
ratio = ratios[c]
max_sharpe = sharpe
order_target_percent(context.symbols[0], ratio[0] * leverage)
order_target_percent(context.symbols[1], ratio[1] * leverage)