WSTĘP

Tematem poniższej pracy jest analiza strategii inwestycyjnej Pair Trading opartej na kointegracji - jednej z własności szeregów czasowych. Celem jest zweryfikowanie skuteczności tej strategii w oparciu o pięc par spółek notowanych na Warszawskiej Giełdzie Papierów Wartościowych.

Strategia Pair Trading polega na zakupie akcji (lub innego instrumentu finansowego) jednej spółki (przyjęcia pozycji długiej) oraz sprzedaży akcji drugiej spółki (krótka sprzedaż), w której głównym założeniem jest fakt, że spółki te są ze sobą w pewien sposób powiązane (na przykład pochodzą z tego samego sektora gospodarczego). Najistotniejszym elementem tej strategii jest zdiagnozowanie odpowiedniego momentu otwarcia i zamknięcia pozycji na instrumenty finansowe. Indeks jednej ze spółek jest wwówczas względnie przeszacowany, a drugiej względnie niedoszacowany. To właśnie zjawisko kointegracji szeregów czasowych jest jednym z najczęściej wykrzystywanych przy strategii Pair Trading.

Zmienne skointegrowane, w mniej formalnym znaczeniu, mają wspólny trend stochastyczny. Między nimi zachodzi pewna równowaga długookresowa, od której krótkookresowe odchyły, mogą być wykorzystane dla potrzeb naszej strategii. Poniżej zostały przedstawione analizy pięciu par indeksów notowanych na GPW, na podstawie której została zweryfikowana skuteczność stategii Pair Trading opartej o kointegrację.

Podstawowym założeniem, jest przyjęcie progu otwarcia pozycji na poziomie 2 odchyleń standardowych nierównowagi krótkookresowej, która jest mierzona za pośrednictwem reszt z modelu długookreowej równowagi między skointegrowanymi zmiennymi. Model, jeden szereg jest zmienna niezależną, a drugi z nim skointegrowany zmienną niezależną, może być zbudowany bez obaw o zaistnienie regresji pozornej (kombinacja liniowa obu szeregów oparta na współcznynnikach z takiego modelu jest stacjonarna ). W literaturze głównie spotkać się można z założeniem o otwieraniu pozycji przy jednym odchyleniu standardowym, jednak w poniższej weryfikacji zdecydowano się przyjąć 2 poziomy odchylenia, motywując się przy tym większym bezpieczeństwem takiego portfela.

Analiza dla każdej ze spółek jest zbliżona

I. Analiza cen akcji Citi Handlowy i Pekao Sa

Pierwszą parą analizowanych spółek, jest para spółek pochodząca z obszaru bankowości. Poniżej został przedstawiony wykres obu szeregów:

#wykresiki
plot(BHW_PEO$Date, BHW_PEO$Close_BHW, col = "blue", type = "l", ylim = c(25, 200)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali)
lines(BHW_PEO$Date, BHW_PEO$Close_PEO, col="red")
title(main = 'Indeksy zamkniecia BHW i PEO (in-sample)')
legend("topleft", c("BHW", "PEO"), col = c("blue", "red"), lty = 1)

Na powyższym wykresie widać wyraźną zależność długookresową między indeksami Citi Handlowy i Pekao SA. Oba indeksy dryfują razem. Zbadamy zatem formalnie, za pomocą testu Dickeya Fullera czy zmienne faktycznie są skointegrowane. Najpierw badamy stopień zintegrowania obu zmiennych. Tylko zmienne zintegrowane tego samego stopnia mogą być skointegrowane

testdf(variable = BHW_PEO$Close_BHW,  adf_order = 3)

##   order       adf  p_adf     bgodfrey      p_bg
## 2     0 -1.191461 >10pct 0.0002484047 0.9874252
## 3     1 -1.193883 >10pct 0.0006494234 0.9796691
## 4     2 -1.178754 >10pct 0.0013926536 0.9702312
## 5     3 -0.956222 >10pct 0.0037607845 0.9511002

Na podstawie wyników testu Dickey Fullera dla indeksu zamknięcia spółki Citi Handlowy, nie ma podstaw do odrzucenia Ho, o tym że zmienna jest zintegrowana co najmniej stopnia pierwszego. Nie rozszerzamy testu DF, gdyż test bez opóźnień nie wykazuje autokorelacji (niska wartość statystyki testu bgodfrey ). Bierzemy pod uwagę wartość statystki DF -1.191461. Przeprowadzamy zatem test dla pierwszych różnic

testdf(variable = BHW_PEO$dClose_BHW, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -27.33240 <1pct 6.705121e-04 0.9793417
## 3     1 -19.54928 <1pct 2.346129e-03 0.9613681
## 4     2 -18.16224 <1pct 2.953959e-03 0.9566561
## 5     3 -14.84677 <1pct 7.267574e-06 0.9978490

W tym przypadku również pod uwagę bierzemy test dla zerowej liczby opóźnień (brak autokorelacji reszt w modelu używanym do przeprowadzenia testu DF). Natomiast, wysoka wartość statystyki TAU=-27.33240, zmusza do odrzucenia Ho o niestacjonarności pierwszych różnic. Zatem szereg indeksu BHW jest I(1). Następnie przeprowadzono analogiczne testy dla Pekao SA

testdf(variable = BHW_PEO$Close_PEO,  adf_order = 3)

##   order       adf  p_adf    bgodfrey      p_bg
## 2     0 -1.860970 >10pct 1.587038290 0.2077498
## 3     1 -1.739390 >10pct 0.006782032 0.9343659
## 4     2 -1.514994 >10pct 0.111390881 0.7385662
## 5     3 -1.223252 >10pct 0.001379993 0.9703668
testdf(variable = BHW_PEO$dClose_PEO, adf_order = 3)

##   order       adf p_adf    bgodfrey      p_bg
## 2     0 -28.73485 <1pct 0.010912776 0.9168010
## 3     1 -21.43432 <1pct 0.131343642 0.7170430
## 4     2 -18.99696 <1pct 0.002648915 0.9589529
## 5     3 -15.95574 <1pct 0.005008961 0.9435776

W przypadku oryginalego szeregu cen zamknięcia, nie ma podstaw do odrzucenia Ho o niestacjonarności szeregu. Wartość statystyki testowej DF wynosi -1.860970, przy braku autokorelacji reszt w nierozszerzonym teście DF. Natomiast w przypadku pierwszych różnic, odrzucamy Ho o niestacjonarności (DF=-28.73485, przy p value z testu BG=0.9168010) Szereg jest zatem I(1). Pierwszy warunek kointegracji szeregów jest zatem spełniony. W następnym kroku przeprowadzona została regresja zmiennej BHW na PEO. Jeśli reszty z tego modelu okazałyby się stacjonarne, to oba szeregi podlegałyby zjawisku kointegracji

summary(model)
## 
## Call:
## lm(formula = BHW_PEO$Close_BHW ~ BHW_PEO$Close_PEO)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -13.1487  -3.4003  -0.2042   3.2580  15.9097 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -46.29474    1.56481  -29.59   <2e-16 ***
## BHW_PEO$Close_PEO   0.88578    0.01167   75.93   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.8 on 745 degrees of freedom
## Multiple R-squared:  0.8856, Adjusted R-squared:  0.8854 
## F-statistic:  5765 on 1 and 745 DF,  p-value: < 2.2e-16
testdf(variable = model$residuals, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -6.302020 <1pct 5.799099e-01 0.4463476
## 3     1 -6.088262 <1pct 4.738786e-04 0.9826324
## 4     2 -5.614177 <1pct 3.711516e-02 0.8472308
## 5     3 -4.800030 <1pct 3.290765e-05 0.9954229

Na podstawie wartości statystyki DF równej -6.302020 odrzucamy Ho o niestacjonarności reszt z modelu. Reszty są zatem stacjonarne. Oznacza to, że oba szeregi są skointegrowane, a wektor oszacowań z modelu (1,46.29474,- 0.88578 ) jest wektorem kointegrującym. W oparciu o te szeregi można budować strategię Pair Trading.

std<-sd(model$residuals)
std 
## [1] 4.796356

Odchylenie standardowe reszt, czyli wartości nierównowagi krótkookresowej, wyniosło 4.796356. Zatem uwzglęniając założenia przyjętej strategii, pozycja będzie otwierana w momencie przekroczenia dwukrotności tej wartości. Pozycja będzie zamykana, w momencie powrotu do równowagi długookresowej, czyli gdy reszty będą przekraczały 0.

Poniżej został przedstawiony wykres reszt z naniesionymi punktami otwarcia (zielone kwadraciki) i zamknięcia pozycji (czerwone kwadraciki).Zgodnie z założeniami przyjętymi w analizie, sygnały do otwarcia/zamknięcia pozycji są wyznaczane na podstawie cen zamknięcia, natomiast otwieramy/zamykamy pozycje już po cenach otwarcia z dnia następnego

plot(BHW_PEO$Date, BHW_PEO$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=BHW_PEO$Date, y=BHW_PEO$open_pos_spread, col="green",pch=15)
points(x=BHW_PEO$Date, y=BHW_PEO$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (in-sample)", cex.main=0.85)

Na podstawie tych punktów otwarcia zamknięcia została skonstruowana strategia Pair Trading w okresie In Sample. Poniżej przedstawione są wykresy Equity Line dla strategii Pair Trading oraz prostej strategii Buy & Hold z Wig20

plot(BHW_PEO$Date, BHW_PEO$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(BHW_PEO$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Na podstawie wykresu Equity Line widać, że wyraźnie wyższe stopy zwrotu z inwestycji uzyskamy korzystająć z analizowanej strategii Pair Trading. Pora zatem wyznaczyć prognozy Out of Sample na podstawie oszacowań z modelu in Sample oraz przedstawić strategie na tej próbce badawczej. Wartość odchylenia standardowego również pozostaje niezmieniona, wzięta z modelu dla próbie In Sample.

Poniżej został przedstawiony wykres przedstawiający momenty otwarcia i zamknięcia pozycj

plot(BHW_PEO_fore$Date, BHW_PEO_fore$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=BHW_PEO_fore$Date, y=BHW_PEO_fore$open_pos_spread, col="green",pch=15)
points(x=BHW_PEO_fore$Date, y=BHW_PEO_fore$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (out-of-sample))", cex.main=0.85)

Wyznaczamy stopy zwrotu i wartości portfela w poszczególnych dniach. Poniżej przedstawiony został wykres Euity Line

plot(BHW_PEO_fore$Date, BHW_PEO_fore$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(BHW_PEO_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading BHW & PEO vs Buy&Hold Wig20  (out-ofsample)", cex.main=.85)

Poniżej zostały przedstawione miary podstawowych statystyk

annualized_return
## [1] 0.1967122
annualized_std
## [1] 0.147862
sharpe_ratio
## [1] 1.320863
beta
## [1] -0.02804571
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.1207845
annualized_return_fore
## [1] 0.07519181
annualized_std_fore
## [1] 0.2146058
sharpe_ratio_fore
## [1] 0.3202227
beta_fore
## [1] -0.1162857
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.1987661

Stopa zwrotu dla spółek z sektora bankowego na poziomie 20% w okresie In Sample i dosyć wysokim w okresie Out of Sample 7,5%. Portfel znacznie bardziej zyskowny niż stopa wolna od ryzyka. Współczynnik beta wskazuje z kolei na niską korelację między portfel opartym na strategii Pair Trading a Wig 20.

Podobne analizy zostały przeprowadzone dla pozostałych czterech par spółek. Wszystkie pary są skointegrowane. Skoncentrujemy się zatem tylko na końcowych wynikach strategii

II. Analiza cen akcji Netia i Orange

Wykresy

plot(NET_OPL$Date, NET_OPL$Close_NET, col = "blue", type = "l", ylim = c(2, 20)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali)
lines(NET_OPL$Date, NET_OPL$Close_OPL, col="red")
title(main = 'Indeksy zamkniecia NET i OPL (i-sample)')
legend("topleft", c("NET", "OPL"), col = c("blue", "red"), lty = 1)

testdf(variable = NET_OPL$Close_NET,  adf_order = 3)

##   order       adf  p_adf     bgodfrey      p_bg
## 2     0 -2.192875 >10pct 1.828576e+00 0.1762959
## 3     1 -2.294234 >10pct 5.644089e-05 0.9940058
## 4     2 -2.218590 >10pct 5.697716e-04 0.9809564
## 5     3 -2.125076 >10pct 4.395755e-03 0.9471386
testdf(variable = NET_OPL$dClose_NET, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -26.11246 <1pct 0.0001044929 0.9918440
## 3     1 -19.55180 <1pct 0.0001101666 0.9916255
## 4     2 -16.50781 <1pct 0.0069838589 0.9333987
## 5     3 -15.05215 <1pct 0.0004952950 0.9822444
testdf(variable = NET_OPL$Close_OPL,  adf_order = 3)

##   order        adf  p_adf     bgodfrey      p_bg
## 2     0 -1.0421035 >10pct 1.094670e-01 0.7407518
## 3     1 -0.9269240 >10pct 2.602808e-02 0.8718318
## 4     2 -1.0068602 >10pct 1.854438e-04 0.9891349
## 5     3 -0.9929921 >10pct 8.511422e-05 0.9926390
testdf(variable = NET_OPL$dClose_OPL, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -28.07449 <1pct 2.583025e-02 0.8723156
## 3     1 -18.36574 <1pct 2.638045e-04 0.9870413
## 4     2 -15.44769 <1pct 6.046445e-05 0.9937958
## 5     3 -13.62109 <1pct 3.539203e-04 0.9849905
model <- lm(NET_OPL$Close_NET ~ NET_OPL$Close_OPL)
summary(model)
## 
## Call:
## lm(formula = NET_OPL$Close_NET ~ NET_OPL$Close_OPL)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.89705 -0.18943  0.01208  0.24777  0.73076 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       2.905085   0.047613   61.02   <2e-16 ***
## NET_OPL$Close_OPL 0.136109   0.004218   32.27   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3154 on 745 degrees of freedom
## Multiple R-squared:  0.583,  Adjusted R-squared:  0.5824 
## F-statistic:  1041 on 1 and 745 DF,  p-value: < 2.2e-16
testdf(variable = model$residuals, adf_order = 3)

##   order       adf p_adf    bgodfrey      p_bg
## 2     0 -3.310565 <5pct 0.022764646 0.8800707
## 3     1 -3.278375 <5pct 0.003045098 0.9559931
## 4     2 -3.155003 <5pct 0.001713815 0.9669784
## 5     3 -3.008791 <5pct 0.003035092 0.9560654
std<-sd(model$residuals)
plot(NET_OPL$Date, model$residuals, col = "blue", type = "l", )#ylim zakres skali
abline(h=std,lty = 2, col = "gray")
abline(h =-std,lty = 2, col = "gray")
title(main = 'Indeksy NET i OPL')
legend("topleft", c("NET", "OPL"), col = c("blue", "red"), lty = 1)

plot(NET_OPL$Date, NET_OPL$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=NET_OPL$Date, y=NET_OPL$open_pos_spread, col="green",pch=15)
points(x=NET_OPL$Date, y=NET_OPL$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (in-sample)", cex.main=0.85)

plot(NET_OPL$Date, NET_OPL$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(NET_OPL$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Wykresy zamknięcia dla okresu Out of Sample

plot(NET_OPL_fore$Date, NET_OPL_fore$Close_NET, col = "blue", type = "l", ylim = c(2, 15)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali
lines(NET_OPL_fore$Date, NET_OPL_fore$Close_OPL, col="red")
title(main = 'Indeksy zamknięcia NET i OPL (out-of-sample')
legend("topleft", c("NET", "OPL"), col = c("blue", "red"), lty = 1)

plot(NET_OPL_fore$Date, NET_OPL_fore$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=NET_OPL_fore$Date, y=NET_OPL_fore$open_pos_spread, col="green",pch=15)
points(x=NET_OPL_fore$Date, y=NET_OPL_fore$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (out-of-sample))", cex.main=0.85)

Wykresy Equity Line dla Out of Sample

plot(NET_OPL_fore$Date, NET_OPL_fore$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(NET_OPL_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading NET & OPL vs Buy&Hold Wig20  (out-ofsample)", cex.main=.85)

annualized_return
## [1] 0.2001393
annualized_std
## [1] 0.2883333
sharpe_ratio
## [1] 0.7406402
beta
## [1] 0.08411452
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.1971665
annualized_return_fore
## [1] -0.2161272
annualized_std_fore
## [1] 0.2861637
sharpe_ratio_fore
## [1] -0.798884
beta_fore
## [1] 0.3174322
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.4022601

Portfel w okresie In Sample odznaczył się średnią stopą zwrotu (około 20%) Z kolei w okresie Out of Sample stopa zwrotu była ujemna. Bardzo wysoki stopień obsunięcia (zwłaszcza w okresie out of sample) pokazuje że strategia oparta na spółkach telekomunikacji była dosyć ryzykowna. Powiązania (współczynnik Beta) między Wig 20 a strategią na niskim poziomie dla In Sample, około 8 procent i średnim dla Out of Sample , około 30%

III. Analiza cen akcji PZU i Cyfrowy Polsat

Wykresy

plot(PZU_CPS$Date, PZU_CPS$Close_PZU, col = "blue", type = "l", ylim = c(0,500)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali)
lines(PZU_CPS$Date, PZU_CPS$Close_CPS, col="red")
title(main = 'Indeksy zamkniecia PZU i CPS (i-sample)')
legend("topleft", c("PZU", "CPS"), col = c("blue", "red"), lty = 1)

testdf(variable = PZU_CPS$Close_PZU,  adf_order = 3)

##   order         adf  p_adf     bgodfrey      p_bg
## 2     0 -0.26146998 >10pct 1.047061e-02 0.9184979
## 3     1 -0.31063781 >10pct 1.628519e-05 0.9967802
## 4     2 -0.13747630 >10pct 2.365911e-02 0.8777555
## 5     3 -0.01665418 >10pct 1.750075e-02 0.8947546
testdf(variable = PZU_CPS$dClose_PZU, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -27.20516 <1pct 0.0000298277 0.9956424
## 3     1 -21.05166 <1pct 0.0241198481 0.8765804
## 4     2 -17.70466 <1pct 0.0175349686 0.8946524
## 5     3 -15.98764 <1pct 0.0081681539 0.9279870
testdf(variable = PZU_CPS$Close_CPS,  adf_order = 3)

##   order       adf  p_adf     bgodfrey      p_bg
## 2     0 -1.466213 >10pct 4.528558e-02 0.8314798
## 3     1 -1.471556 >10pct 4.958791e-05 0.9943814
## 4     2 -1.284658 >10pct 4.398418e-04 0.9832677
## 5     3 -1.257708 >10pct 3.942976e-09 0.9999499
testdf(variable = PZU_CPS$dClose_CPS, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -27.17286 <1pct 0.0002868911 0.9864862
## 3     1 -21.18890 <1pct 0.0009208816 0.9757911
## 4     2 -16.94907 <1pct 0.0000680199 0.9934196
## 5     3 -15.67776 <1pct 0.0028651082 0.9573123
model <- lm(PZU_CPS$Close_PZU ~ PZU_CPS$Close_CPS)
summary(model)
## 
## Call:
## lm(formula = PZU_CPS$Close_PZU ~ PZU_CPS$Close_CPS)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -62.900 -24.943  -5.104  21.649  75.103 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         3.2597     6.8761   0.474    0.636    
## PZU_CPS$Close_CPS  18.6362     0.4225  44.106   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 29.98 on 745 degrees of freedom
## Multiple R-squared:  0.7231, Adjusted R-squared:  0.7227 
## F-statistic:  1945 on 1 and 745 DF,  p-value: < 2.2e-16
testdf(variable = model$residuals, adf_order = 3)

##   order       adf  p_adf     bgodfrey      p_bg
## 2     0 -3.036280  <5pct 2.1633860032 0.1413329
## 3     1 -2.856152 <10pct 0.0036535449 0.9518016
## 4     2 -2.692108 <10pct 0.0002650837 0.9870099
## 5     3 -2.648984 <10pct 0.0015979466 0.9681136
std<-sd(model$residuals)
plot(PZU_CPS$Date, model$residuals, col = "blue", type = "l", )#ylim zakres skali
abline(h=std,lty = 2, col = "gray")
abline(h =-std,lty = 2, col = "gray")
title(main = 'Indeksy PZU i CPS')
legend("topleft", c("PZU", "CPS"), col = c("blue", "red"), lty = 1)

plot(PZU_CPS$Date, PZU_CPS$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=PZU_CPS$Date, y=PZU_CPS$open_pos_spread, col="green",pch=15)
points(x=PZU_CPS$Date, y=PZU_CPS$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (in-sample)", cex.main=0.85)

plot(PZU_CPS$Date, PZU_CPS$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(PZU_CPS$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Wykresy zamknięcia dla okresu Out of Sample

plot(PZU_CPS_fore$Date, PZU_CPS_fore$Close_PZU, col = "blue", type = "l", ylim = c(0,500)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali
lines(PZU_CPS_fore$Date, PZU_CPS_fore$Close_CPS, col="red")
title(main = 'Indeksy zamknięcia PZU i CPS (out-of-sample')
legend("topleft", c("PZU", "CPS"), col = c("blue", "red"), lty = 1)

plot(PZU_CPS_fore$Date, PZU_CPS_fore$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=PZU_CPS_fore$Date, y=PZU_CPS_fore$open_pos_spread, col="green",pch=15)
points(x=PZU_CPS_fore$Date, y=PZU_CPS_fore$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (out-of-sample))", cex.main=0.85)

Wykresy Equity Line dla Out of Sample

plot(PZU_CPS_fore$Date, PZU_CPS_fore$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(PZU_CPS_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading PZU & CPS vs Buy&Hold Wig20  (out-ofsample)", cex.main=.85)

annualized_return
## [1] 0.07751675
annualized_std
## [1] 0.11871
sharpe_ratio
## [1] 0.6070396
beta
## [1] 0.00816938
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.1291577
annualized_return_fore
## [1] 0.1822238
annualized_std_fore
## [1] 0.1509628
sharpe_ratio_fore
## [1] 1.151097
beta_fore
## [1] -0.03147384
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.08832696

CO ciekawe w przypadku strategii Pair Trading na Cyfrowym Polsacie i PZU wyższa zaanualizowana stopa zwrotu pojawiła się dla okresu Out of Sample. Ponadto współczynnik Sharpea na wysokim poziomie w obydwu przypadkach pkazuje że strategia była bardziej opłacalna niż prosta Buy & Hold na Wig-u. Niskie współczynniki obsunięcia pokazują że portfel był raczej bezpieczny

IV. Analiza cen akcji Kino Polska TV SA (KPL) AC SA (ACG)

Wykresy

plot(KPL_ACG$Date, KPL_ACG$Close_KPL, col = "blue", type = "l", ylim = c(5,100)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali)
lines(KPL_ACG$Date, KPL_ACG$Close_ACG, col="red")
title(main = 'Indeksy zamkniecia KPL i ACG (i-sample)')
legend("topleft", c("KPL", "ACG"), col = c("blue", "red"), lty = 1)

testdf(variable = KPL_ACG$Close_KPL,  adf_order = 3)

##   order       adf  p_adf    bgodfrey      p_bg
## 2     0 0.2664051 >10pct 0.304640354 0.5809879
## 3     1 0.2602211 >10pct 0.002459852 0.9604436
## 4     2 0.2842359 >10pct 0.004629093 0.9457558
## 5     3 0.4920398 >10pct 0.162601336 0.6867727
testdf(variable = KPL_ACG$dClose_KPL, adf_order = 3)

##   order       adf p_adf    bgodfrey      p_bg
## 2     0 -22.03695 <1pct 0.002436359 0.9606328
## 3     1 -15.52027 <1pct 0.005055155 0.9433185
## 4     2 -14.86994 <1pct 0.163006638 0.6864033
## 5     3 -10.97646 <1pct 0.005704585 0.9397941
testdf(variable = KPL_ACG$Close_ACG,  adf_order = 3)

##   order      adf  p_adf   bgodfrey       p_bg
## 2     0 1.008576 >10pct 5.15872171 0.02312991
## 3     1 1.249244 >10pct 0.03214232 0.85771566
## 4     2 1.437751 >10pct 0.03687691 0.84771587
## 5     3 1.675112 >10pct 0.03217131 0.85765218
testdf(variable = KPL_ACG$dClose_ACG, adf_order = 3)

##   order       adf p_adf   bgodfrey      p_bg
## 2     0 -24.86192 <1pct 0.02411195 0.8766004
## 3     1 -17.94058 <1pct 0.02707934 0.8692919
## 4     2 -15.45830 <1pct 0.02203243 0.8820009
## 5     3 -13.53607 <1pct 0.02362619 0.8778399
model <- lm(KPL_ACG$Close_KPL ~ KPL_ACG$Close_ACG)
summary(model)
## 
## Call:
## lm(formula = KPL_ACG$Close_KPL ~ KPL_ACG$Close_ACG)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.6429 -0.7439 -0.1169  0.5539  6.5991 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -11.06297    0.25711  -43.03   <2e-16 ***
## KPL_ACG$Close_ACG   0.99962    0.01075   92.96   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.719 on 513 degrees of freedom
## Multiple R-squared:  0.944,  Adjusted R-squared:  0.9439 
## F-statistic:  8642 on 1 and 513 DF,  p-value: < 2.2e-16
testdf(variable = model$residuals, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -3.491628 <1pct 2.223618e+00 0.1359143
## 3     1 -3.160975 <5pct 3.525501e-03 0.9526527
## 4     2 -3.075632 <5pct 1.224583e-04 0.9911707
## 5     3 -3.070106 <5pct 3.216014e-06 0.9985691
std<-sd(model$residuals)
plot(KPL_ACG$Date, model$residuals, col = "blue", type = "l", )#ylim zakres skali
abline(h=std,lty = 2, col = "gray")
abline(h =-std,lty = 2, col = "gray")
title(main = 'Indeksy KPL i ACG')
legend("topleft", c("KPL", "ACG"), col = c("blue", "red"), lty = 1)

plot(KPL_ACG$Date, KPL_ACG$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=KPL_ACG$Date, y=KPL_ACG$open_pos_spread, col="green",pch=15)
points(x=KPL_ACG$Date, y=KPL_ACG$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (in-sample)", cex.main=0.85)

plot(KPL_ACG$Date, KPL_ACG$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(KPL_ACG$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Wykresy zamknięcia dla okresu Out of Sample

plot(KPL_ACG_fore$Date, KPL_ACG_fore$Close_KPL, col = "blue", type = "l", ylim = c(5,100)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali
lines(KPL_ACG_fore$Date, KPL_ACG_fore$Close_ACG, col="red")
title(main = 'Indeksy zamknięcia KPL i ACG (out-of-sample')
legend("topleft", c("KPL", "ACG"), col = c("blue", "red"), lty = 1)

plot(KPL_ACG_fore$Date, KPL_ACG_fore$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=KPL_ACG_fore$Date, y=KPL_ACG_fore$open_pos_spread, col="green",pch=15)
points(x=KPL_ACG_fore$Date, y=KPL_ACG_fore$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (out-of-sample))", cex.main=0.85)

Wykresy Equity Line dla Out of Sample

plot(KPL_ACG_fore$Date, KPL_ACG_fore$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(KPL_ACG_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading KPL & ACG vs Buy&Hold Wig20  (out-ofsample)", cex.main=.85)

annualized_return
## [1] 0.24604
annualized_std
## [1] 0.2581801
sharpe_ratio
## [1] 0.8339373
beta
## [1] -0.05281841
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.2695261
annualized_return_fore
## [1] -0.3420987
annualized_std_fore
## [1] 0.6286419
sharpe_ratio_fore
## [1] -0.776394
beta_fore
## [1] 0.1588326
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.6536755

Strategia dla czwartej pary społek cechowała wysoka stopa zwrotu dla IN Sample i także wysoka ale ujemna dla Out of Sample. Współczynnik powiązania BEta z indeksem WIg 20 pokazuje ujemną korelacje dla In Sample i dodatnio dla Out of Sample Drawdown pokazuje bardzo silne (zwłaszcza w przypadku okresu Out of Sample - 60%) ryzyko utraty wartości w krótkim odstępie czasu

V. Makarony Polskie SA (MAK) Wilbo SA (WLB)

Wykresy

plot(MAK_WLB$Date, MAK_WLB$Close_MAK, col = "blue", type = "l", ylim = c(0,15)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali)
lines(MAK_WLB$Date, MAK_WLB$Close_WLB, col="red")
title(main = 'Indeksy zamkniecia MAK i WLB (i-sample)')
legend("topleft", c("MAK", "WLB"), col = c("blue", "red"), lty = 1)

testdf(variable = MAK_WLB$Close_MAK,  adf_order = 3)

##   order       adf  p_adf    bgodfrey       p_bg
## 2     0 -2.632753 <10pct 3.664044086 0.05559853
## 3     1 -2.599853 <10pct 0.001372316 0.97044930
## 4     2 -2.554686 >10pct 0.000112726 0.99152882
## 5     3 -2.560032 >10pct 0.001706388 0.96704999
testdf(variable = MAK_WLB$dClose_MAK, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -28.52330 <1pct 9.504695e-04 0.9754054
## 3     1 -18.98390 <1pct 5.716772e-05 0.9939673
## 4     2 -15.65675 <1pct 1.943793e-03 0.9648339
## 5     3 -14.87054 <1pct 4.382167e-02 0.8341857
testdf(variable = MAK_WLB$Close_WLB,  adf_order = 3)

##   order       adf  p_adf     bgodfrey      p_bg
## 2     0 -2.345262 >10pct 0.7973441346 0.3718886
## 3     1 -2.404558 >10pct 0.0001010849 0.9919781
## 4     2 -2.319202 >10pct 0.0023314376 0.9614891
## 5     3 -2.383860 >10pct 0.0025073140 0.9600641
testdf(variable = MAK_WLB$dClose_WLB, adf_order = 3)

##   order       adf p_adf     bgodfrey      p_bg
## 2     0 -27.37992 <1pct 6.843820e-05 0.9933994
## 3     1 -19.19083 <1pct 2.212977e-03 0.9624795
## 4     2 -15.10379 <1pct 2.785524e-03 0.9579087
## 5     3 -13.53579 <1pct 2.778971e-05 0.9957939
model <- lm(MAK_WLB$Close_MAK ~ MAK_WLB$Close_WLB)
summary(model)
## 
## Call:
## lm(formula = MAK_WLB$Close_MAK ~ MAK_WLB$Close_WLB)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.47513 -0.42000 -0.09524  0.40490  1.72141 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        1.79638    0.04022   44.66   <2e-16 ***
## MAK_WLB$Close_WLB  2.77692    0.04231   65.64   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.5927 on 708 degrees of freedom
## Multiple R-squared:  0.8589, Adjusted R-squared:  0.8587 
## F-statistic:  4308 on 1 and 708 DF,  p-value: < 2.2e-16
testdf(variable = model$residuals, adf_order = 3)

##   order       adf p_adf     bgodfrey       p_bg
## 2     0 -3.700874 <1pct 6.9653237120 0.00831044
## 3     1 -3.286287 <5pct 0.0076572519 0.93026954
## 4     2 -3.363875 <5pct 0.0001456620 0.99037052
## 5     3 -3.287457 <5pct 0.0003186986 0.98575682
std<-sd(model$residuals)
plot(MAK_WLB$Date, model$residuals, col = "blue", type = "l", )#ylim zakres skali
abline(h=std,lty = 2, col = "gray")
abline(h =-std,lty = 2, col = "gray")
title(main = 'Indeksy MAK i WLB')
legend("topleft", c("MAK", "WLB"), col = c("blue", "red"), lty = 1)

plot(MAK_WLB$Date, MAK_WLB$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=MAK_WLB$Date, y=MAK_WLB$open_pos_spread, col="green",pch=15)
points(x=MAK_WLB$Date, y=MAK_WLB$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (in-sample)", cex.main=0.85)

plot(MAK_WLB$Date, MAK_WLB$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(MAK_WLB$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Wykresy zamknięcia dla okresu Out of Sample

plot(MAK_WLB_fore$Date, MAK_WLB_fore$Close_MAK, col = "blue", type = "l", ylim = c(0,15)
     ,ylab = "Indeks", xlab ="Data",)#ylim zakres skali
lines(MAK_WLB_fore$Date, MAK_WLB_fore$Close_WLB, col="red")
title(main = 'Indeksy zamknięcia MAK i WLB (out-of-sample')
legend("topleft", c("MAK", "WLB"), col = c("blue", "red"), lty = 1)

plot(MAK_WLB_fore$Date, MAK_WLB_fore$resid, type="l", ylab = "Short Run Non Equilibrum", xlab =
       "Data",col="blue")
abline(h=c(2*std,-2*std), col="red")
abline(h=0, col = "black")
points(x=MAK_WLB_fore$Date, y=MAK_WLB_fore$open_pos_spread, col="green",pch=15)
points(x=MAK_WLB_fore$Date, y=MAK_WLB_fore$close_pos, col="red", pch=15)
title("Sygnały otwarcia/zamknięcia (out-of-sample))", cex.main=0.85)

Wykresy Equity Line dla Out of Sample

plot(MAK_WLB_fore$Date, MAK_WLB_fore$portfolio, type="l", ylim=c(0.75, 1.8), ylab = "ROI", xlab = "Data", col="blue")
lines(MAK_WLB_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading MAK & WLB vs Buy&Hold Wig20  (out-ofsample)", cex.main=.85)

Statystyki dla In Sample i Out Of Sample

annualized_return
## [1] 0.5072387
annualized_std
## [1] 0.6224207
sharpe_ratio
## [1] 0.756963
beta
## [1] -0.1609487
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.8952224
annualized_return_fore
## [1] -0.006576618
annualized_std_fore
## [1] 0.5308993
sharpe_ratio_fore
## [1] -0.01285024
beta_fore
## [1] 0.04961285
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.2664756

Podsumowując wyniki dla ostatniej grupy spółek, należy stwierdzić, że wystąpiły spore rozbieżności pomiędzy oboma okresami. Stopa zwrotu bardzo wysoka dla In Sample, w okresie Out of Sample była ujemna. Ponadto porfele oparte o strategie Pair Trading cechował wysoki poziom dyspersji (okolo 50%) Współczynnik Sharpe’a podobnie jak stopa zwrotu, dodatnia dla Im Sample i bardzo wysoka, a dla Out of Sample ujemna.

Vi Analiza skonkatenowanych trzech par spółek

Do tej analizy wykorzystane zostały spółki notowane na giełdzie w pełnym okresie, a zatem pary pochodzące z trzech pierwszych punktów

Wykres Equity In Sample

plot(WIG20$Date, concatanate_stategy$portfolio, type="l", ylim=c(0.75, 1.8),
     ylab = "ROI", xlab = "Data", col="blue")
lines(WIG20$Date, WIG20$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (in-sample)", cex.main=.85)

Policzone zostały również zwroty dla okresu Out of Sample

Wykres Equity Line

plot(WIG20_fore$Date, concatanate_stategy_fore$portfolio, type="l", ylim=c(0.75, 1.8),
     ylab = "ROI", xlab = "Data", col="blue")
lines(WIG20_fore$Date, WIG20_fore$portfolio, type="l", col="red")
legend(bty="n", ncol=3, "topleft", "groups", c("Pair Trading","Buy&Hold"), lty=
         1, col=c("blue", "red"))
title("Equity Line : Pair Trading vs Buy&Hold Wig20  (out of sample)", cex.main=.85)

Wartości statystyk in sample

annualized_return
## [1] 0.1710953
annualized_std
## [1] 0.1176567
sharpe_ratio
## [1] 1.376598
beta
## [1] 0.02141273
maximum_drawdown[1]
## $maxdrawdown
## [1] 0.07468959

Wartości statystyk out of sample

annualized_return_fore
## [1] 0.01607088
annualized_std_fore
## [1] 0.1272185
sharpe_ratio_fore
## [1] 0.1641759
beta_fore
## [1] 0.05655758
maximum_drawdown_fore[1]
## $maxdrawdown
## [1] 0.1157962

Dla portfela mieszanego, zarówno w przypadku In Sample jak i Out of Sample stopa zwrotu była dodatnia. Dla okresu In Sample około 17 % zaś Out of Sample 1,5%. Odchylenie standardowe wyniosło w obu przypadkach okolo 11-12% Współczynnik Sharpea większy od zera w obu przypadkach pokazuje że portfel był bardziej zyskowny niż stopa wolna od ryzyka. Współczynnik beta wskazuje na słabą korelację dodatnią, względem strategii opartej o indeks Wig 20. Współczynnik obsunięcia w obu przypadkach na poziomie około 10%.

Zakończenie

Wydaje się że strategia oparta na kilku parach skointegrowanych szeregów z punktu widzenia powyższego badania jest najrozsądniejsza. Zdecydowanie mniej ryzykowna jest gra na bardziej renomowanych spółkach niż tych mniej znanych, gdzie ryzyko utraty wartości portfela okazało się znacznie większe Podsumowując, należy stwierdzić, że strategia inwestycyjna oparta na bazie kointegracji jest bardzo interesująca z perspektywy badawczej. Jednakże, biorąc pod uwagę w zasadzie niezliczoną liczbę czynników wpływającą na działanie giełdy, wątpliwym jest by mogłabybyć stosowana skutecznie w praktyce.