
Fiyat Korelasyonunun İstatistiksel Verilerine Dayalı Sinyalleri Filtreleme
Bu Nasıl Başladı
Bu makaleyi yazmama yol açan fikir, Larry Williams'ın yatırımlarda dünya rekoru sahibi olan (1987'de sermayesini % 11.000 artırdı) "Kısa Vadeli Ticaretin Uzun Vadeli Sırları" kitabını okuduktan sonra ortaya çıktı. fiyatların geçmişteki davranışları ile gelecekteki eğilimler arasında herhangi bir korelasyon bulunmadığına dair "... teoride zengin ve piyasa bilgisi bakımından fakir olan üniversite profesörleri ve diğer akademisyenler..." tarafından mitleri tamamen ortadan kaldırmak.
100 kez yazı tura atarsanız, 50 kez tura ve 50 kez tura gelir. Birbirini takip eden her atışta, tura gelme olasılığı %50'dir ve yazı olasılığı ile aynıdır. Olasılık atıştan atışa değişmez, çünkü bu oyun rastgeledir ve hafızası yoktur. Piyasaların kaotik bir şekilde madeni para gibi davrandığını varsayalım.
Sonuç olarak, yeni bir çubuk göründüğünde, fiyatın yukarı veya aşağı gitme şansı eşittir ve önceki çubuklar mevcut olanı en ufak bir şekilde etkilemez. İdil! Bir ticaret sistemi oluşturun, karı al zararı durdur değerinden daha büyük bir değere ayarlayın (yani, matematik. beklentiyi pozitif bölgeye ayarlayın) ve sihir gerçekleşir. Tek kelimeyle nefes kesici. Ancak sorun şu ki, piyasanın davranışı hakkındaki varsayımımız pek doğru değil. Açıkçası, bu çok saçma! Ve bunu kanıtlayacağım.
MQL5 Sihirbazını kullanarak bir Expert Advisor şablonu oluşturalım ve basit alfanümerik müdahaleler kullanarak onu görevin yerine getirilmesine uygun bir durumda sunalım. Bir, iki ve üç çubuğun kapanmasını takip eden satın almayı simüle etmek için bir Uzman Danışman kodlayacağız. Simülasyon, programın analiz edilen çubukların parametrelerini basitçe hatırlayacağı anlamına gelir. Bu durumda emir göndermek (daha olağan bir yol) işe yaramaz, çünkü spread’ler ve takaslar alınan bilgilerin güvenilirliğini sorgulayabilir.
İşte kod:
//+------------------------------------------------------------------+ //| explorer.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //---Variables--- double profit_percent,open_cur,close_cur; double profit_trades=0,loss_trades=0,day_cur,hour_cur,min_cur,count; double open[],close[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { /* Calculate percent of closures with increase from the total number */ profit_percent=NormalizeDouble(profit_trades*100/(profit_trades+loss_trades),2); Print("Percent of closures with increase ",profit_percent,"%"); // Enter data to the Journal } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //---find out the time--- MqlDateTime time; // Create a structure to store time TimeToStruct(TimeCurrent(),time); // Structuring the data day_cur=time.day_of_week; // Receive the value of the current day hour_cur=time.hour; // Receive the current hour min_cur=time.min; // Receive the current minute //---Find out the prices--- CopyOpen(NULL,0,0,4,open);ArraySetAsSeries(open,true); CopyClose(NULL,0,0,4,close);ArraySetAsSeries(close,true); if(close[1]<open[1]/*&&close[2]<open[2]&&close[3]<open[3]*/ && count==0) // If it closed with a loss { open_cur=open[0]; // Remember open price of the current bar count=1; } if(open_cur!=open[0] && count==1) // The current bar has closed { close_cur=close[1]; // Remember the close price of the formed bar count=0; if(close_cur>=open_cur)profit_trades+=1; // If the close price is higher than open, else loss_trades+=1; // +1 to closures with profit, otherwise +1 to closures with loss } } //+------------------------------------------------------------------+
Test, 1 Ocak 2000 ile 31 Aralık 2010 tarihleri arasında EUR/USD üzerinden gerçekleştirilecektir:
Şekil 1. Artışla birlikte kapanma yüzdesi
(Birinci sütun tüm dönem için verileri gösterir, ikinci, üçüncü ve dördüncü - tekli, ikili ve üçlü kapanıştan sonra)
Ben de bundan bahsediyordum! Önceki çubuklar, mevcut çubuk üzerinde oldukça önemli bir etkiye sahiptir, çünkü fiyat her zaman kayıpları geri kazanmaya çalışır.
İleriye doğru bir adım daha
Harika! Fiyatların davranışının tesadüfi olmadığından emin olduktan sonra, bu şaşırtıcı gerçeği bir an önce kullanmalıyız. Tabii ki, bağımsız bir ticaret sistemi için yeterli değil, ancak sizi sıkıcı ve genellikle hatalı sinyallerden kurtarabilecek güzel bir araç olacaktır. Hadi uygulayalım!
Yani ihtiyacımız olan şey bu:
- En azından geçen yıl için olumlu sonuçlar gösteren bir kendi kendine ticaret sistemi.
- Fiyatların davranışında korelasyonların varlığını doğrulayan bazı eğlenceli örnek.
L. Williams'ın kitabında birçok faydalı fikir buldum. Bunlardan birini sizlerle paylaşacağım.
TDW (Haftanın Ticaret Günü) stratejisi. Haftanın bazı günleri sadece alım yaparsak ve diğer günler sadece kısa pozisyon açarsa ne olacağını görmemize izin verecek. Sonuçta, bir gün içindeki fiyatın, vakaların yüzdesinde diğerinden daha fazla arttığını varsayabiliriz. Bunun nedeni nedir? Jeopolitik durum, makroekonomik istatistikler veya A. Elder'in kitabında yazdığı gibi, Pazartesi ve Salı, meslekten olmayanların günleri, Perşembe ve Cuma günleri ise profesyonellerin zamanı mı? Anlamaya çalışalım.
İlk önce sadece haftanın her günü yapacağız ve sonra sadece satacağız. Çalışmanın sonunda en iyi sonuçları eşleştireceğiz ve bu, ticaret sistemimize bir filtre olacaktır. Bu arada, bu konuda birkaç sözüm var. Bu tam bir klasik!
Sistem iki MA ve MACDake'e dayanmaktadır. Sinyaller:
- Hızlı hareket eden ortalama yavaş olanı aşağıdan yukarıya kesiyorsa ve MACD histogramı sıfır çizgisinin altındaysa, SATIN AL.
- Hızlı hareket eden ortalama yavaş olanı tersten keserse ve MACD sıfırın üzerindeyse SATIN.
Bir noktadan takip eden durdurma kullanarak bir pozisyondan çıkın. Parti sabittir - 0,1.
Kolaylık sağlamak amacıyla, Uzman Danışman sınıfını ayrı bir başlık dosyasına yerleştirdim:
//+------------------------------------------------------------------+ //| moving.mqh | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Класс my_expert | //+------------------------------------------------------------------+ class my_expert { // Creating a class // Closed class members private: int ma_red_per,ma_yel_per; // Periods of MAs int ma_red_han,ma_yel_han,macd_han; // Handles double sl,ts; // Stop orders double lots; // Lot double MA_RED[],MA_YEL[],MACD[]; // Arrays for the indicator values MqlTradeRequest request; // Structure of a trade request MqlTradeResult result; // Structure of a server response // Open class members public: void ma_expert(); // Constructor void get_lot(double lot){lots=lot;} // Receiving a lot void get_periods(int red,int yel){ma_red_per=red;ma_yel_per=yel;} // Receiving the periods of MAs void get_stops(double SL,double TS){sl=SL;ts=TS;} // Receiving the values of stops void init(); // Receiving the indicator values bool check_for_buy(); // Checking for buy bool check_for_sell(); // Checking for sell void open_buy(); // Open buy void open_sell(); // Open sell void position_modify(); // Position modification }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ /* Function definition */ //---Constructor--- void my_expert::ma_expert(void) { //--- Reset the values of variables ZeroMemory(ma_red_han); ZeroMemory(ma_yel_han); ZeroMemory(macd_han); } //---The function for receiving the indicator values--- void my_expert::init(void) { ma_red_han=iMA(_Symbol,_Period,ma_red_per,0,MODE_EMA,PRICE_CLOSE); // Handle of the slow MA ma_yel_han=iMA(_Symbol,_Period,ma_yel_per,0,MODE_EMA,PRICE_CLOSE); // Handle of the fast MA macd_han=iMACD(_Symbol,_Period,12,26,9,PRICE_CLOSE); // Handle of MACDaka //---Copy data into arrays and set indexing like in a time-series--- CopyBuffer(ma_red_han,0,0,4,MA_RED); CopyBuffer(ma_yel_han,0,0,4,MA_YEL); CopyBuffer(macd_han,0,0,2,MACD); ArraySetAsSeries(MA_RED,true); ArraySetAsSeries(MA_YEL,true); ArraySetAsSeries(MACD,true); } //---Function to check conditions to open buy--- bool my_expert::check_for_buy(void) { init(); //Receive values of indicator buffers /* If the fast MA has crossed the slow MA from bottom up between 2nd and 3rd bars, and there was no crossing back. MACD-hist is below zero */ if(MA_RED[3]>MA_YEL[3] && MA_RED[1]<MA_YEL[1] && MA_RED[0]<MA_YEL[0] && MACD[1]<0) { return(true); } return(false); } //----Function to check conditions to open sell--- bool my_expert::check_for_sell(void) { init(); //Receive values of indicator buffers /* If the fast MA has crossed the slow MA from up downwards between 2nd and 3rd bars, and there was no crossing back. MACD-hist is above zero */ if(MA_RED[3]<MA_YEL[3] && MA_RED[1]>MA_YEL[1] && MA_RED[0]>MA_YEL[0] && MACD[1]>0) { return(true); } return(false); } //---Open buy--- /* Form a standard trade request to buy */ void my_expert::open_buy(void) { request.action=TRADE_ACTION_DEAL; request.symbol=_Symbol; request.volume=lots; request.price=SymbolInfoDouble(Symbol(),SYMBOL_ASK); request.sl=request.price-sl*_Point; request.tp=0; request.deviation=10; request.type=ORDER_TYPE_BUY; request.type_filling=ORDER_FILLING_FOK; OrderSend(request,result); return; } //---Open sell--- /* Form a standard trade request to sell */ void my_expert::open_sell(void) { request.action=TRADE_ACTION_DEAL; request.symbol=_Symbol; request.volume=lots; request.price=SymbolInfoDouble(Symbol(),SYMBOL_BID); request.sl=request.price+sl*_Point; request.tp=0; request.deviation=10; request.type=ORDER_TYPE_SELL; request.type_filling=ORDER_FILLING_FOK; OrderSend(request,result); return; } //---Position modification--- void my_expert::position_modify(void) { if(PositionGetSymbol(0)==_Symbol) { //If a position is for our symbol request.action=TRADE_ACTION_SLTP; request.symbol=_Symbol; request.deviation=10; //---If a buy position--- if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { /* if distance from price to stop loss is more than trailing stop and the new stop loss is not less than the previous one */ if(SymbolInfoDouble(Symbol(),SYMBOL_BID)-PositionGetDouble(POSITION_SL)>_Point*ts) { if(PositionGetDouble(POSITION_SL)<SymbolInfoDouble(Symbol(),SYMBOL_BID)-_Point*ts) { request.sl=SymbolInfoDouble(Symbol(),SYMBOL_BID)-_Point*ts; request.tp=PositionGetDouble(POSITION_TP); OrderSend(request,result); } } } //---If it is a sell position--- else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) { /* if distance from price to stop loss is more than the trailing stop value and the new stop loss is not above the previous one. Or the stop loss from the moment of opening is equal to zero */ if((PositionGetDouble(POSITION_SL)-SymbolInfoDouble(Symbol(),SYMBOL_ASK))>(_Point*ts)) { if((PositionGetDouble(POSITION_SL)>(SymbolInfoDouble(Symbol(),SYMBOL_ASK)+_Point*ts)) || (PositionGetDouble(POSITION_SL)==0)) { request.sl=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+_Point*ts; request.tp=PositionGetDouble(POSITION_TP); OrderSend(request,result); } } } } } //+------------------------------------------------------------------
"MQL5 Nesneye Yönelik Yaklaşımı Kullanarak Uzman Danışman Yazmak" makalesinin yazarına mütevazi saygılarımı sunarım. Onsuz ne yapardım! Bu kötülüğü çok iyi bilmeyen, ancak son derece işlevsel Nesne yönelimli programlamaya sahip herkese bu makaleyi okumasını tavsiye ederim.
Sınıfla birlikte dosya, Uzman Danışmanın ana koduna eklensin mi? bir nesne oluşturun ve işlevleri başlatın:
//+------------------------------------------------------------------+ //| Moving.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //---Include a file with the class--- #include <moving.mqh> //---External Variables--- input int MA_RED_PERIOD=7; // The period of a slow MA input int MA_YEL_PERIOD=2; // The period of a fast MA input int STOP_LOSS=800; // Stop loss input int TRAL_STOP=800; // Trailing stop input double LOTS=0.1; // Lot //---Create an object--- my_expert expert; //---Initialize the MqlDataTime structure--- MqlDateTime time; int day_of_week; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //---Initialize the EA expert.get_periods(MA_RED_PERIOD,MA_YEL_PERIOD); // Set the MA periods expert.get_lot(LOTS); // Set the lot expert.get_stops(STOP_LOSS,TRAL_STOP); // Set stop orders return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { TimeToStruct(TimeCurrent(),time); day_of_week=time.day_of_week; if(PositionsTotal()<1) { if(day_of_week==5 && expert.check_for_buy()==true){expert.open_buy();} else if(day_of_week==1 && expert.check_for_sell()==true){expert.open_sell();} } else expert.position_modify(); } //+------------------------------------------------------------------+
Tamamlandı! Bazı özel özelliklere dikkat çekmek istiyorum. Yazılım düzeyinde haftanın günlerini belirlemek için MqlDateTime yapısını kullandım. İlk olarak, mevcut sunucu zamanını yapılandırılmış bir formata dönüştürüyoruz. Mevcut günün (1-Pazartesi, ..., 5-Cuma) indeksini alır ve belirlediğimiz değerle karşılaştırırız.
Deneyin! Can sıkıcı araştırmalar ve fazladan rakamlarla sizi sıkmamak için tüm sonuçları tabloya getiriyorum.
İşte burada:
Tablo 1. Haftanın her günü Satın Alma Özeti
Tablo 2. Haftanın her günü Satış Özeti
En iyi sonuçlar yeşil renkle vurgulanır, en kötü sonuçlar turuncu renkle vurgulanır.
Yukarıda açıklanan eylemlerden sonra, sistemin düşük nispi düşüş, iyi bir kazanç yüzdesi (burada, ne kadar az işlem o kadar iyi) ve işlem başına nispeten yüksek kâr ile birlikte kâr sağlaması gerektiğine dair bir rezervasyon yapıyorum.
Açıkçası, en etkili sistem Cuma günü alıp Pazartesi günü satmaktır. Bu koşulların her ikisini de birleştirin:
if(PositionsTotal()<1){ if(day_of_week==5&&expert.check_for_buy()==true){expert.open_buy();} else if(day_of_week==1&&expert.check_for_sell()==true){expert.open_sell();}} else expert.position_modify();
Artık Uzman Danışman, pozisyonları her iki yönde de ancak kesin olarak tanımlanmış günlerde açar. Netlik için, filtre olmadan ve filtreyle elde edilen diyagramları çizeceğim:
Şekil 2. Filtre kullanmadan EA testinin sonuçları (EURUSD, H1, 01.01.2010-31.12.2010,)
Şekil 3. Filtre kullanılarak EA testinin sonuçları (EURUSD, H1, 01.01.2010-31.12.2010)
Sonuçları nasıl buldunuz? Filtreyi kullanarak ticaret sistemi daha kararlı hale geldi. Değişikliklerden önce, Uzman Danışman esas olarak test süresinin ilk yarısında dengeyi artırıyordu, "yükseltmeden" sonra tüm dönem boyunca artıyor.
Raporları karşılaştırıyoruz:
Tablo 3. Filtreyi kullanmadan önce ve sonra test sonuçları
Göz ardı edilemeyecek tek üzücü faktör, net karın neredeyse 1000 USD (%26) oranında düşmesidir. Ancak işlem sayısını neredeyse 3,5 kat azaltıyoruz, yani ilk olarak negatif işlem yapma potansiyelini ve ikinci olarak spread için giderleri (218*2-62*2=312 USD) önemli ölçüde azaltıyoruz. sadece EUR/USD için). Kazanma yüzdesi zaten önemli olan %57'ye yükseltildi. İşlem başına kâr %14 artarak 113 USD'ye yükselirken. L. Williams’ın dediği gibi: "Bu, işlem yapmaya değer olan miktardır!"
Sonuç
Fiyatlar rastgele davranmaz - bu bir gerçektir. Bu gerçek kullanılabilir ve kullanılmalıdır. Ticaret sisteminizin performansını artırabilecek sayısız varyasyon ve tekniğin küçük bir kısmı olan sadece bir örnek verdim. Ancak bu çeşitlilik bir kusuru gizler. Her filtre entegre edilemez, bu nedenle tüm olası senaryoları düşünerek dikkatlice seçilmelidir.
Unutmayın, filtre ne kadar mükemmel olursa olsun, karlı işlemleri, yani kazancınızı da eler... İyi şanslar!
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/269





- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz