MetaTrader 5 herunterladen

Spontane Änderung der Expert-Advisor-Parameter vom Bedienfeld aus

27 Juni 2016, 16:44
Anatoli Kazharski
0
339

Inhalt

Einleitung
1. Behandelte Themen
2. Struktur des Expert Advisors
3. Interaktion mit dem Bedienfeld
Fazit


Einleitung

Bei der Erstellung eines Expert Advisors kann die Anzahl externer Parameter sehr groß sein. Die Einstellungen müssen oft manuell geändert werden, was den gesamten Prozess aufgrund der vielen Parameter zeitaufwendig macht. Es ist natürlich möglich, Einstellungen im Vorhinein vorzubereiten und sie zu speichern, aber das ist in manchen Fällen möglicherweise nicht das Richtige. In solchen Fällen ist MQL5 sehr praktisch.

Erstellen wir also ein Bedienfeld, das es uns erlaubt, die Parameter eines Expert Advisors spontan zu ändern. Das ist für Benutzer interessant, die manuell oder semi-automatisch handeln wollen. Nach jeder Änderung werden die Parameter in eine Datei geschrieben, von der aus sie dann vom Expert Advisor gelesen werden, um dann auf dem Bedienfeld angezeigt zu werden.


1. Behandelte Themen

Zu Demonstrationszwecken werden wir einen einfachen Expert Advisor erstellen, der eine Position im Verzeichnis des JMA-Indikators öffnet. Der Expert Advisor wird an fertiggestellten Balken des aktuellen Symbols und Zeitrahmens arbeiten. Externe Parameter sind Indicator Period, Stop Loss, Take Profit, Reverse und Lot. Diese Optionen sind für unser Beispiel ausreichend.

Fügen wir zwei zusätzliche Parameter hinzu, um das Feld an- und auszuschalten (On/Off Info Panel) und die Parametereinstellungen der Expert-Advisor zu aktivieren/deaktivieren ("On The Fly" Setting). Bei einer großen Anzahl an Parametern ist es immer einfacher, zusätzliche Optionen am Anfang oder Ende der Liste anzubringen, um einen einfachen und schnellen Zugriff zu garantieren.

Abb. 1. Bedienfeld mit Parametern des Expert Advisors

Abb. 1. Bedienfeld mit Parametern des Expert Advisors

Spontane Einstellungen sind standardmäßig deaktiviert. Bei der ersten Aktivierung dieser Einstellung erstellt der Expert Advisor eine Datei, um alle aktuellen Parameter zu speichern. Das gleiche trifft zu, wenn die Datei versehentlich gelöscht wird. Der Expert Advisor erkennt, dass etwas gelöscht wurde und stellt die Datei wieder her. Wenn die spontane Einstellung deaktiviert ist, wird der Expert Advisor von externen Parametern gesteuert.

Wenn diese Einstellung aktiviert ist, wird der Expert Advisor die Parameter der Datei lesen und Sie können entweder den gewünschten Wert auswählen, indem Sie auf einen beliebigen Parameter des Bedienfelds klicken, oder einen neuen Wert im Pop-Up-Fenster eingeben. Die Daten in der Datei werden mit jeder neuen Auswahl eines Wertes aktualisiert.


2. Struktur des Expert Advisors

Obwohl das Programm klein ist und alle Funktionen leicht in eine Datei passen, ist es immer noch einfacher, die Projektinformationen zu managen, wenn diese richtig kategorisiert sind. Daher ist es am besten, die Funktionen nach Typen zu kategorisieren und sie von Anfang an in verschiedenen Dateien zu speichern, um sie später in die Stammdatei aufzunehmen. Die untere Abbildung zeigt einen gemeinsamen Projektordner mit dem Spontanen Expert Advisor und allen "Include"-Dateien. Die "Include"-Dateien werden in einem separaten Ordner gespeichert (Include).

Abb. 2. Projektdateien im Navigationsfenster des MetaEditor

Abb. 2. Projektdateien im Navigationsfenster des MetaEditor

Wenn die "Include"-Dateien im gleichen Ordner sind wie die Stammdatei lautet der Code wie folgt:

//+------------------------------------------------------------------+
//| 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"

Weitere Informationen über die Inklusion von Dateien können im Nachschlagewerk MQL5 gefunden werden.

Wir brauchen globale Variablen - Kopien von externen Parametern. Ihre Werte werden entweder von externen Parametern zugeteilt, oder von der Datei, je nach Einstellung des Expert Advisors. Diese Variablen werden im gesamten Programm-Code benutzt, zum Beispiel bei der Darstellung von Werten im Bedienfeld, bei Handelsfunktionen, etc.

// COPY OF EXTERNAL PARAMETERS
int    gPeriod_Ind = 0;
double gTakeProfit = 0.0;
double gStopLoss   = 0.0;
bool   gReverse    = false;
double gLot        = 0.0;

Wie bei allen anderen Expert Advisors haben wir folgende Hauptfunktionen: OnInit, OnTick und OnDeinit. Und es gibt auch die OnTimer-Funktion. Jede Sekunde wird sie die Existenz der Parameter-Datei kontrollieren und wiederherstellen, falls sie versehentlich gelöscht wurde. Da wir mit dem Bedienfeld arbeiten müssen, verwenden wir auch die OnChartEvent-Funktion. Diese Funktion wird mit anderen verwandten Funktionen in eine separate Datei gespeichert (!OnChartEvent.mqh).

Der Kern-Code der Stammdatei lautet folgendermaßen:

#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
     }
  }

Ich habe auch ein paar weitere Funktionen in die Stammdatei eingearbeitet.

  • GetIndicatorsHandles – holt den Indikator-Identifikator.
  • NewBar – bestimmt das Ereignis "Neuer Balken".
  • SetParameters – stellt Parameter je nach Modus ein.
  • iZeroMemory – stellt einige Variablen und Arrays auf Null
Der Quellcode für diese Funktionen ist in den an diesen Artikel angehängten Dateien zu finden. Wir werden hier nur die Funktion "SetParameters" bewerten (erklärende Kommentare stehen im Code zur Verfügung):
//+------------------------------------------------------------------+
//| 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);
        }
     }
  }

Der Quellcode der Funktion "SetParameters" ist einfach. Werfen wir einen genaueren Blick auf die Funktion "WriteReadParameters". Alles ist ziemlich einfach hier. Als erstes kontrollieren wir, ob die Datei mit Parametern existiert. Wenn dem so ist, lesen wir die Datei und schreiben Parameterwerte auf einen Array mit der Funktion "GetValuesParamsFromFile". Wenn die Datei noch nicht existiert, wird sie mit aktuellen externen Parametern erstellt.

Unten ist der Code mit detaillierten Kommentaren für die Implementierung der oben beschriebenen Ereignisse:

//+------------------------------------------------------------------+
//| 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
  }

Die Funktionen "WriteReadParameters" und "GetValuesParamsFromFile" sind in der Datei FILE_OPERATIONS.mqh.

Einige der Funktionen wurden bereits in meinem vorigen Artikel, "Wie erstelle ich MetaTrader5-Angebote für andere Applikationen", beschrieben und werden daher hier nicht noch einmal erwähnt. Sie sollten keinerlei Schwierigkeiten mit den Handelsfunktionen haben, da diese sehr einfach und gut dokumentiert sind. Wir befassen uns nun mit dem Hauptthema des Artikels.


3. Interaktion mit dem Bedienfeld

Die Datei "!OnChartEvent.mqh" enthält Funktionen für Interaktionen mit dem Bedienfeld. Variablen und Arrays, die in vielen Funktionen verwendet werden, werden im globalen Umfang gleich am Anfang festgestellt.

// 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';

Danach folgt die Hauptfunktion, die Ereignisse identifiziert. In unserem Beispiel müssen wir zwei Ereignisse identifizieren:

  • Das Ereignis CHARTEVENT_OBJECT_CLICK – linker Mausklick auf das graphische Objekt.
  • Das Ereignis CHARTEVENT_OBJECT_EDIT – Ende der Textbearbeitung im graphischen Objekt "Bearbeitung".

Lesen Sie mehr über weitere MQL5-Ereignisse im Nachschlagewerk MQL5.

Setzen wir zuerst eine Kontrolle für die Identifikation von Ereignissen in Echtzeit fest, unter der Bedingung, dass Spontane Einstellungen aktiviert sind (SettingOnTheFly). Die Identifikation von Ereignissen wird von separaten Funktionen ausgeführt: ChartEvent_ObjectClick und 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;
  }

Wenn Sie auf das zu der Liste gehörende Objekt klicken, wird ein Dialogfenster auf dem Infofeld auftauchen, mit dem Sie weitere Werte auswählen oder einen neuen Wert in das Input-Feld eingeben können.

Abb. 3. Dialogfenster für Wertänderungen der ausgewählten Parameter

Abb. 3. Dialogfenster für Wertänderungen der ausgewählten Parameter

Werfen wir einen genaueren Blick auf die Funktionsweise. Wenn ein graphisches Objekt angeklickt wurde, verwendet das Programm zuerst die Funktion ChartEvent_ObjectClick um mit dem Ereignis-Identifikator zu kontrollieren, ob tatsächlich auf ein graphisches Objekt geklickt wurde.

Wenn Sie wollen, dass sich das Dialogfenster in der Mitte des Diagramms öffnet, müssen Sie die Diargammgröße kennen. Diese bekommen Sie, indem Sie die Eigenschaften "Diagrammbreite in Pixeln" (CHART_WIDTH_IN_PIXELS) und "Diagrammhöhe in Pixeln" (CHART_HEIGHT_IN_PIXELS) in die Funktion ChartGetInteger eingeben. Das Programm schaltet dann um zu DialogWindowInfoPanel. Im Nachschlagewerk MQL5 können Sie sich mit allen Diagrammeigenschaften vertraut machen.

Unten ist der Code für die Implementierung der obigen Aktionen:

//+------------------------------------------------------------------+
//| 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);
  }

Mit der Funktion DialogWindowInfoPanel kontrollieren wir zuerst, ob das Dialogfenster gerade offen ist. Wenn das Fenster nicht gefunden wurde, kontrolliert die Funktion GetNumberClickedObjIP ob der Klick in Bezug zu einem Objekt der Liste des Infofeldes war. Wenn das angeklickte Objekt das Objekt von der Liste ist, wird die Funktion die relevante Elementnummer des Array der Objekte zurückgeben. Mit dieser Nummer bestimmt die Funktion InitArraysAndDefault schließlich die Größe der Liste im Dialogfenster und Standardwerte. Wenn alle Ereignisse erfolgreich waren, wird das Dialogfenster erscheinen.

Wenn die Funktion DialogWindowInfoPanel bestimmt, dass das Dialogfenster immer offen ist, wird das Programm überprüfen, ob ein Objekt im Dialogfenster angeklickt wurde. Zum Beispiel, nach dem Öffnen des Dialogfensters wird die Zeile, dessen Wert gerade in dem Feld angezeigt wird, als ausgewählt erscheinen. Wenn Sie eine weitere Option in der Liste auswählen, wird das Programm die Funktion SelectionOptionInDialogWindow ausführen, die die Dialogfensterliste auswählt.

Wenn Sie auf die Listenoption klicken, die gerade ausgewählt ist, wird das Objekt als ein Objekt identifiziert, das bearbeitet werden muss. Ein Eingabefeld wird erscheinen, damit ein neuer Wert eingegeben werden kann, wenn Sie auf das Feld klicken. Die Funktion SetEditObjInDialogWindow ist für die Einstellung des Eingabefeldes verantwortlich.

Und schließlich wird das Programm, wenn die Apply-Taste geklickt wurde, überprüfen, ob der Wert geändert wurde. Wenn dem so ist, wird der neue Wert auf dem Bedienfeld erscheinen und in die Datei geschrieben.

Der Code der Hauptfunktion des Dialogfensters ist unten gegeben:

//+------------------------------------------------------------------+
//| 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();
        }
     }
  }

Jedes Mal wenn ein neuer Wert in das Inputfeld eingegeben wird, wird das Ereignis CHARTEVENT_OBJECT_EDIT erstellt und das Programm schaltet um zur Funktion ChartEvent_ObjectEndEdit. Wenn der Wert des Dialogfensters verändert wurde, wird der eingegebene Wert gespeichert, auf Richtigkeit überprüft und den Objekten in der Liste zugeteilt. Unten ist es detaillierter in Code geschrieben:

//+------------------------------------------------------------------+
//| 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);
  }

Der Expert Advisor in Action ist in diesem Video zu sehen:


Fazit

Die komprimierten Dateien am Ende des Artikels können für nähere Betrachtung heruntergeladen werden.

Ich hoffe, dieser Artikel wird mit diesen einfachen Beispielen MQL5-Neulingen helfen, schnelle Antworten zu finden. Ich habe absichtlich einige Kontrollen der zur Verfügung gestellten Codeschnipsel ausgelassen.

Wenn Sie zum Beispiel die Diagrammhöhe oder -breite ändern, wenn das Dialogfenster offen ist, wird das Dialogfenster nicht automatisch in der Mitte sein. Und wenn Sie eine weitere Option von der Liste auswählen, wird das Objekt, mit dem die relevante Zeile ausgewählt wurde, erheblich verschoben. Dies ist die Hausaufgabe. Programmieren zu üben ist sehr wichtig, und je mehr man übt, desto besser wird man.

Viel Erfolg!

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/572

Beigefügte Dateien |
onthefly_en.zip (26.38 KB)
Maschinelles Lernen: Wie Support Vector Machines beim Handeln verwendet werden können Maschinelles Lernen: Wie Support Vector Machines beim Handeln verwendet werden können

Support Vector Machines wurden lange in Bereichen wie Bioinformatik und angewandter Mathematik verwendet, um komplexe Datensätze zu evaluieren und nützliche Muster für die Datenklassifikation zu extrahieren. In diesem Artikel wird besprochen, was eine Support Vector Machine ist, wie sie arbeitet und warum sie so nützlich bei der Extraktion komplexer Muster ist. Danach werden wir untersuchen, wie sie auf dem Markt angewandt werden können und vielleicht beim Handeln Ratschläge geben. Mit dem "Support Vector Machine Learning Tool" bietet der Artikel Beispiele, anhand derer Leser mit ihrem eigenen Handeln experimentieren können.

Die Grundlagen von MQL5 Strings Die Grundlagen von MQL5 Strings

Dieser Artikel behandelt alle Funktionsweisen von Strings in MQL5. Er ist vor allem für neue MQL5-Programmierer interessant, und für erfahrene Entwickler ist es eine gute Möglichkeit, ihre Kenntnisse zusammenzufassen und zu systematisieren.

Grafische Interfaces II: Das Menu-Item-Element (Kapitel 1) Grafische Interfaces II: Das Menu-Item-Element (Kapitel 1)

In dem zweiten Teil dieser Serie, werden wir im Detail auf die Entwicklung von Interface Elementen, wie einen Hauptmenü und Kontextmenüs eingehen. Wir werden auch das Zeichnen und das Entwickeln einer speziellen Klasse für diese Elemente berücksichtigen. Wir werden ausführlich den Fragen der Verwaltung von Events und benutzerdefinierten Events nachgehen.

Universeller Expert Advisor: Ein benutzerdefiniertes Trailing Stop (Part 6) Universeller Expert Advisor: Ein benutzerdefiniertes Trailing Stop (Part 6)

Der sechste Teil des Artikels über den universellen Expert Advisor beschreibt die Verwendung eines Trailingstops. Dieser Artikel führt sie durch die Erstellung eines Trailingstop-Moduls, welches einheitliche Regeln verwendet, sowie durch den Vorgang, wie dieses Modul der Trading Engine hinzugefügt wird, damit es automatisch Positionen verwaltet.