Overall Statistics |
Total Trades 126 Average Win 3.44% Average Loss -2.91% Compounding Annual Return 0.443% Drawdown 3.900% Expectancy 0.057 Net Profit 4.517% Sharpe Ratio 0.196 Probabilistic Sharpe Ratio 0.249% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.18 Alpha 0.004 Beta -0.003 Annual Standard Deviation 0.02 Annual Variance 0 Information Ratio -0.853 Tracking Error 0.135 Treynor Ratio -1.384 Total Fees $605.78 |
from sklearn.linear_model import LinearRegression import numpy as np class PairsTradingAlgorithm(QCAlgorithm): closes_by_symbol = {} def Initialize(self): self.SetStartDate(2010,1,1) self.SetEndDate(2020,1,1) self.SetCash(100000) self.threshold = 1. self.numdays = 250 # set the length of training period self.x_symbol = self.AddEquity("XLK", Resolution.Daily).Symbol self.y_symbol = self.AddEquity("QQQ", Resolution.Daily).Symbol for symbol in [self.x_symbol, self.y_symbol]: history = self.History(symbol, self.numdays, Resolution.Daily) self.closes_by_symbol[symbol] = history.loc[symbol].close.values \ if not history.empty else np.array([]) def OnData(self, data): for symbol in self.closes_by_symbol.keys(): if not data.Bars.ContainsKey(symbol): return for symbol, closes in self.closes_by_symbol.items(): self.closes_by_symbol[symbol] = np.append(closes, data[symbol].Close)[-self.numdays:] log_close_x = np.log(self.closes_by_symbol[self.x_symbol]) log_close_y = np.log(self.closes_by_symbol[self.y_symbol]) spread, beta = self.regr(log_close_x, log_close_y) mean = np.mean(spread) std = np.std(spread) x_holdings = self.Portfolio[self.x_symbol] if x_holdings.Invested: if x_holdings.IsShort and spread[-1] <= mean or \ x_holdings.IsLong and spread[-1] >= mean: self.Liquidate() else: if beta < 1: x_weight = 0.5 y_weight = 0.5 / beta else: x_weight = 0.5 / beta y_weight = 0.5 if spread[-1] < mean - self.threshold * std: self.SetHoldings(self.y_symbol, -y_weight) self.SetHoldings(self.x_symbol, x_weight) if spread[-1] > mean + self.threshold * std: self.SetHoldings(self.x_symbol, -x_weight) self.SetHoldings(self.y_symbol, y_weight) scale = 10000 self.Plot("Spread", "Top", (mean + self.threshold * std) * scale) self.Plot("Spread", "Value", spread[-1] * scale) self.Plot("Spread", "Mean", mean * scale) self.Plot("Spread", "Bottom", (mean - self.threshold * std) * scale) self.Plot("State", "Value", np.sign(x_holdings.Quantity)) def regr(self, x, y): regr = LinearRegression() x_constant = np.column_stack([np.ones(len(x)), x]) regr.fit(x_constant, y) beta = regr.coef_[1] alpha = regr.intercept_ spread = y - x*beta - alpha return spread, beta