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)