My question comes from this paper. The picture bellow provides a summary of the equations.
Suppose prices of two stocks satisfy (2.1) SDE. Then X(t) is expressed as (2.2) and can be modeled with as an OU process (2.3). To estimate OU coefficients we run an OLS (2.4) where R1 and R2 are time series of two stocks. Then we calculate the random walk series X(k) (2.5) and run a lagged regression on it (2.6). From which we estimate mu, sigma and theta.
Author says that after we obtain OU parameters "At this stage, we can use the standardized version of X(t) , called Z-score as trading signal." Ok, Z score is (X(t) - mu)/sigma.
What is X(t) in the Z-score? are those residuals series from (2.5) or residuals from OLS in (2.4)? How do we fit the OU coefficients to model the spread as an OU process?
EDIT:
Since I searched the internet far and wide for the implementation of the equations above and found nothing that would be usefull for this task, I wrote a Python script, it's rusty, but it does the job. Hopefully it will help someone to avoid troubles that I encountered
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from sklearn import linear_model
path = "C:\Users\PC\Desktop\Magistr\models\\test_data"
os.chdir(path)
data = pd.read_csv("stocks.csv", index_col = 'Date')
startDate = 0
endDate = 60
s_scores = []
for i in range(0, 100):
#S-score estimation
Y = data['007310 KS Equity'][startDate+i:endDate+i] #cointegrated securities
X = data['001680 KS Equity'][startDate+i:endDate+i]
Y = (Y.shift(1) / Y - 1)[1:]
X = (X.shift(1) / X - 1)[1:]
clf = linear_model.LinearRegression()
clf.fit(np.array(X).reshape(len(X),1), np.array(Y).reshape(len(Y),1))
beta_hr = clf.coef_[0]
alpha = clf.intercept_[0]
residuals = Y - beta_hr*X - alpha #residuals of the OLS (2.4)
Xk = np.cumsum(residuals) #auxiliary values (2.5)
#Xk = Xk[:-1] #remove the last value which is 0
#create two time series for AR(1) process
x_k = Xk[0:-1] #x(t-1)
y_k = Xk[1:] #x(t)
clf = linear_model.LinearRegression()
clf.fit(np.array(x_k).reshape(len(x_k),1), np.array(y_k).reshape(len(y_k),1))
ar1_beta = clf.coef_[0]
ar1_alpha = clf.intercept_[0]
ar1_resids = np.array(y_k) - ar1_beta*np.array(x_k) - ar1_alpha #calcualte residuals of AR(1)
mu = ar1_alpha/(1-ar1_beta) #calculate MU
sigma_eq = np.sqrt(np.var(ar1_resids)/(1-ar1_beta**2)) #calculate sigma
s = -mu/sigma_eq #s-score
s_scores.append(s)