English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
MQL5'i kullanarak trendler ve grafik formasyonları nasıl tespit edilir?

MQL5'i kullanarak trendler ve grafik formasyonları nasıl tespit edilir?

MetaTrader 5Alım-satım | 6 Şubat 2025, 12:40
162 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Giriş

Yatırımcılar olarak hepimiz grafiklerle ilgileniriz ve doğru tahminler ve kararlar vermek için onları doğru okumaya çalışırız. Bir grafik, potansiyel fiyat hareketlerini tahmin etmemize yardımcı olabilecek birçok formasyon içerir. Geliştireceğimiz yararlı araçlar bu görevi basitleştirebilir. Bu makalede, MQL5’i kullanarak en önemli fiyat formasyonlarını nasıl otomatik olarak tespit edebileceğimizi göreceğiz.

Aşağıdaki konuları ele alacağız: 

Bu makaleyi okuduktan sonra, yüksek ve düşük seviyeleri, trend türlerini, Çift Tepe ve Çift Dipleri belirleyebileceksiniz. Bahsedilen kodları ayrıca kendiniz de yazarak kodlama pratiği yapın ve gerçek bir hesapta kullanmadan önce en iyi sonuçları elde edebilmek amacıyla neye ihtiyacınız olduğunu görmek için onları test edin ve geliştirin. Bu makalenin temel amacı, MQL5 dilinde kodlama yaparak grafik formasyonlarının otomatik bir şekilde nasıl tespit edilebileceğine dair temel fikrin anlaşılmasını sağlamaktır. Grafiklerde görülebilen birçok anlamlı formasyon vardır. Onlardan nasıl yararlanacağınızı öğrenirseniz, onları alım-satımınızın çok önemli bir parçası haline getirebilirsiniz.

Bu makalede, MetaTrader 5 işlem terminalinde yerleşik olarak bulunan MQL5 geliştirme ortamını kullanacağız. MetaTrader 5'in nasıl kurulacağı ve MetaEditor’ın nasıl kullanılacağı hakkında daha fazla bilgi edinmek istiyorsanız, önceki makalelerimden birinde yer alan "MetaEditor'da MQL5 kodu yazma" bölümünü okuyabilirsiniz.

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.

Yüksek ve düşük seviye tespiti

Bu bölümde, MQL5’i kullanarak grafikteki yüksek ve düşük seviyeleri tanımlayacağız ve ardından bu tanımı, her bir grafik formasyonuna göre koşullarımızı beyan etmek için bir temel olarak kullanacağız.

Yüksek seviye:

Bir yüksek seviyesinin oluşması, alıcıların gücü nedeniyle belirli bir seviyeye kadar yukarı doğru bir hareket olduğu, ardından satıcıların ortaya çıktığı ve fiyatı aşağı çektiği anlamına gelir. Aşağıdaki şekil buna bir örnektir.   

Yüksek seviye

Düşük seviye:

Bir düşük seviyesinin oluşması, satıcıların gücü nedeniyle belirli bir seviyeye doğru aşağı doğru bir hareket olduğu, ardından alıcıların ortaya çıktığı ve fiyatı yukarı taşıdığı anlamına gelir. Aşağıdaki şekil buna bir örnektir.

Düşük seviye

Şimdi bu tür hareketleri tespit edebilecek bir MQL5 programı (Uzman Danışman) oluşturmamız gerekiyor. Farklı şekillerde oluşturulabilir. Bunlardan birini göreceğiz.

Belirli fiyat seviyelerini (yüksek ve düşük seviyeleri) belirlememiz, ardından diğer belirli fiyat seviyelerine (potansiyel yüksek ve düşük seviyeleri) doğru gitmemiz ve başka bir yüksek veya düşük seviyesi olup olmadığını belirlemek için önceki yüksek ve düşük seviyeleri ile mevcut yüksek ve düşük seviyelerini karşılaştırmamız gerekir. Bunu yapmak için belirli adımları izleyeceğiz.

“OnTick()” kapsamının dışında yüksek veya düşük seviyesini geri döndürecek bir fonksiyon oluşturalım. Bir tamsayı değişken şeklinde getNextMove olarak adlandıracağız. Bu fonksiyon için ayarlamamız gereken parametreler şunlardır:

  • int move - Yüksek veya düşük olup olmadığını belirlemek için.
  • int count - startPos değişkeniyle ilgili sayacı belirlemek için.
  • int startPos - başlangıç konumunu belirlemek için.
int getNextMove(int move, int count, int startPos)

Bu fonksiyonun içinde, fonksiyon parametrelerinin değerini belirlemek için “if” deyimini kullanarak aşağıdaki sınamayı gerçekleştirmemiz gerekir. startPos değerinin sıfırdan küçük olup olmadığını kontrol etmemiz, eğer öyleyse startPos değerini count değerine eklememiz ve mevcut çubuktan başlamak için startPos değerini sıfır değeriyle güncellememiz gerekir.

   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }

Fonksiyonda count ve startPos değişkenlerini tanımladık. move değişkeni, fonksiyonu sonlandıran ve sonuç değerini geri döndüren “return” operatörü kullanılarak geri dönüş değerinde tanımlanacaktır. Üçlü operatör (?:), ilki bool türünde veri geri döndüren üç ifadeden oluşur. İlk ifade doğru ise, ikinci ifade yürütülür; yanlış ise, üçüncü ifade yürütülür.

İlk ifadede move değişkeninin Yüksek fiyatı moduna eşit olup olmadığını belirtiriz. Doğru ise en yüksek değer, yanlış ise en düşük değer geri döndürülür.

move değişkeninin Yüksek fiyatı moduna eşit olup olmadığını kontrol etmek için, Yüksek fiyatını geri döndürmek üzere “iHighest()” ve “iLowest()” fonksiyonlarında kullanılan zaman serisi tanımlayıcılarından biri olan (MODE_HIGH)’ı kullanacağız. En yüksek ve en düşük değerin indeksini geri döndürmek için “iHighest()” ve “iLowest()” fonksiyonlarının parametreleri:

  • symbol - Mevcut sembol adını const string olarak geri döndürmek için Symbol() kullanacağız.
  • timeframe - Mevcut zaman dilimini ENUM_TIMEFRAMES olarak geri döndürmek için Period() kullanacağız.
  • type - move türünü bir zaman serisi tanımlayıcısı olarak geri döndürmek için (ENUM_SERIESMODE) move kullanacağız. Bu tür, iHighest için Yüksek fiyatı modu ve iLowest için Düşük fiyatı modu olacaktır.
  • count - Eleman sayısını geri döndürmek için int (count) değişkenini kullanacağız.
  • start - İndeksi geri döndürmek için int (startPos) değişkenini kullanacağız.
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));

Bir sonraki hareketi geri döndüren bu fonksiyonu oluşturduktan sonra, mevcut hareketin yüksek veya düşük seviyesini almak için ana fonksiyon olacak başka bir int fonksiyon oluşturacağız. Buna getmove adını verelim ve parametre olarak üç int değişken sağlayalım (move, count ve startPos).

int getmove(int move, int count, int startPos)

Fonksiyonun içinde, move değişkeninin (MODE_HIGH) veya (MODE_LOW)'a eşit olup olmadığını kontrol etmemiz gerekir, eğer herhangi bir eşitlik yoksa geri dönüş değeri (-1) olacaktır.

if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);

currentBar adında int türünde yeni bir değişken oluşturalım ve buna startPos değişkenini atayalım.

int currentBar=startPos;

moveReturned adında int türünde yeni bir değişken oluşturalım ve (move), (count*2+1) ve (currentBar-count) parametreleriyle oluşturulan “getNextMove” fonksiyonunu buna atayalım.

int moveReturned=getNextMove(move,count*2+1,currentBar-count);

“while” kullanarak bir döngü oluşturalım. Eğer true ise, operatör çalıştırılacaktır. Burada ifadede, moveReturned değerinin currentBar değerine eşit olmamasını kontrol ediyoruz. Eğer true ise, aşağıdaki şunları yapmamız gerekiyor:

  • currentBar değişkenini “getNextMove” kullanarak (move, count, currentBar+1) parametreleriyle güncelliyoruz.
  • moveReturned değişkenini “getNextMove” kullanarak (move, count*2+1, currentBar-count) parametreleriyle güncelliyoruz.
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }

Daha sonra currentBar değerini geri döndürerek fonksiyonu sonlandırmak için “return” fonksiyonunu kullanalım.

return(currentBar);

Ardından “OnTick()” fonksiyonunun içine gireceğiz ve yüksek ve düşük seviyelerini tespit etmemize yardımcı olacak oluşturduğumuz fonksiyonları çağıracağız. İlk olarak, int türünde üç değişken oluşturalım.

   int checkBars= 5; 
   int move1;
   int move2;

İki yüksek seviyeyi tespit etmek amacıyla move1 için (MODE_HIGH, checkBars, 0) ve move2 için (MODE_HIGH, checkBars, move1+1) parametreleriyle önceden oluşturulmuş “getmove” fonksiyonumuzu kullanarak move1 ve move2'yi güncelleyelim.

   move1=getmove(MODE_HIGH,checkBars,0);
   move2=getmove(MODE_HIGH,checkBars,move1+1);

Aşağıdaki adımları izleyerek bu iki yüksek seviye üzerinde bir çizgi oluşturalım:

Ad belirtilerek nesneyi silen “ObjectDelete” fonksiyonu ile mevcut herhangi bir çizgiyi silelim. Bu fonksiyon için parametreler şunlardır: ilk parametre grafik tanımlayıcısıdır ve mevcut grafik için (0) kullanacağız. İkinci parametre nesne adıdır, dizge şeklinde “topLine” kullanacağız.

ObjectDelete(0,"topLine");

“topLine” adında yeni bir nesne oluşturmak için “ObjectCreate” fonksiyonunu kullanalım. Parametreleri şunlardır:

  • chart_id - Grafik tanımlayıcısı olarak bir long türü geri döndürmek için (0) kullanacağız.
  • name - Nesnenin adı olarak bir string türü geri döndürmek için "topLine" kullanacağız.
  • type - Bir ENUM_OBJECT türü veya nesne türünü geri döndürmek için (OBJ_TREND) kullanacağız.
  • nwin - Pencere indeksi olarak mevcut grafik için (0) kullanacağız.
  • time1 - move2 çapasının zamanını belirlemek ve bir datetime türü geri döndürmek için iTime(Symbol(), Period(), move2) kullanacağız.
  • price1 - move2 çapasının fiyatını belirlemek ve bir double türü geri döndürmek için iHigh(Symbol(), Period(), move2) kullanacağız.
  • timeN=0 - move1 çapasının zamanını belirlemek ve bir datetime türü geri döndürmek için iTime(Symbol(), Period(), move1) kullanacağız.
  • priceN=0 - move1 çapasının fiyatını belirlemek ve bir double türü geri döndürmek için iHigh(Symbol(), Period(), move1) kullanacağız.

Gördüğümüz gibi, “iHigh” fonksiyonu çubuğun Yüksek fiyatını geri döndürür ve parametreleri sembol, zaman dilimi ve indeks şeklinde kayma miktarıdır. “iTime” fonksiyonu çubuğun açılış zamanını geri döndürür ve parametreleri “iHigh” fonksiyonunun parametreleriyle aynıdır.

ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iHigh(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iHigh(Symbol(),Period(),move1));

“ObjectSetInteger” fonksiyonunu kullanarak oluşturulan nesne için renk, genişlik ve çizgi türünü ayarlayalım. Parametreleri şunlardır:

  • chart_id - Grafik tanımlayıcısı. (0) kullanacağız.
  • name - Nesne adı. Yüksek seviyeler için "TopLine" kullanacağız.
  • prop_id - Nesne özelliği. Renk için (OBJPROP_COLOR), genişlik için (OBJPROP_WIDTH) ve çizgi türü için (OBJPROP_RAY_RIGHT) kullanacağız.
  • prop_value - İstenen değer. Renk için (clrRed), genişlik için (3) ve çizgi türü için (true) kullanacağız.
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);

move1 ve move2 değişkenlerini yüksek seviyeler için yaptığımız gibi güncelleyerek iki düşük seviye elde edelim, ancak zaman serisi tanımlayıcısı olarak (MODE_LOW) kullanacağız.

   move1=getmove(MODE_LOW,checkBars,0);
   move2=getmove(MODE_LOW,checkBars,move1+1);

Bu iki düşük seviyenin altında varsa mevcut çizgi nesnesini silelim ve yüksek seviyeler için oluşturduğumuz şekilde düşük seviyeler için de çizgi nesnesini oluşturalım, ancak nesne adı “bottomLine” ve rengi yeşil olacaktır.

   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iLow(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iLow(Symbol(),Period(),move1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);

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

//+------------------------------------------------------------------+
//|                                                   moveFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5; 
   int move1;
   int move2;
   move1=getmove(MODE_HIGH,checkBars,0);
   move2=getmove(MODE_HIGH,checkBars,move1+1);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iHigh(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iHigh(Symbol(),Period(),move1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   move1=getmove(MODE_LOW,checkBars,0);
   move2=getmove(MODE_LOW,checkBars,move1+1);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iLow(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iLow(Symbol(),Period(),move1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Kod başarıyla derlenip yürütüldükten sonra, grafik üzerinde iki yüksek ve bunların üzerinde kırmızı bir çizgi ve iki düşük ve bunların altında yeşil bir çizgi elde ederiz. Örnekler aşağıda verilmiştir:

moveFinder sinyal 1

Gördüğümüz gibi, bu iki çizgi grafikte bir formasyon gösterebilir ve ayrıca fiyat hareketini de yansıtabilir. Yukarıdaki örnekte, iki yükselen çizgimiz olduğu ve üstteki çizginin açısı alttakinden daha geniş olduğu için keskin bir yukarı doğru hareketimiz olduğunu söyleyebiliriz. Dolayısıyla, fiyat hareketini yorumlamak için çok faydalı bir araç olabilirler.

Aşağıda, farklı bir fiyat hareketine dayanan farklı bir formasyona sahip başka bir örnek bulunmaktadır:

moveFinder sinyal 2

Burada farklı bir fiyat hareketiyle karşı karşıyayız. Yine iki çizgiye sahibiz; ama alt çizgi yukarı ve üst çizgi aşağı doğru hareket ediyor, bu da alıcıların fiyatı yükseltiyor ve satıcıların da aynı anda fiyatı düşürüyor olduğunu, yani alıcılar ve satıcılar arasında bir denge olduğunu gösteriyor.

Aşağıda da başka bir fiyat hareketi formasyonu örneği yer almaktadır:

moveFinder sinyal 3

Burada da fiyatı aşağı çekebildikleri için satıcıların gücünü yansıtabilecek iki aşağı yönlü çizgimiz var.

Önceki bölümde bir grafikteki yüksek ve düşük seviyeleri nasıl tespit edebileceğimizi öğrendik, artık bir grafikteki trendleri tespit etmek için bu kodu geliştirebiliriz. İki yüksek ve iki düşük seviyeyi nasıl tespit edeceğimizi gördük. Trend tespiti için ihtiyacımız olan şey budur. Bir grafikteki trendleri tespit etmek için mümkün olduğunca önceki kodumuzu geliştirerek kullanacağız.

Basit bir ifadeyle, trendler fiyat hareketleridir ve bu hareket yukarı veya aşağı yönlü olabilir ya da net bir yönü olmayabilir. Her üç hareket türünü de inceleyelim:

Yükseliş trendi:

Bu durumda, piyasadaki güçlü taraf alıcılardır. Grafikte fiyatın açıkça daha yüksek düşükler ve daha yüksek yüksekler oluşturduğunu görebiliriz. Aşağıdaki şekil yükseliş trendinin grafiğini göstermektedir:

Yükseliş trendi

Düşüş trendi:

Bu durumda, satıcılar piyasada güçlü olan taraftır ve fiyatı aşağı çeker. Grafikte fiyatların daha düşük yüksekler ve daha düşük düşükler oluşturduğunu görebiliriz.

Aşağıda bunu görsel açıdan anlatan bir şekil yer almaktadır:

Düşüş trendi

Yatay hareket:

Bu durumda net bir yön yoktur. Yatay hareketin birçok şekli vardır. Aşağıdakiler bunlardan bazılarıdır:

Yatay hareket 1  Yatay hareket 2  Yatay hareket 3

Şimdi bir trendimiz (yükseliş veya düşüş) olup olmadığını (yatay hareket) belirleyebilecek bir MQL5 Uzman Danışmanı oluşturacağız. Aşağıdaki kod, böyle bir Uzman Danışman oluşturmak içindir:

//+------------------------------------------------------------------+
//|                                                  trendFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(lowVal1>lowVal2&&highVal1>highVal2)
     {
      Comment("Uptrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }
   else
      if(highVal1<highVal2&&lowVal1<lowVal2)
        {
         Comment("Downtrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
        {
         Comment("Sideways",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Aşağıdakiler, trendleri tespit etmek için bu koddaki farklılıklardır.

“OnTick” fonksiyonu kapsamında iki yüksek ve iki düşük için int türünde dört değişken ve iki yüksek değer ve iki düşük değer için double türünde dört değişken oluşturuyoruz.

   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;

Yüksek değerlerin sonucunu yuvarlamak için “NormalizeDouble” fonksiyonunu kullanarak yüksek değerlerin iki değerini (highVal1, highVal2) güncelliyoruz. Parametreleri şunlardır:

  • value - Normalleştirilecek sayı. Yüksek fiyatını geri döndürmek için “iHigh” fonksiyonunu kullanacağız. “iHigh” fonksiyonu için kullanacağımız parametreler: mevcut sembol için (_Symbol), mevcut zaman dilimi için (_Period) ve indeks şeklinde kayma miktarı için (high1) ve (high2).
  • digits - Ondalık noktadan sonraki basamak sayısı. (5) kullanacağız.
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);

“NormalizeDouble” fonksiyonunu kullanarak iki düşük değeri (lowVal1, lowVal2) daha önce bahsettiğimiz aynı parametrelerle ve aşağıdaki farklarla güncelliyoruz:

  • value - Normalleştirilecek sayı. Düşük fiyatını geri döndürmek için “iLow” fonksiyonunu kullanacağız. Parametreleri (low1) ve (low2) olacak indeksler şeklinde kayma miktarı dışında aynıdır.
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);

Sırada trendleri belirlemek için ayarlamamız gereken koşullar var. Bunlar için “if” ifadesini kullanacağız. Uzman Danışmanın sürekli olarak yüksek ve düşük dört değeri kontrol etmesine, devamında birbirleriyle ilişkili konumlarını belirlemesine ve ardından bir trendimiz (yükseliş veya düşüş) olup olmadığına (yatay hareket) karar vermesine ihtiyacımız var.

Yükseliş trendi durumu:

lowVal1, lowVal2'den yüksekse ve aynı zamanda highVal1, highVal2'den yüksekse, bir yükseliş trendimiz vardır ve Uzman Danışman aşağıdaki yorumu grafikte geri döndürmelidir:

  • Yükseliş trendi
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   if(lowVal1>lowVal2&&highVal1>highVal2)
     {
      Comment("Uptrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Düşüş trendi durumu:

HighVal1, highVal2'nin altındaysa ve aynı zamanda lowVal1, lowVal2'nin altındaysa, bir düşüş trendimiz vardır ve Uzman Danışman bu sefer aşağıdaki şu yorumu grafikte geri döndürmelidir:

  • Düşüş trendi
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   else
      if(highVal1<highVal2&&lowVal1<lowVal2)
        {
         Comment("Downtrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Yatay hareket durumu:

Dört değerin konumu yükseliş trendi ve düşüş trendi koşullarından başka bir şeyi temsil ediyorsa, yatay bir hareket vardır ve Uzman Danışman şu yorumu grafikte geri döndürmelidir:

      else
        {
         Comment("Sideways",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Kodu derleyerek ve Uzman Danışmanı çalıştırarak gerekli trend sinyallerini alabiliriz. Aşağıda trend durumuna göre örnekler verilmiştir.

Yükseliş trendi:

trendFinder - Yükseliş trendi sinyali

Grafikte, daha yüksek bir düşük ve daha yüksek bir yüksek fiyata sahip olduğumuz için bir yükseliş trendi örneği görüyoruz. Böylece, grafiğin sol üst köşesinde yorum olarak bir yükseliş trendi sinyali aldık.

Düşüş trendi:

trendFinder - Düşüş trendi sinyali

Grafikte, daha düşük bir yüksek ve daha düşük bir düşük fiyata sahip olduğumuz için bir düşüş trendi örneği görüyoruz. Dolayısıyla, grafikte yorum olarak bir düşüş trendi sinyali aldık.

Yatay hareket:

trendFinder - Yatay hareket sinyali

Daha düşük bir yüksek ve daha yüksek bir düşük seviyemiz var. Bu, yatay bir harekete işaret ediyor. Dolayısıyla, grafikte yorum olarak yatay hareket sinyali aldık.

Çift Tepe tespiti

Şimdi kodumuzu daha da geliştirme zamanı. Potansiyel bir harekete işaret edebilecek belirli fiyat formasyonlarını tespit etmesini sağlayalım.

Ana fikri anlamanız ve diğer önemli formasyonları tespit etme potansiyelini görmeniz için size küçük bir kod değişikliği ile bazı grafik formasyon örnekleri sunacağım. Bu bölümde, popüler grafik formasyonlarından birini inceleyeceğiz - Çift Tepe.

Bu, kabaca eşit yükseklerden oluşan bir formasyondur ve alıcıların zayıflığına ve fiyatların düşme olasılığına işaret eder. Aşağıdaki şekil, potansiyel bir Çift Tepe formasyonunun görsel bir temsilidir:

Çift Tepe potansiyeli

Potansiyel bir Çift Tepeye bakıyoruz. Aşağıdaki şekilde gösterildiği gibi, fiyat iki tepe noktası arasındaki düşük seviyesinin altına düşerse doğrulanmış olacaktır:

Çift Tepe

Şimdi MetaTrader 5'te bu iki formasyonu tespit etmek için kullanılabilecek bir MQL5 Uzman Danışmanı oluşturalım. Uzman Danışmanın iki yüksek ve iki düşük seviyeyi sürekli kontrol etmesine ve birbirlerine göre konumlarını belirlemesine ve ardından Çift Tepe formasyonunun belirli bir koşuluna dayalı olarak belirli bir sonuç geri döndürmesine ihtiyacımız var. Elbette, gerçek dünya koşullarında, formasyon nadiren mükemmel bir şekilde görünür. Eğer mevcut yüksek seviye bir önceki yüksek seviyenin altında ya da ona eşitse ve aynı zamanda mevcut düşük seviye bir önceki düşük seviyenin üzerindeyse, bu potansiyel bir Çift Tepe formasyonuna işaret eder. Eğer mevcut yüksek seviye bir önceki yüksek seviyenin altında ya da ona eşitse ve aynı zamanda mevcut düşük seviye bir önceki düşük seviyenin altındaysa, bu bir Çift Tepe sinyali olacaktır.

Bunu yapmak için gerekli kodun tamamı aşağıda verilmiştir:

//+------------------------------------------------------------------+
//|                                             DT patternFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(highVal1<=highVal2&&lowVal1>lowVal2)
     {
      Comment("Potential Double Top",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

   else
      if(highVal1<=highVal2&&lowVal1<lowVal2)
        {
         Comment("Double Top",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
         Comment(" ");
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Bu koddaki farklılıklar formasyonun koşullarıdır.

Potansiyel bir Çift Tepe durumunda, highVal1 highVal2'den daha düşük veya ona eşitse ve lowVal1 lowVal2'den daha yüksekse, grafikte aşağıdaki değerlerle yorum şeklinde bir sinyal almalıyız:

  • Potansiyel Çift Tepe
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   if(highVal1<=highVal2&&lowVal1>lowVal2)
     {
      Comment("Potential Double Top",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Oluşmuş bir Çift Tepe durumunda, highVal1 highVal2'den daha düşük veya ona eşitse ve lowVal1 lowVal2'den daha düşükse, grafikte aşağıdaki değerlerle yorum şeklinde bir sinyal almalıyız:

  • Çift Tepe
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   else
      if(highVal1<=highVal2&&lowVal1<lowVal2)
        {
         Comment("Double Top",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Formasyon olmaması durumunda, herhangi bir yorum çıktısı almamalıyız.

      else
         Comment(" ");

Derledikten sonra, Uzman Danışmanı grafik üzerinde çalıştıralım.

Potansiyel Çift Tepe durumunda:

DT patternFinder - Potansiyel Çift Tepe sinyali

Gördüğümüz gibi, sinyalin tetiklenme koşulları yerine gelmiştir: yüksekler aynıdır, yakın indeksli düşük diğerinden biraz daha yüksektir.

Çift Tepe durumunda:

DT patternFinder - Çift Tepe sinyali

Sinyalin tetiklenme koşulları yerine gelmiştir: daha düşük veya eşit bir yüksek ve daha düşük bir düşük.

Çift Dip tespiti

Çift Dip, Çift Tepenin tam tersidir. Kabaca eşit düşük seviyelerden oluşan bir formasyondur ve satıcıların zayıf olduğunu ve fiyatların yükselebileceğini gösterir. Aşağıdaki şekil potansiyel bir Çift Dip formasyonunun görsel bir örneğidir:

Çift Dip potansiyeli

Çift Dip, aşağıdaki şekilde gösterildiği gibi fiyat iki dip arasındaki yüksek seviyenin üzerinde kapandığında doğrulanır:

Çift Dip

Şimdi de MetaTrader 5'te bu iki formasyonu tespit etmek için kullanılabilecek bir MQL5 Uzman Danışmanı oluşturalım. Uzman Danışmanın sürekli olarak iki düşük ve iki yüksek seviyeyi kontrol etmesine ve birbirlerine göre konumlarını belirlemesine ve ardından Çift Dip formasyonunun belirli bir koşuluna dayalı olarak belirli bir sonuç geri döndürmesine ihtiyacımız var. Mevcut düşük seviye bir önceki düşük seviyenin üzerinde veya ona eşitse ve aynı zamanda mevcut yüksek seviye bir önceki yüksek seviyenin altındaysa, bu potansiyel bir Çift Dip sinyali olacaktır. Mevcut düşük seviye bir önceki düşük seviyenin üzerinde veya ona eşitse ve aynı zamanda mevcut yüksek seviye bir önceki yüksek seviyenin üzerindeyse, bu da bir Çift Dip sinyali olacaktır.

Bunu yapmak için gerekli kodun tamamı aşağıda verilmiştir:

//+------------------------------------------------------------------+
//|                                             DB patternFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(lowVal1>=lowVal2&&highVal1<highVal2)
     {
      Comment("Potential Double Bottom",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }
   else
      if(lowVal1>=lowVal2&&highVal1>highVal2)
        {
         Comment("Double Bottom",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
         Comment(" ");
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Bu koddaki farklılıklar formasyonun koşullarıdır.

Potansiyel bir Çift Dip durumunda, lowVal1 lowVal2'den daha yüksek veya eşitse ve highVal1 highVal2'den daha düşükse, grafikte aşağıdaki değerlerle yorum şeklinde bir sinyal almalıyız:

  • Potansiyel Çift Dip
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   if(lowVal1>=lowVal2&&highVal1<highVal2)
     {
      Comment("Potential Double Bottom",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Çift Dip oluşması durumunda, lowVal1 lowVal2'den daha yüksek veya eşitse ve highVal1 highVal2'den daha yüksekse, grafikte aşağıdaki değerlerle yorum şeklinde bir sinyal almalıyız:

  • Çift Dip
  • Mevcut yüksek
  • Önceki yüksek
  • Mevcut düşük
  • Önceki düşük
   else
      if(lowVal1>=lowVal2&&highVal1>highVal2)
        {
         Comment("Double Bottom",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Uzman Danışmanın kodunu derliyoruz, ardından terminaldeki Kılavuz penceresinde görünecektir. Devamında Uzman Danışmanı grafik üzerinde çalıştırıyoruz.

Potansiyel Çift Dip durumunda:

DB patternFinder - Potansiyel Çift Dip sinyali

Gördüğümüz gibi, sinyalin tetiklenme koşulları yerine gelmiştir: daha düşük bir yüksek ve eşit veya daha yüksek bir düşük.

Çift Dip durumunda:

DB patternFinder - Çift Dip sinyali

Sinyalin tetiklenme koşulları yerine gelmiştir: daha yüksek bir yüksek ve eşit veya daha yüksek bir düşük.

Sonuç

Fiyat hareketinin tam olarak anlaşılması, yatırımcıların daha iyi yatırım ve alım-satım kararları almasını sağlar. Fiyat hareketi, bilmemiz gereken birçok formasyon oluşturur. Bu makalede, MetaTrader 5 işlem terminalinde kullanılmak üzere MQL5 Uzman Danışmanları oluşturarak bu görevi basitleştirmeye çalıştık.

Yüksek ve düşük seviyeleri nasıl belirleyeceğimizi öğrendikten sonra, trendleri (yükseliş, düşüş ve yatay hareket) ve popüler grafik formasyonlarından biri olan Çift Tepe ve onun tersi Çift Dipi nasıl belirleyeceğimizi ve bunlara dayalı Uzman Danışmanların nasıl oluşturulacağını öğrendik. Makaledeki fikirler üzerine inşa edebilir ve baş ve omuzlar, üçgenler, dikdörtgenler gibi diğer grafik formasyonlarını tespit eden daha fazla sistem geliştirebilirsiniz. Umarım makaleyi faydalı bulursunuz ve alım-satım sistemleri geliştirmenize ve alım-satım hedeflerinize ulaşmanıza yardımcı olur.

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

Ekli dosyalar |
moveFinder.mq5 (2.24 KB)
trendFinder.mq5 (3.18 KB)
MQL5’i kullanarak bir özel gösterge (Heiken Ashi) nasıl oluşturulur? MQL5’i kullanarak bir özel gösterge (Heiken Ashi) nasıl oluşturulur?
Bu makalede, MetaTrader 5'te grafikleri yorumlamak için kullanılacak veya Uzman Danışmanların bir parçası olarak kullanılacak şekilde tercihlerimize göre MQL5’i kullanarak kendi göstergemizi nasıl oluşturacağımızı öğreneceğiz.
MacOS’ta MetaTrader 5 MacOS’ta MetaTrader 5
MacOS'ta MetaTrader 5 işlem platformu için özel bir yükleyici sağlıyoruz. Uygulamayı yerel olarak yüklemenizi sağlayan tam teşekküllü bir sihirbazdır. Yükleyici gerekli tüm adımları gerçekleştirir: sisteminizi tanımlar, en son Wine sürümünü indirir ve yükler, yapılandırır ve ardından MetaTrader'ı içine yükler. Tüm adımlar otomatik olarak tamamlanır ve kurulumdan hemen sonra platformu kullanmaya başlayabilirsiniz.
Popülasyon optimizasyon algoritmaları: Armoni arama (Harmony Search, HS) Popülasyon optimizasyon algoritmaları: Armoni arama (Harmony Search, HS)
Bu makalede, mükemmel ses uyumunu bulma sürecinden esinlenen en güçlü optimizasyon algoritması olan armoni aramayı (HS) inceleyecek ve test edeceğiz. Peki şu anda sıralamamızda lider olan algoritma hangisi?
MacOS’ta MetaTrader 4 MacOS’ta MetaTrader 4
MacOS'ta MetaTrader 4 işlem platformu için özel bir yükleyici sağlıyoruz. Uygulamayı yerel olarak yüklemenizi sağlayan tam teşekküllü bir sihirbazdır. Yükleyici gerekli tüm adımları gerçekleştirir: sisteminizi tanımlar, en son Wine sürümünü indirir ve yükler, yapılandırır ve ardından MetaTrader'ı içine yükler. Tüm adımlar otomatik olarak tamamlanır ve kurulumdan hemen sonra platformu kullanmaya başlayabilirsiniz.