Overall Statistics |
Total Trades 153 Average Win 6.66% Average Loss -3.37% Compounding Annual Return 15.661% Drawdown 23.700% Expectancy 0.840 Net Profit 563.122% Sharpe Ratio 0.745 Loss Rate 38% Win Rate 62% Profit-Loss Ratio 1.97 Alpha 0.286 Beta -9.22 Annual Standard Deviation 0.182 Annual Variance 0.033 Information Ratio 0.655 Tracking Error 0.182 Treynor Ratio -0.015 Total Fees $5872.97 |
import numpy as np import pandas as pd class BasicTemplateAlgorithm(QCAlgorithm): def __init__(self): #self.symbols = ['IVV','IJH','IJR','IEV','EEM','ILF','EPP','TLT'] #728.27 % #self.symbols = ['SPY','IEV','EEM','ILF','EPP','TLT'] #ret=836.63 %, But 2015 DD, #73 self.symbols = ['SPY','IEV','EEM','ILF','EPP','TLT','SHY'] #ret=562 %, best stable, #73 #self.symbols = ['SPY','IEV','EEM','ILF','EPP','TLT','IEF','SHY'] #ret=386.38 % #self.symbols = ['SPY','IVV','IJH','IJR','IEV','EEM','ILF','EPP','TLT','SHY'] #ret=562 %, best stable, #73 #self.symbols = ['SPY','IEV','EEM','ILF','EPP','TLT','SHY','XLV','XLK','XLI','XLU','XLF','XLY','XLP','XLB','XLE'] #ret=562 %, best stable, #73 self.back_period =73 #73 def Initialize(self): self.SetCash(100000) self.SetStartDate(2005,1,1) # self.SetEndDate(2016,2,1) self.spy = self.AddEquity('SPY', Resolution.Daily).Symbol for i in range(len(self.symbols)): symbol = self.AddEquity(self.symbols[i], Resolution.Daily).Symbol self.symbols[i] = symbol self.Schedule.On(self.DateRules.MonthStart(self.spy), self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.rebalance)) def OnData(self, slice): pass # calculate historical return and volatility for each stock def get_history(self): history = self.History(self.back_period, Resolution.Daily) for i in self.symbols: bars = map(lambda x: x[i], history) i.prices = pd.Series([float(x.Close) for x in bars]) vol = np.mean(pd.rolling_std(i.prices, 20)*np.sqrt(self.back_period/20.0)) i.volatility = vol/i.prices[0] i.ret = (i.prices.iloc[-1] - i.prices.iloc[0])/i.prices.iloc[0] # normalise the mesures of returns and volatilities def normalise(self): rets = [x.ret for x in self.symbols] vols = [x.volatility for x in self.symbols] self.ret_max, self.ret_min = max(rets), min(rets) # vol_min is actually the max volatility. min means low score on this. self.vol_min, self.vol_max = max(vols), min(vols) # select the best one with the highest score. def select(self): self.get_history() self.normalise() for i in self.symbols: ret = (i.ret - self.ret_min)/(self.ret_max - self.ret_min) vol = (i.volatility - self.vol_min)/(self.vol_max - self.vol_min) i.score = ret*0.7 + vol*0.3 select = sorted(self.symbols, key = lambda x: x.score, reverse = True) return select[0] def rebalance(self): target = self.select() if self.Portfolio[target].Quantity != 0: return self.Liquidate() self.SetHoldings(target,1)