English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
Farklı hareketli ortalama türlerinin performansının test edilmesi

Farklı hareketli ortalama türlerinin performansının test edilmesi

MetaTrader 5Sınayıcı |
262 1
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Giriş

Önceki makalelerimden birinde, en popüler hareketli ortalama türlerini (basit, ağırlıklı, üstel) incelemiştik: “Hareketli ortalamalara dayalı sistemler nasıl geliştirilir?”. Burada bu konuya devam edecek ve basit hareketli ortalamanın sonuçlarını diğer hareketli ortalama türlerinin sonuçlarıyla karşılaştıracağız. Birçok yatırımcı tercihlerine göre farklı türlerde hareketli ortalamalar kullanır. Bu nedenle, bu makalede farklı hareketli ortalama türlerine daha yakından bakacak, performanslarını test edecek ve hangi türün daha iyi çalıştığını belirlemek için sonuçları karşılaştıracağız.

Bu makalenin amacı doğrultusunda, yerleşik MetaTrader 5 Strateji Sınayıcıda hareketli ortalamaları test etmek için basit bir uygulama oluşturacağız. Test sonuçlarını değerlendirirken nelere dikkat etmeniz gerektiğini anlamak için “MQL5 Strateji Sınayıcıyı anlayın ve etkin bir şekilde kullanın” başlıklı makalemi okuyabilirsiniz. İçinde birçok yararlı bilgi bulacaksınız.

Aşağıdaki konular üzerinden ilerleyeceğiz:

Lütfen unutmayın: En iyi sonuçları elde etmek için her hareketli ortalamanın ayarlarını optimize etmeye çalışsam da, kendi başınıza bazı ek kontroller ve testler yapmalısınız. Bu makale yalnızca eğitim amaçlı yazılmıştır. Dolayısıyla, test etmeli, optimize etmeli ve size en iyi sonuçları verebilecek en iyi ayarları bulmalısınız. Bu türlerden biri veya hepsi sizin alım-satım tarzınıza uygun olmayabilir. Ancak, alım-satım bilginizi geliştirmenize yardımcı olacak fikirler bulacağınızı umuyorum. Herhangi bir alım-satım stratejisini gerçek bir hesapta kullanmadan önce her zaman performansını test edin.

Sorumluluk reddi: Sağlanan tüm bilgiler 'olduğu gibi' yalnızca bilgilendirme amaçlıdır, alım-satım tavsiyesi değildir. Bu bilgiler herhangi bir sonucu garanti etmemektedir. Bu materyalleri herhangi bir işlem hesabında kullanırsanız, ortaya çıkabilecek tüm riskler size ait olacaktır.

Simple Moving Average (SMA) göstergesine dayalı sistemin testi

Bu bölümde, Simple Moving Average’a dayalı basit bir sistemin sonuçlarını paylaşacağım. Bu sistem, fiyatın hareketli ortalama çizgisini çaprazlamasını tespit ederek alış ve satış sinyalleri üretir ve bu sinyallere göre otomatik olarak alım-satım işlemleri gerçekleştirir.

Alım-satım işlemlerini gerçekleştirmek için aşağıdaki sinyalleri kullanacağız:


Alış sinyali:

Kapanış fiyatı Simple Moving Average değerinin üzerindedir.

Ve önceki kapanış fiyatı, Simple Moving Average’ın önceki değerinin altındadır.

Satış sinyali:

Kapanış fiyatı Simple Moving Average değerinin altındadır.

Ve önceki kapanış fiyatı, Simple Moving Average’ın önceki değerinin üzerindedir.

Simple Moving Average ve diğer popüler hareketli ortalama türleri hakkında daha fazla bilgiyi önceki makalelerimden birinde bulabilirsiniz: “Hareketli ortalamalara dayalı sistemler nasıl geliştirilir?”.

Aşağıda, belirtilen sinyallere göre alış ve satış emirlerini otomatik olarak gerçekleştirebilecek bu tür bir alım-satım sistemi oluşturma adımları bulunmaktadır.

Global kapsamda, #include önişlemcisini kullanarak sinyallerimize dayalı emirleri gerçekleştirmek için programa standart kütüphaneden Trade sınıfını ekleyelim. Önişlemci hakkında daha fazla bilgiyi “MQL5 program yapısı hakkında bilmeniz gereken her şey” makalesinde bulabilirsiniz.

#include <Trade\Trade.mqh>

double türünde lotSize değişkeni, ENUM_TIMEFRAMES türünde timeFrame değişkeni ve integer türünde MAPeriod değişkeni için üç kullanıcı girdisi oluşturalım. Bunlar için varsayılan değerler belirleyeceğiz, ancak kullanıcılar daha sonra program ayarlarından istedikleri gibi bu değerleri değiştirebilirler.

input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;

Daha sonra OnInit() bölümünde tanımlayacağımız simpleMA ve barTotal adlı iki integer değişkeni atama yapmadan oluşturalım.

int simpleMA;
int barsTotal;

Alım-satım fonksiyonlarına kolay erişim için CTrade sınıfının trade adında bir nesnesini oluşturalım.

CTrade trade;

OnInit() bölümünde, hareketli ortalama göstergesinin tanıtıcısını geri döndüren “iMA” fonksiyonunu kullanarak simpleMA değişkenini tanımlayalım. Parametreleri şunlardır:

  • symbol - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • period - Zaman dilimi. Varsayılan değeri 1 saat olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_period - Hareketli ortalama periyodu. Varsayılan değeri 50 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_shift - Hareketli ortalama kayma miktarı. (0) ayarlayacağız. 
  • ma_method - Hareketli ortalama yöntemi. Simple Moving Average (MODE_SMA) kullanacağız.
  • applied_price - Hesaplamada kullanılan fiyat türü. Kapanış fiyatını (PRICE_CLOSE) kullanacağız.
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);

Çubuk sayısını geri döndüren “iBars” fonksiyonunu kullanarak barsTotal değişkenini tanımlayalım. Parametreleri şunlardır:

  • symbol - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • timeframe - Zaman dilimi. Varsayılan değeri 1 saat olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
   barsTotal=iBars(_Symbol,timeFrame);

OnTick() içinde iki dizi oluşturalım: fiyat, hacim ve makas bilgilerini depolayan MqlRates türünde priceArray (fiyatlar için) ve double türünde mySMAArray (SMA değerleri için).

   MqlRates priceArray[];
   double mySMAArray[];

“ArraySetAsSeries” fonksiyonunu kullanarak bu iki diziyi mevcut veriden başlayarak sıralayalım. Parametreleri şunlardır:

  • array[] - Sıralama yapılacak dizi.
  • flag - Dizi indeksleme yönü. Mevcut veriden başlamak için (true) kullanacağız.
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);

Mevcut ask ve bid fiyatları için double türünde Ask ve Bid değişkenlerini oluşturalım.

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);

“CopyRates” fonksiyonunu kullanarak geçmiş MqlRates verilerini alalım. Parametreleri şunlardır:

  • symbol_name - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • timeframe - Zaman dilimi. Mevcut zaman dilimine uygulanmak üzere (_Period) kullanacağız.
  • start_pos - Kopyalamanın başlangıç konumu. Mevcut konumdan başlaması için (0) ayarlayacağız.
  • count - Kopyalanacak veri miktarı. (3) ayarlayacağız.
  • rates_array[] - Kopyalamanın yapılacağı hedef dizi. (priceArray) dizisini kullanacağız.
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);

CopyBuffer fonksiyonunu kullanarak hareketli ortalama göstergesinin arabellek verilerini alalım. Parametreleri şunlardır:

  • indicator_handle - Gösterge tanıtıcısı. (simpleMA) kullanacağız.
  • buffer_num - Gösterge arabellek numarası. (0) ayarlayacağız.
  • start_pos - Kopyalamanın başlangıç konumu. Mevcut konumdan başlaması için (0) ayarlayacağız.
  • count - Kopyalanacak veri miktarı. (3) ayarlayacağız.
  • buffer[] - Kopyalamanın yapılacağı hedef dizi. (mySMAArray) kullanacağız.
CopyBuffer(simpleMA,0,0,3,mySMAArray);

Son kapanış fiyatını ve aynı mumun Simple Moving Average değerini, bu iki değer için double türünde değişkenler oluşturarak tanımlayalım.

   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);

Önceki kapanış fiyatını ve aynı mumun Simple Moving Average değerini, bu iki değer için double türünde değişkenler oluşturarak tanımlayalım.

   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);

Oluşturulan barsTotal değişkeni ile karşılaştırmak için integer türünde bars değişkeni oluşturalım.

int bars=iBars(_Symbol,timeFrame);

barsTotal değerinin bars değerine eşit olup olmadığını sınayarak yeni bir çubuk olup olmadığını kontrol edelim.

if(barsTotal != bars)

barsTotal değeri bars değerine eşit değilse, barsTotal değerini bars değeri ile güncelleyelim.

barsTotal=bars;

barsTotal, bars’a eşit değilse, strateji koşullarımızı da kontrol etmemiz gerekiyor. Alış sinyali için: önceki kapanış fiyatı aynı mumun Simple Moving Average değerinin altında mı ve aynı zamanda son kapanış fiyatı aynı mumun Simple Moving Average değerinin üzerinde mi? Eğer öyleyse, programın mevcut açık pozisyonu kapatmasına ve bir alış pozisyonu açmasına ihtiyacımız var.

      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }

Satış sinyali için: önceki kapanış fiyatı aynı mumun Simple Moving Average değerinin üzerinde mi ve aynı zamanda son kapanış fiyatı aynı mumun Simple Moving Average değerinin altında mı? Eğer öyleyse, programın mevcut açık pozisyonu kapatmasına ve bir satış pozisyonu açmasına ihtiyacımız var.

      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }

Daha sonra kodu derleyelim ve hata veya uyarı olmadan derlendiğini görelim.

Kodun tamamı aşağıda tek bir blok halinde verilmiştir:

//+------------------------------------------------------------------+
//|                                                   SMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int simpleMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double mySMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);
   int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
   CopyBuffer(simpleMA,0,0,3,mySMAArray);
   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Stratejiyi geriye dönük test etmek için Uzman Danışmanı EURUSD üzerinde çalıştıralım. Test dönemi, belirtilen tüm hareketli ortalama türleri için olduğu gibi 1 Ocak - 30 Haziran 2022 aralığıdır. SMA sistemi için ayarlarımız aşağıdaki gibi olacaktır:

  • Lot büyüklüğü: 1
  • Zaman dilimi: 1 saat
  • MA periyodu: 50

Test sonuçları:

SMA sistemi sonuçları

Aşağıdaki değerlerle ilgileniyoruz:

  • Net kar: 2700.30 (27%)
  • Göreceli bakiye düşüşü: 37.07%
  • Göreceli varlık düşüşü: 41.76%
  • Kar faktörü: 1.10
  • Beklenen getiri: 12.68
  • Düzelme faktörü: 0.45
  • Sharpe oranı: 0.57

Adaptive Moving Average (AMA)

Bu bölümde, başka bir hareketli ortalama türü olan Adaptive Moving Average (AMA) hakkında bilgi edineceğiz. Perry J. Kaufman tarafından geliştirilmiştir ve bu nedenle KAMA olarak da adlandırılır. Ana konsept, fiyat hareketindeki gürültüyü azaltmaktır. Trend takip eden bir göstergedir, dolayısıyla trend ve pivot noktalarını belirlemek için kullanılabilir.

Gösterge birkaç adımda hesaplanır.

Birinci adım: AMA'nın hesaplanması

Birinci adım

İkinci adım: Yumuşatma sabitinin (Smoothing Constant, SC) hesaplanması

İkinci adım

Üçüncü adım: Verimlilik oranının (Efficiency Ratio, ER) hesaplanması

Üçüncü adım

AMA göstergesinin manuel olarak nasıl hesaplandığını öğrendik, ancak mevcut hazır göstergelerden seçerek MetaTrader 5'e otomatik olarak ekleyebileceğimiz için buna ihtiyacımız yok. Kapanış fiyatının AMA göstergesini çaprazlamasına dayalı olarak alış ve satış emirlerini gerçekleştirebilen bir alım-satım sistemi oluşturmanın zamanı geldi. Stratejimiz için aşağıdaki sinyalleri kullanacağız.

Alış sinyali:

Kapanış fiyatı Adaptive Moving Average değerinin üzerindedir.

Ve önceki kapanış fiyatı, Adaptive Moving Average’ın önceki değerinin altındadır.

Satış sinyali:

Kapanış fiyatı Adaptive Moving Average değerinin altındadır.

Ve önceki kapanış fiyatı, Adaptive Moving Average’ın önceki değerinin üzerindedir.

Bu stratejiye dayalı alım-satım sisteminin tam kodu aşağıda gösterilmektedir:

//+------------------------------------------------------------------+
//|                                                  iAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
input int fastMAPeriod= 5;
input int slowMAPeriod= 100;
int adaptiveMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   adaptiveMA = iAMA(_Symbol, timeFrame, MAPeriod,fastMAPeriod,slowMAPeriod, 0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(adaptiveMA,0,0,3,myAMAArray);
   double lastClose=(priceArray[1].close);
   double AMAVal = NormalizeDouble(myAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevAMAVal = NormalizeDouble(myAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>AMAVal && prevClose<prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<AMAVal && prevClose>prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Bu koddaki fark, Adaptive Moving Average göstergesinin tanıtıcısını geri döndüren “iAMA” fonksiyonunun kullanılmasıdır. Parametreleri şunlardır:

  • symbol - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • period - Zaman dilimi. Varsayılan değeri 1 saat olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ama_period - Adaptive Moving Average periyodu. Varsayılan değeri 50 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • fast_ma_period - Hızlı hareketli ortalama periyodu. Varsayılan değeri 5 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • slow_ma_period - Yavaş hareketli ortalama periyodu. Varsayılan değeri 100 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ama_shift - Adaptive Moving Average kayma miktarı. (0) ayarlayacağız.
  • applied_price - Hesaplamada kullanılacak fiyat türü. (PRICE_CLOSE) kullanacağız.

Sonuçlarını görmek için AMA sistemini aynı dönemde test edelim:

  • Lot büyüklüğü: 1
  • Zaman dilimi: 1 saat
  • AMA periyodu: 50
  • Hızlı MA periyodu: 5
  • Yavaş MA periyodu: 100

Sonuçlar:

AMA sistemi sonuçları

Aşağıdaki değerlerle ilgileniyoruz:

  • Net kar: 3638.20 (36.39%)
  • Göreceli bakiye düşüşü: 22.48%
  • Göreceli varlık düşüşü: 35.53%
  • Kar faktörü: 1.31
  • Beklenen getiri: 35.67
  • Düzelme faktörü: 0.65
  • Sharpe oranı: 0.86

Double Exponential Moving Average (DEMA)

Patrick Mulloy tarafından geliştirilmiş trend takip eden bir göstergedir. Bu göstergenin temel amacı, EMA'nın gecikmesini azaltmak, ancak onu piyasa hareketlerine daha duyarlı hale getirmektir.

Bu gösterge, fiyatların bu hareketli ortalamaya göre konumunu değerlendirerek trend veya pivot noktalarını belirlemek için kullanılabilir. Göstergeyi hesaplama adımları aşağıda gösterilmiştir:

1. İlk Exponential Moving Average’ın (EMA) hesaplanması

EMA bir = n periyotlu EMA

2. EMA bir'in EMA'sının hesaplanması

EMA iki = EMA bir'in EMA'sı

3. DEMA'nın hesaplanması

DEMA = (2 * EMA bir) - EMA iki

Bildiğimiz gibi, bu manuel hesaplamaları yapmamıza gerek yok. Göstergenin daha iyi anlaşılması için gereklidirler. Bu göstergeye MetaTrader 5'teki birçok teknik göstergeyle aynı şekilde zaten sahibiz. Şimdi daha önce oluşturduğumuz aynı alım-satım sistemini oluşturmamız gerekiyor, ancak bu kez DEMA'yı kullanarak. Bu alım-satım sistemi, çaprazlamaya dayalı olarak aynı alış ve satış emirlerini uygulayacaktır, ancak bu sefer fiyat ile DEMA göstergesi arasındaki çaprazlama olacaktır. Sinyaller şu şekildedir:

Alış sinyali:

Kapanış fiyatı Double Exponential Moving Average değerinin üzerindedir.

Ve önceki kapanış fiyatı, Double Exponential Moving Average’ın önceki değerinin altındadır.

Satış sinyali:

Kapanış fiyatı Double Exponential Moving Average değerinin altındadır.

Ve önceki kapanış fiyatı, Double Exponential Moving Average’ın önceki değerinin üzerindedir.

Aşağıda, Double Exponential Moving Average göstergesinin tanıtıcısını geri döndüren “iDEMA” fonksiyonunun kullanımıyla küçük bir farkla alım-satım sisteminin tam kodu bulunmaktadır. Parametreleri şunlardır:

  • symbol - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • period - Zaman dilimi. Varsayılan değeri 1 saat olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_period - Hareketli ortalama periyodu. Varsayılan değeri 50 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_shift - Hareketli ortalama kayma miktarı. Gerek olmadığı için (0) ayarlayacağız.
  • applied_price - Hesaplamada kullanılan fiyat türü. Kapanış fiyatını (PRICE_CLOSE) kullanacağız.

Tek blok halinde kod:

//+------------------------------------------------------------------+
//|                                                 iDEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int DEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   DEMA = iDEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myDEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myDEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(DEMA,0,0,3,myDEMAArray);
   double lastClose=(priceArray[1].close);
   double DEMAVal = NormalizeDouble(myDEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevDEMAVal = NormalizeDouble(myDEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>DEMAVal && prevClose<prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<DEMAVal && prevClose>prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Derledikten sonra, kodu öncekilerle aynı dönemde test edelim. Gösterge ayarları aşağıdaki gibi olacaktır:

  • Lot büyüklüğü: 1
  • Zaman dilimi: 1 saat
  • MA periyodu: 50

Testi çalıştırdıktan sonra aşağıdaki sonuçları alırız:

DEMA sistemi sonuçları

Aşağıdaki değerlerle ilgileniyoruz:

  • Net kar: -961.60 (-9.62%)
  • Göreceli bakiye düşüşü: 39.62%
  • Göreceli varlık düşüşü: 41.15%
  • Kar faktörü: 0.97
  • Beklenen getiri: -3.12
  • Düzelme faktörü: -0.18
  • Sharpe oranı: -0.21

Triple Exponential Moving Average (TEMA)

Bu hareketli ortalama türü, göstergeyi daha hassas ve kısa vadeli alım-satıma uygun hale getirmek için Patrick Mulloy tarafından geliştirilmiştir. Gösterge üçlü, ikili ve tekli yumuşatma ile EMA’lar kullanır. Böylece, bu gösterge fiyata daha yakın olacak ve daha hassas hale gelecektir. Double Exponential Moving Average’ı kullandığımız gibi, Triple Exponential Moving Average’ı da fiyata daha hızlı yanıt vermesine ek olarak aynı şekilde uygulayabiliriz. Ayrıca, trend ve pivot noktalarını veya trend değişikliklerini belirlemek için de kullanılabilir.

TEMA göstergesini hesaplama adımları aşağıdadır:

1. İlk Exponential Moving Average’ın (EMA) hesaplanması

EMA bir = n periyotlu EMA

2. EMA bir'in EMA'sının hesaplanması

EMA iki = EMA bir'in EMA'sı

3. EMA iki'nin EMA'sının hesaplanması

EMA üç = EMA iki’nin EMA'sı

4. TEMA'nın hesaplanması

DEMA = (3 * EMA bir) - (3 * EMA iki) + (EMA3)

Bu göstergeyi MetaTrader 5'teki mevcut hazır teknik göstergelerden manuel hesaplama yapmadan ekleyebiliriz. Şimdi, test etmek ve sonuçlarını diğer türlerle karşılaştırmak için bu TEMA göstergesini kullanarak alım-satım sistemimizi oluşturmamız gerekiyor. Aşağıda bu alım-satım sistemini oluşturmak için tam kod bulunmaktadır. “iTEMA” fonksiyonunun Triple Exponential Moving Average göstergesinin tanıtıcısını geri döndürmek için kullanılması farkıyla öncekilere benzer (parametreleri DEMA ve SMA'da bahsettiklerimizle aynıdır).

//+------------------------------------------------------------------+
//|                                                 iTEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int TEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   TEMA = iTEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myTEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myTEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(TEMA,0,0,3,myTEMAArray);
   double lastClose=(priceArray[1].close);
   double TEMAVal = NormalizeDouble(myTEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevTEMAVal = NormalizeDouble(myTEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>TEMAVal && prevClose<prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<TEMAVal && prevClose>prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Bu yazılımı derleyip çalıştırdıktan sonra, sonuçlarını diğer hareketli ortalama türleriyle karşılaştırmak için aynı dönemde test edebiliriz. Aşağıda, bu test sürecinde tüm parametrelerin sabit olmasını sağlamak için kullanılacak girdiler yer almaktadır:

  • Lot büyüklüğü: 1
  • Zaman dilimi: 1 saat
  • MA periyodu: 50

Bu testi çalıştırıp tamamladıktan sonra aşağıdaki sonuçları elde ederiz:

TEMA sistemi sonuçları

Aşağıdaki değerlerle ilgileniyoruz:

  • Net kar: -3973.10 (-39.74%)
  • Göreceli bakiye düşüşü: 63.98%
  • Göreceli varlık düşüşü: 66.06%
  • Kar faktörü: 0.90
  • Beklenen getiri: -10.59
  • Düzelme faktörü: -0.52
  • Sharpe oranı: -0.83

Fractal Adaptive Moving Average (FrAMA)

Bu hareketli ortalama türü John Ehlers tarafından geliştirilmiştir. Trend takip eden bir göstergedir ve piyasa fiyatlarının fraktal olduğunu varsayar. Trend ve pivot noktalarını belirlemek için kullanılabilir. Hesaplama adımları aşağıda gösterilmiştir:

FrAMA

Bu göstergeyi MetaTrader 5'teki mevcut hazır teknik göstergeler listesinden ekleyebiliriz. Şimdi FrAMA göstergesini kullanarak aşina olduğumuz bir alım-satım stratejisi oluşturalım. Strateji, fiyat ile FrAMA göstergesi arasındaki çaprazlamaya dayanır. Fiyat FrAMA'nın üzerine çıktığında, bu bir alış sinyali olacak ve fiyat FrAMA'nın altına düştüğünde, bu bir satış sinyali olacaktır.

Alış sinyali:

Kapanış fiyatı Fractal Adaptive Moving Average değerinin üzerindedir.

Ve önceki kapanış fiyatı, Fractal Adaptive Moving Average’ın önceki değerinin altındadır.

Satış sinyali:

Kapanış fiyatı Fractal Adaptive Moving Average değerinin altındadır.

Ve önceki kapanış fiyatı, Fractal Adaptive Moving Average’ın önceki değerinin üzerindedir.

Aşağıda, Fractal Adaptive Moving Average göstergesinin tanıtıcısını geri döndüren “iFrAMA” fonksiyonunun kullanımıyla küçük bir farkla alım-satım sisteminin tam kodu bulunmaktadır. Parametreler şunlardır:

  • symbol - Sembol adı. Mevcut sembole uygulanmak üzere (_Symbol) kullanacağız.
  • period - Zaman dilimi. Varsayılan değeri 1 saat olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_period - Hareketli ortalama periyodu. Varsayılan değeri 50 olan kullanıcı girdisini kullanacağız, ancak kullanıcı bunu değiştirebilir.
  • ma_shift - Hareketli ortalama kayma miktarı. (0) ayarlayacağız. 
  • applied_price - Hesaplamada kullanılacak fiyat türü. (PRICE_CLOSE) kullanacağız.
//+------------------------------------------------------------------+
//|                                                iFrAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int FrAMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   FrAMA = iFrAMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myFrAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myFrAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(FrAMA,0,0,3,myFrAMAArray);
   double lastClose=(priceArray[1].close);
   double FrAMAVal = NormalizeDouble(myFrAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevFrAMAVal = NormalizeDouble(myFrAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>FrAMAVal && prevClose<prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<FrAMAVal && prevClose>prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Kodu derledikten ve Uzman Danışmanı çalıştırdıktan sonra, aşağıdaki ayarlarla FrAMA göstergesini kullanarak stratejiyi test edelim:

  • Lot büyüklüğü: 1
  • Zaman dilimi: 1 saat
  • MA periyodu: 50

Bu Uzman Danışmanı yukarıda bahsedilen diğer tüm hareketli ortalamalarla aynı dönemde test ediyoruz ve aşağıdaki sonuçları alıyoruz:

FrAMA sistemi sonuçları

Aşağıdaki değerlerle ilgileniyoruz:

  • Net kar: -2993.70 (-29.94%)
  • Göreceli bakiye düşüşü: 73.28%
  • Göreceli varlık düşüşü: 74.81%
  • Kar faktörü: 0.93
  • Beklenen getiri: -6.45
  • Düzelme faktörü: -0.33
  • Sharpe oranı: -0.46

Sonuçların SMA sonuçlarıyla karşılaştırılması

Yukarıda bahsedilen her hareketli ortalama türünün sonuçlarını karşılaştıralım. Ancak her hareketli ortalama, onu optimize edersek, periyodunu veya testin yapıldığı dönemi değiştirirsek farklı sonuçlar verebilir. Ayrıca hareketli ortalama, diğer gösterge ayarlarına ve piyasa koşullarına bağlı olarak da farklı sonuçlar gösterebilir.

Buradaki temel amaç, kendi bakış açımızdan seçebileceğimiz en iyi ayarlara göre hareketli ortalama çeşitlerini objektif olarak değerlendirmek için mümkün olduğunca çok sayıda aynı koşulu sağlamaktır. En önemli değerleri ele alalım:

  • Net kar: Ne kadar yüksekse o kadar iyidir
  • Düşüş: Ne kadar düşükse o kadar iyidir
  • Kar faktörü: Ne kadar yüksekse o kadar iyidir
  • Beklenen getiri: Ne kadar yüksekse o kadar iyidir
  • Düzelme faktörü: Ne kadar yüksekse o kadar iyidir
  • Sharpe oranı: Ne kadar yüksekse o kadar iyidir

Aşağıdaki tabloyu kullanarak Simple Moving Average’ın sonuçlarını bu ölçütlere dayalı olarak diğer hareketli ortalama türleriyle karşılaştıralım:

Ölçüt SMA AMA DEMA TEMA FrAMA
Net kar 2700.30 (27%) 3638.20 (36.39%) -961.60 (-9.62%) -3973.10 (-39.74%) -2993.70 (-29.94%)
Göreceli bakiye düşüşü 37.07% 22.48% 39.62% 63.98% 73.28%
Göreceli varlık düşüşü  41.76% 35.53% 41.15% 66.06% 74.81%
Kar faktörü 1.10 1.31 0.97 0.90 0.93
Beklenen getiri 12.68 35.67 -3.12 -10.59 -6.45
Düzelme faktörü 0.45 0.65 -0.18 -0.52 -0.33
Sharpe oranı 0.57 0.86 -0.21 -0.83 -0.46

Tüm testlerimize göre, ayarlara ve test dönemine bağlı olarak en iyi performansa sahip iki türümüz var. Bunlar Simple Moving Average (SMA) ve Adaptive Moving Average’dır (AMA). Bunlardan en iyisi Adaptive Moving Average’dır (AMA). Şunlara sahiptir:

  • En yüksek net kar
  • En düşük göreceli bakiye düşüşü
  • En düşük göreceli varlık düşüşü
  • En yüksek kar faktörü
  • En yüksek beklenen getiri
  • En yüksek düzelme faktörü
  • En yüksek Sharpe oranı

Daha önce de belirttiğimiz gibi, daha optimize ayarlar ve stratejilerle daha iyi sonuçlar elde edebiliriz, ancak buradaki amaç test sürecini gerçek bir örnek üzerinde anlamak ve uygulamaktı, böylece aynı süreci daha sonra başka test amaçları için de kullanabiliriz.

Sonuç

Bu makalede, aşağıdaki hareketli ortalama türlerinin performans sonuçlarını inceledik:

  • Adaptive Moving Average (AMA)
  • Double Exponential Moving Average (DEMA)
  • Triple Exponential Moving Average (TEMA)
  • Fractal Adaptive Moving Average (FrAMA)

Her tür için alım-satım sistemleri oluşturduk ve sonuçlarını en popüler hareketli ortalama türü olan Simple Moving Average’ın sonuçlarıyla karşılaştırdık. Test sonuçlarına göre, en iyi sonuçlar Simple Moving Average (SMA) ve Adaptive Moving Average (AMA) ile elde edildi. Adaptive Moving Average (AMA) tüm hareketli ortalamaların zirvesine yerleşti. Kazananı belirlemek için aşağıdaki ölçütleri analiz ettik ve karşılaştırdık:

  • Net kar
  • Düşüş
  • Kar faktörü
  • Beklenen getiri
  • Düzelme faktörü
  • Sharpe oranı

Test etmek alım-satımda çok önemli bir konudur. Bu nedenle, sizi daha fazla strateji üzerinde daha fazla test yapmaya teşvik ediyorum. Stratejinin kendisini değerlendirmenin yanı sıra, her test anlayışımızı derinleştirdiğinden, testler sayesinde beklenmedik fikirler edinebiliriz.

İlginiz için çok teşekkür ederim! Bu makalenin sizin için yararlı olduğunu ve bilgilerinize değer kattığını umuyorum. Yayınlar bölümünden, RSI, MACD, Stochastic Oscillator, Bollinger Bands vb. popüler teknik göstergelere dayalı alım-satım sistemleri oluşturmaya adanmış olanlar da dahil olmak üzere diğer makalelerimi okuyabilirsiniz. Umarım bu makaleler de sizin için faydalı olur.

MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/13130

Ekli dosyalar |
SMA_System.mq5 (2.07 KB)
iAMA_System.mq5 (2.15 KB)
iDEMA_System.mq5 (2.06 KB)
iTEMA_System.mq5 (2.06 KB)
iFrAMA_System.mq5 (2.08 KB)
Son yorumlar | Tartışmaya git (1)
go123
go123 | 26 Şub 2024 saat 03:27
Forex'te 1 saatlik döngü için yalnızca bir uyarlanabilir ortalama kullanarak kar elde edebilir miyim? Onları geriye dönük test ettiğimde neden forex öğelerinin çoğunda para kaybediyorum?
MQL5'te emir yerleştirme MQL5'te emir yerleştirme
Herhangi bir alım-satım sistemi oluştururken, verimli bir şekilde çözülmesi gereken bir görev vardır. Bu görev, emirlerin yerleştirilmesi veya bunların alım-satım sistemi tarafından otomatik olarak yönetilmesidir. Makale, verimli emir yerleştirme açısından bir alım-satım sisteminin oluşturulmasını ele almaktadır.
MQL5 program yapısı hakkında bilmeniz gereken her şey MQL5 program yapısı hakkında bilmeniz gereken her şey
Tüm programlama dillerinde programların belirli bir yapısı vardır. Bu makalede, MetaTrader 5 için bir alım-satım sistemi oluştururken çok yararlı olabilecek MQL5 program yapısının ana bileşenlerini inceleyeceğiz.
Alım-satımda kaos teorisi (Bölüm 1): Giriş, finansal piyasalarda uygulama ve Lyapunov üssü Alım-satımda kaos teorisi (Bölüm 1): Giriş, finansal piyasalarda uygulama ve Lyapunov üssü
Kaos teorisi finansal piyasalara uygulanabilir mi? Bu makalede, geleneksel kaos teorisinin ve kaotik sistemlerin Bill Williams tarafından önerilen konseptten nasıl farklı olduğunu ele alacağız.
MQL5'te fonksiyonları uygulamalarla anlama MQL5'te fonksiyonları uygulamalarla anlama
Fonksiyonlar her programlama dilinde kritik bileşenlerdir. Diğer birçok faydasının yanı sıra, geliştiricilerin DRY (Don't Repeat Yourself, kendini tekrar etme) ilkesini uygulamalarına yardımcı olurlar. Bu makalede, fonksiyonlar hakkında çok daha fazla bilgi edinecek ve alım-satım sisteminizi zenginleştiren ancak karmaşıklaştırmayan basit uygulamalar yardımıyla MQL5'te kendi fonksiyonlarınızı nasıl oluşturacağınızı göreceksiniz.