RSI(5) ucuz hisseler stratejisi ve kümülatif momentum filtresi
Dün ele aldığımız stratejide RSI(5) göstergesine göre en ucuz hisseleri alıp portföy getirisini incelemiştik.
Bugün stratejiyi kümülatif momentum göstergesi ile birleştirip filtrelediğimizde elde edeceğimiz sonuçların orijinal strateji ile karşılaştırmalı olarak analizini yapacağım.
Kodlamayı yine Matlab ortamında gerçekleştirdim.
Matlab için iyi bir kaynak:
Python başlangıç için iyi bir kaynak:
Matlab neden elverişli?
Kod vektörize çalışır, başka programlarda satırlar boyu yapılan analiz sadece tek bir komutla gerçekleştirilebilir.
Hazır fonksiyonları vardır.
Süper bir web sitesi ve kod paylaşan on binlerce geliştirici mevcuttur.
Python neden elverişli?
Kütüphaneleri son zamanlarda çok gelişti.
Mükemmel bir paylaşım ortamı mevcut. Pek çok insan kodları paylaşıp daha iyileştirmeye çalışıyor.
Ücretsiz.
Çok hızlı.
Yazılım öğrenmek için iyi bir web sitesi:
Filtre kullanılmış RSI (5) testimize geçebiliriz.
Kümülatif momentum stratejisi
Al
½ daha al
Kısa yap
Şeklinde 3 sinyal üretiyordu. Aldığımız ve sattığımız pozisyonların göstergeye göre ortalamaya yakınlaştığı yerlerde de pozisyondan çıkıyorduk.
Kümülatif momentum yazıları köşede bulunabilir.
Bugünkü testler için 2 yeni bir fonksiyon yazmak gerekti, en sona aldım.
Kümülatif momentum trade fonksiyon girdilerini alıp kümülatif momentum göstergesini, pozisyonları, uzun pozisyonları ve kısa pozisyonları döndürecek.
Gelen pozisyonlara göre RSI (5) stratejisi:
Orijinal halinde
Sadece Long sinyali geldiğinde
Sadece Long Sinyali geldiğinde 2X kaldıraçlı
Short sinyali olmadığında
Çalıştırılacak.
Veri seti dün kullandığımız olacak. Test sonuçlarına bakalım:
Orijinal Strateji Yıllık ortalama getiri 0.3161 Sharpe rasyosu: 1.1135
Karlı gün oranı 0.55
Zararlı gün oranı 0.44
Kar faktörü: 0.80
En büyük düşüş -0.6026 oldu. Bu kayıp: 571 gün sonra geri alındı
Long only Yıllık ortalama getiri 0.1912 Sharpe rasyosu: 1.3352
En büyük düşüş -0.1856 oldu. Bu kayıp: 182 gün sonra geri alındı
2x Kaldıraçlı Long only Yıllık ortalama getiri 0.3112 Sharpe rasyosu: 1.1215
En büyük düşüş -0.3765 oldu. Bu kayıp: 216 gün sonra geri alındı
Short Sinyali Yok İken Yıllık ortalama getiri 0.2903 Sharpe rasyosu: 1.1420
En büyük düşüş -0.5505 oldu. Bu kayıp: 428 gün sonra geri alındı
Elapsed time is 12.651095 seconds.
Grafiklere de bakalım:
2016-17 yılı için grafikler:
Sonuç:
Strateji Long only / Short sinyali olmadığında pozisyonsuz günlere %8/365 günlük faiz ekledim. 2X kaldıraçlıda ise %12/365 günlük faiz düştüm.
Orijinal strateji tüm filtrelenmiş stratejilerden getiri olarak daha iyi
Sadece long sinyali olduğunda işlem yaparsak Sharpe rasyosu yükseliyor.
2X long yaptığımızda orijinal strateji ile aynı Sharpe rasyosunu elde ediyoruz. Getiri çok yaklaşıyor, portföy düşüşleri ise ciddi gerilemiş durumda.
Sadece short sinyali olmadığında işlem yapmak getirileri azaltıyor, Sharpe rasyosunda da anlamlı bir gelişim yok.
Kümülatif momentum filtresi ile işlem yapacaksak 2X long only riski sevenler için, esnek fon gibi çalışmak istenirse de sadece long sinyalinde işlem yapılabilir.
Strateji hareketli ortalama, volatilite vs. gibi filtrelere de tabi tutulabilir.
Kod değiştirilmiş haliyle aşağıda.
Kümülatif momentum için:
function out=kumulatifMomentum(closePx,regDays,stockNames)
regVec=(1:regDays)';
hisseSay=size(stockNames,2);
betaMat=zeros(size(closePx));
logPx=log(closePx);
for i=(regDays+1):size(closePx,1);
for j=1:hisseSay
betaMat(i,j)=exp(regcoeff2(regVec,logPx(i-regDays:i-1, j)))-1;
end
out=smartmean(betaMat,2);
end
Kümülatif momentum işlemi için:
function [slope,numUnits,longUnits,shortUnits]=kumulMomentumTrade(closePx,regDays,stockNames,
longLevel,shortLevel,tradeClose,secondPos,longSecondClose,buffer,shortSecond,shortSecondClose)
%sistem 75 günlük regresyon ortalamasına göre işlem
%yapar. Long 1 + Long2 - Short 1 olarak çalışır
%short 2 denedim ama getirileri pozitif olarak etkilemedi.
%prensip ucuzken 1 tane al, pahalılandığında 1 tane daha al
%pahalı hale gelince sat, bir tane short yap
slope=kumulatifMomentum(closePx,regDays,stockNames);
%slope=slopemedyan;
longlevel=-longLevel/100;
shortlevel=shortLevel/100;
tradeclose=tradeClose/100;
%ikinci pozisyonlar için kriterler
secondpos=secondPos/100;
longSecondClose=longSecondClose/100;
buffer=buffer/100;
shortSecond=-shortSecond/100;
shortSecondClose=-shortSecondClose/100;
longsEntry = (slope
%bir yerden yukarı keserse bir daha alalım alalım, belirli bir yerde kapatalım
longSecond=lag(slope)<secondpos&slope>secondpos;
longSecondExit=slope>longSecondClose|(((lag(slope)>(secondpos-buffer))&(slope<(secondpos-buffer))));
shortsEntry = ( slope>shortlevel);
shortsExit = ( slope<tradeclose) ;
shortSecond=lag(slope)>shortSecond&slope<shortSecond;
shortSecondExit=((lag(slope)<shortSecond)&slope>(shortSecond+buffer))|slope<shortSecondClose;
numUnitsLong=NaN(size(closePx,1),1);
numUnitsShort=NaN(size(closePx,1),1);
numUnitsLong2=NaN(size(closePx,1),1);
numUnitsShort2=NaN(size(closePx,1),1);
numUnitsLong(1)=0;
numUnitsLong(longsEntry)=1; %burada uzun pozisyon girişlerini 1 yapıyor
numUnitsLong(longsExit)=0;%uzun poz çıkışlar sıfır yapılıyor
%numdene=numUnitsLong;
%buydates=find(numdene==1);
%selldates=find(numdene==0);
numUnitsLong=fillMissingData(numUnitsLong);%takipeden günler dolduruluyor.
%short pozisyonlar için de yukarıdaki mantıkta iş yapılıyor.
numUnitsShort(1)=0;
numUnitsShort(shortsEntry)=-1;
numUnitsShort(shortsExit)=0;
numUnitsShort=fillMissingData(numUnitsShort);
%aşağıdaki blok kesişim sonrası alıyor kritere göre satıyor
numUnitsLong2(1)=0;
numUnitsLong2(longSecond)=1; %burada uzun pozisyon girişlerini 1 yapıyor
numUnitsLong2(longSecondExit)=0;%uzun poz çıkışlar sıfır yapılıyor
numUnitsLong2=fillMissingData(numUnitsLong2);%takipeden günler dolduruluyor.
numUnitsShort2(1)=0;
numUnitsShort2(shortSecond)=-1; %burada uzun pozisyon girişlerini 1 yapıyor
numUnitsShort2(shortSecondExit)=0;%uzun poz çıkışlar sıfır yapılıyor
numUnitsShort2=fillMissingData(numUnitsShort2);%takipeden günler dolduruluyor.
%short pozisyonlar için de yukarıdaki mantıkta iş yapılıyor.
numUnits=1.0*numUnitsLong+1.0*numUnitsShort+0.5*numUnitsLong2+numUnitsShort2;
shortUnits=numUnitsShort+numUnitsShort2;
longUnits=numUnitsLong+0.5*numUnitsLong2;
end
Değiştirilmiş Matlab kod:
clc,clear
tic
load('xu100kumulmom', 'Tarih','xu100Hisse', 'xu100cl');
%load('xu030LongShort', 'dates', 'xu100Hisse', 'xu100cl');
%Tarih=dates;
rsiThresholdUp=70;
rsiThresholdDown=30;
noOfStocks=3;
rsiDays=5;
[row,col]=size(xu100cl);
rsiVec=zeros(size(xu100cl));
rsi2Vec=zeros(size(xu100cl));
for i=1:col
rsiVec(:,i)=rsindex(xu100cl(:,i),rsiDays);
end
rsiUp=sum(rsiVec>rsiThresholdUp,2);
rsiDown=sum(rsiVec<rsiThresholdDown,2);
%buradan itibaren ucuz rsi stratejisini yapacak
checkRsi=createind3(rsiVec);
%rsi hesaplandığı gün sayısından bir fazla olmalı
portfolioIndex=checkRsi(rsiDays+1:end-1,1:noOfStocks);
%hisse getirileri
stockReturns=log(xu100cl)-log(lag(xu100cl));
%rsi gününden 2 fazla olmalı. rsi ile bugün aldık, yarın sattık
returnsUsed=stockReturns(rsiDays+2:end,:);
[row2]=size(returnsUsed,1);
portRet=zeros(size(returnsUsed));
%getiriler içerisinden portföye aldığımız hisselerin getirilerini bulacağız
for ii=1:row2
for jj=1:noOfStocks
portRet(ii,jj)=returnsUsed(ii,portfolioIndex(ii,jj));
end
end
%hisse isimlerini bulalım:
secilenHisse=num2cell(zeros(size(portfolioIndex)));
for idx=1:size(portfolioIndex,1)
for idx2=1:noOfStocks
secilenHisse(idx,idx2) = xu100Hisse(portfolioIndex(idx,idx2));
end
end
%kümülatif momentum trade fonksiyonuna aşağıdaki parametreler gönderilecek;
% longlevel=0.15
% shortlevel=0.25
% tradeclose=0.011
% %ikinci pozisyonlar için kriterler
% secondpos=0.11
% longSecondClose=0.20
% buffer=0.015
%
% shortSecond=10
% shortSecondClose=0.25
%[numUnits,longUnits,shortUnits]=kumulMomentumTrade(closePx,regDays,stockNames,longLevel,
shortLevel,tradeClose,secondPos,longSecondClose,buffer,shortSecond,shortSecondClose)
[slope,numUnits,longUnits,shortUnits]=kumulMomentumTrade(xu100cl,75,xu100Hisse,
0.15,0.25,0.011,0.11,0.20,0.015,10,25);
%portföy normal getiri:
portRet2=smartsum(portRet,2)/noOfStocks;
%sadece long sinyal geldiğinde işlem yaparsak port getirisi
portLongSignal=portRet2.*longUnits(rsiDays+2:end);
%2X kaldıraç olduğunda %12 faiz gideri koydum.
portLongSignal2X=(2*portRet2-0.12/365).*longUnits(rsiDays+2:end);
%portföyün pozisyonda olmadığı günleri bulalım:
findNoPosDays=find(longUnits(rsiDays+2:end)==0);
%bulduğumuz günlere faiz eklemek gerekir, yıllık %8 net yaptım.
portLongSignal(findNoPosDays)=0.08/365;
portLongSignal2X(findNoPosDays)=0.08/365;
%short sinyal olmadığı günleri belirleyelim:
tradeWhenNoShortSignal=numUnits>-1;
%short sinyal olmadığında getiriler
portLongSignal2=portRet2.*tradeWhenNoShortSignal(rsiDays+2:end);
%short sinyalinin olduğu günleri bulalım
findNoShortDays=find(shortUnits(rsiDays+2:end)==-1);
%faiz ekleyelim:
portLongSignal2(findNoShortDays)=0.08/365;
pozitifGun=sum(portRet2>0)/size(portRet2,1);
negatifGun=sum(portRet2<0)/size(portRet2,1);
pozitifGunler=portRet2>0;
negatifGunler=portRet2<0;
pozitifGunOrt=sum((pozitifGunler.*portRet2))/sum(portRet2>0);
negatifGunOrt=sum((pozitifGunler.*portRet2))/sum(portRet2<0);
karFaktoru=pozitifGunOrt/abs(negatifGunOrt);
%portföy istatistikleri
[apr,sharpe,maxDD,maxDDD,drawdown]=portMetrics(portRet2);
[apr2,sharpe2,maxDD2,maxDDD2,drawdown2]=portMetrics(portLongSignal);
[apr3,sharpe3,maxDD3,maxDDD3,drawdown3]=portMetrics(portLongSignal2);
[apr4,sharpe4,maxDD4,maxDDD4,drawdown4]=portMetrics(portLongSignal2X);
close all
%portföy grafikleri
figure
subplot(2,2,1)
plot(Tarih(rsiDays+1:end-1,:),cumprod(portRet2+1)-1)
title('Orijinal Strateji Portföy Getirisi')
subplot(2,2,2)
plot(Tarih(rsiDays+1:end-1,:),cumprod(portLongSignal+1)-1)
title('Sadece Long Sinyal Olduğunda İşlem')
subplot(2,2,3)
plot(Tarih(rsiDays+1:end-1,:),cumprod(portLongSignal2X+1)-1)
title('Sadece Long Sinyal Olduğunda 2X Kaldıraçlı İşlem')
subplot(2,2,4)
plot(Tarih(rsiDays+1:end-1,:),cumprod(portLongSignal2+1)-1)
title('Sadece Short Sinyal Olmadığında İşlem')
%2016-2017 yılı getirilerini çekip grafik yapacağız
ret2017=portRet2(end-325:end);
ret2017L=portLongSignal(end-325:end);
ret2017L2=portLongSignal2X(end-325:end);
ret2017S=portLongSignal2(end-325:end);
date2017=Tarih(end-325:end);
figure
%2016-17 getirileri
subplot(2,2,1)
plot(date2017,cumprod(ret2017+1)-1,'r')
title('2016-17 Orijinal Portföy Getirisi')
subplot(2,2,2)
plot(date2017,cumprod(ret2017L+1)-1,'r')
title('2016-17 Sadece Long Sinyalinde Portföy Getirisi')
subplot(2,2,3)
plot(date2017,cumprod(ret2017L2+1)-1,'r')
title('2016-17 2x Long Portföy Getirisi')
subplot(2,2,4)
plot(date2017,cumprod(ret2017S+1)-1,'r')
title('2016-17 Short Sinyal Olmadığında Portföy Getirisi')
% kümülatif rsi için grafikler
figure
subplot(1,2,1)
plot(Tarih(end-100:end),rsiUp(end-100:end))
hold on
plot(Tarih(end-100:end),rsiDown(end-100:end))
%
legend('Pozitif Trend','Negatif Trend')
title('2017 İlk Çeyrek')
%
% %2016 aynı dönem
%
subplot(1,2,2)
plot(Tarih(1422:1510),rsiUp(1422:1510))
hold on
plot(Tarih(1422:1510),rsiDown(1422:1510))
legend('Pozitif Trend','Negatif Trend')
title('2016 İlk Çeyrek')
fprintf('Orijinal Strateji Yıllık ortalama getiri %.4f sharpe rasyosu: %.4f\n',apr,sharpe);
fprintf('Karlı gün oranı %.2f\n',pozitifGun);
fprintf('Zararlı gün oranı %.2f\n',negatifGun);
fprintf('Kar faktörü: %.2f\n',karFaktoru);
fprintf('En büyük düşüş %.4f oldu. Bu kayıp: %d gün sonra geri alındı\n\n',maxDD,maxDDD);
fprintf('Long only Yıllık ortalama getiri %.4f sharpe rasyosu: %.4f\n',apr2,sharpe2);
fprintf('En büyük düşüş %.4f oldu. Bu kayıp: %d gün sonra geri alındı\n\n',maxDD2,maxDDD2);
fprintf('2x Kaldıraçlı Long only Yıllık ortalama getiri %.4f sharpe rasyosu: %.4f\n',apr4,sharpe4);
fprintf('En büyük düşüş %.4f oldu. Bu kayıp: %d gün sonra geri alındı\n\n',maxDD4,maxDDD4);
fprintf('Short Sinyali Yok İken Yıllık ortalama getiri %.4f sharpe rasyosu: %.4f\n',apr3,sharpe3);
fprintf('En büyük düşüş %.4f oldu. Bu kayıp: %d gün sonra geri alındı\n',maxDD3,maxDDD3);
toc
Orijinal Strateji Yıllık ortalama getiri 0.3161 sharpe rasyosu: 1.1135
Karlı gün oranı 0.55
Zararlı gün oranı 0.44
Kar faktörü: 0.80
En büyük düşüş -0.6026 oldu. Bu kayıp: 571 gün sonra geri alındı
Long only Yıllık ortalama getiri 0.1912 sharpe rasyosu: 1.3352
En büyük düşüş -0.1856 oldu. Bu kayıp: 182 gün sonra geri alındı
2x Kaldıraçlı Long only Yıllık ortalama getiri 0.3112 sharpe rasyosu: 1.1215
En büyük düşüş -0.3765 oldu. Bu kayıp: 216 gün sonra geri alındı
Short Sinyali Yok İken Yıllık ortalama getiri 0.2903 sharpe rasyosu: 1.1420
En büyük düşüş -0.5505 oldu. Bu kayıp: 428 gün sonra geri alındı
Elapsed time is 12.671882 seconds.
Sayfada yer alan bilgiler tavsiye niteliği taşımayıp yatırım danışmanlığı kapsamında değildir. Yatırımcı profilinize uymayabilir.
-
Can D.14 Nisan 2017 11:43
Matlab ve Python dışında R dili ve finansal zaman serileri ile çalışmayı verimli hale getiren Quantmod paketini de öneririm. Pythonda bu işler için kullanılan pandas paketi zaten Cliff Asness'in AQR Capital'inde çalışan bir quant tarafından R'daki fonksiyon ve veri yapılarının Python'a aktarılmasından başka bir şey değildir. Python ve Matlab'ın R'a göre hızlı olması şehir efsanesidir. R'ın bazı fonksiyonları R'ın kendisi ve fortranda yazıldığı için performans düşüklüğü vardır ama hemen hemen her fonskisyonun tıpkı python ve matlabdaki gibi C++'da yazılmış birer alternatifi de vardır ve bunlar kullanılırsa, performans ciddi artmaktadır. Ayrıca işlemcinin bütün çekirdeklerini kullanabilen parallel processing libraryleri python ve matlab'dan daha basit olduğu için 4 çekirdekli basit bir makinede bile özellikle taramalarda (loop) 300x kat daha hızla çalışmaktadır.
-
11 Kasım 2024, Pazartesi
Trump’ın zaferi Türkiye’yi nasıl etkileyecek?
Devamını Oku -
06 Kasım 2024, Çarşamba
Trump geliyor, peki piyasalar hazır mı?
Devamını Oku - 28 Ekim 2024, Pazartesi Devamını Oku
-
22 Ekim 2024, Salı
Altın ve gümüşte yükseliş nereye kadar sürecek?
Devamını Oku -
01 Ekim 2024, Salı
Piyasalar sıkıştı, bekle-gör stratejisi hakim
Devamını Oku - 11 Eylül 2024, Çarşamba Devamını Oku
-
12 Ağustos 2024, Pazartesi
Merkez’in faiz sinyali hangi şirketleri etkileyecek?
Devamını Oku -
06 Ağustos 2024, Salı
Finansal dalgalanmanın ortasında neler oluyor?
Devamını Oku -
23 Temmuz 2024, Salı
TCMB’nin faiz kararı ve piyasaların seyri
Devamını Oku -
01 Temmuz 2024, Pazartesi
Gri listeden çıkış ve CDS’lerin seyri
Devamını Oku
- ARACI KURUM RAPORLARI
- 15:28Tekfen Holding yılbaşından bu yana %118 kazandırdı
- 08:24Borsada alıcılı başlangıç bekleniyor
- 15:03Türk Hava Yolları hissesinde kurumların en yüksek beklentisi yüzde 82.3
- 09:03Bugün dikkatler NVDA’nın sonuçlarında! Hayal kırıklığı olacak mı?
- 07:59Borsada yatay başlangıç bekleniyor
- Tümünü Göster