Are Danish Stocks Cointegrated?

This is just a quick test to see whether any danish OMXC20 stocks are cointegrated. Daily adjusted closed prices from yahoo are used. Rows with missing prices are simply dropped for this quick test. The first way to test for cointegration is through statsmodels’ cointegration function. It’s a bit blackboxish and yields some relationships between some stocks. I also try the classical way i.e. estimate betas with a simple OLS, extract predictions from the linear combination and finally test for cointegration through ADF. This methods yields no relationships, however.

Packages Used

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

import yfinance as yf
import seaborn as sns

import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.stattools import coint

Preparation

adf = lambda s: adfuller(s, autolag='AIC')
p_val = lambda s: adfuller(s, autolag='AIC')[1]

# %%
data = yf.download("TRYG.CO CARL-B.CO DSV.CO NOVO-B.CO CHR.CO VWS.CO RBREW.CO AMBU-B.CO NZYM-B.CO FLS.CO MAERSK-A.CO SIM.CO PNDORA.CO MAERSK-B.CO COLO-B.CO ROCK-B.CO LUN.CO GN.CO DANSKE.CO JYSK.CO", start="2012-01-01", end="2019-11-27")
data = data['Adj Close'].dropna()
[*********************100%***********************]  20 of 20 completed

Correlation Heatmap

# %% Correlation heatmap
corr = data.corr()
ax = sns.heatmap(
    corr, 
    vmin=-1, vmax=1, center=0,
    cmap=sns.diverging_palette(20, 220, n=200),
    square=True
)
ax.set_xticklabels(
    ax.get_xticklabels(),
    rotation=45,
    horizontalalignment='right'
);

Heatmap

Tests For Cointegration (Method 1)

cointegrations = pd.DataFrame(np.zeros((200, 2)))

for i in range(0, 19):
    y1 = data
    y1 = y1.iloc[:,i]
    
    for j in range(0, 19):
        y2 = data
        y2 = y2.drop([y1.name], axis=1)
        y2 = y2.iloc[:,j]
        if coint(y1, y2, trend='c', autolag="AIC")[1] <= 0.05:
            print(y1.name, "&", y2.name, "is cointegrated")
            cointegrations.iloc[i,0] = y1.name
            cointegrations.iloc[i,1] = y2.name


cointegrations = cointegrations.loc[~(cointegrations==0).all(axis=1)]
AMBU-B.CO & CHR.CO is cointegrated
AMBU-B.CO & ROCK-B.CO is cointegrated
CARL-B.CO & DSV.CO is cointegrated
CHR.CO & AMBU-B.CO is cointegrated
COLO-B.CO & TRYG.CO is cointegrated
MAERSK-A.CO & MAERSK-B.CO is cointegrated
MAERSK-B.CO & MAERSK-A.CO is cointegrated
NOVO-B.CO & NZYM-B.CO is cointegrated
NZYM-B.CO & NOVO-B.CO is cointegrated
ROCK-B.CO & AMBU-B.CO is cointegrated
TRYG.CO & COLO-B.CO is cointegrated

Tests For Cointegration (Method 2)

for i in range(0, 19):
    y = data
    y = y.iloc[:,i]
    
    for j in range(0, 19):
        x = data
        x = x.drop([y1.name], axis=1)
        x = x.iloc[:,j]
        x = sm.add_constant(x)
        model = sm.OLS(y, x)
        results = model.fit()
        yhat = results.predict()
        if adfuller(yhat, regression="c")[1] <= 0.05:
            print(y.name, "&", x.name, "is cointegrated")

Overall I haven’t found out why the “coint” function from Statsmodels finds several cointegrated relationships compared to the other method. When testing the linear combination of all stock from the residuals of a simple OLS, no stocks are cointegrated. For now I suspect the coint-function uses another beta then the one from the estimated OLS.