
"Çalışma Sırasında" Kullanıcı Panelinden Uzman Danışman Parametrelerini Değiştirme
İçindekiler
Giriş
1. Odaktaki Sorunlar
2. Uzman Danışmanın Yapısı
3. Kullanıcı Paneli ile Etkileşim
Sonuç
Giriş
Karmaşık Uzman Danışmanlar geliştirirken, harici parametrelerin sayısı çok fazla olabilir. Ayarların da sık sık manuel olarak değiştirilmesi gerekir, bu da büyük bir parametreler listesini düşündüğümüzde tüm süreci çok zaman alıcı hale getirir. Elbette, setleri önceden hazırlayıp kaydedebilirsiniz, ancak bazı durumlarda gereken bu olmayabilir. MQL5'in her zaman olduğu gibi kullanışlı olduğu yer burasıdır.
Alım satım yaparken bir Uzman Danışmanın parametrelerini "çalışma sırasında" değiştirmemizi sağlayacak bir kullanıcı paneli oluşturmaya çalışalım. Bu, manuel veya yarı otomatik modda alım satım yapanların dikkatini çekebilir. Herhangi bir değişiklik yapıldığında, parametreler daha sonra panelde daha fazla görüntülenmek üzere bir dosyaya yazılacak ve Uzman Danışman tarafından okunacaktır.
1. Odaktaki Sorunlar
Örnek olarak, JMA göstergesi yönünde bir pozisyon açan basit bir EA geliştireceğiz. Bu EA, mevcut sembol ve zaman aralığında tamamlanmış çubuklar üzerinde çalışacaktır. Harici parametreler Gösterge Dönemi, Zarar Durdur, Kâr Al, Ters ve Lotu içerecektir. Örneğimizde bu seçenekler gayet yeterli olacaktır.
Paneli açmak/kapatmak (Bilgi Panelini Aç/Kapat) ve Uzman Danışman parametre ayar modunu ("Çalışma Sırasında" Ayarı) etkinleştirmek/devre dışı bırakmak için iki parametre daha ekleyelim. Parametre sayısı fazla olduğunda, ek seçenekleri listenin en başına veya sonuna yerleştirmek kolay ve hızlı erişim için her zaman daha uygundur.
Şekil 1. Uzman Danışman parametrelerine sahip Bilgi Paneli
"Çalışma Sırasında" ayar modu varsayılan olarak devre dışıdır. Bu modu ilk kez etkinleştirdiğinizde, Uzman Danışman, o anda sahip olduğu tüm parametreleri kaydetmek için bir dosya oluşturur. Dosya yanlışlıkla silinirse de aynısı olur. Uzman Danışman, silme işlemini algılayacak ve dosyayı yeniden oluşturacaktır. "Çalışma Sırasında" ayar modu devre dışı bırakıldığında, Uzman Danışman harici parametreler ile yönlendirilecektir.
Bu mod etkinleştirilirse, Uzman Danışman dosyadaki parametreleri okuyacak ve gerekli değeri bilgi panelindeki herhangi bir parametreye tıklayarak seçebilecek veya açılan iletişim penceresinde yeni bir değer girebileceksiniz. Dosya verileri her yeni değer seçildiğinde güncellenecektir.
2. Uzman Danışmanın yapısı
Program küçük olmasına ve tüm fonksiyonlar tek bir dosyaya kolayca sığabilmesine rağmen, tüm proje bilgileri arasında gezinmek düzgün bir şekilde kategorize edildiğinde hala çok kolaydır. Bu nedenle, fonksiyonları türe göre kategorize etmek ve bunları ilk başta farklı dosyalarda tutarak daha sonra ana dosyaya eklemek en iyisidir. Aşağıdaki şekil, Çalışma Sırasında Uzman Danışman ile paylaşılan bir proje klasörünü ve tüm içerik dosyalarını göstermektedir. İçerik dosyaları ayrı bir klasöre (Include) yerleştirilir.
Şekil 2. MetaEditor'ın Navigatör penceresindeki proje dosyaları
Kod, içerik dosyaları ana dosyayla aynı klasörde olduğunda, aşağıdaki gibidir:
//+------------------------------------------------------------------+ //| CUSTOM LIBRARIES | //+------------------------------------------------------------------+ #include "Include/!OnChartEvent.mqh" #include "Include/CREATE_PANEL.mqh" #include "Include/FILE_OPERATIONS.mqh" #include "Include/ERRORS.mqh" #include "Include/ARRAYS.mqh" #include "Include/TRADE_SIGNALS.mqh" #include "Include/TRADE_FUNCTIONS.mqh" #include "Include/GET_STRING.mqh" #include "Include/GET_COLOR.mqh" #include "Include/ADD_FUNCTIONS.mqh"
Dosyaların nasıl ekleneceğine dair daha fazla bilgi MQL5 Referansı bölümünde bulunabilir.
Global değişkenlere - harici parametrelerin kopyalarına - ihtiyacımız olacaktır. Bunların değerleri, Uzman Danışmanın moduna göre harici parametrelerden veya dosyadan atanacaktır. Bu değişkenler tüm program kodu boyunca kullanılır: örneğin değerlerin bilgi panelinde görüntülenmesinde, alım satın fonksiyonlarında vb.
// COPY OF EXTERNAL PARAMETERS int gPeriod_Ind = 0; double gTakeProfit = 0.0; double gStopLoss = 0.0; bool gReverse = false; double gLot = 0.0;
Diğer tüm Uzman Danışmanlarda olduğu gibi, ana fonksiyonlarımız olacak: OnInit, OnTick ve OnDeinit. Ayrıca OnTimer fonksiyonu olacak. Bu fonksiyon, parametre dosyasının varlığını her saniye kontrol edecek ve yanlışlıkla silinmesi durumunda bunu geri yükleyecektir. Kullanıcı paneli ile etkileşime geçmemiz gerektiği için, OnChartEvent fonksiyonu da kullanılacaktır. Bu fonksiyon, diğer ilgili fonksiyonlarla birlikte ayrı bir dosyaya (!OnChartEvent.mqh) yerleştirilmiştir.
Ana dosyanın çekirdek kodu aşağıdaki gibidir:
#define szArrIP 5 // Size of the parameter array #define NAME_EXPERT MQL5InfoString(MQL5_PROGRAM_NAME) // Name of EA #define TRM_DP TerminalInfoString(TERMINAL_DATA_PATH) // Folder that contains the terminal data //+------------------------------------------------------------------+ //| STANDARD LIBRARIES | //+------------------------------------------------------------------+ #include <Trade/SymbolInfo.mqh> #include <Trade/Trade.mqh> //+------------------------------------------------------------------+ //| CUSTOM LIBRARIES | //+------------------------------------------------------------------+ #include "Include/!OnChartEvent.mqh" #include "Include/CREATE_PANEL.mqh" #include "Include/FILE_OPERATIONS.mqh" #include "Include/ERRORS.mqh" #include "Include/ARRAYS.mqh" #include "Include/TRADE_SIGNALS.mqh" #include "Include/TRADE_FUNCTIONS.mqh" #include "Include/GET_STRING.mqh" #include "Include/GET_COLOR.mqh" #include "Include/ADD_FUNCTIONS.mqh" //+------------------------------------------------------------------+ //| CREATING CLASS INSTANCES | //+------------------------------------------------------------------+ CSymbolInfo mysymbol; // CSymbolInfo class object CTrade mytrade; // CTrade class object //+------------------------------------------------------------------+ //| EXTERNAL PARAMETERS | //+------------------------------------------------------------------+ input int Period_Ind = 10; // Indicator Period input double TakeProfit = 100; // Take Profit (p) input double StopLoss = 30; // Stop Loss (p) input bool Reverse = false; // Reverse Position input double Lot = 0.1; // Lot //--- input string slash=""; // * * * * * * * * * * * * * * * * * * * sinput bool InfoPanel = true; // On/Off Info Panel sinput bool SettingOnTheFly = false; // "On The Fly" Setting //+------------------------------------------------------------------+ //| GLOBAL VARIABLES | //+------------------------------------------------------------------+ int hdlSI=INVALID_HANDLE; // Signal indicator handle double lcheck=0; // For the check of parameter values bool isPos=false; // Position availability //--- COPY OF EXTERNAL PARAMETERS int gPeriod_Ind = 0; double gTakeProfit = 0.0; double gStopLoss = 0.0; bool gReverse = false; double gLot = 0.0; //+------------------------------------------------------------------+ //| EXPERT ADVISOR INITIALIZATION | //+------------------------------------------------------------------+ void OnInit() { if(NotTest()) { EventSetTimer(1); } // If it's not the tester, set the timer //--- Init_arr_vparams(); // Initialization of the array of parameter values SetParameters(); // Set the parameters GetIndicatorsHandles(); // Get indicator handles NewBar(); // New bar initialization SetInfoPanel(); // Info panel } //+------------------------------------------------------------------+ //| CURRENT SYMBOL TICKS | //+------------------------------------------------------------------+ void OnTick() { // If the bar is not new, exit if(!NewBar()) { return; } else { TradingBlock(); } } //+------------------------------------------------------------------+ //| TIMER | //+------------------------------------------------------------------+ void OnTimer() { SetParameters(); SetInfoPanel(); } //+------------------------------------------------------------------+ //| EXPERT ADVISOR DEINITIALIZATION | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Get the deinitialization reason code if(NotTest()) { { Print(getUnitReasonText(reason)); } //--- // When deleting from the chart if(reason==REASON_REMOVE) { // Delete all objects created by the Expert Advisor DeleteAllExpertObjects(); //--- if(NotTest()) { EventKillTimer(); } // Stop the timer IndicatorRelease(hdlSI); // Delete the indicator handle } }
Ayrıca ana dosyaya birkaç fonksiyon daha ekledim:
- GetIndicatorsHandles – gösterge işleyiciyi elde eder.
- NewBar – yeni çubuk etkinliğini belirler.
- SetParameters – moda göre parametreleri ayarlar.
- iZeroMemory – bazı değişkenleri ve dizileri sıfırlar.
//+------------------------------------------------------------------+ //| SETTING PARAMETERS IN TWO MODES | //+------------------------------------------------------------------+ // If this variable is set to false, the parameters in the file are read from the array // where they are saved for quick access after they have been read for the first time. // The variable is zeroed out upon the change in the value on the panel. bool flgRead=false; double arrParamIP[]; // Array where the parameters from the file are saved //--- void SetParameters() { // If currently in the tester or // in real time but with the "On The Fly" Setting mode disabled if(!NotTest() || (NotTest() && !SettingOnTheFly)) { // Zero out the variable and parameter array flgRead=false; ArrayResize(arrParamIP,0); //--- // Check the Indicator Period for correctness if(Period_Ind<=0) { lcheck=10; } else { lcheck=Period_Ind; } gPeriod_Ind=(int)lcheck; //--- gStopLoss=StopLoss; gTakeProfit=TakeProfit; gReverse=Reverse; //--- // Check the Lot for correctness if(Lot<=0) { lcheck=0.1; } else { lcheck=Lot; } gLot=lcheck; } else // If "On The Fly" Setting mode is enabled { // Check whether there is a file to write/read parameters to/from the file string lpath=""; //--- // If the folder exists if((lpath=CheckCreateGetPath())!="") { // Write or read the file WriteReadParameters(lpath); } } }
SetParameters fonksiyonunun kaynak kodu basit ve anlaşılırdır. WriteReadParameters fonksiyonuna daha yakından bakalım. Burada her şey oldukça basit. İlk olarak parametreleri içeren dosyanın mevcut olup olmadığını kontrol ederiz. Varsa, dosyayı okuruz ve bir diziye GetValuesParamsFromFile fonksiyonunu kullanarak parametre değerlerini yazarız. Dosya yoksa, kendisine yazılan mevcut harici parametreler ile oluşturulacaktır.
Aşağıda, yukarıda açıklanan eylemlerin uygulanması için daha ayrıntılı yorumlar içeren kod yer almaktadır:
//+------------------------------------------------------------------+ //| WRITE DATA TO FILE | //+------------------------------------------------------------------+ void WriteReadParameters(string pth) { string nm_fl=pth+"ParametersOnTheFly.ini"; // File name and path //--- // Get the file handle to read the file int hFl=FileOpen(nm_fl,FILE_READ|FILE_ANSI); //--- if(hFl!=INVALID_HANDLE) // If the handle has been obtained, the file exists { // Get parameters from the file if(!flgRead) { // Set the array size ArrayResize(arrParamIP,szArrIP); //--- // Fill the array with values from the file flgRead=GetValuesParamsFromFile(hFl,arrParamIP); } //--- // If the array size is correct,... if(ArraySize(arrParamIP)==szArrIP) { // ...set the parameters to the variables //--- // Check the Indicator Period for correctness if((int)arrParamIP[0]<=0) { lcheck=10; } else { lcheck=(int)arrParamIP[0]; } gPeriod_Ind=(int)lcheck; //--- gTakeProfit=arrParamIP[1]; gStopLoss=arrParamIP[2]; gReverse=arrParamIP[3]; //--- // Check the Lot for correctness if(arrParamIP[4]<=0) { lcheck=0.1; } else { lcheck=arrParamIP[4]; } gLot=lcheck; } } else // If the file does not exist { iZeroMemory(); // Zero out variables //--- // When creating the file, write current parameters of the Expert Advisor //--- // Get the file handle to write to the file int hFl2=FileOpen(nm_fl,FILE_WRITE|FILE_CSV|FILE_ANSI,""); //--- if(hFl2!=INVALID_HANDLE) // If the handle has been obtained { string sep="="; //--- // Parameter names and values are obtained from arrays in the ARRAYS.mqh file for(int i=0; i<szArrIP; i++) { FileWrite(hFl2,arr_nmparams[i],sep,arr_vparams[i]); } //--- FileClose(hFl2); // Close the file //--- Print("File with parameters of the "+NAME_EXPERT+" Expert Advisor created successfully."); } } //--- FileClose(hFl); // Close the file }
WriteReadParameters ve GetValuesParamsFromFile fonksiyonları FILE_OPERATIONS.mqh dosyasında bulunabilir.
Fonksiyonlardan bazıları, "Diğer Uygulamalar için MetaTrader 5 Kotasyonları Nasıl Hazırlanır?" başlıklı önceki makalemde zaten anlatılmıştır, bu yüzden burada bunların üzerinde durmayacağız. Çok anlaşılır olmalarından ve kapsamlı bir şekilde yorumlanmalarından dolayı alım satım fonksiyonlarına dair herhangi bir zorluk yaşamamanız lazım. Burada makalenin ana konusuna odaklanacağız.
3. Kullanıcı Paneli ile Etkileşim
!OnChartEvent.mqh dosyası, kullanıcı paneliyle etkileşime yönelik fonksiyonlar içerir. Birçok fonksiyonda kullanılan değişkenler ve diziler, ilk başta global kapsamda bildirilir:
// Current value on the panel or // entered in the input box string currVal=""; bool flgDialogWin=false; // Flag for panel existence int szArrList=0,// Size of the option list array number=-1; // Parameter number in the panel list string nmMsgBx="", // Name of the dialog window nmValObj=""; // Name of the selected object //--- // Option list arrays in the dialog window string lenum[],lenmObj[]; //--- // colors of the dialog window elements color clrBrdBtn=clrWhite, clrBrdFonMsg=clrDimGray,clrFonMsg=C'15,15,15', clrChoice=clrWhiteSmoke,clrHdrBtn=clrBlack, clrFonHdrBtn=clrGainsboro,clrFonStr=C'22,39,38';
Bundan sonra olayları işleyen ana fonksiyon gelir. Örneğimizde, iki olayı ele almamız gerekiyor:
- CHARTEVENT_OBJECT_EDIT olayı – grafik nesnesine sola tıklama.
- CHARTEVENT_OBJECT_EDIT olayı – Düzenleme grafik nesnesinde metin düzenlemesinin sonu.
Diğer MQL5 olaylarına dair daha fazla bilgiyi MQL5 Referansı içinde okuyabilirsiniz.
İlk olarak, "Çalışma Sırasında" ayar modunun etkin olması (SettingOnTheFly) koşuluyla, olayları yalnızca gerçek zamanlı olarak işlemek için bir kontrol ayarlayalım. Olayların işlenmesi ayrı fonksiyonlar ile ele alınacaktır: ChartEvent_ObjectClick ve ChartEvent_ObjectEndEdit.
//+------------------------------------------------------------------+ //| USER EVENTS | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { // If the event is real time and the "On The Fly" setting mode is enabled if(NotTest() && SettingOnTheFly) { //+------------------------------------------------------------------+ //| THE CHARTEVENT_OBJECT_CLICK EVENT | //+------------------------------------------------------------------+ if(ChartEvent_ObjectClick(id,lparam,dparam,sparam)) { return; } //--- //+------------------------------------------------------------------+ //| THE CHARTEVENT_OBJECT_ENDEDIT EVENT | //+------------------------------------------------------------------+ if(ChartEvent_ObjectEndEdit(id,lparam,dparam,sparam)) { return; } } //--- return; }
Listedeki nesneye tıkladığınızda, bilgi paneli üzerinde, başka bir değer seçmenizi veya giriş kutusuna yeni bir değer girmenize olanak sağlayan bir iletişim penceresi görünecektir.
Şekil 3. Seçilen parametre değerinde değişiklik için iletişim penceresi
Bunun nasıl çalıştığına daha yakından bakalım. Program, bir grafik nesnesine tıklandığında, bir grafik nesnesine gerçekten bir tıklama olup olmadığını olay tanımlayıcısı ile kontrol etmek için ilk olarak ChartEvent_ObjectClick fonksiyonunu kullanır.
İletişim penceresinin grafiğin ortasında açılmasını istiyorsanız, grafik boyutunu bilmeniz gerekir. Bu, ChartGetInteger fonksiyonunda CHART_WIDTH_IN_PIXELS ve CHART_HEIGHT_IN_PIXELS özelliklerinin belirtilmesi ile yapılabilir. Daha sonra program DialogWindowInfoPanel'e geçer. MQL5 Referansı bölümünde tüm grafik özelliklerine aşinalık kazanabilirsiniz.
Aşağıda, yukarıdaki eylemlerin uygulanmasına yönelik kod yer almaktadır:
//+------------------------------------------------------------------+ //| THE CHARTEVENT_OBJECT_CLICK EVENT | //+------------------------------------------------------------------+ bool ChartEvent_ObjectClick(int id,long lparam,double dparam,string sparam) { // If there was an event of clicking on a graphical object if(id==CHARTEVENT_OBJECT_CLICK) // id==1 { Get_STV(); // Get all data on the symbol //--- string clickedChartObject=sparam; // Name of the clicked object //--- // Get the chart size width_chart=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0); height_chart=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,0); //--- DialogWindowInfoPanel(clickedChartObject); } //--- return(false); }
İlk olarak iletişim penceresinin o anda açık olup olmadığını DialogWindowInfoPanel fonksiyonunu kullanarak kontrol ederiz. Pencere bulunamazsa, GetNumberClickedObjIP fonksiyonu, tıklamanın bilgi panelindeki listeden bir nesneyle ilişkili olup olmadığını kontrol eder. Tıklanan nesne listeden bir nesneyse, fonksiyon nesneler dizisinden ilgili öğe sayısını döndürür. InitArraysAndDefault fonksiyonu, bu sayıyı kullanarak iletişim penceresindeki liste dizi boyutunu ve varsayılan değerleri belirler. Tüm eylemler başarılıysa iletişim penceresi görünür.
DialogWindowInfoPanel fonksiyonu iletişim penceresinin zaten açık olduğunu belirlerse, program, iletişim penceresinde bir nesneye tıklama olup olmadığını kontrol eder. Örneğin iletişim penceresi açıldığında panelde o anda değeri görüntülenen satır seçili görünecektir. Listedeki başka bir seçeneğe tıklarsanız, program tıklanan iletişim penceresi listesi seçeneğini seçen SelectionOptionInDialogWindow fonksiyonunu kullanacaktır.
Zaten seçili olan liste seçeneğine tıklarsanız, bu nesne düzenlenecek bir nesne olarak tanımlanacaktır, böylece kutuya tıkladığınızda yeni bir değer girilebilmesi için bir giriş kutusu görünecektir. SetEditObjInDialogWindow fonksiyonu, giriş kutusunun ayarlanmasından sorumludur.
Son olarak Apply (Uygula) butonuna tıklandığında program değerin değiştirilip değiştirilmediğini kontrol edecektir. Değiştirilmişse, panelde yeni değer görünecek ve dosyaya yazılacaktır.
İletişim penceresinin ana fonksiyonunun kodu aşağıda yer almaktadır:
//+------------------------------------------------------------------+ //| DIALOG WINDOW OF THE INFO PANEL | //+------------------------------------------------------------------+ void DialogWindowInfoPanel(string clickObj) { // If there is currently no dialog window if(!flgDialogWin) { // Get the object number in the array // Exit if none of the parameters displayed on the panel has been clicked if((number=GetNumberClickedObjIP(clickObj))==-1) { return; } //--- // Initialization of default values //and determination of the list array size if(!InitArraysAndDefault()) { return; } //--- // Set the dialog window SetDialogWindow(); //--- flgDialogWin=true; // Mark the dialog window as open ChartRedraw(); } else // If the dialog window is open { // Set the input box for the modification of the value SetEditObjInDialogWindow(clickObj); //--- // If one of the buttons in the dialog box is clicked if(clickObj=="btnApply" || clickObj=="btnCancel") { // If the Apply button is clicked if(clickObj=="btnApply") { // Compare values on the panel with the ones on the list // If the value on the list is different from the one that is currently displayed on the panel // (which means it is different from the one in the file), // ...change the value on the panel and update the file if(currVal!=ObjectGetString(0,nmValObj,OBJPROP_TEXT)) { // Update the value on the panel ObjectSetString(0,nmValObj,OBJPROP_TEXT,currVal); ChartRedraw(); //--- // Read all data on the panel and write it to the file WriteNewData(); } } //--- DelDialogWindow(lenmObj); // Delete the dialog window iZeroMemory(); // Zero out the variables //--- // Update the data SetParameters(); GetHandlesIndicators(); SetInfoPanel(); //--- ChartRedraw(); } else // If neither Apply nor Cancel has been clicked { // Selection of the dialog window list option SelectionOptionInDialogWindow(clickObj); //--- ChartRedraw(); } } }
Giriş kutusuna her yeni bir değer girildiğinde, CHARTEVENT_OBJECT_EDIT olayı oluşturulur ve program ChartEvent_ObjectEndEdit fonksiyonuna geçer. İletişim penceresindeki değer değiştirilmişse, girilen değer saklanacak, bunun doğruluğu kontrol edilecek ve bu değer listedeki nesneye atanacaktır. Bunu aşağıdaki kodda daha ayrıntılı olarak görebilirsiniz:
//+------------------------------------------------------------------+ //| THE CHARTEVENT_OBJECT_ENDEDIT EVENT | //+------------------------------------------------------------------+ bool ChartEvent_ObjectEndEdit(int id,long lparam,double dparam,string sparam) { if(id==CHARTEVENT_OBJECT_ENDEDIT) // id==3 { string editObject=sparam; // Name of the edited object //--- // If the value has been entered in the input box in the dialog window if(editObject=="editValIP") { // Get the entered value currVal=ObjectGetString(0,"editValIP",OBJPROP_TEXT); //--- // (0) Period Indicator if(number==0) { // Correct the value if it is wrong if(currVal=="0" || currVal=="" || SD(currVal)<=0) { currVal="1"; } //--- // Set the entered value ObjectSetString(0,"enumMB0",OBJPROP_TEXT,currVal); } //--- // (4) Lot if(number==4) { // Correct the value if it is wrong if(currVal=="0" || currVal=="" || SD(currVal)<=0) { currVal=DS(SS.vol_min,2); } //--- // Set the entered value ObjectSetString(0,"enumMB0",OBJPROP_TEXT,DS2(SD(currVal))); } //--- // (1) Take Profit (p) // (2) Stop Loss (p) if(number==1 || number==2) { // Correct the value if it is wrong if(currVal=="0" || currVal=="" || SD(currVal)<=0) { currVal="1"; } //--- // Set the entered value ObjectSetString(0,"enumMB1",OBJPROP_TEXT,currVal); } //--- DelObjbyName("editValIP"); ChartRedraw(); } } //--- return(false); }
Çalışma halindeki Uzman Danışman aşağıdaki videoda görülebilir:
Sonuç
Makalenin sonuna eklenen sıkıştırılmış dosyalar daha detaylı inceleme için indirilebilir.
Umarım bu makale, MQL5 öğrenmeye yeni başlayanların, verilen basit örnekleri kullanarak birçok soruya hızlı yanıt bulmalarına yardımcı olacaktır. Sağlanan kod parçacıklarındaki bazı kontrolleri kasıtlı olarak dahil etmedim.
Örneğin, grafiğin yüksekliğini/genişliğini iletişim penceresi açıkken değiştirirseniz, iletişim penceresi otomatik olarak ortalanmayacaktır. Bunu listeden başka bir seçenek seçerek tamamlarsanız, ilgili satırı seçmeye yarayan nesne önemli ölçüde kaydırılacaktır. Bu sizin ev ödeviniz olsun. Programlama pratiği yapmak çok önemlidir ve ne kadar çok pratik yaparsanız o kadar iyi olursunuz.
İyi şanslar!
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/572





- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz