Overall Statistics |
Total Trades 67 Average Win 3.55% Average Loss -1.85% Compounding Annual Return 18.128% Drawdown 8.600% Expectancy 0.326 Net Profit 19.863% Sharpe Ratio 0.919 Loss Rate 55% Win Rate 45% Profit-Loss Ratio 1.92 Alpha 0.16 Beta -0.075 Annual Standard Deviation 0.16 Annual Variance 0.026 Information Ratio -0.098 Tracking Error 0.194 Treynor Ratio -1.959 Total Fees $406.34 |
import numpy as np import pandas as pd import statsmodels.api as sm class TrendFollowingAlgorithm(QCAlgorithm): def __init__(self): self.symbols = ['DIA','QQQ','LQD','HYG','USO','GLD','VNQ','RWX','UNG','DBA'] self.num_history = 252/2 self.slope_min = 0.15 self.exit = 1 self.multiple = 5 def Initialize(self): self.SetCash(50000) self.SetStartDate(2013,03,01) self.SetEndDate(2014,04,01) for i in range(len(self.symbols)): self.symbols[i] = self.AddEquity(self.symbols[i],Resolution.Minute).Symbol history = self.History(self.num_history, Resolution.Daily) for i in self.symbols: bars = map(lambda x: x[i],history) i.time = [str(x.Time) for x in bars] i.prices = [float(x.Open) for x in bars] i.stopprice = None i.slope = None self.Schedule.On(self.DateRules.EveryDay(self.symbols[0]), self.TimeRules.AfterMarketOpen(self.symbols[0], 2), Action(self.do_regression)) # self.Schedule.On(self.DateRules.EveryDay(self.symbols[0]), # self.TimeRules.AfterMarketOpen(self.symbols[0], 4), Action(self.trade)) def OnData(self, data): if False in [data.ContainsKey(x) for x in self.symbols]: return time = str(self.Time).split(' ')[1] hour = time.split(':')[0] m = time.split(':')[1] #update price for regression if hour == '09' and m == '31': for i in self.symbols: i.prices.append(float(data[i].Open)) i.prices.pop(0) #stop loss if float(m)%5 == 0: for i in self.symbols: price = float(data[i].Close) if self.Portfolio[i].Quantity > 0: if price/i.order_price - 1 < -0.02: self.Liquidate(i) elif price/i.order_price - 1 > 0.03: self.Liquidate(i) elif self.Portfolio[i].Quantity < 0: if price/i.order_price - 1 > 0.02: self.Liquidate(i) elif price/i.order_price - 1 < -0.03: self.Liquidate(i) else: pass # i.stoploss = abs(i.slope*self.num_history / 252)+1 # if self.Portfolio[i].Quantity > 0: # if i.stopprice < 0: # i.stopprice = price/i.stoploss # else: # i.stopprice = max(price/i.stoploss,i.stopprice) # if price < i.stopprice: # self.Liquidate(i) # elif self.Portfolio[i].Quantity < 0: # if i.stopprice < 0: # i.stopprice = price * i.stoploss # else: # i.stopprice = min(price*i.stoploss,i.stopprice) # if price > i.stopprice: # self.Liquidate(i) # else: # i.stopprice = None def regression(self,asset): x = sm.add_constant(range(len(asset.prices))) asset.model = sm.OLS(asset.prices,x).fit() def do_regression(self): for i in self.symbols: self.regression(i) i.beta = i.model.params[1] i.intercept = i.model.params[0] i.slope = i.beta/i.intercept * 252.0 # i.delta = i.prices - (np.dot(i.beta,range(len(i.prices))) + i.intercept) i.delta = i.model.resid i.sd = np.std(i.prices) #exit long postion if self.Portfolio[i].Quantity > 0 and i.slope < 0: self.Liquidate(i) #exit short position if self.Portfolio[i].Quantity < 0 and i.slope > 0: self.Liquidate(i) #trend is up: if i.slope > self.slope_min: if i.delta[-1] > 0 and i.delta[-2] < 0 and self.Portfolio[i].Quantity == 0: i.stopprice = None self.SetHoldings(i, i.slope*self.multiple) i.order_price = float(self.Portfolio[i].Price) if i.delta[-1] > self.exit*i.sd and self.Portfolio[i].Quantity > 0: self.Liquidate(i) self.Log('profit take') #trend is down if i.slope < -self.slope_min: if i.delta[-1] < 0 and i.delta[-2] > 0 and self.Portfolio[i].Quantity == 0: i.stopprice = None self.SetHoldings(i,i.slope*self.multiple) i.order_price = float(self.Portfolio[i].Price) if i.delta[-1] < -self.exit * i.sd and self.Portfolio[i].Quantity < 0: self.Liquidate(i) self.Log('profit take')