Die Orders-Berechnung in einem großen Programm

Сергей Ковалев | 30 November, 2015

Wenn eine Handlungsstrategie eine Arbeit mit der geringen Anzahl der Orders vermutet, zum Beispiel, nur mit einer Order Buy und mit einer Order Sell, dann der Experte, der diese Strategie realisiert, kann keine Orders berechnen, sondern kann die Handlungsentscheidungen treffen, welche nach seiner Ideologie orientiert sind. Das heißt, man geht dann von der Bedienung aus, dass keine als nur eine eingerichtete Order im Terminal sein kann.

Diese Art ist im Prinzip annehmbar, ist aber nur für ein kleines Programm geeignet und kann nicht um Universalität beanspruchen. Tatsächlich, was soll dieser Experte machen, wenn über einem Währungswerkzeug zwei oder noch mehrere gleiche Orders geraten werden. Man kann widersprechen, dass die Handlungsstrategie keine solche Situation vornimmt und die soll nicht kommen. Dieser gerechte Einwand ist richtig, aber es zeichnet sich durch Unzulänglichkeit und Begrenzung dieser Ideologie.

Ab dem Moment, wenn der Trader genug Erfahrung gesammelt hat, um das Handeln mit mehreren Orders zu führen, darunter Pending Orders, entsteht die Notwendigkeit, die Orders zu berechnen, weil die Pending Orders zu den geöffneten Orders werden können. Außerdem weiß man, dass der Trader eine Order immer manuell öffnen kann, und vergessen, dass ein Experte schon im Terminal arbeitet. Es ist auch eine Situation möglich, in der mehrere Trader gleichzeitig auf dem gleichen Konto handeln. Und in einem allgemeinen Fall kann die Handelsstrategie selbst eine große Menge der Orders vornehmen.

Versuchen wir zu verstehen, wie eine Orders-Berechnung in einem großen Programm besser eingestellt werden kann.

1. Die Charakteristika des Raums und allgemeine Überlegungen

Halten wir uns kurz an den Charakteristiken des Raums, in dem unser Programm funktioniert.

1. Vor allem möchten wir natürlich erfahren (Das heißt, dass die Dateien vom Programm aufgerufen werden), wie viel und welche Orders wir haben. Dabei reicht es nicht, einfach zu sagen, dass wir 3 Sell-Orders oder 4 Buy-Orders haben. Wahrscheinlich enthält jedes Intelligentes Handelssystem einen Steuerungsalgorithmus über den Orderparameter StopLoss und TakeProfit,und für die Pending Orders enthält es noch die Position der Order - OpenPrice. Außerdem brauchen wir das Wissen , wie viel jede Order kostet, wie lange ihre Gültigkeit ist, von welchem Programm es erstellt wurde.

2. Ticks Jede Information hat einen Sinn, wenn es rechtzeitig betrachtet wird. Jeder Experte hat mit Preisnotierungen zu tun, welche ständig in den Terminal kommen. Es ist offensichtlich, dass die Situation sich mit Orders in jeder Preisänderung ändern kann, das heißt, man muss eine "neue Berechnung" bei jedem neuen Tick durchführen.

3. Zum allgemeinen Charakteristiken kann man das Währungswerkzeug beziehen, in deren Fenster der Experte hinzugefügt wurde.


Mit der Rücksicht auf diese einfachen Informationen können wir die allgemeinen Prinzipien des Programm-Aufbaus bestimmen, der auch die Berechnung der Orders enthält.

Erstens, außer der Orders-Berechnung-Aufgabe kann und muss das Handelssystem andere Aufgaben lösen, zum Beispiel, die Qualität und den Bestand der Orders zu analysieren und davon ausgehend die Handels-Entscheidung zu treffen. Jede Analyse einer entstandenen Situation kann erst in dem Fall durchgeführt werden, falls sie bekannt ist. Das heißt, dass der Code des Programms, der für die Orders-Berechnung verantwortlich ist, muss früher, als andere Codes ausgeführt werden. Am besten ist es, wenn der Code der Berechnung in Form von einer einzelnen Funktion gestaltet wird. Nennen wir sie Terminal(), denn das Wichtigste ist, was sie tun wird - sie wird die Orders sichten, die im Terminal angezeigt werden.

Zweitens, die Informationen, welche mit der Funktion Terminal()angesammelt werden, müssen für andere Funktionen erreichbar sein, deshalb sind Variablen, welche die nützliche Information tragen, müssen auf dem globalen Level angezeigt werden (nicht mit der GlobalVariable verwechseln).

Drittens, da wir serienweise mit den Informationen zu tun haben , wird es logisch, die Berechnung auf Basis Arrays Orders zuzuordnen.


2. Die Struktur des Programms

Die vorherige Besprechung lässt uns eine allgemeine Struktur des Programms zusammenlegen, die die Orders-Berechnung enthält:

// My_expert.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
#include ...
#include <Peremen.mq4>          // Die Beschreibung der Experte-Variablen.   
#include <Terminal.mq4>         // Die Einschließung der Funktion Terminal.
#include <Sobytiya.mq4>         // Die Einschließung der Funktion Sobytiya.
#include ...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
// 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
   ...                                       // Der Code der Funktion init()
   return;
   } 
//=================================================================
int start() 
   {
   Terminal();                   // Die Funktion steht als Erste in ..
                                 // ..der Funktionsreihe
   ...                           // Der nächste Code der Funktion ist start()
   Sobytiya();                   // Die Funktion der Bearbeitung der Ereignisse
   ...                           // Der nächste Code der Funktion ist start()
   return;                                                                 
   }
//=================================================================
int deinit() 
   {   
   ...                                    // Der Code der Funktion deinit()
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Die Datei Peremen.mq4 beschreibt Variablen und muss die Beschreibung der Arrays enthalten, welche die Information über Orders tragen.

//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//=================================================================
int
...
//=================================================================
double
...
Mas_Ord_Tek[31][8], Mas_Ord_Old[31][8], 
// Das laufende und alte Orders-Array 
// Der 1-e Index = die Ordnungsnummer der Order in diesem Array
// [][0] wird nicht bestimmt
// [][1] der Kurs der Eröffnung. der Order   (der absolute Wert des Kurses)
// [][2] StopLoss der Order     (der absolute Wert des Kurses)
// [][3] TakeProfit der Order   (der absolute Wert des Kurses)
// [][4] Die Nummer der Order        
// [][5] die Anzahl  der Lots der Order (der absolute Wert des Kurses)
// [][6] Der Typ der Order 1=B,2=S,3=BL,4=SL,5=BS,6=SS
// [][7] Die magische Zahl der Order
...
//=================================================================
string 
...
//=================================================================
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Wenn die globalen Variablen in kleinen Programmen bestimmt werden müssen, werden sie in der Regel vor der ersten kommenden Funktion eingeschrieben. In mittleren und großen Programmen, hat es den Sinn, alle globalen Variablen in einer Datei zu sammeln und die Datei zum Experten durch die Anleitung #include anzuschließen. Aus der Sicht der Leistungsfähigkeit des Codes ist es egal, nach welcher Weise es getan wird, aber aus der Sicht des Nutzungskomforts ist lieber die Einschließung der Datei. In diesem Beispiel wird die Datei Peremen.mq4 zum Experten nach dieser Weise angeschlossen.


3. Arrays

In der Datei Peremen.mq4 sind zwei Arrays als globale Variablen bestimmt:

Mas_Ord_Tek[31][8] - Das laufende Orders-Array;

Mas_Ord_Old[31][8] - Das alte Orders-Array.

Warum haben wir nicht nur eines, sondern gleich zwei Arrays gebraucht? Um die Möglichkeit zu haben, die Ereignisse zu verfolgen. Welche Ereignisse es sein können, betrachten wir später und soweit Erinnern Sie sich nur daran, dass das Ereignis selbst auf Basis des Vergleichens seines Anfangs und Läufendes-Status identifiziert wird. Wenn keine Information über ein Status vorhanden ist, dann kann das Ereignis nicht identifiziert werden. In diesem Fall übernimmt diese Rolle die Arrays der Orders, welche die Information über den Handelsraum-Status vor und nach dem Tick tragen.

Warum wird ein 2D-Array verwendet? Weil wir gleichzeitig mehrere Orders berechnen werden, und dabei speichern wir von jeder Order die Information über ihre einige Parameter. Der erste Index - die Ordnungsnummer der Order in diesem Array, der zweite - der Order-Parameter nach dem vorgegebenen Kriterium. In diesem Beispiel lässt der erste Index nicht mehr als 30 Orders im Terminal sein. Sie können diese Zahl nach freiem Ermessen willkürlich ändern, in der Annahme, dass alle im Terminal gebliebene berechnet werden, zum Beispiel, 50 oder 100 Orders. Selbstverständlich hat es einen Sinn, erst wenn Ihr Handelssystem mit dieser Menge der Orders arbeiten kann. In einer normalen Situation werden 1-2 Orders, im selten - 4 verwendet. In meiner Vorstellung 30 ist es schon zu viel.

Warum werden in Index-Klammern der Arrays die Werte 31 und 8 angezeigt und nicht 30 und 7? Die Sache ist die, dass die Arrays in MQL4, die Index-Zählung von 0 beginnt. Die Verwendung der nullwertigen Einheiten für normale Elemente ist nicht immer gerechtfertigt. Nach meiner Sicht ist es logisch, wenn die Ordnungsnummer der Order entsprechend der Ordnungsnummer des Elementes des Arrays eingesetzt wird, zum Beispiel, die dritte Order in der Reihe muss in der Zeile sein, in der Index 3 ist. In der Tat wird es in der zahlenmäßigen Reihe die vierte Zeile sein, aber der Index ist bei ihr 3, weil bei der ersten Zeile der Index 0 ist.

Betrachten wir die Tabelle, in der anschaulich die innere Füllung der Arrays dargestellt ist. Nehmen wir an, dass es insgesamt 3 Orders gibt: Buy, Sell und BuyStop unterschiedlicher Qualität.



Die aufschlussreiche Information über Orders befindet sich in den Einheiten der Arrays von [1][1] bis [7][30]. Außerdem bringen wir die Gesamtmenge der Orders unter der Einheit mit dem Index [0][0], die das Array enthält. In diesem Fall - 3. In weiteren Berechnungen wird dieser Ziffer für das Organisieren der Loops gebraucht, in den die Analyse des laufenden Status durchgeführt wird.

Auf diese Weise können wir die Information über 30 Orders speichern und bei jeder Order wird 7 Parameter angemerkt.

Falls es Ihre Handel-Strategie vermutet, das Handeln gleichzeitig über einige Währungswerkzeugen durchzuführen, kann man auch einige Arrays öffnen und sie entsprechend dem Währungspaar einsetzen. Diese Variante ist zwar gestattet, aber unbequem. Unter solchem Organisieren der Berechnung musste man noch ein Array für die Lagerung der Array-Namen öffnen, das die Information über Orders getragen hätte.

Eine bequemere Variante der Lösung ist die Verwendung eines großen Arrays (eines alten und eines neuen), um alle Orders zu berechnen. Diese Wahl ist besser, weil während der Bearbeitung des Arrays im weiteren Code braucht man nicht die Arrays-Namen von Orders der Währungswerkzeuge zu suchen, sondern reicht es, eine Sortierung in der Loop der formalen numerischen Variable über den einem von Arrays-Index zu organisieren.

Das Array, das die Information über alle Orders enthält, kann so geordnet werden:



Die Information über Orders für jedes Währungswerkzeug wird in einer Index-Ebene gespeichert, wie im obigen Beispiel. Der Unterschied besteht darin, dass solche Ebenen in diesem Fall ein paar sind ( auf dem Bild sind 3 dargestellt - gelb, rosa und grün ). Die Höhe der Gesamtmenge ist der Höhe der Währungspaare gleich, die wir uns vornehmen, zu arbeiten, plus noch eine weitere, die nullwertige (die zero one). In dieser Index-Ebene (grau), in der Einheit mit dem Index[0] [0] [0] wird ein einziger Wert gespeichert - die Gesamtmenge der Orders.

Die Größe des Arrays, beispielsweise für 25 Währungswerkzeuge über dem ersten Index wird 26. In diesem Fall die Datei Peremen.mq4, die das Array beschreibt, wird so aussehen:

//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//============================================================================
int
...
//============================================================================
double
...
Mas_Ord_Tek[26][31][8], Mas_Ord_Old[26][31][8], // Das laufende und alte Orders-Array
                                 // Der 1-e Index = die Ordnungsnummer des Währungswerkzeuges
                                 // Der 2-e Index = die Ordnungsnummer der Order..
                                 // .. Auf der Ebene des Währungswerkzeuges
                                 // [][][0] wird nicht bestimmt
                                 // [][][1] der Kurs der Eröffnung. der Order   (der absolute Wert des Kurses)
                                 // [][][2] StopLoss der Order     (der absolute Wert des Kurses)
                                 // [][][3] TakeProfit der Order   (der absolute Wert des Kurses)
                                 // [][][4] Die Nummer der Order        
                                 // [][][5]  die Anzahl der Lots der Order (der absolute Wert des Kurses)
                                 // [][][6] Der Typ der Order 1=B,2=S,3=BL,4=SL,5=BS,6=SS
                                 // [][][7] Die magische Zahl der Order
//=================================================================
string 
      Instrument[26];          // Das Array der Namen der Währungswerkzeuge 
...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Predopred()
   {
//=============================================== Vorbestimmung =
   Instrument[1] = "EURUSD";
   Instrument[2] = "GBPUSD";
   ...
   Instrument[25]= "AUDCAD";
//==================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж


Im unteren Titel des Eröffnungsbloks der Variablen dieser Datei wurde das Array Instrument[26] eröffnet.

In einem großen Programm gibt es in der Regel ein paar Variablen, deren Werte sich während der Programmausführung nicht ändern. In diesem Fall gehören zu ihnen die Elemente des Arrays Instrument[]. Um die Programmierung bequemer zu machen, hat es einen Sinn, solche Variablen in einer Funktion zu sammeln, man kann sie auch in der Form von einer einzelnen Datei erstellen, diese zum Programm mit der Hilfe #include angeschlossen wird.

In diesem Beispiel wird die Vorbestimmung der Elemente des Arrays Instrument[] in der Funktion Predopred() angezeigt, welche in der gleichen Datei Peremen.mq4 enthalten sind. Es reicht schon, die Funktion nur einmal auf die Ausführung anzuweisen, deshalb hat es einen Sinn, sie zum Programm unter der besonderen Funktion init() anzuschließen:

int init()  
   {
   Predopred();            // Die Vorbestimmung einiger Variablen
   return;
   }

Aus dieser Weise werden einige ganze Zähle, in diesem Fall, sind diejenige, die in den Werten der Index des Arrays Instrument[] enthalten sind, entsprechend der Währungswerkzeuge eingesetzt.


4. Die Funktion der Orders-Berechnung

Nun betrachten wir, woraus die Funktion Terminal() für die Orders-Berechnung über einem Währungswerkzeug besteht. Diese Funktion wird genauso in der Form von einer einzelnen Datei mit dem Namen Terminal.mq4 geordnet und wird zum Experten mit der Hilfe der Anleitung #include angeschlossen.

// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//============================================== Vorbestimmung ==
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// Speichern wir die vorherige History 
   int Kol=0;                         // Die Zurücksetzung des Order-Zählers auf 0  
   ArrayInitialize(Mas_Ord_Tek,0);    // Die Zurücksetzung des Arrays auf 0
//=============================================== Die Analyse der Orders ==
   for (int i=0; i<OrdersTotal(); i++)// über allen Orders des Terminals
     {
      if((OrderSelect(i, SELECT_BY_POS)==true) && 
          (OrderSymbol()==Symbol()))
                                //Wenn das nächste und unser Währungspaar gibt 
       {                                                                     
        Kol++;                  // Zählen die Gesamtmenge der Orders
//--------------------------  Umformen des neuen Arrays der Orders --
        Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                              Digits); 
// Der Eröffnungskurs der Orders
        Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(),
                                              Digits); 
// Der Kurs SL 
        Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                              Digits); 
// Der Kurs TP 
        Mas_Ord_Tek[Kol][4] = OrderTicket();     // Die Nummer der Order
        Mas_Ord_Tek[Kol][5] = OrderLots();       // Die Anzahl der Lots
        Mas_Ord_Tek[Kol][6] = OrderType();       // Der Typ der Order
        Mas_Ord_Tek[Kol][7] = OrderMagicNumber();// Die magische Zahl 
//------------------------------------------------------------------
       }
     }
   Mas_Ord_Tek[0][0] = Kol; // Speichern wir in der nullwertigen Einheit
//==================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Das erste, was man machen muss, wenn das System die Steuerung der Funktion Terminal () übergeben hat, - das vorherige Order-Status speichern. Das befindet sich im Array Mas_Ord_Tek[][], aber momentan ist es nicht aktuell, denn es zeigt das Status der Orders an, welche im letzten Tick zusammengelegt wurden. Das aktuelle Status am Anfnagsmoment ist noch nicht bekannt.

In der Zeile

   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// Speichern wir die vorherige History 

Das letzte bekannte Orders-Status wird ins Array Mas_Ord_Old[][] übergeben.

In der Funktion wird die lokale Variable Kol verwendet, die die neue laufende Anzahl der Orders anzeigt. Die Notwendigkeit der Verwendung dieser Variable ist darum entstanden, weil MQL4 die Verwendung der Indexed-Index nicht zulässt. Wie wir aus dem Code sehen können, wird sie als Index-Wert verwendet. Setzen wir diese Variable auf 0 zurück, und auch das ganze Array des aktuellen Status und zeigen Interesse für den aktuellen Stand der Dinge.

Dafür organisieren wir die Loop über dem Terminal, das heißt, wir rufen nacheinander alle verfügbaren Orders auf und erfahren ihre Parameter.

   for (int i=0; i<OrdersTotal(); i++)
// über allen Orders des Terminals

Achten Sie bitte darauf, dass OrdersTotal() die Anzahl der Orders bestimmt, und die Berechnung der Ordnungsnummern beginnt im Terminal von 0. Deshalb wird in der Zeile das Symbol "<" verwendet und die Änderung der inneren Variable der Loop beginnt von 0: i=0.

Im weiteren Code zeichnet sich eine Order aus, die zum Währungswerkzeug gehört, in deren Fenster der Experte hinzugefügt wurde. Mit der Hilfe der Funktion, die die unterschiedlichen Parameter einer Order bestimmt, wird eine erhaltende Information ins entsprechende Element des Arrays Mas_Ord_Tek[][] eingetragen.

//------------------------- Umformen des neuen Arrays der Orders --
       Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                             Digits); 
// Der Eröffnungskurs der Order
       Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(),
                                             Digits); 
// Der Kurs SL
       Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                             Digits); 
// Der Kurs TP
       Mas_Ord_Tek[Kol][4] = OrderTicket(); // Die Nummer der Order
       Mas_Ord_Tek[Kol][5] = OrderLots();   // Die Anzahl der Lots
       Mas_Ord_Tek[Kol][6] = OrderType();   //Der Typ der Order
       Mas_Ord_Tek[Kol][7] = OrderMagicNumber();// Die magische Zahl 
//-----------------------------------------------------------------


Der parallel gefühlter Zähler wird am Ende der Loop seinen Wert dem nullwertigen Element des Arrays übergeben.

   Mas_Ord_Tek[0][0] = Kol;    // Speichern wir in der nullwertigen Einheit

Falls es zugleich über ein paar Währungswerkzeuge der Funktion Terminal() gehandelt werden muss, kann es so erstellt werden:

// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//============================================== Vorbestimmung =
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// Speichern wir die vorherige History 
   ArrayInitialize(Mas_Ord_Tek,0); 
// die Zurücksetzung auf 0 des Arrays der laufenden Orders 
//=============================================== Die Analyse der Orders =
   for (int i=0; i<OrdersTotal(); i++)// über allen Orders des Terminals
      {
      if(OrderSelect(i, SELECT_BY_POS)==true)
// Wenn es noch eine gültige Order gibt
         {
//-------------------- Die Bestimmung des Index des Währungswerkzeuges -
         string Symb=OrderSymbol();
// Stellen wir die Währung der laufenden Order klar
         for (int ind=1; ind<=25; ind++)
// Suchen über dem Array  des Währungswerkzeuges
            {
            if (Symb==Instrument[ind])
// Der Index ist definiert worden, die Suche ist beendet 
               break;                                   
// Verlassen die Loop über ind
            }
//----------------------  Umformen des neuen Arrays der Orders----
         Mas_Ord_Tek[0][0][0]++;
// Zählen die Gesamtmenge der Orders
         Mas_Ord_Tek[ind][0][0]++;
// Zählen die Anzahl der Orders über dem Währungspaar
         int k=Mas_Ord_Tek[ind][0][0]; // Formvariable
         
         Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                                  Digits); 
// der Kurs der Eröffnung der Orders
         Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),
                                                  Digits); 
// Der Kurs SL
         Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),
                                                  Digits); 
// Der Kurs TP
         Mas_Ord_Tek[ind][k][4] = OrderTicket(); //  Die Nummer der Order
         Mas_Ord_Tek[ind][k][5] = OrderLots();   // Die Anzahl der Lots
         Mas_Ord_Tek[ind][k][6] = OrderType();   // Der Typ der Order
         Mas_Ord_Tek[ind][k][7] = OrderMagicNumber();
// Die magische Zahl 
         
//-----------------------------------------------------------------
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Der Unterschied ist im Algorithmus zwischen dem Berechnungsalgorithmus der Orders für ein paar Währungswerkzeuge und dem Algorithmus, der nur für ein Währungspaar erstellt, ist ein kleiner Block für die Bestimmung des Währungswerkzeuges-Index.

//----------------- Die Bestimmung des Währungswerkzeuges-Index ----
         string Symb=OrderSymbol();
// Stellen wir die Währung der laufenden Order klar
         for (int ind=1; ind<=25; ind++)
// Suchen über dem Array  des Währungswerkzeuges
            {
            if (Symb==Instrument[ind])
// Der Index ist definiert worden, die Suche ist beendet 
               break;                 // Verlassen die Loop über ind
            }

In den weiteren Zeilen der Funktion Terminal() wird der gefundene Index-Wert des Währungswerkzeuges ind die Index-Ebene des Arrays bestimmen, das die Information über die Orders enthält, die entsprechend dem Währungswerkzeug sind.

In dargestellten Beispielen der Realisierung der Funktion Terminal() wird die Normalisierung während der Berechnung einige Variablen verwendet:

Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),Digits); 
// der Kurs der Eröffnung der Order
Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),Digits); 
// Der Kurs SL
Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),Digits); 
// Der Kurs TP

Diese Berechnungen sind notwendig, damit Sie die normalisierten Werte der Variablen in den künftigen Berechnungen in Vergleichs-Operatoren verwenden. Dabei wird die Anzahl der bedeutenden Zahlen auf Basis der vorbestimmten Variable Digits bestimmt.

Ein einzelnes Handelssystem kann auch andere Besonderheiten und Parameter der Orders berechnen. In den dargestellten Beispielen werden nur allgemeine Grundlagen der Orders-Berechnung in einem großen Programm betrachtet. Zum Beispiel, hier wird keine Berechnung der geschlossenen und gelöschten Orders betrachtet, werden keine einige Parameter der Orders berechtigt, zum Beispiel, die Ablaufzeit der Pending Order. Falls Sie sowas brauchen, können Sie locker ein paar Arrays-Konfigurationen ändern, damit Sie die zusätzliche Information speichern. Zum Beispiel, kann man die Anzahl der Elements über dem letzten Index vermehren, damit Sie die Information über die Ablaufzeit der Pending Orders speichern.

5. Die Bearbeitung der Ereignisse

Also, der neue Tick ist aufgetreten und die Funktion Terminal()hat es ausgelöst. Die Kontrolle wird dem Operator übergeben, der direkt nach der Funktion Terminal()steht. Man kann nicht im Voraus sagen, in welchem Teil der Sonder-Funktion start() wird sich die oder die Benutzer-Funktion der Bearbeitung der Ereignisse befinden - das hängt von der Idee ab, die ins Handelssystem gelegt wird. In einem einfachen Fall kann die Bearbeitung mindestens einige Ereignisse direkt durchgeführt werden.

Bevor das Beispiel der Bearbeitung der Ereignisse betrachtet wird, müssen wir Sie erinnern, dass eine spezifische Situation existiert, in der eine intuitiv erwartete Ereignisreihe nicht gehalten wird.

Erstens, es gibt einige Dealers (zum Beispiel, die Banken mit ihrer spezifischen Berechnung), die am Ende des Handelstages zwangsweise alle geöffneten Orders schließen, und gleich am Anfang des nächsten Handelstages die gleichen Orders öffnen, aber schon nach dem Kurs, der vom aktuellen Kurs auf ein paar Zehntel Punkten unterschiedlicher ist. Mit diesen Teilen des Punktes wird SWAP in der Ökonomie der Order gelegt. SWAP alleine wird im Terminal nullwertig angezeigt. Aus der Sicht der Ökonomie verstoßen Dillers nichts. Für uns ist es in dieser Situation wichtig, dass die wieder neu geöffneten Orders neue Nummer bekommen werden, die nichts mit den vorherigen Nummern zu tun haben.

Zweitens, wird die teilweise Schließung einer separaten Order durch zwei Stufen durchgeführt. In der ersten Stufe wird die Order voll geschlossen, und in der zweiten Stufe wird eine neue Order mit dem niedrigem Preis geöffnet, aber diesmal mit einer neuen Nummer. Dabei wird die Nummer der Anfangs-Order in den Kommentaren der neuen Order eingetragen.

Drittens, die ähnliche Spezifikation entsteht während der Schließung einer Order auf Kosten einer anderen, wenn die Orders einen unterschiedlichen Preis haben. In diesem Fall wird tatsächlich die Situation der teilweisen Schließung einer Order wiederholt.

Die einzige Möglichkeit der Identifizierung der Order ist eine Analyse eines ihres Parameters, der sich nicht ändert und nicht wiederholt. Aus allen Möglichkeiten, die MQL4 anbietet, ist mir gelungen, nur einen solchen Parameter MagicNumber herauszufinden. Aber auch in diesem Fall kann Programmierer nicht darauf zählen, dass die ganze Kontrolle über der Situation erstellt wird. Die Sache ist die, dass die MagicNumber programmatisch nicht geändert werden kann. Einerseits gibt es da einen unwiderleglichen Vorteil, wir können sicher sein, dass dieser Parameter sich nicht ändert, sogar versehentlich, solange noch eine Order gibt. Aber anderseits würde man gern mindestens einen regelbaren Parameter haben, deren Zugriff programmatisch zugelassen ist. In diesem Moment gibt es keine solche Möglichkeit, deswegen, wenn eine irgendwelche Order (eine oder mehrere) nicht von unserem Handelssystem geöffnet wurde, sondern von dem Programm oder "per Hand" (manuell), dann können wir es nicht, solche Orders irgendwie auszuzeichnen, oder ein Kennzeichen zu haben, das sie voneinander und von unseren unterscheidet würde.

Eine schwache Alternative zu einem eindeutigen Kennzeichen kann der Zeitpunkt der Ordersöffnung sein. Aber dieses Kriterium kann nicht zuverlässig und universal akzeptiert werden, da es immer eine theoretische Möglichkeit gibt, dass mehrere Orders gleichzeitig (in der gleichen Sekunde) geöffnet werden können. Beispielsweise zwei Pending Orders auf verschiedenen Währungswerkzeugen können zugleich unter einer heftigen Preisbewegung geöffnet werden.

Betrachten wir das Beispiel der Realisierung der Funktion Sobytiya(), die in der gleichnamigen Datei Sobytiya.mq4 enthalten ist. Betrachten wir ein einfaches Ereignis - die Löschung oder die Schließung der Pending Order.

Wir haben schon herausgefunden, dass die Order-Nummer für diesen Zweck nicht tauglich ist, deshalb werden wir MagicNumber analysieren.

// Sobytiya.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya()
   {
//==================================== Die Suche der verlorenen Orders ====
   for (int oo=1;oo<=Mas_Ord_Old[0][0];oo++)     
// Nehmen wir die Order-Nummer aus dem alten Array
      {   
      int Sovpadenie=0;                          
// Zuerst setzen wir die Tatsache des Kennzeichens der Kongruenz auf 0
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)     
// Suchen wir dieses Orderchen im laufenden Array 
         {
         if (Mas_Ord_Tek[i][7]==Mas_Ord_Old[oo][7]) 
// wenn die MagicNumber der Order zusammengefallen ist, dann speichern, das heisst, es ist noch gültig
// und Verlassen die innere Loop
            {
            Sovpadenie=1;                           
            break;                                
            }
         }      
      if (Sovpadenie==1) continue;  // Gehen wir zum alten
      Alert("Die Order ist geschlossen ",Mas_Ord_Old[oo][4]); 
// Berichten mit dem Text auf das Bildschirm
      PlaySound( "Close_order.wav" );               
// Und das Liedchen.
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Wie Sie sehen können, wenn es dabei die Kriterien gibt, welche das Ereignis beschreiben, wird das einfach gefunden. Es reicht, nacheinander Orders zu vergleichen, die vor dem Tick mit den Orders sind, die auch nach dem Tick bleiben, - und das ist es, der Unterschied, und mit ihm die Tatsache, die bestätigt, dass das Ereignis passiert ist.

Im nächsten Beispiel wird die Suche des anderen Ereignisses betrachtet - die Transformation des Typs der Order. Hier wird das gleiche Prinzip verwendet, aber das wird zu einem anderen Kriterium angewendet. Um eine Situation zu verfolgen, ist es durchaus gestattet, die Analyse der Order-Nummern und ihren Typs anzuwenden.

// Sobytiya_2.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya_2()
   {
//============================== Die Suche der Orders, die ihren Typ geändert haben ====
   for(int oo=1;oo<=Mas_Ord_Old[0][0]; oo++)               
// Kommen wir mal bei dem alten Array vorbei
      {
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)              
// Suchen wir diese Order im laufenden Array 
         {
         if (Mas_Ord_Tek[i][4] == Mas_Ord_Old[oo][4] &&    
// Wenn es im alten die gleiche Order war, aber mit dem anderen Typ, dann:
             Mas_Ord_Tek[i][6] != Mas_Ord_Old[oo][6])      
            {                                                  // die Pending Order ist offensichtlich geworden 
            Alert("die Order hat sich transformiert,",Mas_Ord_Tek[i][4]);
// Berichten mit dem Text auf das Bildschirm
            PlaySound("Transform.wav" );                       
// Und das Liedchen
            }
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

Ausgehend von der Idee , die vom Programmiere in den Experten gelegt wird, kann man das Ereignis an unterschiedlichen Orten des Programms verfolgen. Nach Bedarf kann man die Analyse aller interessanten Ereignisse in einer einzigen Datei auftragen. Daraufhin soll der Code etwas modifiziert werden, um die Sortierung in Arrays für jedes Kriterium nicht zu wiederholen. Es ist auch einfach, einen Algorithmus zu komponieren, um die Anfangsnummer aus den Kommentaren einer teilweise geschlossenen Order rauszuholen, um die weiter zu analysieren. Dafür ist es genug, die Funktion OrderComment() anzuwenden.

Außer den erwähnten Besonderheiten, welche die Berechnung der Orders betreffen, gibt es auch andere, bei denen wir eine nützliche Information bekommen könnten, zum Teil unsere Wirklichkeit zu vergrößern und uns vor unnötigen Arbeiten und traurigen Fehler zu bewahren. Lassen Sie uns zu Dealers zurückkehren, die Orders am Ende des Handelstages schließen.

Der Swap-Wert ist in der Regel durch den Punkt nicht teilbar , infolgedessen die Anzahl der wertigen Ziffern wird im Kurswert der Eröffnung der Order um 1 zunehmen. Um diese Besonderheit zu berechnen, muss die Normalisierung mit der Genauigkeit von 1 mehr als Digits durchgeführt werden:
   Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                            Digits+1); 
// der Kurs der Eröffnung der Order

Außerdem ist in dieser Situation auffällig, dass der Eröffnungskurs der Order seine Position wesentlich ändern kann. Wenn der Trader ein Handelssystem verwendet, das die Handlungsentscheidungen mit der Rücksicht auf den Eröffnungskurs der Orders trifft, dann kann ein solches System am Ende des Tages einfach in Stücke gehen. Unter der genauen Betrachtung kann man Konsequente ziehen, dass der Eröffnungskurs der Order gar keinen Wert hat! Der wichtigste Faktor ist das Entwicklungstrend der Situation, und wenn sie gegen uns ist, dann muss die Order geschlossen werden, egal wo sie ist.

Die Diskussion über Kriterien, welche die Handelsentscheidungen beeinflussen, wächst weit aus diesem Artikel. Hier ist je immer noch wichtig, zu erwähnen, dass eine richtige Wahl der Kriterien, die im Programm verwendet werden, ist der grundlegende Faktor für jede Strategie.