English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Fiyat Korelasyonunun İstatistiksel Verilerine Dayalı Sinyalleri Filtreleme

Fiyat Korelasyonunun İstatistiksel Verilerine Dayalı Sinyalleri Filtreleme

MetaTrader 5Ticaret | 16 Aralık 2021, 15:37
40 0
Михаил Тарачков
Михаил Тарачков

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. Artan kapanış yüzdesi.

Ş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:

  1. En azından geçen yıl için olumlu sonuçlar gösteren bir kendi kendine ticaret sistemi.
  2. 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:                                                            

  1. Hızlı hareket eden ortalama yavaş olanı aşağıdan yukarıya kesiyorsa ve MACD histogramı sıfır çizgisinin altındaysa, SATIN AL.
  2. 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üne ait Alımların Özeti

Tablo 1. Haftanın her günü Satın Alma Özeti

Tablo 2. Haftanın her gününe ait Satışların Ö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 testi sonuçları (EURUSD, H1, 01.01.2010-31.12.2010,)

Ş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,)

Ş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ı

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

Ekli dosyalar |
explorer.mq5 (2.84 KB)
moving.mq5 (2.28 KB)
moving.mqh (6.98 KB)
Doğrusal Regresyon Örneğiyle 3 Gösterge Hızlandırma Yöntemi Doğrusal Regresyon Örneğiyle 3 Gösterge Hızlandırma Yöntemi
Makale, gösterge hesaplama algoritmaları optimizasyonu yöntemlerini ele alır. Herkes kendi ihtiyaçlarına en uygun yöntemi bulacaktır. Burada üç yöntem açıklanmıştır. Bunlardan biri oldukça basittir, bir sonraki ise sağlam bir matematik bilgisi gerektirir ve sonuncusu ise biraz zeka gerektirir. Göstergeler veya MetaTrader5 terminal tasarım özellikleri, açıklanan yöntemlerin çoğunu gerçekleştirmek için kullanılır. Yöntemler oldukça evrenseldir ve sadece doğrusal regresyon hesaplamasının hızlandırılması için değil, aynı zamanda diğer birçok gösterge için de kullanılabilir.
Satıcı Çalışmasında İstatistiksel Dağılımların Rolü Satıcı Çalışmasında İstatistiksel Dağılımların Rolü
Bu makale, bazı teorik istatistiksel dağılımlarla çalışmak için sınıfları ortaya koyan MQL5'te İstatistiksel Olasılık Dağılımları makalemin mantıklı bir devamıdır. Artık teorik bir temele sahip olduğumuza göre, doğrudan gerçek veri setlerine geçmemizi ve bu temelden bilgi amaçlı yararlanmaya çalışmamızı öneriyorum.
MQL5'te İstatistiksel Olasılık Dağılımları MQL5'te İstatistiksel Olasılık Dağılımları
Makale, Uygulamalı İstatistiklerde kullanılan rastgele değişkenlerin olasılık dağılımlarını (normal, log-normal, binom, lojistik, üstel, Cauchy dağılımı, Öğrencinin t dağılımı, Laplace dağılımı, Poisson dağılımı, Hiperbolik Secant dağılımı, Beta ve Gama dağılımı) ele alıp verir. Ayrıca bu dağılımları işlemek için sınıflar özelliğine sahiptir.
Rastgele Yürüyüş ve Trend Göstergesi Rastgele Yürüyüş ve Trend Göstergesi
Rastgele Yürüyüş gerçek piyasa verilerine çok benzer ancak bazı önemli özellikleri vardır. Bu makalede yazı tura oyunu kullanılarak simüle ettiğimiz Rastgele Yürüyüşün özelliklerini ele alacağız. Bu verinin özellikleri üzerinde çalışmak için trend olma göstergesi geliştirilmiştir.