English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Yeni Başlayanlar için MQL5’te Uzman Danışman Yazmak İçin Adım Adım Açıklamalı Kılavuz

Yeni Başlayanlar için MQL5’te Uzman Danışman Yazmak İçin Adım Adım Açıklamalı Kılavuz

MetaTrader 5Ticaret sistemleri | 9 Aralık 2021, 10:48
1 498 0
Samuel Olowoyo
Samuel Olowoyo

Giriş

Bu makale, yeni MQL5 dilinde basit Uzman Danışmanların nasıl yazılacağını öğrenmek isteyen yeni başlayanlara yöneliktir. Önce EA’mızın (Uzman Danışman) ne yapmasını istediğimizi tanımlayarak başlayacağız, sonra EA’nın bunu nasıl yapmasını istediğimize geçeceğiz.


1. Alım-Satım Stratejisi

EA’mız şunları yapacak:

  • Belirli bir koşul (veya koşullar) karşılandığında belirli bir göstergeyi izleyecek, karşılanan mevcut koşula göre bir alım satım işlemi (Kısa/Satış veya Uzun/Alış) yapacaktır.

Buna alım satım stratejisi denir. Bir EA yazmadan önce, ilk olarak EA’da otomatikleştirmek istediğiniz stratejiyi geliştirmelisiniz. Bu yüzden EA’da geliştirmek istediğimiz stratejiyi yansıtması için yukarıdaki ifadeyi değiştirelim.

  • 8 dönemli ve Hareketli Ortalama dediğimiz bir göstergeyi kullanacağız (İstediğiniz dönemi seçebilirsiniz ama bizim stratejimiz için 8’i kullanacağı)

  • Hareketli Ortalama-8 (tartışmamızın kolaylığı için buna MA-8 diyeceğim) yükseldiğinde ve fiyat bunun üstünde kapandığında EA’mızın Uzun (Alış) işlem yapmasını, MA-8 düştüğünde ve fiyat bunun altında kapandığında Kısa (Satış) işlem yapmasını istiyoruz.
  • Ayrıca piyasanın rağbet görüp görmediğini belirlememize yardımcı olması için dönem 8 ile Average Directional Movement (ADX) adlı başka bir göstergeyi de kullanacağız. Bunu yapıyoruz çünkü alım satıma yalnızca piyasa yükseldiğinde girmek ve piyasa dalgalandığında da (yükselmediğinde) sakin kalmak istiyoruz. Bunu başarmak için işlemimizi (Alış veya Satış) yalnızca yukarıdaki koşullar karşılandığında ve ADX değeri 22’den yüksek olduğunda yapacağız. ADX 22’den yüksekse ama düşüyorsa veya ADX 22’den düşükse B koşulu karşılansa bile alım satım yapmayacağız.
  • Ayrıca 30 pip’lik Zararı durdur (Stop loss) belirleyerek kendimizi koruyacağız ve Kâr hedefimiz için 100 pip kâra odaklanacağız.
  • Aynı zamanda EA’mızın yalnızca yeni bir çubuk oluşturulduğunda Alış/Satış fırsatlarına bakmasını istiyoruz ve Alış koşulları karşılandığında ve zaten açılmamışsa bir Alış pozisyonu açtığımızdan; Satış koşulları karşılandığında da ve zaten açılmamışsa bir Satış pozisyonu açtığımızdan emin olmak istiyoruz.

Artık stratejimizi geliştirdiğimize göre şimdi kodumuzu yazmaya başlayabiliriz.


2. Bir Uzman Danışmanın Yazılması

2.1 MQL5 Sihirbazı

MetaQuotes Language Editor 5’i açarak başlayalım. Ardından Ctrl+N tuşlarına basın veya Menü çubuğunda Yeni düğmesine tıklayın

Şekil 1. Yeni bir MQL5 belgesine başlamak

Şekil 1. Yeni bir MQL5 belgesine başlamak

MQL5 Sihirbazı penceresinde Uzman Danışmanı seçin ve Şekil 2’de gösterildiği gibi “Sonraki” üzerine tıklayın:

Şekil 2. Belge türünü seçmek

Şekil 2. Program türünü seçmek

Sonraki pencerede EA’nıza vermek istediğiniz Adı, Ad kutusuna yazın. Bu örnekte ben My_First_EA yazdım. Ardından kendi adınızı Yazar kutusuna ve web sitenizin adresini ya da e-posta adresinizi Bağlantı kutusuna (varsa) yazabilirsiniz.

Şekil 3. Uzman Danışmanın genel özellikleri

Şekil 3. Uzman Danışmanın genel özellikleri

Değerlerin hangilerinin bize en iyi sonucu verebileceğini görmek için EA’mızın bazı parametrelerini değiştirebiliyor olmak istediğimizden bunları “Ekle” düğmesine tıklayarak eklemeliyiz.

Şekil 4. EA giriş parametrelerini ayarlamak

Şekil 4. EA giriş parametrelerini ayarlamak

EA’mızda Zararı Durdur, Kâr Al, ADX Dönemi ve Hareketli Ortalama Dönemi ayarlarıyla deney yapabiliyor olmak istiyoruz bu yüzden bunları bu noktada tanımlayacağız.

Ad kısmının altına Çift Tıklayın ve parametrenin adını yazın, ardından parametrenin veri türünü seçmek için Tür altına çift tıklayın ve Başlangıç değeri altına çift tıklayarak parametrenin başlangıç değerini yazın.

Bitirdikten sonra şu şekilde görünmelidir:

Şekil 5. EA giriş parametrelerinin veri türleri

Şekil 5. EA giriş parametrelerinin veri türleri

Yukarıda gördüğünüz gibi tüm parametreler için tam sayı (int) veri türünü seçtim. Biraz veri türleri hakkında konuşalım.

  • char: char türü 1 baytlık bellek işgal eder (8 bit) ve ikili notasyon 2^8=256 değerlerinin ifade edilmesini sağlar. char türü negatif ve pozitif değerlerin her ikisini de barındırabilir. Değer aralığı -128'den 127'ye kadardır.
  • uchar : Uchar tam sayı türü, char türü gibi 1 baytlık bellek işgal eder ama onun tersine uchar yalnızca pozitif değerler içindir. En küçük değeri sıfırdır, en büyük değeri ise 255'tir. Uchar türünün adındaki ilk harf olan u unsigned (işaretsiz) kelimesinin kısaltmasıdır.
  • short: Short türünün boyutu 2 bayttır (16 bit) ve bu yüzden 2 ila 16 kuvvete eşit değerler aralığını ifade etmeyi mümkün kılar: 2^16 = 65 536. Short türü bir işaret türü olduğundan hem pozitif hem de negatif değerleri içerir, değerler aralığı -32 768 ve 32 767’dir.
  • ushort: İşaretsiz short türü, ushort türüdür ve yine 2 bayt boyutundadır. En küçük 0, en büyük değer ise 65 535'tir.
  • int : Int türünün boyutu 4 bayttır (32 bit). En küçük değer -2 147 483 648, en büyük değer ise 2 147 483 647’dir.
  • uint :  İşaretsiz tam sayı tipi uint'tir. 4 baytlık bellek işgal eder ve 0 ile 4 294 967 295 arası tam sayıların ifade edilmesini sağlar.
  • long : Long türünün boyutu 8 bayttır (64 bit). En küçük değer -9 223 372 036 854 775 808, en büyük değer ise 9 223 372 036 854 775 807'dir.
  • ulong : Ulong türü de 8 bayt kaplar ve 0 ile 18 446 744 073 709 551 615 arası değerleri saklayabilir.

Çeşitli veri türlerinin yukarıdaki açıklamasına göre, işaretsiz tam sayı türleri negatif değerleri saklamak için tasarlanmamıştır, negatif bir değer belirlemeyi denemek beklenmedik sonuçlara yol açabilir. Örneğin negatif değerleri saklamak istiyorsanız bunları işaretsiz türlerin içinde (yani uchar, uint, ushort, ulong) içinde saklayamazsınız.

EA’mıza geri dönelim. Veri türlerine bakarsak, char veya uchar veri türlerini kullanmamız gerektiği konusunda benimle aynı fikirdesinizdir, çünkü bu parametrelerde saklamak istediğimiz veri, sırasıyla 127 veya 255’ten düşüktür. İyi bir bellek yönetimi için yapılması gereken en doğru şey budur. Ancak tartışmamızın yararı açısından int türünü kullanacağız.

Gereken tüm parametreleri ayarladıktan sonra Bitti düğmesine tıklayın ve MetaQuotes Editor sonraki şekilde gösterildiği gibi sizin için kodun iskeletini oluşturacaktır.


Daha iyi anlamak için şimdi kodu çeşitli parçalara ayıralım.

Kodun üst kısmı (başlık), EA’nın özelliğinin tanımlandığı bölümdür. Şekil 3’te MQL5 Sihirbazında girdiğiniz değerlerin olduğunu görebilirsiniz. 

Kodun bu kısmında açıklama (EA’nın kısa metin açıklaması) gibi ek parametreleri tanımlayabilir, sabitleri bildirebilir, ek dosyaları veya içe aktarma fonksiyonlarını dahil edebilirsiniz. 


Bir ifade # sembolüyle başlıyorsa önişlemci direktifi olarak adlandırılır ve noktalı virgül “;” ile bitmez, diğer önişlemci örnekleri arasında şunlar yer alır:

#define : 

#define direktifi sabitlerin deklarasyonu için kullanılır. Şu formda yazılır:

#define tanımlayıcı token_string

Bu, kodunuzdaki tanımlayıcıyı her seferinde token_string değeriyle değiştirir.

Örnek:

#define ABC               100
#define COMPANY_NAME      "MetaQuotes Software Corp."

COMPANY_NAME geçtiğinde bunu "MetaQuotes Software Corp." dizgisi ile değiştirecektir veya ABC her geçtiğinde kodunuzda bunu char (veya tam sayı) 100 ile değiştirecektir.

Önişlemci direktifleri hakkında daha fazla bilgiyi MQL5 Kılavuzunda bulabilirsiniz. Şimdi tartışmamıza devam edelim.

Kodumuzun başlığının ikinci kısmı giriş parametreleri kısmıdır:

 

Bu bölümde EA’mızda kullanılacak tüm parametreleri belirtiyoruz. Bunlara, EA’mızda yazacağımız tüm fonksiyonlar tarafından kullanılacak tüm değişkenler dahildir.

Bu seviyede bildirilen değişkenlere Global Değişkenler denir çünkü EA’mızda bunlara ihtiyaç duyan her fonksiyon, bunlara erişebilir. Giriş parametreleri yalnızca EA’mızın dışında değiştirilebilecek parametrelerdir. Ayrıca bu bölümde EA’mızın gidişatı sırasında değiştirebileceğimiz ama EA’mızın dışında kullanılamayacak diğer değişkenleri de ifade edebiliriz.

Şimdi sıra EA’yı başlatma fonksiyonuna geldi. EA başlatıldığına ilk çağrılan veya bir grafiğe eklendiğinde ve sadece bir kez çağrılan fonksiyondur.


EA’mızın çok iyi çalıştığından emin olmak amacıyla bazı önemli kontrolleri yapmak için burası en uygun kısımdır.

Grafikte EA’mızın çalışmasına yetecek çubuk olup olmadığını bilmeye karar verebiliriz vs.

Ayrıca göstergelerimiz (ADX ve Hareketli Ortalama göstergeleri) için kullanacağımız tanıtıcı değerleri edinmek için en uygun yerdir.

 
EA grafikten kaldırıldığından dolayı OnDeinit fonksiyonu çağrılır.

EA’mız için bu bölümde başlatma sırasında Göstergelerimiz için oluşturulan tanıtıcı değerleri serbest bırakacağız.


Bu fonksiyon, bir sembol için yeni bir teklif alındığında oluşturulan Yeni Tik olayını işler.

Unutmayın ki istemci terminalinde Uzman Danışmanlarının kullanımına izin verilmediyse (“Otomatik Alım Satım” düğmesi) Uzman Danışman alım satım işlemleri yapamaz.

Şekil 6. Otomatik alım satım etkindir

Şekil 6. Otomatik alım satım etkindir

Daha önceden geliştirilmiş alım satım stratejimizi uygulayacak kodlarımızın çoğu bu bölümde yazılacaktır.

EA’mızın kodunun çeşitli kısımlarına baktığımıza göre iskelete biraz kas eklemeye başlayalım.

2.2 GİRİŞ PARAMETRELERİ BÖLÜMÜ

//--- input parameters
input int      StopLoss=30;      // Stop Loss
input int      TakeProfit=100;   // Take Profit
input int      ADX_Period=8;     // ADX Period
input int      MA_Period=8;      // Moving Average Period
input int      EA_Magic=12345;   // EA Magic Number
input double   Adx_Min=22.0;     // Minimum ADX Value
input double   Lot=0.1;          // Lots to Trade
//--- Other parameters
int adxHandle; // handle for our ADX indicator
int maHandle;  // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[]; // Dynamic array to hold the values of Moving Average for each bars
double p_close; // Variable to store the close value of a bar
int STP, TKP;   // To be used for Stop Loss & Take Profit values

Gördüğünüz gibi daha fazla parametre ekledik. Yeni parametreleri tartışmaya devam etmeden önce şimdi görebileceğiniz bir şeyi irdeleyelim. İki ileri bölü işareti “//” kodlarımıza yorumlar eklememizi sağlar. Yorumlar sayesinde değişkenlerimizin neyi temsil ettiğini veya kodumuzda o anda ne yaptığımızı bilebiliriz. Ayrıca kodumuzu daha iyi anlamamızı sağlar. Yorumları yazmanın iki temel yolu vardır:

// Diğer Parametreler …

Bu tek satırlık yorumdur

/*

Bu çok satırlı yorumdur

*/

Bu çok satırlı yorumdur. Çok satırlı yorumlar /* sembol çifti ile başlar ve */ sembol çifti ile biter.

Kodunuz derlenirken derleyici, tüm yorumları yok sayar.

Giriş parametreleri için tek satırlık yorumları kullanmak, EA kullanıcılarımızın bu parametrelerin neyi temsil ettiğini anlamasını sağlamanın güzel bir yoludur. EA Giriş özelliklerinde kullanıcılarımız parametrenin kendisini görmeyecek, bunun yerine aşağıda gösterildiği gibi yorumları görecektir:

Şekil 7. Uzman Danışman giriş parametreleri

Şekil 7. Uzman Danışman için giriş parametreleri

Şimdi kodumuza geri dönelim...

EA’mız için ilave parametreler eklemeye karar verdik. EA_Magic EA’mızın gerçekleştirdiği tüm emirler için sihirli sayıdır.  En küçük ADX değeri (Adx_Min) double veri türü olarak bildirilir. Kayan nokta sabitlerini saklamak için double veri kullanılır ve bunun içinde tam sayı kısmı, ondalık noktası ve kesirli kısım bulunur.

Örnek:

double mysum = 123.5678;

double b7 = 0.09876;

İşlem lotu (Lot) alım satım yapmak istediğimiz finansal enstrümanın hacmini temsil eder. Ardından kullanacağımız diğer parametreleri ifade ettik:

adxHandle ADX göstergesi tanıtıcı değerini saklamak için kullanılır, maHandle ise Hareketli Ortalama göstergesini saklamak içindir. plsDI[], minDI[], adxVal[], grafikteki her çubuk için +DI, -DI ve ana ADX (ADX Göstergesinin) değerlerini tutacak olan dinamik dizilerdir. maVal[] , grafikteki her çubuk için Hareketli Ortalama göstergesinin değerlerini tutacak olan dinamik bir dizidir.

Bu arada, dinamik diziler nedir? Dinamik dizi, boyut olmadan bildirilen bir dizidir. Diğer bir deyişle, köşeli parantez çiftinde belirtilen bir değer yoktur. Diğer yandan statik dizi ise ifade etme noktasında tanımlanan kendi boyutlarına sahiptir.

Örnek:

double allbars[20]; // bu, 20 eleman gerektirecektir

p_close , Alış/Satış işlemlerinin kontrolü amacıyla izleyeceğimiz çubuk için Kapanış fiyatı öğesini saklamak amacıyla kullanacağımız bir değişkendir.

STP ve TKP EA’mızdaki Zararı Durdur (Stop Loss) ve Kâr Al (Take Profit) değerlerini saklamak için kullanılacaktır.

2.3. EA’YI BAŞLATMA BÖLÜMÜ

int OnInit()
  {
//--- Get handle for ADX indicator
   adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
   maHandle=iMA(_Symbol,_Period,MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
   if(adxHandle<0 || maHandle<0)
     {
      Alert("Error Creating Handles for indicators - error: ",GetLastError(),"!!");
     }

Burada ilgili gösterge fonksiyonlarını kullanarak göstergemizin tanıtıcı değerlerini ediniriz.

ADX gösterge tanıtıcı değeri, iADX fonksiyonunu kullanarak elde edilir. İndisi parametreler veya argümanlar olarak hesaplamak için grafik sembolü (NULL aynı zamanda geçerli grafikteki geçerli sembol anlamına gelir), grafik dönemi/zaman aralığı (0 aynı zamanda geçerli grafikteki geçerli zaman aralığı anlamına gelir), ADX ortalama dönemi (daha önce giriş parametreleri kısmında açıklamıştık) gereklidir.  

int  iADX(
   string           symbol,         // sembol adı
   ENUM_TIMEFRAMES  period,         // dönem
   int              adx_period      // ortalama dönemi
   );

Hareketli Ortalama gösterge tanıtıcı değeri iMA fonksiyonu kullanılarak elde edilir. Aşağıdaki argümanlara sahiptir:

  • Grafik sembolü (geçerli grafikte geçerli sembol için _symbol, symbol() veya NULL kullanılarak elde edilebilir),
  • Grafik dönemi/zaman aralığı (geçerli grafikte geçerli zaman aralığı için _period, period() veya 0 kullanılarak elde edilebilir),
  • Hareketli Ortalama ortalama dönemi (daha önce giriş parametreleri kısmında açıklamıştık),
  • Göstergenin kaydırması fiyat grafiğine göredir (burada kaydırma 0’dır),
  • Hareketli ortalama düzleştirme türü (aşağıdaki ortalama yöntemlerinden herhangi biri olabilir: Basit Ortalama-MODE_SMA, Üssel Ortalama-MODE_EMA, Düzleştirilmiş Ortalama-MODE_SMMA veya Doğrusal Ağırlıklı Ortalama-MODE_LWMA) ve
  • Ortalama için kullanılan fiyat (burada kapanış fiyatını kullanıyoruz).

int  iMA(
   string               symbol,            // sembol adı
   ENUM_TIMEFRAMES      period,            // dönem
   int                  ma_period,         // ortalama dönemi
   int                  ma_shift,          // yatay kaydırma
   ENUM_MA_METHOD       ma_method,         // düzleştirme türü
   ENUM_APPLIED_PRICE   applied_price      // fiyatın veya tanıtıcı değerin türü
   );

Bu gösterge fonksiyonları hakkında daha fazla bilgi almak için lütfen MQL5 kılavuzunu okuyun. Bu her göstergenin nasıl kullanılacağını daha iyi anlamanızı sağlar.

Fonksiyonun işleyiciyi vermeme ihtimaline karşı yine hata olup olmadığını kontrol etmeye çalışacağız, aksi takdirde INVALID_HANDLE hatası oluşacaktır. Hatayı görüntülemek için GetlastError fonksiyonu aracılığıyla uyarı fonksiyonunu kullanıyoruz.

//--- Let us handle currency pairs with 5 or 3 digit prices instead of 4
   STP = StopLoss;
   TKP = TakeProfit;
   if(_Digits==5 || _Digits==3)
     {
      STP = STP*10;
      TKP = TKP*10;
     }

Zararı Durdur (Stop Loss) ve Kâr Al (Take Profit) değişkenlerini daha önce bildirmiş olduğumuz STP ve TKP değişkenlerinde saklamaya karar verdik. Bunu neden yapıyoruz?

Çünkü GİRİŞ parametrelerinde saklanan değerler salt okunur ve değiştirilemez. Bu yüzden EA’mızın tüm aracılarla iyi çalıştığından emin olmak istiyoruz. Digits veya Digits() bize mevcut grafik sembolünün fiyat doğruluğunu belirleyen ondalık basamak sayısını verir. 5 basamaklı veya 3 basamaklı fiyat grafiğinde hem Zararı Durdur (Stop Loss) hem de Kâr Al (Take Profit) öğesini 10 ile çarpıyoruz.

2.4. EA’NIN SONLANDIRILMASI BÖLÜMÜ

 

EA devre dışı kaldığında ve bir grafikten kaldırıldığında bu fonksiyon çağrıldığı için başlatma sürecinde oluşturduğumuz tüm gösterge tanıtıcı değerlerini burada geri çağıracağız. Biri ADX göstergesi ve diğeri Hareketli Ortalama göstergesi olmak üzere iki tanıtıcı değer oluşturduk.

Bunu yapmak için IndicatorRelease() fonksiyonunu kullanacağız. Bir argüman gereklidir (gösterge tanıtıcı değeri)

bool  IndicatorRelease(
   int       indicator_handle,     // gösterge tanıtıcı değeri
   );

Fonksiyon bir gösterge tanıtıcı değerini kaldırır ve kullanılmıyorsa hesaplama bloğunu serbest bırakır.

2.5 EA ONTICK BÖLÜMÜ

Burada ilk yapmamız gereken, mevcut grafikte yeterince çubuğumuz olup olmadığını kontrol etmektir. Herhangi bir grafiğin geçmişindeki toplam çubuk sayısını Çubuklar fonksiyonunu kullanarak öğrenebiliriz. İki parametre gereklidir; bunlar symbol (bunu _Symbol veya Symbol() kullanarak elde edebiliriz. Bu ikisi EA’mızın eklenmiş olduğu geçerli grafikteki geçerli sembolü verir) ve geçerli grafiğin dönem veya zaman dilimi öğeleridir (Period veya Period() kullanarak elde edilebilir. Bunlar EA’nın eklenmiş olduğu geçerli grafiğin zaman dilimini verecektir).

Mevcut çubukların toplam sayısı 60’tan az ise EA’mızın, grafikte yeterli sayıda çubuğa sahip olana kadar rahatlamasını isteriz.  Uyarı fonksiyonu, ayrı bir pencerede bir mesaj gösterir. Parametreler/argümanlar olarak virgülle ayrılmış herhangi bir değer yeterlidir. Bu durumda yalnızca tek dizgi değerimiz olur. Döndürme, EA’mızın başlatmasından çıkar.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// Do we have enough bars to work with
   if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }
// We will use the static Old_Time variable to serve the bar time.
// At each OnTick execution we will check the current bar time with the saved one.
// If the bar time isn't equal to the saved time, it indicates that we have a new tick.
   static datetime Old_Time;
   datetime New_Time[1];
   bool IsNewBar=false;

// copying the last bar time to the element New_Time[0]
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // ok, the data has been copied successfully
     {
      if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar time
        {
         IsNewBar=true;   // if it isn't a first call, the new bar has appeared
         if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);
         Old_Time=New_Time[0];            // saving bar time
        }
     }
   else
     {
      Alert("Error in copying historical times data, error =",GetLastError());
      ResetLastError();
      return;
     }

//--- EA should only check for new trade if we have a new bar
   if(IsNewBar==false)
     {
      return;
     }
 
//--- Do we have enough bars to work with
   int Mybars=Bars(_Symbol,_Period);
   if(Mybars<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }

//--- Define some MQL5 Structures we will use for our trade
   MqlTick latest_price;     // To be used for getting recent/latest price quotes
   MqlTradeRequest mrequest;  // To be used for sending our trade requests
   MqlTradeResult mresult;    // To be used to get our trade results
   MqlRates mrate[];         // To be used to store the prices, volumes and spread of each bar
   ZeroMemory(mrequest);     // Initialization of mrequest structure

Uzman Danışman alım satım işlemlerini yeni bir çubuğun başlangıcında yapacaktır, bu yüzden sorunu yeni çubuk tanımlamasıyla çözmek gereklidir. Diğer bir deyişle EA’mızın her tikte Uzun/Kısa ayarlarını kontrol etmediğinden ve EA’mızın yalnızca yeni bir çubuk olduğunda Uzun/Kısa pozisyonları kontrol ettiğinden emin olmak istiyoruz. 

Çubuk zamanını saklayacak olan statik bir tarih saat değişkeni olan Old_Time öğesini bildirerek başlayacağız. Bunu statik olarak bildiriyoruz çünkü değerin, OnTick fonksiyonunun bir sonraki çağrılmasında bellekte tutulmasını istiyoruz. Ardından bunun değerini yeni (geçerli) çubuk zamanını tutacak elemanın bir dizisi olan New_Time değişkeni (ayrıca tarih/saat veri türünün değişkeni) ile karşılaştırabileceğiz. Ayrıca IsNewBar bool veri türü değişkenini bildirdik ve değerini false olarak ayarladık. Bunun sebebi, bu değerin yalnızca yeni bir çubuğumuz olduğunda TRUE olmasını istememizdir.

Geçerli çubuğun zamanını elde etmek için CopyTime fonksiyonunu kullanırız. Çubuk zamanını New_Time dizisine tek elemanla kopyalarız ve başarılı olursa yeni çubuğun zamanını önceki çubuk zamanı ile karşılaştırırız. Zamanlar eşit değilse bu, yeni bir çubuğumuz olduğu anlamına gelir ve IsNewBar TRUE olarak ayarlanır ve geçerli çubuk zamanının değerini Old_Time değişkenine kaydederiz.

IsNewBar değişkeni, yeni bir çubuğumuz olduğunu belirtir. FALSE ise OnTick fonksiyonunun yürütülmesini bitiriyoruz.

Koda bakın

if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);

Hata ayıklama modunun yürütülmesini kontrol eder, hata ayıklama modunda çubuk zamanları hakkındaki mesajı yazdırır, buna daha çok eğileceğiz.

Burada yapmak istediğimiz bir sonraki şey çalışabilmemiz için yeterli çubuğumuz olup olmadığını kontrol etmektir. Bunu neden tekrarlıyoruz? Sadece EA’mızın doğru çalıştığından emin olmak istiyoruz. OnInit fonksiyonu yalnızca EA bir grafiğe eklendiğinde bir defa çağrılırken OnTick fonksiyonunun her yeni tikte (fiyat teklifi) çağrıldığı unutulmamalıdır.

Yine burada bunu daha farklı şekilde yaptığımızı görüyorsunuz. Toplam çubukları, OnTick fonksiyonuyla birlikte bildirilen

int Mybars=Bars(_Symbol,_Period);

yeni bir değişken olan Mybars değişkenindeki ifadeden elde ettiğimiz geçmişte saklamaya karar verdik. Bu yeni değişken türü, kodumuzun GİRİŞ PARAMETRELERİ bölümünde bildirdiğimiz değişkenin aksine yerel bir değişkendir. Kodumuzun Giriş Parametreleri bölümünde bildirilen değişkenlere, kodumuzdaki bunlara ihtiyaç duyabilecek tüm fonksiyonlar erişebilecektir, tek fonksiyonda bildirilen  değişkenler kısıtlıdır ve sadece o fonksiyon tarafından kullanılabilir. Bu fonksiyonun dışında kullanılamaz.

Sonra, EA’mızın bu bölümünde kullanılacak olan MQL5 yapı türlerinin birkaç değişkenini bildirdik. MQL5’te, EA geliştiricileri için bir çok şeyi kolaylaştıran çok sayıda yerleşik Yapı mevcuttur. Yapıları birbiri ardına ele alalım.

MqlTick

Bu, sembollerin en son fiyatlarını saklamak için kullanılan bir yapıdır.

struct MqlTick
  {
   datetime     time;          // Son fiyat güncellemesinin zamanı
   double       bid;           // Mevcut Alış fiyatı
   double       ask;           // Mevcut Satış fiyatı
   double       last;          // Son sözleşme fiyatı (Last)
   ulong        volume;        // Mevcut Son fiyatın hacmi
  };

MqlTick türü olarak bildirilen her değişken, Satış, Alış, Son ve Hacim öğelerinin geçerli değerlerini elde etmek için (SymbolInfoTick() fonksiyonunu çağırdığınızda) kolayca kullanılabilir.

Bu yüzden latest_price öğesini MqlTick türü olarak bildirdik, böylece Satış ve Alış fiyatlarını almak için bunu kullanabiliriz

MqlTradeRequest

Bu yapı, bir alım satım işleminin tüm alım satım taleplerini gerçekleştirmek için kullanılır. Bu yapıda bir alım satım sözleşmesi yapmak için gereken tüm alanları içerir.

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;       // Alım-satım işlemi türü
   ulong                         magic;        // Uzman Danışman Kimliği (sihirli sayı)
   ulong                         order;        // Emir fişi
   string                        symbol;       // Alım-satım sembolü
   double                        volume;       // Lot bazında bir sözleşme için istenen hacim
   double                        price;        // Fiyat
   double                        stoplimit;    // Emrin StopLimit seviyesi
   double                        sl;           // Emrin Zararı Durdur (Stop Loss) seviyesi
   double                        tp;           // Emrin Kâr Al (Take Profit) seviyesi
   ulong                         deviation;    // İstenen fiyattan maksimum olası sapma
   ENUM_ORDER_TYPE               type;          // Emir türü
   ENUM_ORDER_TYPE_FILLING       type_filling;  // Emir gerçekleştirme türü
   ENUM_ORDER_TYPE_TIME          type_time;     // Emir gerçekleştirme zamanı
   datetime                      expiration;    // Emir zaman aşımı zamanı (ORDER_TIME_SPECIFIED türü emirler için)
   string                        comment;       // Emir yorumu
  };

MqlTradeRequest türü olarak bildirilen her değişken kolayca alım satım işlemlerimiz için emirler gönderebilir. Burada mrequest öğesini MqlTradeRequest türü olarak bildirdik.

MqlTradeResult

Herhangi bir alım satım işleminin sonucu MqlTradeResult türünün özel bir önceden tanımlı yapısı olarak geri döner. MqlTradeResult türü olarak bildirilen her değişken, alım satım talebi sonuçlarına erişebilir.

struct MqlTradeResult
  {
   uint     retcode;          // İşlem dönüş kodu
   ulong    deal;             // Sözleşme fişi, gerçekleşmişse
   ulong    order;            // Emir fişi, işleme konulmuşsa
   double   volume;           // Sözleşme hacmi, aracı tarafından onaylanmış
   double   price;            // Sözleşme fiyatı, aracı tarafından onaylanmış
   double   bid;              // Geçerli Alış fiyatı
   double   ask;              // Geçerli Satış fiyatı
   string   comment;          // Aracı işlem yorumu (varsayılan olarak bu, işlem açıklaması ile doldurulur)
  };

Burada mresult öğesini MqlTradeResult türü olarak bildirdik.

MqlRates

Her çubuğun Fiyatı (Açılış, Kapanış, Yüksek, Düşük), Zamanı ve Hacimleri ve bir sembolün spread’i (alım-satım farkı) bu yapıda saklanır.   MqlRates türü olarak bildirilen her dizi, bir sembolün fiyat, hacim ve spread (alım-satım farkı) geçmişini saklamak için kullanılabilir.

struct MqlRates
  {
   datetime time;         // Dönem başlangıç zamanı
   double   open;         // Açılış fiyatı
   double   high;         // Dönemin en yüksek fiyatı
   double   low;          // Dönemin en düşük fiyatı
   double   close;        // Kapanış fiyatı
   long     tick_volume;  // Tik hacmi
   int      spread;       // Spread (alım-satım farkı)
   long     real_volume;  // Alım-satım hacmi
  };

Burada bu bilgileri saklamak için kullanılacak olan mrate[]  dizisini bildirdik.

/*
     Let's make sure our arrays values for the Rates, ADX Values and MA values 
     is store serially similar to the timeseries array
*/
// the rates arrays
   ArraySetAsSeries(mrate,true);
// the ADX DI+values array
   ArraySetAsSeries(plsDI,true);
// the ADX DI-values array
   ArraySetAsSeries(minDI,true);
// the ADX values arrays
   ArraySetAsSeries(adxVal,true);
// the MA-8 values arrays
   ArraySetAsSeries(maVal,true);

Ardından Çubuk ayrıntılarını seriler olarak saklamak için kullanacağımız tüm dizileri ayarlayacağız. Bu, dizilere kopyalanacak olan değerlerin, zaman serileri olarak yani 0, 1, 2, 3 gibi indisleneceğinden (çubuklar indisine karşılık düşmesi için) emin olmak içindir. Bu yüzden ArraySetAsSeries() fonksiyonunu kullanırız.

bool  ArraySetAsSeries(
   
void  array[],     // referans dizi
   bool  set          // true değeri indisleme sırasının tersine çevrildiğini ifade eder
   );

Bunun ayrıca kodumuzun başlatma bölümünde de yapılabileceğini unutmayın. Ancak bu noktada açıklamamıza faydası dokunması için bunu göstermeye karar verdim.

//--- Get the last price quote using the MQL5 MqlTick Structure
   if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

Şimdi en son fiyat teklifini elde etmek için SymbolInfoTick fonksiyonunu kullanıyoruz. Bu fonksiyonda iki argüman vardır - grafik symbol ve MqlTick yapısı değişkeni (latest_price). Yine, bir hata varsa bunu bildirdik.

//--- Get the details of the latest 3 bars
   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }

Ardından son üç çubuk hakkındaki bilgileri Mqlrates türü dizimize CopyRates fonksiyonunu kullanarak kopyaladık. CopyRates fonksiyonu, belirtilen sembol ve dönemin MqlRates yapısının geçmiş verisini MqlRates türü diziye belirtilen miktarda kopyalar.

int  CopyRates(
   string           symbol_name,       // sembol adı
   ENUM_TIMEFRAMES  timeframe,         // dönem
   int              start_pos,         // başlangıç pozisyonu
   int              count,             // kopyalanacak veri sayısı
   MqlRates         rates_array[]      // kopyalanacak hedef dizi
   );

Sembol adı “_symbol” kullanılarak, geçerli dönem/zaman dilimi de “_period” kullanılarak elde edilir. Başlangıç pozisyonu için mevcut çubuk olan Çubuk 0’dan başlayacağız ve yalnızca üç Çubuğu sayacağız, Çubuk 0, 1 ve 2. Sonuç, mrate[] dizimizde saklanacaktır.

mrate[] dizisi şimdi çubuk 0, 1 ve 2 için tüm fiyat, zaman, hacim ve spread (alım-satım farkı) bilgilerini içerir.  Böylece her çubuğun ayrıntılarını öğrenmek için aşağıdakileri kullanacağız:

mrate[bar_number].bar_property

örneğin, her çubuk için aşağıdaki bilgilere sahip olabiliriz:

mrate[1].time   // Çubuk 1 Başlangıç zamanı
mrate[1].open   // Çubuk 1 Açılış fiyatı
mrate[0].high   // Çubuk 0 (geçerli çubuk) yüksek fiyat vs.

Ardından bildirdiğimiz tüm gösterge değerlerini, CopyBuffer fonksiyonunu kullanarak dinamik dizilere kopyaladık.

int  CopyBuffer(
   int       indicator_handle,     // gösterge tanıtıcı değeri
   int       buffer_num,           // gösterge tamponunun numarası
   int       start_pos,            // başlangıç pozisyonu
   int       count,                // kopyalanacak miktar
   double    buffer[]              // kopyalanacak hedef dizi
   );

Gösterge tanıtıcı değeri, OnInit bölümünde oluşturduğumuz tanıtıcı değerdir. Tampon numaraları konusunda ADX göstergesinin üç (3) tamponu vardır:

  • 0 - MAIN_LINE,
  • 1 - PLUSDI_LINE,
  • 2 - MINUSDI_LINE.

Hareketli Ortalama göstergesinde sadece bir (1) tampon bulunur:

  • 0 – MAIN_LINE.

Mevcut çubuktan (0) önceki iki çubuğa kopyalıyoruz. Böylece kopyalanacak kayıt miktarı 3 olur (çubuk 0, 1 ve 2). buffer[], daha önce bildirdiğimiz hedef dinamik dizilerdir – adxVal, plsDI, minDI ve maVal.

Burada yine gördüğünüz gibi kopyalama sürecinde olabilecek hataları yakalamaya çalışıyoruz. Hata varsa ilerlemeye gerek yoktur.

CopyBuffer() ve CopyRates() fonksiyonunun, başarıyla kopyalanan kayıtları verdiğini ve hata olduğunda -1 değerini verdiğini unutmamak önemlidir. Bu yüzden burada hata kontrolü fonksiyonlarında 0’dan (sıfır) küçük bir değeri kontrol ediyoruz.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(adxHandle,0,0,3,adxVal)<0 || CopyBuffer(adxHandle,1,0,3,plsDI)<0
      || CopyBuffer(adxHandle,2,0,3,minDI)<0)
     {
      Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(maHandle,0,0,3,maVal)<0)
     {
      Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
      return;
     }

Bu noktada zaten açık bir Alış veya Satış pozisyonumuzun olup olmadığını kontrol etmek, diğer bir deyişle tek seferde sadece BİR Satış veya Alış işlemi olduğundan emin olmak istiyoruz. Zaten varsa yeni bir Alış pozisyonu açmak istemiyoruz ve zaten varsa yeni bir Satış pozisyonu açmak istemiyoruz.

Bunun için önce açılmış bir Alış veya Satış pozisyonu varsa TRUE değerine sahip olan iki bool veri türü değişkenini bildireceğiz (Buy_opened ve Sell_opened).

//--- we have no errors, so continue
//--- Do we have positions opened already?
    bool Buy_opened=false;  // variable to hold the result of Buy opened position
    bool Sell_opened=false; // variable to hold the result of Sell opened position
    
    if (PositionSelect(_Symbol) ==true)  // we have an opened position
    {
         if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
         {
            Buy_opened = true;  //It is a Buy
         }
         else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
         {
            Sell_opened = true; // It is a Sell
         }
    }

Açık bir pozisyonumuz olup olmadığını görmek için PositionSelect alım satım fonksiyonunu kullanırız. Zaten açılmış bir pozisyon varsa bu fonksiyon TRUE değerini ve yoksa FALSE değerini verir.

bool  PositionSelect(
   string  symbol      // Symbol name 
 );

Ana argüman/parametre olarak kontrol etmek istediğimiz sembol (para birimi çifti) gereklidir. Burada _symbol öğesini kullanırız çünkü geçerli sembolü (para birimi çifti) kontrol ediyoruz.

Bu ifade TRUE değerini verirse açılan pozisyonun Alış mı Satış mı olduğunu kontrol ederiz. Bunun için PositionGetInteger fonksiyonunu kullanırız. Bunu POSITION_TYPE değiştiricisi ile kullandığımızda bize açılan pozisyon türünü verir. POSITION_TYPE_BUY veya POSITION_TYPE_SELL olabilecek Pozisyon türü tanımlayıcısını verir.

long  PositionGetInteger(
   ENUM_POSITION_PROPERTY  property_id      // Property identifier
   );

Bizim örneğimizde bunu hangi pozisyonun zaten açılmış olduğunu belirlemek için kullandık. Bu bir Satışsa Sell_opened içinde TRUE değerini saklarız ve bu bir Alışsa Buy_opened içinde TRUE değerini saklarız. Daha sonra kodumuzda Satış veya Alış koşullarımızı kontrol ederken bu iki değişkeni kullanabileceğiz.

Şimdi Alış/Satış ayarımız için kullanacağımız çubuğun kapanış fiyatını saklama işlemine sıra geldi. Bunun için daha önce bir değişken bildirdiğimizi unutmayın

// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1

   p_close=mrate[1].close;  // bar 1 close price

Bunu yaptığımıza göre sonraki adıma ilerliyoruz.

/*
    1. Check for a long/Buy Setup : MA-8 increasing upwards, 
    previous price close above it, ADX > 22, +DI > -DI
*/
//--- Declare bool type variables to hold our Buy Conditions
   bool Buy_Condition_1 = (maVal[0]>maVal[1]) && (maVal[1]>maVal[2]); // MA-8 Increasing upwards
   bool Buy_Condition_2 = (p_close > maVal[1]);         // previuos price closed above MA-8
   bool Buy_Condition_3 = (adxVal[0]>Adx_Min);          // Current ADX value greater than minimum value (22)
   bool Buy_Condition_4 = (plsDI[0]>minDI[0]);          // +DI greater than -DI

//--- Putting all together   
   if(Buy_Condition_1 && Buy_Condition_2)
     {
      if(Buy_Condition_3 && Buy_Condition_4)
        {
         // any opened Buy position?
         if (Buy_opened) 
         {
            Alert("We already have a Buy Position!!!"); 
            return;    // Don't open a new Buy Position
         }
         mrequest.action = TRADE_ACTION_DEAL;                                // immediate order execution
         mrequest.price = NormalizeDouble(latest_price.ask,_Digits);          // latest ask price
         mrequest.sl = NormalizeDouble(latest_price.ask - STP*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.ask + TKP*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                         // currency pair
         mrequest.volume = Lot;                                            // number of lots to trade
         mrequest.magic = EA_Magic;                                        // Order Magic Number
         mrequest.type = ORDER_TYPE_BUY;                                     // Buy Order
         mrequest.type_filling = ORDER_FILLING_FOK;                          // Order execution type
         mrequest.deviation=100;                                            // Deviation from current price
         //--- send order
         OrderSend(mrequest,mresult);

Şimdi bir Alış imkanını kontrol etmeye başlamanın sırası geldi.

Daha önce tasarladığımız stratejiyi temsil ettiği için yukarıdaki ifadeyi analiz edelim. Bir emir verilmeden önce karşılanması gereken her koşulumuz için bir bool türü değişken bildiriyoruz. Bool türü bir değişken yalnızca TRUE veya FALSE içerebilir. Bu yüzden Alış stratejimiz dört koşula ayrılır.  Koşullardan herhangi biri karşılanır veya gerçekleşirse bool türü değişkenimizde TRUE değeri saklanır, aksi takdirde FALSE değeri saklanacaktır. Bunlara tek tek bakalım.

bool Buy_Condition_1 = (maVal[0]>maVal[1]) && (maVal[1]>maVal[2]);

Burada MA-8 değerlerine (Çubuk 0, 1 ve 2 üzerindeki) bakıyoruz. Geçerli çubuktaki MA-8 değeri önceki Çubuk 1 üzerindeki değerinden büyükse ve ayrıca Çubuk 1 üzerindeki MA-8 değeri Çubuk 2 üzerindeki değerinden büyükse MA-8 yükselerek artıyor demektir. Bu, Alış ayarımızın koşullarından birini karşılar.

bool Buy_Condition_2 = (p_close > maVal[1]); 

Bu ifade, Çubuk 1 Kapanış fiyatının aynı dönemdeki (Çubuk 1 dönemi) MA-8 değerinden yüksek olup olmadığını kontrol eder. Fiyat daha yüksekse ikinci koşulumuz da karşılanmıştır, ardından diğer koşulları kontrol edebiliriz. Ancak belirttiğimiz iki koşul karşılanmazsa diğer koşulları kontrol etmeye ihtiyaç olmayacaktır. Bu yüzden bu iki başlangıç koşulundaki sonraki ifadeleri dahil etmeye karar verdik (ifadeler).

bool Buy_Condition_3 = (adxVal[0]>Adx_Min);

Şimdi geçerli ADX değerinin (Çubuk 0’daki ADX değeri) giriş parametrelerinde bildirilen En Düşük ADX değerinden büyük olup olmadığını kontrol etmek istiyoruz. İfade doğru ise yani mevcut ADX değeri gereken En Düşük değerden büyükse ayrıca plusDI değerinin de minusDI değerinden büyük olduğundan emin olmak isteriz. Sonraki ifadede elde ettiğimiz budur

bool Buy_Condition_4 = (plsDI[0]>minDI[0]);

Tüm bu koşullar karşılandığında, yani true sonucunu verdiğinde zaten bir Alış pozisyonu varsa yeni bir Alış pozisyonu açmadığımızdan emin olmak isteriz. Şimdi kodumuzda daha önce bildirdiğimiz Buy_opened değişkeninin değerini kontrol etme zamanı geldi.

// any opened Buy position?
if (Buy_opened) 
   {
      Alert("We already have a Buy Position!!!"); 
      return;    // Don't open a new Buy Position
   }

Buy_opened, true ise başka bir Alış pozisyonu açmak istemeyiz, bu yüzden bizi bilgilendirecek ve ardından geri dönecek bir uyarı görüntüleriz ve böylece EA’mız şimdi sonraki Tiki bekler. Ancak Buy_opened FALSE ise o zaman kayıtlarımızı, emrimizi göndermek için daha önce bildirdiğimiz MqlTradeRequest türü değişkenini (mrequest) kullanarak hazırlarız.

  • Buradaki alım satım işlemi türündeki eylem TRADE_ACTION_DEAL’dir çünkü hemen gerçekleştirilmek üzere bir alım satım emri veriyoruz. Bir emri değiştiriyorsak TRADE_ACTION_MODIFY öğesini kullanırız. Bir emri silmek için TRADE_ACTION_REMOVE öğesini kullanırız.  MqlTick türü latest_price öğemizi kullanarak en son Satış fiyatını aldık.  Zararı durdur (Stop loss) emrinin fiyatı, puan bazında StopLoss değerini Satış fiyatından çıkararak, kâr al (take profit) emrinin fiyatı da puan bazında TakeProfit değerini Satış fiyatına ekleyerek elde edilir. Ayrıca Satış fiyatı, StopLoss ve TakeProfit değerleri için NormalizeDouble fonksiyonunu kullandığımızı fark edeceksiniz, bu fiyatları alım satım sunucusuna göndermeden önce para birimi çiftini basamak sayısına göre normalleştirmek iyi bir uygulamadır. 
  • Sembol, geçerli semboldür (_Symbol veya Symbol()). Emir türü verdiğimiz emir türüdür, burada ORDER_TYPE_BUY satış emri verdik. Satış emri için bu, ORDER_TYPE_SELL olacaktır.
  • type_filling emri, emir gerçekleştirme türüdür; ORDER_FILLING_FOK, sözleşmenin emirde belirtilen fiyata eşit veya bundan yüksek bir fiyattan ve belirtilen hacimle özel olarak gerçekleştirilebileceği anlamına gelir. Emir sembolünde yeterli emir hacmi yoksa emir gerçekleştirilmez.

OrderSend() fonksiyonu için iki argüman gerekir, MqlTradeRequest türü değişken ve MqlTradeResult türü değişken.

bool  OrderSend(
   MqlTradeRequest&  request      // query structure
   MqlTradeResult&   result       // structure of the answer
   );

Burada yine gördüğünüz gibi MqlTradeRequest türü değişkenimizi ve MqlTradeResult türü değişkenimizi kullanarak OrderSend öğesinden faydalandık.

         // get the result code
         if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
           {
            Alert("A Buy order has been successfully placed with Ticket#:",mresult.order,"!!");
           }
         else
           {
            Alert("The Buy order request could not be completed -error:",GetLastError());
            ResetLastError();           
            return;
           }

Emrimizi gönderdikten sonra şimdi emrimizin sonucunu kontrol etmek için MqlTradeResult türü değişkeni kullanacağız. Emrimizin başarıyla gerçekleştirilip gerçekleştirilmediğini bilmek isteriz. Emir verilirse MqlTradeResult türü değişken “mresult” ile İşlem dönüş koduna ve ayrıca emir fişi numarasına erişebilirsiniz.

10009 dönüş kodu OrderSend talebinin başarıyla tamamlandığını gösterirken 10008 ise emrimizin verildiğini gösterir. Bu yüzden bu iki dönüş kodunu kontrol ettik. Bunlardan herhangi biri varsa emrimizin tamamlandığından veya verildiğinden emin oluruz.

Satış Fırsatını kontrol etmek için ADX’imizin belirtilen En düşük değerden büyük olması şartı haricinde Alış Fırsatı için yaptıklarımızın tam tersini kontrol ederiz.

/*
    2. Check for a Short/Sell Setup : MA-8 decreasing downwards, 
    previous price close below it, ADX > 22, -DI > +DI
*/
//--- Declare bool type variables to hold our Sell Conditions
   bool Sell_Condition_1 = (maVal[0]<maVal[1]) && (maVal[1]<maVal[2]);  // MA-8 decreasing downwards
   bool Sell_Condition_2 = (p_close <maVal[1]);                         // Previous price closed below MA-8
   bool Sell_Condition_3 = (adxVal[0]>Adx_Min);                         // Current ADX value greater than minimum (22)
   bool Sell_Condition_4 = (plsDI[0]<minDI[0]);                         // -DI greater than +DI
   
 //--- Putting all together
   if(Sell_Condition_1 && Sell_Condition_2)
       {
         if(Sell_Condition_3 && Sell_Condition_4)
           {
            // any opened Sell position?
            if (Sell_opened) 
            {
                Alert("We already have a Sell position!!!"); 
                return;    // Don't open a new Sell Position
            }
            mrequest.action = TRADE_ACTION_DEAL;                                 // immediate order execution
            mrequest.price = NormalizeDouble(latest_price.bid,_Digits);          // latest Bid price
            mrequest.sl = NormalizeDouble(latest_price.bid + STP*_Point,_Digits); // Stop Loss
            mrequest.tp = NormalizeDouble(latest_price.bid - TKP*_Point,_Digits); // Take Profit
            mrequest.symbol = _Symbol;                                         // currency pair
            mrequest.volume = Lot;                                            // number of lots to trade
            mrequest.magic = EA_Magic;                                        // Order Magic Number
            mrequest.type= ORDER_TYPE_SELL;                                     // Sell Order
            mrequest.type_filling = ORDER_FILLING_FOK;                          // Order execution type
            mrequest.deviation=100;                                           // Deviation from current price
            //--- send order
            OrderSend(mrequest,mresult);

Tıpkı alış bölümünde yaptığımız gibi bir emir verilmeden önce karşılanması gereken her koşulumuz için bir bool türü değişken bildiriyoruz. Bool türü bir değişken yalnızca TRUE veya FALSE içerebilir. Bu yüzden Satış stratejimiz dört koşula ayrılır.  Koşullardan herhangi biri karşılanır veya gerçekleşirse bool türü değişkenimizde TRUE değeri saklanır, aksi takdirde FALSE değeri saklanacaktır. Alış kısmında yaptığımız gibi bunlara tek tek bakalım

   bool Sell_Condition_1 = (maVal[0]<maVal[1]) && (maVal[1]<maVal[2]);

Burada MA-8 değerlerine (Çubuk 0, 1 ve 2 üzerindeki) bakıyoruz. Geçerli çubuktaki MA-8 değeri önceki Çubuk 1 üzerindeki değerinden küçükse ve ayrıca Çubuk 1 üzerindeki MA-8 değeri Çubuk 2 üzerindeki değerinden küçükse bu, MA-8 azalarak düşüyor anlamına gelir. Bu, Satış ayarımızın koşullarından birini karşılar.

   bool Sell_Condition_2 = (p_close <maVal[1]); 

Bu ifade, Çubuk 1 Kapanış fiyatının, aynı dönemde (Çubuk 1 dönemi) MA-8 değerinden düşük olup olmadığını kontrol eder. Fiyat düşükse ikinci koşulumuz da karşılanmış demektir ardından diğer koşulları kontrol edebiliriz. Ancak belirttiğimiz iki koşul karşılanmadıysa diğer koşulları kontrol etmemiz gerekmez. Bu yüzden bu iki başlangıç koşulundaki sonraki ifadeleri dahil etmeye karar verdik (ifadeler).

   bool Sell_Condition_3 = (adxVal[0]>Adx_Min); 

Şimdi geçerli ADX değerinin (Çubuk 0’daki ADX değeri) giriş parametrelerinde bildirilen En Düşük ADX değerinden büyük olup olmadığını kontrol etmek istiyoruz. İfade doğru ise yani mevcut ADX değeri gereken En Düşük değerden büyükse ayrıca MinusDI değerinin de plusDI değerinden büyük olduğundan emin olmak isteriz. Sonraki ifadede elde ettiğimiz budur

bool Sell_Condition_4 = (plsDI[0]<minDI[0]);

Bu koşullar karşılandığında, yani true sonucunu verdiğinde zaten bir Alış pozisyonu varsa yeni bir Alış pozisyonu açmadığımızdan emin olmak isteriz. Şimdi kodumuzda daha önce bildirdiğimiz Buy_opened değişkeninin değerini kontrol etme zamanı geldi.

// any opened Sell position?
            if (Sell_opened) 
            {
                Alert("We already have a Sell position!!!"); 
                return;    // Don't open a new Sell Position
            }

Sell_opened, true ise başka bir Satış pozisyonu açmak istemeyiz, bu yüzden bizi bilgilendirecek ve ardından geri dönecek bir uyarı görüntüleriz ve böylece EA’mız şimdi sonraki Tiki bekler. Ancak Sell_opened FALSE olursa Satış işlemi talebimizi Alış emrinde olduğumuz gibi ayarlarız.

Buradaki büyük fark, zararı durdurma fiyatımızı ve kâr alma fiyatımızı hesaplama şeklimizdir. Ayrıca satış yaptığımız için Alış fiyatından satıyoruz, bu yüzden MqlTick türü latest_price değişkenimizi kullanarak en son alış fiyatını elde ediyoruz. Daha önce açıkladığımız gibi buradaki diğer tür ORDER_TYPE_SELL’dir.

Ayrıca burada Alış fiyatı, StopLoss ve TakeProfit değerleri için NormalizeDoublefonksiyonunu kullandığımızı fark edeceksiniz, bu fiyatları alım satım sunucusuna göndermeden önce para birimi çiftinin basamak sayısına göre normalleştirmek iyi bir uygulamadır. 

Tıpkı Alış emrimizde yaptığımız gibi, ayrıca Satış emrimizin de başarılı olup olmadığını kontrol etmeliyiz. Bu yüzden Alış emrimizdeki aynı ifadeyi kullandık.

         if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
           {
            Alert("A Sell order has been successfully placed with Ticket#:",mresult.order,"!!");
           }
         else
           {
            Alert("The Sell order request could not be completed -error:",GetLastError());
            ResetLastError();
            return;
           }
        }


3. Hata Ayıklama ve Uzman Danışmanımızı Test Etme

Bu noktada, stratejimizin işe yarayıp yaramadığını test etmemiz gerekir. Ayrıca EA kodumuzda bir veya iki hata olabilir. Bu, sonraki adımda keşfedilecektir.

3.1 HATA AYIKLAMA

Kodumuzda hata ayıklamak, kodumuzun satır satır nasıl çalıştığını (kesme noktaları belirlediysek) görmemizi ve hemen o anda kodumuzdaki hatayı veya açığı fark etmemizi, kodumuzu gerçek alım satım işlemlerinde kullanmadan önce düzeltmeleri hızla yapabilmemizi sağlar.

Burada önce kırılma noktaları belirleyerek ve ikinci olarak kesme noktaları olmadan Uzman Danışmanımızda adım adım hata ayıklama sürecine başlayacağız. Bunu yapmak için Editor’ı kapattığınızdan emin olun. Öncelikle EA’mızı test etmek istediğimiz grafiği seçelim. Editor Menü çubuğunda Araçlar üzerine tıklayın ve aşağıda gösterildiği gibi Seçenekleröğesine tıklayın:

Şekil 8. Hata ayıklama seçeneklerini ayarlama

Şekil 8. Hata ayıklama seçeneklerini ayarlama

Seçenekler penceresi göründüğünde para birimi çiftini ve kullanılacak dönem/zaman aralığını seçin ve Tamam düğmesine tıklayın:

Şekil 9. Hata ayıklama seçenekleri penceresi

Hata ayıklayıcıyı başlatmadan önce kesme noktalarını ayarlayalım. Kesme noktaları seçilen konumlarda veya satırlarda kodumuzun davranışını/performansını izlememizi sağlar. Tüm kodu tek seferde incelemek yerine hata ayıklayıcı bir kesme noktası gördüğünde duracak ve sonraki eyleminizi bekleyecektir. Bu sayede kodumuzu analiz edebilecek ve her kırılma noktasında davranışını izleyebileceğiz. Ayrıca bazı değişkenlerimizin değerlerini inceleyebilecek ve her şeyin tasarladığımız gibi olup olmadığını görebileceğiz.

Bir kesme noktası eklemek için kodunuzda kesme noktasını belirlemek istediğiniz satıra gidin. Sol tarafta kod satırının sınırının yanındaki gri alana çift tıklayın ve içinde beyaz bir kare olan küçük yuvarlak bir mavi düğme göreceksiniz. Alternatif olarak fare imlecini kod satırında kırılma noktasının görünmesini istediğiniz yere getirin ve F9 tuşuna basın. Kesme noktalarını kaldırmak için tekrar F9 tuşuna basın veya üstüne çift tıklayın.

Şekil 10. Bir kesme noktası ayarlama

Şekil 10. Bir kesme noktasını ayarlama

Kodumuz için beş farklı satırda kesme noktası belirleyeceğiz. 

Açıklamanın kolaylığı açısından bunları 1 - 5 olarak etiketleyeceğiz.

Devam etmek için aşağıdaki şekilde gösterildiği gibi yedi kod satırında kesme noktası belirleyin. Kesme noktası 1  yukarıda oluşturduğumuz kesme noktasıdır.

Şekil 11. Ek kesme noktaları ayarlama

Şekil 11. Ek kesme noktaları ayarlama

Kesme noktalarımızı ayarlamayı bitirdikten sonra kodumuzda hata ayıklamaya başlayabiliriz.

Hata ayıklayıcıyı başlatmak için F5’e basın veya MetaEditor Araç Çubuğunda yeşil düğmeye tıklayın:

 Şekil 12. Hata ayıklayıcıyı başlatmak

Şekil 12. Hata ayıklayıcıyı başlatmak

Editor’ın yaptığı ilk şey kodu derlemektir o sırada bir hata varsa bunu görüntüleyecek ve hata yoksa kodun başarıyla derlendiğini size bildirecektir.

Şekil 13. Derleme Raporu

Şekil 13. Derleme Raporu

Lütfen kodun başarıyla derlenmesinin, kodunuzda hata olmadığı anlamına gelmediğini unutmayın. Kodunuzun nasıl yazıldığına bağlı olarak çalışma zamanı hataları olabilir. Örneğin ifadelerimizden herhangi biri ufak bir gözden kaçırmadan dolayı doğru değerlendirme yapmazsa kodumuz doğru derleme yapacaktır ama düzgün çalışmayabilir. Çok konuştuk, şimdi uygulamaya geçelim...

Hata ayıklayıcı kodu derlemeyi bitirdikten sonra sizi alım satım terminaline götürür ve EA’yı MetaEditor Seçenekleri ayarlarında belirttiğiniz grafiğe ekleyecektir. Aynı zamanda EA’nın Giriş parametreleri bölümünü gösterir. Henüz hiçbir şeyi ayarlamadığımız için sadece Tamam düğmesine tıklayın.

Şekil 14. Hata Ayıklama İçin Uzman Danışman Giriş Parametreleri

Şekil 14. Hata Ayıklama İçin Uzman Danışman Giriş Parametreleri

Şimdi grafiğin sağ üst köşesinde EA’yı net bir şekilde göreceksiniz.

OnTick() öğesini başlattıktan sonra kesme noktası 1’e gelir gelmez duracaktır.

Şekil 15. Hata ayıklayıcı ilk kesme noktasında durur

Şekil 15. Hata ayıklayıcı ilk kesme noktasında durur

O kod satırında yeşil bir ok göreceksiniz. Bu size önceki kod satırının yürütüldüğünü ve şimdi mevcut satırı yürütmeye hazır olduğumuzu anlatır.

Devam etmeden önce burada bazı açıklamalar yapayım. Editor’ın Araç Çubuğunda daha önce gri olan kıvrımlı oklara sahip üç düğmenin şimdi etkinleştirildiğini göreceksiniz. Bunun nedeni, o anda hata ayıklayıcıyı çalıştırıyor olmamızdır. Bu düğmeler/komutlar kodumuzda adımlar oluşturmak için kullanılır (Gir, Atla veya Dışarı Adımla)

Şekil 16. Gir komutu

Şekil 16. Gir komutu

Gir komutu bir program yürütme adımından sonraki adıma geçmek ve o kod satırında çağrılan fonksiyonlara girmek için kullanılır. Komutu başlatmak için düğmeye tıklayın veya F11 tuşuna basın. (Kodumuzun adım adım hata ayıklamasında bu komutu kullanacağız.)

Şekil 17. Atla komutu

Şekil 17. Atla komutu

Atla komutu ise o kod satırında çağrılan herhangi bir fonksiyona girmez. Komutu başlatmak için düğmeye tıklayın veya F10 düğmesine basın

Şekil 18. Dışarı adımla komutu

Şekil 18. Dışarı adımla komutu

Bir üst seviye program adımını yürütmek için bu düğmeye tıklayın veya Shift+F11 tuşuna basın.

Ayrıca Editor’ın alt kısmında araç kutusu penceresini göreceksiniz. Bu penceredeki Hata Ayıklama sekmesinde aşağıdaki başlıklar bulunur:

  • Dosya: Burada, çağrılan dosyanın adı gösterilir
  • Fonksiyon: Bu, çağrılan dosyadaki mevcut fonksiyonu görüntüler
  • Satır: Bu, fonksiyonun çağrıldığı dosyadaki kod satırının numarasını görüntüler.
  • İfade: Burada kodumuzda izlemek istediğiniz herhangi bir ifadeyi/değişkenin adını yazabilirsiniz.
  • Değer: Bu, İfade alanında yazdığımız ifadenin/değişkenin değerini görüntüler.
  • Tür: Bu, izlenen ifadenin/değişkenin veri türünü görüntüler.

Şimdi hata ayıklama işlemimize geri dönelim…

Burada yapmak istediğimiz bir sonraki şey kodumuzda izlemek istediğimiz değişkenleri/ifadeleri yazmaktır. Yalnızca kodunuzdaki gerçekten önemli değişkenleri/ifadeleri izlediğinizden emin olun. Bizim örneğimizde aşağıdakileri izleyeceğiz:

  • Old_Time (eski çubuk zamanı)
  • New_Time[0] (geçerli çubuk zamanı)
  • IsNewBar (yeni çubuğu belirten bayrak)
  • Mybars (Geçmişteki toplam çubuklar) - EA’mız buna bağlıdır

Örneğin ADX değerleri, MA-8 değerleri gibi başka öğeleri ekleyebilirsiniz.

İfade/değişken eklemek için İfadeler alanının altına çift tıklayın veya İfadeler alanının altına sağ tıklayın ve yukarıdaki şekilde gösterildiği gibi Ekle öğesini seçin.

İzlenecek veya gözlemlenecek ifadeyi/değişkeni yazın.

Şekil 19. İfadeleri izleme penceresi

Şekil 19. İfadeleri izleme penceresi

Gerekli tüm değişkenleri/ifadeleri yazın...

Şekil 20. İzlenecek ifadeleri veya değişkenleri ekleme

Şekil 20. İzlenecek ifadeleri veya değişkenleri ekleme

Değişken henüz bildirilmemişse türü “Bilinmeyen tanımlayıcı” olur (statik değişkenler hariç).

Şimdi devam edelim...

Şekil 21. Gir komutu uygulanırken

Şekil 21. Gir komutu uygulanırken

Gir düğmesine tıklayın veya F11  tuşuna basarak ne olacağını gözlemleyin. Kesme noktası 2’yi elde edene kadar bu düğmeye veya F11’e basmaya devam edin, aşağıda gösterildiği gibi kesme noktası 4’e ulaşana kadar devam edin ve ifade izleme penceresini gözlemleyin.


Şekil 22. İfadeleri veya değişkenleri izleme

Şekil 22. İfadeleri veya değişkenleri izleme

Şekil 23. İfadeleri veya değişkenleri izleme

Şekil 23. İfadeleri veya değişkenleri izleme

Şekil 24. İfadeleri veya değişkenleri izleme

Şekil 24. İfadeleri veya değişkenleri izleme

Yeni bir tik olduğunda OnTick() fonksiyonunun ilk kod satırına geri dönecektir. Değişkenlerimizin/ifademizin tüm değerleri şimdi sıfırlanacaktır çünkü bunlardan herhangi biri statik bir değişken olarak bildirilmediği takdirde bu yeni bir tiktir. Bizim örneğimizde bir statik Old_Time değişkenimiz var.

Şekil 25. NewTick olayındaki değişkenlerin değerleri

Şekil 25. NewTick olayındaki değişkenlerin değerleri

Süreci tekrar gözden geçirmek için F11 tuşuna basmaya devam edin ve ifadeleri izleme penceresindeki değişkenleri izlemeyi sürdürün. Hata ayıklayıcıyı durdurabilir ve ardından tüm kesme noktalarını kaldırabilirsiniz.

Gördüğümüz gibi Hata Ayıklama modunda “Burada yeni bir çubuğumuz var...” mesajını yazdırır.

Şekil 26. Uzman Danışman, Hata Ayıklayıcı modunda mesajı yazdırır

Şekil 26. Uzman Danışman, Hata Ayıklayıcı modunda mesajı yazdırır

Hata ayıklama sürecini bu sefer kesme noktaları olmadan başlatalım. Her tiki izlemeye devam edin, Alış/Satış koşullarımızdan herhangi biri karşılanırsa bir alım satım işlemi gerçekleştirecektir ve kodumuzu, bir emrin başarıyla verilip verilmediğini bildirecek şekilde yazdığımız için bir uyarı görürüz.

Şekil 27. Uzman Danışman, hata ayıklama sırasında alım satımı işleme koyar

Şekil 27. Uzman Danışman, hata ayıklama sırasında alım satımı işleme koyar

EA’yı birkaç dakika boyunca çalışmaya bırakıp bir fincan kahve alabilirsiniz. Geri döndüğünüzde ve biraz para kazandıktan sonra (şaka yapıyorum) hata ayıklamayı durdurmak için MetaEditor’da DURDUR (Kırmızı) düğmesine tıklayın.

Şekil 28. Hata ayıklayıcıyı durdurmak

Şekil 28. Hata ayıklayıcıyı durdurmak

Aslında burada yaptığımız şey EA’mızın yalnızca yeni bir Çubuk açıldığında bir işlemi kontrol ettiğini ve EA’mızın gerçekten çalıştığını görmektir. EA kodumuzda hala ayarlamalar yapabiliriz.

Açıklamaya çalışayım, bu noktada Alım Satım terminali internete bağlı olmalıdır, aksi takdirde hata ayıklama çalışmayacaktır çünkü terminal, işlem yapamayacaktır.

3.2 EA STRATEJİMİZİ TEST ETME

Bu noktada Alım Satım Terminaline yerleşik Strateji Test Cihazını kullanarak EA’mızı test etmek istiyoruz.  Strateji Test Cihazını başlatmak için CONTROL+R üzerine basın veya aşağıda gösterildiği gibi Terminal Menü Çubuğunda Görüntüle menüsüne tıklayın ve Strateji Test Cihazına tıklayın

Şekil 26. Strateji Testini Başlatmak

Şekil 26. Strateji Testini Başlatmak

Test Cihazı (Strateji Test Cihazını) terminalin alt kısmında gösterilir. Test Cihazının tüm ayarlarını görmeniz için bunu genişletmeniz/yeniden boyutlandırmanız gerekir. Bunu yapmak için fare imlecinizi kırmızı ok ile gösterilen noktaya getirin (aşağıda gösterildiği gibi)

Şekil 27. Strateji Test Cihazı penceresi

Şekil 27. Strateji Test Cihazı penceresi

Fare imleci, çift uçlu oka dönüşür, fareyi basılı tutun ve çizgiyi yukarıya sürükleyin. Ayarlar sekmesinde her şeyi görebildiğinizi fark edince durun.

Şekil 28. Strateji Test Cihazı Ayarları sekmesi

Şekil 28. Strateji Test Cihazı Ayarları Sekmesi

  1. Sınamak istediğiniz EA’yı seçin
  2. Sınama için kullanılacak Para birimi çiftini seçin
  3. Sınama için kullanılacak Dönem/Zaman Aralığını seçin
  4. Özel Dönemi seçin ve 5’te tarihleri ayarlayın
  5. Sınama için kullanılacak özel dönemin tarihlerini ayarlayın
  6. Yürütme Normaldir
  7. Sınama için kullanılarak yatırma tutarını USD cinsinden seçin
  8. Optimizasyonu Devre Dışı olarak ayarlayın (Şu anda optimizasyon yapmıyoruz, sadece sınama yapıyoruz)
  9. Teste başlamak için bu düğmeye tıklayın.

Başlat düğmesine tıklamadan önce Test Cihazındaki diğer sekmelere bakalım

Aracılar Sekmesi

Test için Test Cihazı tarafından kullanılacak işlemci. Bilgisayarınızın işlemci türüne bağlıdır. Benimki yalnızca bir (1) çekirdekli işlemci.

Şekil 29. Strateji Test Cihazı Aracıları sekmesi

Şekil 29. Strateji Test Cihazı Aracıları sekmesi

Aracıya baktığınızda aşağıdaki şekle benzer bir şey göreceksiniz

Şekil 30. Test sırasında Strateji Test Cihazı Aracıları sekmesi

Şekil 30. Test sırasında Strateji Test Cihazı Aracıları sekmesi

Günlük Sekmesi

Burası test boyunca devam eden tüm olayların görüntülendiği yerdir

Şekil 31. Alım satım işlemlerini gösteren Strateji Test Cihazı Günlüğü sekmesi

Şekil 31. Alım satım işlemlerini gösteren Strateji Test Cihazı Günlüğü sekmesi

Girdiler Sekmesi

Burası EA için giriş parametrelerini belirteceğiniz yerdir.

Şekil 32. Strateji Test Cihazı Girdiler sekmesi

Şekil 32. Strateji Test Cihazı Girdiler sekmesi

EA’mızı optimize ediyorsak daire içindeki alandaki değerleri ayarlamamız gereklidir.

  • Başlat, Test Cihazının başlamasını istediğiniz değerlerdir.
  • Adım, seçtiğiniz değerin artış oranıdır ve
  • Durdur ise Test Cihazının o parametre için değeri artırmayı durduracağı değerdir.

Ancak bizim örneğimizde biz EA’mızı optimize etmiyoruz, bu yüzden buna şimdilik dokunmayacağız.

Her şey ayarlandıktan sonra Ayarlar sekmesine geri dönüyoruz ve Başlat düğmesine tıklıyoruz. Test cihazı çalışmaya başlar. Şimdi tek yapacağınız isterseniz bir fincan kahve daha almaktır veya benim gibiyseniz her bir olayı izlemek isteyebilir, ardından Günlük sekmesine dönebilirsiniz.

Grafik sekmesi

Günlük sekmesinde gönderilmiş emirlerle ilgili mesajlar görmeye başladığınızda Grafik adlı YENİ oluşturulmuş bir sekmeye geçmek isteyebilirsiniz. Grafik sekmesine geçtiğinizde, işlemlerinizin sonucuna bağlı olarak grafiğin yükseldiğini veya düştüğünü göreceksiniz.

Şekil 33. Uzman Danışman Testinin grafik sonucu

Şekil 33. Uzman Danışman Testinin grafik sonucu

Sonuçlar sekmesi

Sınama tamamlandığında Sonuçlar adlı başka bir sekme göreceksiniz. Sonuçlar sekmesine geçin ve az önce yaptığımız testin bir özetini göreceksiniz.

 Şekil 34. Test sonuçlarının özetini gösteren Strateji Test Cihazı Sonuçlar sekmesi

Şekil 34. Test sonuçlarının özetini gösteren Strateji Test Cihazı Sonuçlar sekmesi

Toplam Brüt Kar, Net Kar, toplam alım satımlar, toplam zararlı alım satımlar ve daha pek çok öğeyi görebilirsiniz. Testimiz için seçtiğimiz dönemde yaklaşık 1.450,0 USD olduğunu görmek gerçekten ilginç. En azından biraz kârımız var.

Burada size bir şeyi net olarak açıklayayım. Strateji test cihazında gördüğünüz EA parametrelerinin ayarlarının, EA’nın Giriş parametrelerindeki başlangıç ayarlarından farklı olduğunu göreceksiniz. EA’nızdan en iyi şekilde faydalanmanız için bu giriş parametrelerinin herhangi birini değiştirebileceğinizi gösterdim. Hareketli Ortalama ve ADX için her biri 8 dönemlik olanı kullanmak yerinde Hareketli Ortalama için 10 ve ADX için 14 olarak bunu değiştirdim. Ayrıca Zararı Durdur (Stop Loss) öğesini 30’dan 35’e değiştirdim. Son ama önemli bir nokta da 2 Saatlik zaman dilimini kullanmamdır. Unutmayın, bu Strateji Test Cihazıdır.

Testin tam raporunu görmek isterseniz Sonuçlar sekmesinde herhangi bir yere sağ tıklayın, bir menü göreceksiniz. Bu menüden “Rapor Olarak Kaydet” öğesini seçin.

Şekil 35. Test sonucu kaydetme

Şekil 35. Test sonucunu kaydetme

Kaydetme iletişim kutusu görünür, raporunuz için bir ad girin (isterseniz varsayılan adı da bırakabilirsiniz) ve kaydet düğmesine tıklayın. Raporun tamamı sizin için HTML formatında kaydedilecektir.

Yapılan testin grafiğini görmek için Grafiği Aç üzerine tıklayın, grafik görüntülenecektir

Şekil 36. Testi gösteren grafik 

Şekil 36. Testi gösteren grafik

İşte bu kadar, EA’mızı başarıyla yazdık, sınadık ve üzerinde çalışacağımız bir sonucumuz var. Şimdi strateji test cihazı Ayarlar sekmesine geri dönebilir ve diğer Zaman Aralıkları/Dönem için test yapabilirsiniz.

Atama

Farklı para birimi çiftlerini, farklı zaman dilimlerini, farklı Zararı Durdur (Stop Loss), farklı Kâr al (Take profit) öğelerini kullanarak test yapmanızı ve EA’nın nasıl çalıştığını görmenizi istiyorum. Yeni Hareketli Ortalama ve ADX değerlerini bile deneyebilirsiniz. Daha önce söylediğim gibi Strateji test aracının temeli budur. Ayrıca sonuçlarınızı benimle paylaşmanızı isterim.

Sonuç

Bu adım adım kılavuzda geliştirilmiş bir alım satım stratejisine dayanarak basit bir Uzman Danışman yazmak için gereken temel adımlara bakmış olduk. Hata ayıklayıcıyı kullanarak EA’mızda hata olup olmadığını nasıl kontrol edeceğimizi inceledik. Ayrıca Strateji Test Cihazını kullanarak EA’mızın performansını nasıl sınayacağımızı tartıştık. Bu sayede yeni MQL5 dilinin gücünü ve sağlamlığını gördük. Gerçek alım satım işlemlerinde kullanılması için hala yapılacak pek çok ayarlama olduğundan EA’mız henüz mükemmel veya tamamlanmış değil.

Hala öğrenilecek başka şeyler var ve MQL5 kılavuzuyla birlikte makaleyi tekrar okumanızı ve bu makalede öğrendiğiniz her şeyi denemenizi istiyorum, yakın gelecekte harika bir EA geliştirici olacağınızdan emin olabilirsiniz.

Keyifli kod yazmalar diliyorum.


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

Ekli dosyalar |
my_first_ea.mq5 (11.86 KB)
Standart Kitaplık Sınıflarını ve Google Grafik API (Uygulama Programlama Arayüzü) kullanarak Bilgi Panosu oluşturmak Standart Kitaplık Sınıflarını ve Google Grafik API (Uygulama Programlama Arayüzü) kullanarak Bilgi Panosu oluşturmak
MQL5 programlama dili öncelikli olarak otomatik alım satım sistemlerinin ve karmaşık teknik analiz enstrümanlarının oluşturulmasını hedef alır. Bunun yanı sıra piyasadaki durumları izlemek için ilginç bilgi sistemlerini oluşturmamızı sağlar ve yatırımcıya bir dönüş bağlantısı sağlar. Makalede MQL5 Standart Kitaplık bileşenleri açıklanır ve bu hedeflere ulaşmak için bunların uygulamalı kullanımının örnekleri gösterilir. Ayrıca grafiklerin oluşturulması için Google Grafik API’sinin kullanım örneğini gösterir.
MetaTrader 5 ile Yeni Fırsatlar MetaTrader 5 ile Yeni Fırsatlar
MetaTrader 4, dünyanın her yerinden yatırımcılar arasında popülerliğini kazandı ve daha fazlasının istenemeyeceği düşünülüyordu. Yüksek işlem hızı, kararlılığı, gösterge yazmak için çok çeşitli olanaklar, Uzman Danışmanlar (EA) ve bilgi işlem sistemleri ve yüzün üzerinde farklı aracı arasından seçim yapma becerisi ile terminal kendini diğerlerinden büyük ölçüde ayırdı. Ancak zaman sabit durmuyor ve kendimizi MetaTrade 4 veya MetaTrade 5 seçimiyle karşı karşıya buluyoruz. Bu makalemizde, 5. nesil terminalin mevcut lehimize olan temel farklarını anlatacağız.
Uzman Danışmanda Para Yönetimi için fonksiyonlar Uzman Danışmanda Para Yönetimi için fonksiyonlar
Alım satım stratejilerinin geliştirilmesi, öncelikli olarak, piyasaya giriş ve çıkış için kalıpların aranmasının yanı sıra pozisyonların muhafaza edilmesine odaklanmaktadır. Eğer bazı modelleri otomatik alım salım için kurallar halinde resmileştirebiliyorsak, bu durumda yatırımcı, pozisyonların hacmini, marjların büyüklüğünü hesaplamanın yanı sıra otomatikleştirilmiş bir açık pozisyonu güvence altına almak için güvenli bir ipotek fonu seviyesini muhafaza etme sorunuyla karşı karşıyadır. Bu yazıda MQL5 dilini, bu hesaplamaları yürütmek için basit örnekler oluşturmak için kullanacağız.
MQL5'te Tik Göstergeleri Oluşturma MQL5'te Tik Göstergeleri Oluşturma
Bu makalede, iki göstergenin oluşturulmasını ele alacağız: fiyatın tik grafiğini çizen tik göstergesi ve belirtilen sayıda tik ile mumları çizen tik mum göstergesi. Göstergelerin her biri gelen fiyatları bir dosyaya yazar ve göstergenin yeniden başlatılmasından sonra kaydedilen verileri kullanır (bu veriler diğer programlar tarafından da kullanılabilir)