Overall Statistics
Total Trades
359
Average Win
0.36%
Average Loss
-0.51%
Compounding Annual Return
6.249%
Drawdown
11.000%
Expectancy
0.410
Net Profit
52.882%
Sharpe Ratio
0.804
Loss Rate
17%
Win Rate
83%
Profit-Loss Ratio
0.70
Alpha
0.053
Beta
-0.02
Annual Standard Deviation
0.064
Annual Variance
0.004
Information Ratio
-0.252
Tracking Error
0.157
Treynor Ratio
-2.627
Total Fees
$564.21
#
#   QuantConnect Basic Template:
#	Fundamentals to using a QuantConnect algorithm.
#
#	You can view the QCAlgorithm base class on Github: 
#	https://github.com/QuantConnect/Lean/tree/master/Algorithm
#

import numpy as np
import pandas as pd

class BasicTemplateAlgorithm(QCAlgorithm):

    # Assets from CSSA blog (VTI, ICF, LQD, DBC, cash = SHY)
	active = [
        "VTI",		# VTI - Vanguard Total Stock Market ETF (Inception: 24 May 01)
        "VNQ",		# VNQ - Vanguard REIT ETF (U.S. Real Estate) (Inception: 23 Sep 04)
        "LQD",		# LQD - iShares iBoxx $ Investment Grade Corporate Bond ETF (Inception: 22 Jul 02)
        "TLT",		# TLT - iShares 20+ Year Treasury Bond ETF
        "DBC",		# DBC - PowerShares DB Commodity Index Tracking Fund (Inception: 3 Feb 06)
	]
	cash = "SHY"

	channels = [60, 120, 180, 252]
	entry = 0.75
	exit = 0.25
	signals = pd.DataFrame(0., index=channels, columns=active)
	
	LEVERAGE = 1.0
	
	def Initialize(self):
		# Set the cash we'd like to use for our backtest
		# This is ignored in live trading 
		self.SetCash(100000)
		
		# Start and end dates for the backtest.
		# These are ignored in live trading.
		self.SetStartDate(2010,1,1)
		self.SetEndDate(2017,1,1)
		
		# Add assets to be used 
		for symbol in self.active:
			self.AddEquity(symbol, Resolution.Minute)
		self.AddEquity(self.cash, Resolution.Minute)

		# Schedule functions
		self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose("SHY", 5), Action(self.CheckChannels))
		self.Schedule.On(self.DateRules.MonthStart("SHY"), self.TimeRules.BeforeMarketClose("SHY", 30), Action(self.Rebalance))

	def OnData(self, slice):
		# Simple buy and hold template
		#if not self.Portfolio.Invested:
		#	self.SetHoldings(self.spy, 1)
		#	self.Debug("numpy test >>> print numpy.pi: " + str(np.pi))
		pass

	def CheckChannels(self):
		h = self.History(self.active, 252, Resolution.Daily).close
		h = pd.concat([h.loc[x] for x in self.active], axis = 1)
		h.columns = self.active
		
		for c in self.channels:
			channel_prices = h[-c:]
			entry = channel_prices.quantile(self.entry)
			exit = channel_prices.quantile(self.exit)
        
			for s in self.active:
				if h[s][-1] >= entry[s]:
					self.signals[s][c] = 1
				if h[s][-1] <= exit[s]:
					self.signals[s][c] = -1

	
	def Rebalance(self):
		h = self.History(self.active, 252, Resolution.Daily).close
		h = pd.concat([h.loc[x] for x in self.active], axis = 1)
		h.columns = self.active
		
		# Allocation
		#inv_vol = 1. / np.log(h)/diff().std()
		inv_vol = np.log(h)
		inv_vol = np.diff(inv_vol)
		inv_vol = np.std(inv_vol)
		inv_vol = 1. / inv_vol

		channel_weight = self.signals.sum() / len(self.channels)
		
		active_weight = channel_weight * inv_vol
		active_weight = active_weight.abs() / active_weight.abs().sum()
		active_weight[channel_weight < 0.] = 0.
		active_weight = active_weight.fillna(0)
    
		# Ordering
		for s in self.active:
			self.SetHoldings(s, active_weight[s] * self.LEVERAGE)
        
		cash_weight = 1. - active_weight.sum()
		self.SetHoldings(self.cash, cash_weight)