Created
July 27, 2020 13:54
-
-
Save 18182324/9194b9d750411d171b145846ba5520a8 to your computer and use it in GitHub Desktop.
Pairs Trading Strategy Backtest for cointegration method [Python Code]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sklearn import linear_model | |
import numpy as np | |
import pandas as pd | |
from scipy import stats | |
from math import floor | |
from datetime import timedelta | |
class PairsTradingAlgorithm(QCAlgorithm): | |
def Initialize(self): | |
self.SetStartDate(2010,1,1) | |
self.SetEndDate(2017,6,30) | |
self.SetCash(10000) | |
self.numdays = 250 # set the length of training period | |
tickers = ["XLK","QQQ"] | |
self.symbols = [] | |
self.threshold = 1. | |
for i in tickers: | |
self.symbols.append(self.AddSecurity(SecurityType.Equity, i, Resolution.Daily).Symbol) | |
for i in self.symbols: | |
i.hist_window = RollingWindow[TradeBar](self.numdays) | |
def OnData(self, data): | |
if not (data.ContainsKey("XLK") and data.ContainsKey("QQQ")): return | |
for symbol in self.symbols: | |
symbol.hist_window.Add(data[symbol]) | |
price_x = pd.Series([float(i.Close) for i in self.symbols[0].hist_window], | |
index = [i.Time for i in self.symbols[0].hist_window]) | |
price_y = pd.Series([float(i.Close) for i in self.symbols[1].hist_window], | |
index = [i.Time for i in self.symbols[1].hist_window]) | |
if len(price_x) < 250: return | |
spread = self.regr(np.log(price_x), np.log(price_y)) | |
mean = np.mean(spread) | |
std = np.std(spread) | |
ratio = floor(self.Portfolio[self.symbols[1]].Price / self.Portfolio[self.symbols[0]].Price) | |
# quantity = float(self.CalculateOrderQuantity(self.symbols[0],0.4)) | |
if spread[-1] > mean + self.threshold * std: | |
if not self.Portfolio[self.symbols[0]].Quantity > 0 and not self.Portfolio[self.symbols[0]].Quantity < 0: | |
self.Sell(self.symbols[1], 100) | |
self.Buy(self.symbols[0], ratio * 100) | |
elif spread[-1] < mean - self.threshold * std: | |
if not self.Portfolio[self.symbols[0]].Quantity < 0 and not self.Portfolio[self.symbols[0]].Quantity > 0: | |
self.Sell(self.symbols[0], 100) | |
self.Buy(self.symbols[1], ratio * 100) | |
else: | |
self.Liquidate() | |
def regr(self,x,y): | |
regr = linear_model.LinearRegression() | |
x_constant = np.column_stack([np.ones(len(x)), x]) | |
regr.fit(x_constant, y) | |
beta = regr.coef_[0] | |
alpha = regr.intercept_ | |
spread = y - x*beta - alpha | |
return spread |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment