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
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
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%
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
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
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.
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%.
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.