English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
MQL5'te fonksiyonları uygulamalarla anlama

MQL5'te fonksiyonları uygulamalarla anlama

MetaTrader 5Alım-satım |
39 23
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Giriş

Programlama dünyasında, herhangi bir yazılımdaki önemi nedeniyle sıklıkla kullandığımız ve duyduğumuz çok popüler bir terim vardır - fonksiyon. İşlevsel ve kaliteli yazılımların nasıl oluşturulacağını öğrenebilmemiz için bu makalede bu konuyu ele alacağız. Fonksiyonların ne olduğuna, onları neden kullanmamız gerektiğine ve uygulamalarımızda nasıl kullanabileceğimize bakacağız. Sonrasında, makalede öğrendiklerimizi uygulamak için herhangi bir alım-satım sisteminde kullanılabilecek bazı basit fonksiyonlara göz atacağız. Makale boyunca aşağıdaki konuların üzerinden geçeceğiz:

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.


Fonksiyonun tanımı

Bu bölümde, programlamadaki fonksiyonu tanımlayacak, türlerine ve neden kullanmamız gerektiğine bakacağız. Fonksiyon, belirli bir görevi yerine getirmek için tekrar tekrar çağrılarak yazılımın başka herhangi bir bölümünde kullanılabilen, belirli bir anlamlı adla bildirilen bir kod bloğudur. Yazılımın kendi birçok bölümünde ya da birçok farklı yazılımda gerçekleştirmesini istediğimiz belirli bir görevimiz varsa, bu görevi yerine getirmek için bir fonksiyon ya da kod bloğu oluştururuz ve daha sonra tüm kodu yeniden yazmadan sadece bu bölümlerde çağırırız. Dolayısıyla, bir fonksiyonun kodumuzu soyutlamanın bir yöntemi olduğunu söyleyebiliriz. Fonksiyonların iki ana türü vardır: yerleşik fonksiyonlar ve kullanıcı tanımlı fonksiyonlar. Yerleşik fonksiyon, programlama dilinin kendisi tarafından hazır olarak sunulan fonksiyondur; kullanıcı tanımlı fonksiyon ise kullanıcının ihtiyaçlarına veya yazılımın gerçekleştirmesini istediği görevlere göre oluşturabileceği fonksiyondur. Bu makalede, kullanıcı tanımlı fonksiyonlara odaklanacağız.

Diyelim ki, varlık maksimum düşüşe ulaştığında yazılımın tüm açık emirleri kapatmasına ihtiyacımız var ve bu görev yazılımın birçok bölümünde gerçekleştirilmelidir. Bu durumda, aynı kodu gerekli tüm yerlerde tekrarlamak yerine, bir fonksiyon oluşturmak ve bu görevi gerçekleştirmek için gerekli kodu (mantığı) dahil etmek ve ardından diğer bölümlerde çağırmak daha iyi olacaktır.

Neden bu tür bir fonksiyon kullanmamız gerektiği sorusunu yanıtlamak için, kullanıcı tanımlı fonksiyonları kullanmanın özelliklerini incelememiz gerekir:

  • DRY (Don't Repeat Yourself, kendini tekrar etme) ilkesini uygulamamıza yardımcı olur: Kullanıcı tanımlı fonksiyonlar sayesinde aynı kodu tekrar tekrar yazmak zorunda kalmayız. Görevimizi yerine getirebilecek bir fonksiyon oluştururuz ve daha sonra yazılımın uygun herhangi bir yerinde çağırırız.
  • Yeniden kullanılabilirlik: Fonksiyonumuzu oluşturduktan sonra, onu istediğimiz zaman yeniden kullanabiliriz.
  • “Böl ve fethet” konseptinin uygulanmasına yardımcı olur: Büyük bir problemi daha küçük problemlere bölebilir ve her birini fonksiyonlarla çözebiliriz.
  • Kodu daha okunabilir ve anlaşılabilir hale getirir: Her bir fonksiyon belirli bir problemi çözer.
  • “Soyutlama” konseptinin uygulanmasına yardımcı olur: Fonksiyonlar olmazsa daha fazla kod satırına ihtiyaç duyarız.
  • “Kapsülleme” konseptinin uygulanmasına yardımcı olur: Fonksiyonlar, kodumuzu ve verilerimizi korumamıza ve daha kolay yönetmemize olanak sağlar.
  • Hata ayıklama sürecini iyileştirir: Fonksiyonlar, hataların bulunmasını ve giderilmesini önemli ölçüde kolaylaştırır.

Fonksiyonları kullanmanın getirdiği avantajlardan bahsettiğimize göre, bu kullanıcı tanımlı fonksiyonları yazılımımızda kullanmanın ne kadar faydalı olacağını kolayca anlayabiliriz.


Fonksiyon yapısı

Bu bölümde şunları ele alacağız:

  • Fonksiyon tanımlama
  • Fonksiyon çağırma

İlk olarak, yeni bir fonksiyon tanımlamamız gerekiyor, bu nedenle aşağıdaki yapıya benzer bir kod yazmamız gerekiyor:

returnedDataType functionName(param1, param2)
{
        bodyOfFunction
}
  • returnedDataType - fonksiyonun yürütüldükten sonra geri döndürmesini istediğimiz veri türü.
  • functionName - fonksiyonun adı. Gerçekleştirilecek görevi ifade eder.
  • (param1, param2) - değişkenler veya yer tutucular (gerekirse).
  • bodyOfFunction - görevi yerine getiren tüm kod. 

İşte basit bir örnek. İki değeri toplama görevini yerine getirmek için basit bir fonksiyon oluşturmamız gerekirse, bunu aşağıdaki kod bloğunu kullanarak yapabiliriz:

//addition function
// returned data type is an integer - the name of the function is add - parameters or arguments are two int variables val1 and val2
int add(int val1, int val2)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of val1 and val2 addition
   int result = val1+val2;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

Fonksiyonumuzu tanımladıktan sonra onu çağırmamız gerekir. Bu da yazılım kodunun istenilen kısmında fonksiyon adının çağrılması ve fonksiyonumuza göre istenilen parametrelerin belirtilmesi ile yapılabilir. Örneğimizde fonksiyon çağrısı şu şekilde görünecektir:

   //calling our defined function by its name and specifying arguments
   add(5,15);

Çağrıldığında, aşağıdaki şekilde gösterildiği gibi fonksiyonumuza ve belirtilen argümanlara göre Uzmanlar sekmesinde 20 sonucunu elde ederiz.

add fonksiyon sonucu

Yukarıdaki örnek, fonksiyonları kullanarak yapabileceklerimizin sadece bir örneğidir, ancak fonksiyonlarda kullanabileceğimiz daha birçok özellik mevcuttur. Aşağıdakiler bunlardan bazılarıdır.

Değişkenli fonksiyon

Yukarıdaki “add” fonksiyonu örneğinde iki tamsayı değişken kullandık: val1 ve val2. Bu değişkenler fonksiyonumuzda argümanlar (parametreler) olarak ele alınır. Bu argümanlar tamsayı, dizge vb. veri türünde olabilir. Örneğimizde bunlar tamsayı değişkenlerdi. Şimdi benzer bir örneği dizge argümanlarla görelim:

//sayHello function
// returned data type is string - name of function is sayHello - parameters or arguments are two string variables greeting and name
string sayHello(string greeting, string name)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string result = greeting+name;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

Bu fonksiyonu daha önce bahsedildiği şekilde çağırabilir ve aşağıda gösterildiği gibi yürütüldükten sonra sonucunu bulabiliriz:

sayHello fonksiyon sonucu

Ayrıca, fonksiyonun gövdesini yürütmek için parametre olarak neye ihtiyaç duyduğumuza bağlı olarak, fonksiyonumuzda bu veri türlerinin bir kombinasyonunu da kullanabiliriz. Bu argümanlar ihtiyaç duyduğumuz sayıda olabilir.

Değişkensiz fonksiyon

Bir fonksiyon herhangi bir parametre belirtilmeden de tanımlanabilir. Sadece fonksiyona anlamlı bir ad verip, argümanlar kısmını boş bırakabilir ve görevi yerine getirmek için fonksiyonun gövdesini doldurarak tamamlayabiliriz. Ardından argüman belirtmeden fonksiyonu çağırabiliriz. Böyle bir fonksiyona örnek:

//sayHello function
// returned data type is a string - the name of the function is sayHello - no parameters
string sayHello()
  {
   //body of the function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string greeting= "Hello, ";
   string name= "World!";
   string result = greeting+name;
   //Print the result in the experts' tab
   Print(result);
   //returning value
   return result;
  }

Fonksiyonu aşağıdaki gibi çağırırız:

sayHello();

Fonksiyonun gövdesi aynı olduğu için sonuç daha önce argümanlı fonksiyonda gösterdiğimizle aynı olacaktır.

Varsayılan değerlere sahip fonksiyon

Bir fonksiyonu tanımlarken parametreler için varsayılan değerler belirleyebiliriz, ancak bunları daha sonra istenen değerleri ayarlayarak güncelleyebiliriz.

//defining function with default values
string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

Varsayılan değerler ile istediğimiz değerler arasındaki farkı görmek için fonksiyonu aşağıdaki gibi iki kez çağırabiliriz. Parametre belirtmezsek, fonksiyon varsayılan değerleri geri döndürür.

   sayHello();
   sayHello("Hi, ", "Developer!");

Sonuç:

sayHello fonksiyonunda varsayılan değerler ile karşılaştırmalı sonuç

Parametreleri iletme

Daha önce de belirttiğimiz gibi, fonksiyona herhangi bir veri türünü iletebiliriz - tamsayı, dizge, dizi vb. Parametreleri değer olarak ilettiğimizde, fonksiyondaki orijinal değişkenler değişmeden kalacaktır. Orijinal değişkenleri güncellememiz gerekiyorsa fonksiyon parametrelerini referans olarak iletebiliriz.

Aşağıda, parametreleri referans olarak iletmeyi anlamak için basit bir örnek verilmiştir.

//passing by reference
void updateNums(int &val1, int &val2)
  {
   val1*=2;
   val2/=2;
  }

Daha sonra yeni değişkenler oluşturacağız, değerlerini yazdıracağız, ardından fonksiyonumuzu bu yeni değişkenler parametreler olacak şekilde çağıracağız ve farkı görmek için çağrıdan sonra değerlerini yazdıracağız:

//new variables
   int firstNum = 10;
   int secondNum = 20;
   
//before calling function
   Print("before calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 
   
// calling   
   updateNums(firstNum, secondNum);

// after calling  
   Print("after calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 

İlk yazdırmada, yeni değişkenlerde tanımladığımız 10 ve 20 değerlerini alırız ve çağrıdan sonra bunlar fonksiyonun gövdesinde 20 ve 10 olarak güncellenir. Sonuç:

Parametreleri referans olarak iletme

return operatörü

Değer geri döndüren bir fonksiyonumuz varsa, bir return operatörüne sahip olmalıdır. Fonksiyonun görevine bağlı olarak, bir fonksiyonda birden fazla return operatörüne sahip olabiliriz, ancak fonksiyon bir değer geri döndürüyorsa, fonksiyonun son satırında en az bir return operatörü olmalıdır. Herhangi bir türde olabilir, ancak bir dizi olamaz. Ancak, bir diziden bir eleman geri döndürebiliriz. Fonksiyonun bir dizi geri döndürmesini istiyorsak, daha önce bahsettiğimiz gibi diziyi fonksiyona referans olarak iletebiliriz.

Aşağıda return operatörü ile ilgili bir örnek verilmiştir.

string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

void türünde fonksiyon

Değer geri döndürmeyen bir fonksiyonumuz varsa, void türünde bir fonksiyon kullanırız, çünkü bu tür bir değer geri döndürmez. Bu tür fonksiyonlara normal olarak parametreler iletebiliriz, ancak bir return operatörü gerektirmez. Aşağıda böyle bir fonksiyon örneği verilmiştir.

void add(int val1, int val2)
  {
   int result= val1+val2;
  }

Fonksiyon aşırı yükleme

Bazı durumlarda, aynı görevi yerine getirmek için aynı ada sahip ancak farklı parametreleri olan birden fazla fonksiyon tanımlamamız gerekir. Örneğin, bir toplama görevimiz varsa ve bu toplamayı iki değer için gerçekleştirmenin yanı sıra üç değer için de gerçekleştirmemiz gerekiyorsa, aynı ada sahip iki fonksiyon oluştururuz, ancak parametreleri göreve göre değiştiririz. Bu, aynı görevi yerine getiren ancak farklı parametrelerle çalışan aşırı yüklenmiş bir fonksiyona sahip olduğumuz anlamına gelir.

Bu farklı parametreler aynı veya farklı veri türlerinde farklı sayılarda olabilir. Aşağıda, aynı veri türüne sahip ancak farklı sayıda parametresi olan aşırı yüklenmiş bir fonksiyon örneği verilmiştir:

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(int val1, int val2, int val3)
{
   int result=val1+val2+val3;
}

Gördüğümüz gibi, aynı fonksiyona sahibiz, ancak parametreler farklı. Fonksiyonu çağırırken, fonksiyon adını yazdığımızda bu iki fonksiyonun göründüğünü görürüz, daha sonra görevimize göre ihtiyacımız olanı seçebiliriz. Aşağıda, veri türüne göre farklı parametrelere sahip aşırı yüklenmiş bir fonksiyon örneği verilmiştir:

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(string message, int val1, int val2)
{
   int result=message+val1+val2;
}

Fonksiyonu çağırırken parametrelere göre ihtiyacımız olan fonksiyonu seçebiliriz.


Fonksiyon uygulamaları

Bu bölümde fonksiyonları kullanarak basit uygulamalar oluşturacağız. Bu uygulamaları oluşturduktan sonra, bunları yazılımın farklı bölümlerinde veya hatta başka bir yazılıma dahil ederek çağırabiliriz.

Haber uyarıları uygulaması

Ekonomik haberler sırasında alım-satım yapmanın çok riskli olduğunu hepimiz biliyoruz ve haberler sırasında alım-satım yapmamamız konusunda pek çok profesyonel tavsiye var. Ekonomik takvim, makroekonomik haberlerin ve göstergelerin açıklamaları, tarihleri, saatleri ve önem dereceleri dahil olmak üzere bu ekonomik olayların yayınlanan değerlerini içerir. Piyasayı ve dolayısıyla işlemlerimizi etkileyebilecek bu önemli değerleri elde etmek için kullanılabilecek birçok kaynak vardır. Ekonomik takvim MetaTrader 5 işlem terminalinde de mevcuttur. Araç Kutusu penceresinde sekmesini bulabilir ve önem, para birimi ve ülke açısından tam olarak neleri görüntülemek istediğinizi özelleştirebilirsiniz. Ekonomik takvimle çalışmak için yerleşik fonksiyonlar da vardır. Bunları MQL5 dokümantasyonunda bulabilirsiniz:

Ekonomik Takvim Fonksiyonları

Dolayısıyla, haberler sırasında işlem yapmaktan kaçınmak için ekonomik takvimi manuel olarak kontrol etmemiz veya haberler yaklaştığında bizi uyaracak bir uygulama oluşturmamız gerekir. Bu süreklilik arz eden bir görevdir. Herhangi bir alım-satım sisteminde veya yazılımın birçok bölümünde buna ihtiyacımız olacaktır. İhtiyacımız olan fonksiyonu oluşturabilir ve daha sonra kolayca çağırabiliriz. Aşağıdaki adımlarla yapacağımız tam olarak bu:

Bu uygulama bir Uzman Danışman olacaktır. Global kapsamda bool türünde “isNewsComing” adında fonksiyonumuzu oluşturacağız, herhangi bir parametre eklemeyeceğiz.

bool isNewsComing()

Fonksiyonun gövdesi, MqlCalendarValue türünde values adlı bir dizi oluşturur. Bu dizi, örneğin açıklanan değerler gibi haber değerlerini içerecektir.

MqlCalendarValue values[];

Mevcut günü tanımlamamız gerekir. Bu amaçla şunları yaparız. Günün başlangıç zamanını tanımlarız: startTime adında yeni bir datetime değişkeni bildirdikten sonra, çubuk açılış zamanını geri döndürmek için “iTime” fonksiyonunu kullanırız. Günün bitiş zamanını tanımlarız: endTime adında yeni bir datetime değişkeni bildirdikten sonra, tanımladığımız günün başlangıç zamanına “PeriodSeconds” fonksiyonunu kullanarak elde ettiğimiz günün saniye sayısını ekleriz.

   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);

“CalendarValueHistory” fonksiyonunu kullanarak, gün içindeki tüm olayların değerlerini values dizimize alıyoruz (zaman aralığı için yukarıda tanımladığımız günün başlangıç ve bitiş zamanlarını kullanıyoruz. Ayrıca ülke ve para birimine göre ek filtreleme de yapabiliriz). Fonksiyonun parametreleri: değerler için dizi, başlangıç zamanı, bitiş zamanı, ülke ve para birimi.

CalendarValueHistory(values,startTime,endTime,NULL,NULL);

Bir döngü oluşturacağız. Oluşturulan (i) int değişkeni ile döngüyü (0) değerinden başlatacağız, (i) values dizisinin büyüklüğünden küçük olduğu sürece döngüye devam edeceğiz ve (i) değerini bir değer artıracağız.

for(int i=0; i<ArraySize(values); i++)

for döngüsünün gövdesi, olay açıklamaları için MqlCalendarEvent türünde event adında bir değişken oluşturur. Bu değişken “CalendarEventById” fonksiyonunda kullanılabilir.

MqlCalendarEvent event;

“CalendarEventById” fonksiyonunu kullanarak olay kimliğine göre olayın açıklamasını alıyoruz. Fonksiyonun parametreleri: olay kimliği ve olay açıklaması için değişken.

CalendarEventById(values[i].event_id,event);

Ülke açıklamaları için MqlCalendarCountry türünde country adında bir değişken oluşturuyoruz. Bu değişken “CalendarCountryById” fonksiyonunda kullanılabilir.

MqlCalendarCountry country;

“CalendarCountryById” fonksiyonunu kullanarak ülke kimliğine göre ülke açıklamasını alıyoruz. Fonksiyonun parametreleri: ülke kimliği ve ülke açıklaması için değişken.

CalendarCountryById(event.country_id,country);

Olayları sembolün para birimine göre filtrelemek için koşulu ayarlıyoruz. Haberlerin önem derecesi orta veya yüksek olmalı.

      if(StringFind(_Symbol,country.currency)<0)
         continue;

      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;

Uyarının zaman aralığı için koşulu ayarlıyoruz (haberin yayınlanmasından 30 saniye önce).

      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))

Ardından Uzmanlar sekmesine olayın adını ve “ is coming! Stop Trading...” metnini içeren bir mesaj yazdırıyoruz.

Print(event.name, " is coming! Stop Trading...");

true değerini geri döndürüyoruz.

return true;

Koşullar doğru değilse, döngüyü bitiyoruz ve fonksiyonu sonlandırmak için false değerini geri döndürüyoruz.

return false;

Daha sonra bu fonksiyonu “OnTick()” fonksiyonu içinde çağırabiliriz ve eğer true değerini geri döndürürse “News is coming...!” mesajını yazdırırız.

   if(isNewsComing())
     {
      Print("News is comming...!");
     }

Fonksiyonumuzu oluşturduk ve çağırdık. İhtiyaçlarımıza göre yazılımımızın herhangi bir bölümünde onu kullanabiliriz. Kodun tamamı tekrar okumayı kolaylaştırmak için aşağıda tek bir blok halinde verilmiştir. Tüm uygulamaların kaynak kod dosyaları makaleye eklenmiştir.

//+------------------------------------------------------------------+
//| News Alert Function                                              |
//+------------------------------------------------------------------+ 
void OnTick()
  {
   if(isNewsComing())
     {
      Print("News is comming...!");
     }
  }
//+------------------------------------------------------------------+
bool isNewsComing()
  {
   MqlCalendarValue values[];
   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);
   CalendarValueHistory(values,startTime,endTime,NULL,NULL);
   for(int i=0; i<ArraySize(values); i++)
     {
      MqlCalendarEvent event;
      CalendarEventById(values[i].event_id,event);
      MqlCalendarCountry country;
      CalendarCountryById(event.country_id,country);
      if(StringFind(_Symbol,country.currency)<0)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;
      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))
        {
         Print(event.name, " is coming! Stop Trading...");
         return true;
        }
     }
   return false;
  }
//+------------------------------------------------------------------+

Lot büyüklüğü hesaplama uygulaması

Risk yüzdesini ve pip cinsinden maksimum zararı belirttikten sonra optimum lot büyüklüğünü hesaplayabilen bir uygulama oluşturmamız gerekiyor. Ayrıca risk yüzdesini, giriş fiyatını ve Zararı Durdur fiyatını belirttikten sonra da optimum lot büyüklüğünü hesaplamak için aşırı yüklenmiş bir fonksiyon oluşturmamız gerekiyor. Bu uygulamayı aşağıdaki adımlarla bir komut dosyası olarak oluşturacağız:

“OptimalLotSize” adında double türünde bir fonksiyon oluşturalım. Fonksiyonun iki parametresi olacaktır: double türünde maksimum risk yüzdesi ve double türünde pip cinsinden maksimum zarar.

double OptimalLotSize(double maxRiskPrc, double maxLossInPips)

Daha sonra bu parametreler için ne yapmamız gerektiğini belirleriz. İlk olarak, bir hesap özelliğinin değerini geri döndüren “AccountInfoDouble” fonksiyonunu kullanarak hesap varlığı değerini tanımlayacağız [fonksiyona özellik kimliği olarak ENUM_ACCOUNT_INFO_DOUBLE numaralandırmasından (ACCOUNT_EQUITY) belirteceğiz]. İlgili değeri içeren bir uyarı oluşturacağız.

   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);

Bir sembol özelliğinin değerini geri döndüren “SymbolInfoDouble” fonksiyonunu kullanarak sembol sözleşme büyüklüğünü tanımlayacağız [fonksiyona şunları belirteceğiz: mevcut sembol için (_Symbol) ve özellik kimliği olarak ENUM_SYMBOL_INFO_DOUBLE numaralandırmasından (SYMBOL_TRADE_CONTRACT_SIZE)]. Geri dönüş değeriyle bir uyarı oluşturacağız.

   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);

Pip değerini hesaplıyoruz ve bu değerle bir uyarı oluşturuyoruz.

   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);

Tanımlanan hesap varlığına göre maksimum zarar değerini hesaplıyoruz ve bu değerle bir uyarı oluşturuyoruz.

   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);

Hesaplanan maksimum zarar değerine göre karşıt para birimindeki maksimum değeri hesaplıyoruz ve bu değerle bir uyarı oluşturuyoruz.

   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);

Optimum lot büyüklüğünü hesaplıyoruz ve bu değerle bir uyarı oluşturuyoruz.

   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);

return operatörü double türünde OptimalLotSize değerini geri döndürecektir.

return OptimalLotSize;

Sonrasında, maksimum risk yüzdesi, giriş fiyatı ve Zararı Durdur fiyatı için double türünde üç parametre ileterek aşırı yüklenmiş bir fonksiyon oluşturuyoruz.

double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)

Pip cinsinden maksimum zararı tanımlıyoruz: giriş fiyatı ve Zararı Durdur fiyatı girdi parametreleri arasındaki farkın mutlak değerini alıyoruz ve bu değeri 0.0001’e bölüyoruz.

double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;

return operatörü, maksimum risk yüzdesi ve pip cinsinden maksimum zarar parametreleri ile “OptimalLotSize” fonksiyonu olacaktır.

return OptimalLotSize(maxRiskPrc,maxLossInPips);

Ardından, ihtiyacımıza göre “OnStart()” kısmında iki fonksiyondan birini çağırabiliriz.

OptimalLotSize(0.01, 1.12303, 1.11920);

Aşağıda bu türde bir fonksiyon oluşturmak için gerekli kodun tamamı yer almaktadır.

//+------------------------------------------------------------------+
//| lotSize Calc Function                                            |
//+------------------------------------------------------------------+
void OnStart()
  {
   OptimalLotSize(0.01, 1.12303, 1.11920);
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double maxLossInPips)
  {
   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);
   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);
   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);
   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);
   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);
   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);
   return OptimalLotSize;
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)
  {
   double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;
   return OptimalLotSize(maxRiskPrc,maxLossInPips);
  }
//+------------------------------------------------------------------+

Bu komut dosyasını çalıştırdığımızda aşağıdaki uyarıyı alırız.

Lot büyüklüğü hesaplama uygulaması

Böylece, kodu yeniden yazmadan görevi tamamlamak için yazılımın farklı bölümlerinde kolayca çağırabileceğimiz bir lot büyüklüğü hesaplama fonksiyonuna sahibiz.

Tümünü kapat uygulaması

Burada, yazılımın herhangi bir uygun bölümünde çağrılabilecek bir fonksiyon oluşturarak açık ve bekleyen emirleri kapatabilecek bir komut dosyası oluşturmamız gerekiyor. Bunu aşağıdaki adımlarla yapabiliriz:

#include kullanarak, tüm alım-satım fonksiyonlarını içeren Trade sınıfının bulunduğu Trade.mqh dosyasını koda dahil ediyoruz.

#include <Trade/Trade.mqh>

Yazılımda kullanılmak üzere CTrade sınıfı türünde bir nesne oluşturuyoruz.

CTrade trade;

Global kapsamda, argüman içermeyen void “closeAll” fonksiyonunu da oluşturmamız gerekiyor.

void closeAll()

Fonksiyon gövdesi, açık emirleri kontrol etmek için bir for döngüsü oluşturur.

for(int i=PositionsTotal()-1; i>=0; i--)

 Döngünün gövdesinde ulong posTicket değişkenini oluşturuyoruz ve ona açık emirlerin fişini atıyoruz.

ulong posTicket=PositionGetTicket(i);

Açık işlemi trade.PositionClose(posTicket) ile kapatıyoruz.

trade.PositionClose(posTicket);

Bekleyen emirleri siliyoruz: bu emirleri tespit etmek için başka bir for döngüsü oluşturuyoruz, fişlerini ulong posTicket değişkenine atıyoruz ve tespit edilen fişe göre bekleyen emri siliyoruz.

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }

Sonrasında, bu fonksiyonu “OnStart()” içinde çağırabiliriz.

closeAll();

Komut dosyası tüm emirleri kapatır ve siler. Aşağıda uygulamanın tam kodu verilmiştir:

//+------------------------------------------------------------------+
//| closeAll Function                                                |
//+------------------------------------------------------------------+ 
#include <Trade/Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
void OnStart()
  {
   closeAll();
  }
//+------------------------------------------------------------------+
void closeAll()
  {
//close all open positions
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      ulong posTicket=PositionGetTicket(i);
      trade.PositionClose(posTicket);
     }
//delete all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }
  }
//+------------------------------------------------------------------+

Yukarıdaki uygulamalar, kullanıcı tanımlı fonksiyonlarla oluşturabileceklerimize sadece birkaç örnektir. Takip eden durdurucu, alım-satım yönetimi, düşüş güvenliği aracı vb. gibi ihtiyaçlarınıza göre başka uygulamalar veya fonksiyonlar oluşturabilirsiniz.


Sonuç

Fonksiyonların kullanımının bir dizi yadsınamaz avantajı vardır:

  • Programlamada DRY (Don't Repeat Yourself, kendini tekrar etme) ilkesini uygulamamızı sağlar.
  • Herhangi bir büyük görevi daha küçük görevlere bölerek basitleştirmeye yardımcı olur.
  • Kodu daha okunabilir hale getirir.
  • Yeniden kullanımı mümkün kılar.
  • Kod soyutlama yapar.
  • Kod kapsüllemeyle güvenliği artırır.
  • Hata ayıklamayı iyileştirir.

Fonksiyonun ne olduğu ve türleri (yerleşik ve kullanıcı tanımlı) hakkında konuştuk. Fonksiyon yapısını gözlemleyerek nasıl tanımlandıklarını öğrendik. Argümanlı fonksiyonları ve argümanlarının (parametrelerinin) nasıl iletildiğini gördük, argümansız fonksiyonlar ve varsayılan değerlere sahip fonksiyonlardan bahsettik. Herhangi bir veri türünü kullanarak bir fonksiyon tanımlayabileceğimizi, buna göre return operatörünü kullanabileceğimizi ve aynı görevi yerine getirmek için aynı ada sahip ancak farklı argümanları olan aşırı yüklenmiş bir fonksiyon oluşturabileceğimizi öğrendik.

Umarım örnek uygulamalar konuyu daha derinlemesine anlamanıza yardımcı olmuştur:

  • Haber uyarıları uygulaması - Önemli haberler yaklaştığında uyarı almak için. Yazılımın herhangi bir bölümünde çağrılabilir. Kaynak kodu (newsAlertApp.mq5) aşağıya eklenmiştir.
  • Lot büyüklüğü hesaplama uygulaması - Belirli bir risk yüzdesine, giriş fiyatına ve Zararı Durdur fiyatına dayalı olarak optimum lot büyüklüğünü elde etmek için. Veya belirli bir risk yüzdesine ve pip cinsinden maksimum zarara dayalı olarak (yani bu uygulamada aşırı yüklenmiş bir fonksiyon oluşturduk). Yazılımın herhangi bir bölümünde çağrılabilir. Kaynak kodu (lotSizeCalcApp.mq5) aşağıya eklenmiştir.
  • Tümünü kapat uygulaması - Tüm açık ve bekleyen emirleri kapatır. Kaynak kodu (closeAllApp.mq5) aşağıya eklenmiştir.

Fonksiyonlar dünyası çok ilginçtir ve kolay ve verimli bir şekilde faydalı kod parçacıkları oluşturabilmek için bu konuya gereken özeni göstermek çok önemlidir. Umarım bu makale sizin için faydalı olmuştur ve alım-satım araçları donanımınızı genişletmiştir. Programlama hakkında daha fazla bilgi edinmek veya Moving Average, RSI, MACD, Stochastic Oscillator, Bollinger Bands, Parabolic SAR vb. en popüler teknik göstergelere dayalı alım-satım sistemlerinin nasıl oluşturulacağını öğrenmek istiyorsanız, önceki makalelerimi okuyabilirsiniz.

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

Ekli dosyalar |
newsAlertApp.mq5 (1.37 KB)
lotSizeCalcApp.mq5 (1.45 KB)
closeAllApp.mq5 (0.86 KB)
Son yorumlar | Tartışmaya git (23)
MrBrooklin
MrBrooklin | 12 Eki 2023 saat 19:09
fxsaber #:

Bunlar (Kim'in işlevleri) uzun zamandır MQL4'ten MQL5'e taşınmıştır.

Cehaletimi mazur görün ve inanın bana, alay etmiyorum, ama taşınan nedir? MQL5 için yeniden mi yazıldılar? Bir yerde toplanmışlarsa ve sizin için zor değilse, lütfen Kim'in MQL5 'e taşınan işlevlerine bir bağlantı sağlayın. Sitede arama yapmaya çalıştım - Kim'in taşınmış fonksiyonları, ancak hiçbir şey bulamadım.

Saygılarımla, Vladimir.

fxsaber
fxsaber | 13 Eki 2023 saat 15:41
MrBrooklin #:

Kim'in MQL5 'e taşınan işlevlerine bir bağlantı sağlayın.

https://www.mql5.com/ru/forum/107476

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi üzerine forum

Kütüphaneler: MT4Orders

fxsaber, 2019.01.13 17:23 PM.

Kim'in MT4 altındaki işlevleri oldukça popüler, bu yüzden tüm kaynakları sitesinden indirdim ve MT5 altında onlar için basit bir "dönüştürücü" yazdım.
#include <KimIVToMT5.mqh> // https://c.mql5.com/3/263/KimIVToMT5.mqh
MrBrooklin
MrBrooklin | 13 Eki 2023 saat 15:43

Teşekkür ederim!

Saygılarımla, Vladimir.

Hilario Miguel Ofarril Gonzalez
Hilario Miguel Ofarril Gonzalez | 9 Ara 2023 saat 16:43
Bilgiye katkıda bulunmak.başkalarından öğrendiğimiz noktayı enceñar etmek.stratejiler.çok somut .ve kesin bir şekilde devam edin.sayıların sonsuz olduğu bir savaşta olmak gibi .de ello es como digo yo sentirce satisfied .when we win the güera .el programa.de las defensas en el tradi.es tratar de cobertice en ganadores .sin afectar.nuestras inversiones.Kendimi her ustanın her makalesini okumaya adadım ve onlardan öğreniyorum, onlar gibi büyük bir usta olma arzusunu uygulamaya koyuyorum ve tradi dünyasının daha güçlü olması için öğretileri aktarıyorum, hepimizi tanımlayan şey bu... irade ve fedakarlık.... ve tradi dünyasını daha güçlü hale getirmek için kendimi feda edeceğim.
Javid Rezaei
Javid Rezaei | 15 Ağu 2025 saat 23:56
Bu faydalı makale için çok teşekkürler.
MQL5 program yapısı hakkında bilmeniz gereken her şey MQL5 program yapısı hakkında bilmeniz gereken her şey
Tüm programlama dillerinde programların belirli bir yapısı vardır. Bu makalede, MetaTrader 5 için bir alım-satım sistemi oluştururken çok yararlı olabilecek MQL5 program yapısının ana bileşenlerini inceleyeceğiz.
Python'da bir alım-satım robotu geliştirme (Bölüm 3): Model tabanlı bir alım-satım algoritmasının uygulanması Python'da bir alım-satım robotu geliştirme (Bölüm 3): Model tabanlı bir alım-satım algoritmasının uygulanması
Python ve MQL5'te bir alım-satım robotu geliştirmeye yönelik makale serisine devam ediyoruz. Bu makalede Python'da bir alım-satım algoritması oluşturacağız.
Farklı hareketli ortalama türlerinin performansının test edilmesi Farklı hareketli ortalama türlerinin performansının test edilmesi
Hareketli ortalama göstergesinin birçok yatırımcı için önemini hepimiz biliyoruz. Alım-satımda faydalı olabilecek farklı hareketli ortalama türleri vardır. Bunlara göz atacağız ve hangisinin en iyi sonuçları gösterebileceğini görmek için basit bir karşılaştırma yapacağız.
Python ve MQL5'te bir robot geliştirme (Bölüm 2): Model seçimi, oluşturulması ve eğitimi, özel Python sınayıcısı Python ve MQL5'te bir robot geliştirme (Bölüm 2): Model seçimi, oluşturulması ve eğitimi, özel Python sınayıcısı
Python ve MQL5'te bir alım-satım robotu geliştirmeye yönelik makale serisine devam ediyoruz. Bugün bir model seçme ve eğitme, test etme, çapraz doğrulama uygulama, ızgara arama (grid search) ve model topluluğu (ensemble) problemini çözeceğiz.