English Русский 中文 Español 日本語 Português
Orders steuern ist einfach

Orders steuern ist einfach

MetaTrader 4Handel | 30 November 2015, 16:03
5 468 0
Andrey Khatimlianskii
Andrey Khatimlianskii

1. Einleitung

In jedem Handelsexperte gibt es ein Kontrollblock über die geöffneten Positionen. Das sind die Sortierung aller Orders in einer Loop, die Auswahl seiner Position nach dem Symbol und nach dem Wert MagicNumber und ihre weitere Änderung oder Schließung. Diese Blöcke sehen miteinander ähnlich aus und haben oft die gleichen Funktionen . Deshalb kann man diesen wiederholenden Teil des Codes aus der Experte auf die Funktion austragen - das wird wesentlich das Schreiben der Experten vereinfachen und macht die Experten-Codes kompakter.

Zuerst teilen wir die Aufgabe in drei Stufen, die in der Komplexität und Funktionalität unterschiedlich sind - diese drei Stufen werden drei Arten der Experten entsprechen:

  • Experten, die nur eine Position zugleich geöffnet haben können;
  • Experten, bei denen je eine Position jeden Typ geöffnet werden kann (beispielsweise eine Position buy und eine Position sell);
  • Experten, die eine beliebige Anzahl von Positionen öffnen können.

2. Eine Position

Es gibt viele Strategien, welche nur eine geöffnete Position verwenden. Ihre Kontrollblöcke ​​sehen ziemlich einfach aus, aber ihr Schreiben braucht trotzdem Zeit und Aufmerksamkeit.

Lassen Sie uns einen einfachen Experte nehmen, der nach dem Signal eine Position öffnet, als Signal gilt für ihn die Kreuzung der Signal- und Hauptlinien MACD und Vereinfachen wir seinen Positionen-Kontrollblock. So sieht er aus, bevor er bearbeitet wird:

extern int  _MagicNumber = 1122;
 
int start()
{
//---- Merken wir uns den Indikator-Wert für die weitere Analyse
    double MACD_1 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, 
                    MODE_MAIN, 1 );
    double MACD_2 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, 
                     MODE_MAIN, 2 );
 
    int _GetLastError = 0, _OrdersTotal = OrdersTotal();
    //---- Sortieren alle geöffneten Positionen
    for ( int z = _OrdersTotal - 1; z >= 0; z -- )
    {
  //---- Wenn während der Position-Wahl ein Fehler aufgetreten ist, springen wir zum nächsten über 
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
            _GetLastError = GetLastError();
            Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - 
                  Error #", _GetLastError );
            continue;
        }
 
// Wenn die Position nicht beim aktuellen Werkzeug geöffnet ist, gehen wir weiter
        if ( OrderSymbol() != Symbol() ) continue;
 
// wenn die MagicNumber mit der _MagicNumber nicht gleich ist, überspringen wir 
// die Posotion
        if ( OrderMagicNumber() != _MagicNumber ) continue;
 
        //---- wenn die Buy-Position geöffnet ist,
        if ( OrderType() == OP_BUY )
        {
            //---- wenn MACD die 0-Linie runter gekreuzt hat,
            if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 && 
                  NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0)
            {
                //---- Schließen wir die Position
                if ( !OrderClose( OrderTicket(), OrderLots(), 
                    Bid, 5, Green ) )
                {
                    _GetLastError = GetLastError();
                    Alert( "Der Fehler OrderClose № ", _GetLastError );
                    return(-1);
                }
            }
// wenn das Signal sich nicht ändert, Verlassen wir es- es ist noch früh 
// eine neue Position zu eröffnen
            else
            { return(0); }
        }
        //---- wenn die SELL-Position geöffnet ist,
        if ( OrderType() == OP_SELL )
        {
            //---- wenn MACD die 0-Linie nach oben gekreuzt hat,
            if(NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 && 
               NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0)
            {
                //---- Schließen wir die Position
                if(!OrderClose( OrderTicket(), OrderLots(), 
                   Ask, 5, Red ) )
                {
                    _GetLastError = GetLastError();
                    Alert( "Der Fehler OrderClose № ", 
                          _GetLastError );
                    return(-1);
                }
            }
// wenn das Signal sich nicht ändert, Verlassen wir es- es ist noch früh 
// eine neue Position zu eröffnen
            else return(0);
        }
    }
 
//+-------------------------------------------------------------------------------------------------------+
//| wenn die Ausführung bis zu diesem Punkt gekommen ist, heißt es, dass es keine geöffnete Position gibt |
//| Überprüfen die Möglichkeit, eine Position zu öffnen                                                   |
//+-------------------------------------------------------------------------------------------------------+
 
    //---- wenn MACD die 0-Linie nach oben gekreuzt hat,
    if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 && 
          NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
    {
        //---- Eröffnen die BUY-Position
        if(OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 
           0.0, "MACD_test", 
              _MagicNumber, 0, Green ) < 0 )
        {
            _GetLastError = GetLastError();
            Alert( "Der Fehler OrderSend № ", _GetLastError );
            return(-1);
        }
        return(0);
    }
    //---- wenn MACD die 0-Linie runter gekreuzt hat,
    if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 && 
          NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
    {
        //---- Eröffnen die SELL-Position
        if(OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 
           0.0, "MACD_test", 
              _MagicNumber, 0, Red ) < 0 )
        {
            _GetLastError = GetLastError();
            Alert( "Der Fehler OrderSend № ", _GetLastError );
            return(-1);
        }
        return(0);
    }

    return(0);
}
  

Nun müssen wir die Funktion schreiben, die den Position-kontrollblock wechselt. Die Funktion muss alle Orders sortieren, muss die nötigste Order finden und alle ihre Parameter in die globalen Variablen speichern. So wird Sie aussehen:

int _Ticket = 0, _Type = 0; double _Lots = 0.0, _OpenPrice = 0.0, 
_StopLoss = 0.0;
double _TakeProfit = 0.0; datetime _OpenTime = -1; 
double _Profit = 0.0, _Swap = 0.0;
double _Commission = 0.0; string _Comment = ""; 
datetime _Expiration = -1;
 
void OneOrderInit( int magic )
{
    int _GetLastError, _OrdersTotal = OrdersTotal();
 
    _Ticket = 0; _Type = 0; _Lots = 0.0; _OpenPrice = 0.0; 
    _StopLoss = 0.0;
    _TakeProfit = 0.0; _OpenTime = -1; _Profit = 0.0; _Swap = 0.0;
    _Commission = 0.0; _Comment = ""; _Expiration = -1;
 
    for ( int z = _OrdersTotal - 1; z >= 0; z -- )
    {
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
          _GetLastError = GetLastError();
          Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", 
                _GetLastError );
          continue;
        }
        if ( OrderMagicNumber() == magic && OrderSymbol() == Symbol() )
        {
            _Ticket        = OrderTicket();
            _Type            = OrderType();
            _Lots            = NormalizeDouble( OrderLots(), 1 );
            _OpenPrice    = NormalizeDouble( OrderOpenPrice(), Digits );
            _StopLoss    = NormalizeDouble( OrderStopLoss(), Digits );
            _TakeProfit    = NormalizeDouble( OrderTakeProfit(), Digits );
            _OpenTime    = OrderOpenTime();
            _Profit        = NormalizeDouble( OrderProfit(), 2 );
            _Swap            = NormalizeDouble( OrderSwap(), 2 );
            _Commission    = NormalizeDouble( OrderCommission(), 2 );
            _Comment        = OrderComment();
            _Expiration    = OrderExpiration();
            return;
        }
    }
}
   
    Wie Sie sehen können, alles ist einfach: es gibt 11 Variablen, jede hat einen Wert eines Parameters einer Position (№ Ticks, Typ, Lot-Größe, u.s.w.) Am Anfang wird die Funktion diese Variablen auf 0 setzen. Das ist üblich, weil sie auf dem globalen Level angezeigt sind und werden nicht während dem Aufruf der Funktion auf 0 gesetzt, und wir brauchen keine Information vom letzten Tick - alle Daten müssen aktuell neu sein. Danach kommt Standardesortierung allen geöffneten Positionen und falls das Symbol und der Wert der MagicNumber gleich zusammenfallen, werden Parameter in den entsprechenden Variablen gespeichert.

Nun lassen Sie uns die Funktion zum unserem Experte anschließen:

extern int  _MagicNumber = 1122;
 
#include <OneOrderControl.mq4>
 
int start()
{
    int _GetLastError = 0;
    
    //---- Merken wir uns die Parameter der geöffneten Position (wenn sie es gibt)
    OneOrderInit( _MagicNumber );
 
    //---- Merken wir uns den Indikator-Wert für die weitere Analyse
    double MACD_1 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, 
                          MODE_MAIN, 1 );
    double MACD_2 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, 
                          MODE_MAIN, 2 );
 
// Und jetzt, statt die Position zu sortieren, Schauen wir einfach, ob eine geöffnete 
// Position gibt:
    if ( _Ticket > 0 )
    {
        //---- wenn die Buy-Position geöffnet ist,
        if ( _Type == OP_BUY )
        {
            //---- wenn MACD die 0-Linie runter gekreuzt hat,
            if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 && 
                  NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
            {
                //---- Schließen wir die Position
                if ( !OrderClose( _Ticket, _Lots, Bid, 5, Green ) )
                {
                    _GetLastError = GetLastError();
                    Alert( "Der Fehler OrderClose № ", _GetLastError );
                    return(-1);
                }
            }
// wenn das Signal sich nicht ändert, Verlassen wir es- es ist noch früh 
// eine neue Position zu eröffnen
            else return(0);
        }
        //---- wenn die SELL-Position geöffnet ist,
        if ( _Type == OP_SELL )
        {
            //---- wenn MACD die 0-Linie nach oben gekreuzt hat,
            if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 && 
                  NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
            {
                //---- Schließen wir die Position
                if ( !OrderClose( _Ticket, _Lots, Ask, 5, Red ) )
                {
                    _GetLastError = GetLastError();
                    Alert( "Der Fehler OrderClose № ", _GetLastError );
                    return(-1);
                }
            }
// wenn das Signal sich nicht ändert, Verlassen wir es- es ist noch früh 
// eine neue Position zu eröffnen
            else return(0);
        }
    }
    //---- Wenn es keine Position gibt, die vom Experte geöffnet wurde ( _Ticket == 0 )
    //---- wenn MACD die 0-Linie nach oben gekreuzt hat,
    if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 && 
          NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
    {
        //---- Eröffnen die BUY-Position
        if(OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, 
           "CrossMACD", _MagicNumber, 0, Green ) < 0 )
        {
            _GetLastError = GetLastError();
            Alert( "Der Fehler OrderSend № ", _GetLastError );
            return(-1);
        }
        return(0);
    }
    //---- wenn MACD die 0-Linie runter gekreuzt hat,
    if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 && 
          NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
    {
        //---- Eröffnen die SELL-Position
        if(OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 
           0.0, "CrossMACD", _MagicNumber, 0, Red ) < 0 )
        {
            _GetLastError = GetLastError();
            Alert( "Der Fehler OrderSend № ", _GetLastError );
            return(-1);
        }
        return(0);
    }

    return(0);
}
    Wie Sie sehen können, der Code vom Experte ist jetzt viel kompakter und es ist bequemer, den Code wahrzunehmen. Und das ist ein einfacher Fall.

    Lassen Sie uns jetzt die nächste Aufgabe lösen.

 

3. Eine Position eines Typs

Um die nächste Funktion zu realisieren, brauchen wir etwa komplizierter Experte. Er muss ein paar Positionen unterschiedlicher Typs eröffnen, und danach irgendwas mit ihnen tun. Versuchen wir den Algorithmus des Experte kurz zu formulieren:

  • Am Start muss der Experte zwei Pending Orders platzieren: Byu-Stop im Level Ask + 20 Punkten und Sell-Stop im Level Bid - 20 Punkten;
  • Wenn eine Order signalisiert hat, muss die andere gelöscht werden;
  • Die geöffnete Position muss mit dem Trailing-Stop begleitet werden;
  • Nach der Schließung der Position über Stop-Loss oder TakeProfit gehen wir zum ersten Punkt, das heisst, wir platzieren wieder zwei Pending Orders.

Der Code des Expertes wird so aussehen:

extern int    _MagicNumber = 1123;
 
extern double Lot          = 0.1;
extern int    StopLoss     = 60;    
// der Absand bis zum Stop-Loss in Punkten (0 -  Ausschalten)
extern int    TakeProfit   = 100;   
// der Absand bis zum TakeProfit in Punkten (0 - Ausschalten)
extern int    TrailingStop = 50;    
// die Größe Trailing-Stops in Punkten (0 - Ausschalten)
 
extern int    Luft         = 20;    
// der Absand bis zum Level, in dem die Pending Order gesetzt wird
 
 
int start()
{
// Die Variablen, bei denen wir uns die Ticks jeden Typ Orders merken. 
    int BuyStopOrder = 0, SellStopOrder = 0, BuyOrder = 0, SellOrder = 0;
    int _GetLastError = 0, _OrdersTotal = OrdersTotal();
// Sortieren wir alle geöffneten Positionen und merken wir uns, 
// welche Positionen mit welchem Typ schon geöffnet sind:
    for ( int z = _OrdersTotal - 1; z >= 0; z -- )
    {
// Wenn während der Position-Wahl ein Fehler aufgetreten ist, springen wir zum nächsten über
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
          _GetLastError = GetLastError();
          Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", 
                _GetLastError );
          continue;
        }
 
// Wenn die Position nicht beim aktuellen Werkzeug geöffnet ist, gehen wir weiter
        if ( OrderSymbol() != Symbol() ) continue;
 
// wenn die MagicNumber mit der _MagicNumber nicht gleich ist, überspringen wir diese Position
        if ( OrderMagicNumber() != _MagicNumber ) continue;
 
// Je nach dem Typ der Position, wechseln wir den Wert der Variable:
        switch ( OrderType() )
        {
          case OP_BUY:      BuyOrder      = OrderTicket(); break;
          case OP_SELL:     SellOrder     = OrderTicket(); break;
          case OP_BUYSTOP:  BuyStopOrder  = OrderTicket(); break;
          case OP_SELLSTOP: SellStopOrder = OrderTicket(); break;
        }
    }
 
    //---- Wenn wir beide Pending Orders haben, dann Verlassen wir es, 
    //---- Es muss abgewartet sein, bevor eine von ihnen signalisiert 
    if ( BuyStopOrder > 0 && SellStopOrder > 0 ) return(0);
 
// Sortieren wir alle geöffneten Positionen das zweite Mal - 
// jetzt werden wir mit ihnen arbeiten:
    _OrdersTotal = OrdersTotal();
    for ( z = _OrdersTotal - 1; z >= 0; z -- )
    {
// Wenn während der Position-Wahl ein Fehler aufgetreten ist, springen wir zum nächsten  
// über
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
          _GetLastError = GetLastError();
          Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", 
                _GetLastError );
          continue;
        }
 
// Wenn die Position nicht beim aktuellen Werkzeug geöffnet ist, gehen wir weiter
        if ( OrderSymbol() != Symbol() ) continue;
 
// wenn die MagicNumber mit der _MagicNumber nicht gleich ist, überspringen wir diese Position
        if ( OrderMagicNumber() != _MagicNumber ) continue;
 
// Je nach dem Typ der Position, wechseln wir den Wert der Variable:
        switch ( OrderType() )
        {
            //---- wenn eine geöffnete Buy-Position gibt,
            case OP_BUY:
            {
                //---- Wenn die Sellstop-Order noch nicht gelöscht wurde, Löschen Wir Sie:
                if ( SellStopOrder > 0 )
                {
                    if ( !OrderDelete( SellStopOrder ) )
                    {
                        Alert( "OrderDelete Error #", GetLastError() );
                        return(-1);
                    }
                }
                //---- Überprüfen Wir, soll die Stop-Loss zurückgesetzt werden:
                //---- wenn die Größe Trailing-Stops nicht zu klein ist,
                if(TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL))
                {
                  //---- wenn das Gewinn der Position als die Punkten der TrailingStop mehr ist,
                  if(NormalizeDouble( Bid - OrderOpenPrice(), Digits) > 
                     NormalizeDouble( TrailingStop*Point, Digits))
                    {
                        // wenn die neue Stopp-Loss-Level höher ist, 
                        // als jetzt bei der Position
                        // (oder wenn die Position keine Stop-Loss hat),
                        if(NormalizeDouble(Bid - TrailingStop*Point, 
                           Digits) > OrderStopLoss()
                           || OrderStopLoss() <= 0.0 )
                        {
                          //---- Modifizieren die Order
                          if(!OrderModify( OrderTicket(), 
                             OrderOpenPrice(), 
                             NormalizeDouble(Bid - 
                             TrailingStop*Point,Digits), 
                             OrderTakeProfit(), 
                             OrderExpiration() ) )
                            {
                              Alert("OrderModify Error #", 
                                    GetLastError());
                              return(-1);
                            }
                        }                    
                    }
                }
                // Wenn eine geöffnete Position gibt, Verlassen wir es - 
                // da gibt es nichts mehr zu tun 
                return(0);
            }
            // Der nächste Block ist voll gleich dem 
            // Block der Bearbeitung der Buy-Positionen,
            // deshalb wurden keine Kommentaren damit eingetragen...
            case OP_SELL:
            {
                if ( BuyStopOrder > 0 )
                {
                    if ( !OrderDelete( BuyStopOrder ) )
                    {
                        Alert("OrderDelete Error #", 
                              GetLastError() );
                        return(-1);
                    }
                }
                if(TrailingStop > MarketInfo( Symbol(), 
                   MODE_STOPLEVEL))
                {
                  if(NormalizeDouble( OrderOpenPrice() - Ask, 
                     Digits) > NormalizeDouble(TrailingStop*Point, 
                     Digits))
                    {
                      if(NormalizeDouble(Ask + TrailingStop*Point, 
                         Digits ) < OrderStopLoss()
                         || OrderStopLoss() <= 0.0 )
                        {
                          if(!OrderModify( OrderTicket(), 
                             OrderOpenPrice(), NormalizeDouble(Ask + 
                             TrailingStop*Point, Digits), 
                             OrderTakeProfit(), OrderExpiration()))
                            {
                              Alert("OrderModify Error #", 
                                    GetLastError() );
                              return(-1);
                            }
                        }                    
                    }
                }
                return(0);
            }
        }
    }
 
//+----------------------------------------------------------------------------------------------------+
//| Wenn die Ausführung bis zu diesem Punkt gekommen ist, heißt es, dass es keine Pending Positionen   |
//| und geöffneten Positionen gibt                                                                     |
//+----------------------------------------------------------------------------------------------------+
//---- Platzieren wir Byu-Stop und Sell-Stop der Order:
    double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel;
    _OpenPriceLevel = NormalizeDouble( Ask + Luft*Point, Digits );
 
    if ( StopLoss > 0 )
    { _StopLossLevel = NormalizeDouble( _OpenPriceLevel - 
                              StopLoss*Point, Digits ); }
    else
    { _StopLossLevel = 0.0; }
 
    if ( TakeProfit > 0 )
    { _TakeProfitLevel = NormalizeDouble( _OpenPriceLevel + 
                         TakeProfit*Point, Digits ); }
    else
    { _TakeProfitLevel = 0.0; }
 
    if(OrderSend(Symbol(), OP_BUYSTOP, Lot, _OpenPriceLevel, 
                   5, _StopLossLevel, _TakeProfitLevel, "", 
                   _MagicNumber ) < 0 )
    {
      Alert( "OrderSend Error #", GetLastError() );
      return(-1);
    }
 
 
    _OpenPriceLevel = NormalizeDouble( Bid - Luft*Point, Digits );
 
    if ( StopLoss > 0 )
    { _StopLossLevel = NormalizeDouble( _OpenPriceLevel + 
                       StopLoss*Point, Digits ); }
    else
    { _StopLossLevel = 0.0; }
 
    if ( TakeProfit > 0 )
    { _TakeProfitLevel = NormalizeDouble( _OpenPriceLevel - 
                         TakeProfit*Point, Digits ); }
    else
    { _TakeProfitLevel = 0.0; }
 
    if ( OrderSend ( Symbol(), OP_SELLSTOP, Lot, _OpenPriceLevel, 
                    5, _StopLossLevel, 
                   _TakeProfitLevel, "", _MagicNumber ) < 0 )
    {
        Alert( "OrderSend Error #", GetLastError() );
        return(-1);
    }

    return(0);
}

Nun lassen Sie uns eine Funktion schreiben, die den Kontrollblock über die geöffneten Positionen vereinfacht. Sie muss je eine Order jeden Typ finden, und ihre Parameter in die globalen Variablen speichern. Sie wird so aussehen:

// Die globalen Variablen, in den Parameter der Orders gespeichert werden 
// .:
int _BuyTicket = 0, _SellTicket = 0, _BuyStopTicket = 0;
int _SellStopTicket = 0, _BuyLimitTicket = 0, _SellLimitTicket = 0;
 
double _BuyLots = 0.0, _SellLots = 0.0, _BuyStopLots = 0.0; 
double _SellStopLots = 0.0, _BuyLimitLots = 0.0, 
                       _SellLimitLots = 0.0;
 
double _BuyOpenPrice = 0.0, _SellOpenPrice = 0.0, 
                       _BuyStopOpenPrice = 0.0;
double _SellStopOpenPrice = 0.0, _BuyLimitOpenPrice = 0.0, 
       _SellLimitOpenPrice = 0.0;
 
double _BuyStopLoss = 0.0, _SellStopLoss = 0.0, 
_BuyStopStopLoss = 0.0;
double _SellStopStopLoss = 0.0, _BuyLimitStopLoss = 0.0, 
_SellLimitStopLoss = 0.0;
 
double _BuyTakeProfit = 0.0, _SellTakeProfit = 0.0, 
_BuyStopTakeProfit = 0.0;
double _SellStopTakeProfit = 0.0, _BuyLimitTakeProfit = 0.0, 
_SellLimitTakeProfit = 0.0;
 
datetime _BuyOpenTime = -1, _SellOpenTime = -1, 
_BuyStopOpenTime = -1;
datetime _SellStopOpenTime = -1, _BuyLimitOpenTime = -1, 
_SellLimitOpenTime = -1;
 
double _BuyProfit = 0.0, _SellProfit = 0.0, _BuySwap = 0.0, 
_SellSwap = 0.0;
double _BuyCommission = 0.0, _SellCommission = 0.0;
 
string _BuyComment = "", _SellComment = "", _BuyStopComment = ""; 
string _SellStopComment = "", _BuyLimitComment = "", 
_SellLimitComment = "";
 
datetime _BuyStopExpiration = -1, _SellStopExpiration = -1;
datetime _BuyLimitExpiration = -1, _SellLimitExpiration = -1;
 
void OneTypeOrdersInit( int magic )
{
// Die Zurücksetzung der Variablen auf 0:
    _BuyTicket = 0; _SellTicket = 0; _BuyStopTicket = 0;
    _SellStopTicket = 0; _BuyLimitTicket = 0; _SellLimitTicket = 0;
 
    _BuyLots = 0.0; _SellLots = 0.0; _BuyStopLots = 0.0; 
    _SellStopLots = 0.0; _BuyLimitLots = 0.0; _SellLimitLots = 0.0;
 
    _BuyOpenPrice = 0.0; _SellOpenPrice = 0.0; 
_BuyStopOpenPrice = 0.0;
    _SellStopOpenPrice = 0.0; _BuyLimitOpenPrice = 0.0; 
_SellLimitOpenPrice = 0.0;
 
    _BuyStopLoss = 0.0; _SellStopLoss = 0.0; 
_BuyStopStopLoss = 0.0;
    _SellStopStopLoss = 0.0; _BuyLimitStopLoss = 0.0; 
_SellLimitStopLoss = 0.0;
 
    _BuyTakeProfit = 0.0; _SellTakeProfit = 0.0; 
_BuyStopTakeProfit = 0.0;
    _SellStopTakeProfit = 0.0; _BuyLimitTakeProfit = 0.0; 
_SellLimitTakeProfit = 0.0;
 
    _BuyOpenTime = -1; _SellOpenTime = -1; 
_BuyStopOpenTime = -1;
    _SellStopOpenTime = -1; _BuyLimitOpenTime = -1; 
_SellLimitOpenTime = -1;
 
    _BuyProfit = 0.0; _SellProfit = 0.0; _BuySwap = 0.0; 
_SellSwap = 0.0;
    _BuyCommission = 0.0; _SellCommission = 0.0;
 
    _BuyComment = ""; _SellComment = ""; _BuyStopComment = ""; 
    _SellStopComment = ""; _BuyLimitComment = ""; 
_SellLimitComment = "";
 
    _BuyStopExpiration = -1; _SellStopExpiration = -1;
    _BuyLimitExpiration = -1; _SellLimitExpiration = -1;
 
    int _GetLastError = 0, _OrdersTotal = OrdersTotal();
    for ( int z = _OrdersTotal - 1; z >= 0; z -- )
    {
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
            _GetLastError = GetLastError();
            Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", 
                  _GetLastError);
            continue;
        }
        if ( OrderMagicNumber() == magic && OrderSymbol() == 
             Symbol() )
        {
            switch ( OrderType() )
            {
                case OP_BUY:
                    _BuyTicket     = OrderTicket();
                    _BuyLots       = NormalizeDouble( OrderLots(), 1 );
                    _BuyOpenPrice  = NormalizeDouble( OrderOpenPrice(), 
                                                      Digits );
                    _BuyStopLoss   = NormalizeDouble( OrderStopLoss(), 
                                                      Digits );
                    _BuyTakeProfit = NormalizeDouble( OrderTakeProfit(), 
                                                      Digits );
                    _BuyOpenTime   = OrderOpenTime();
                    _BuyProfit     = NormalizeDouble( OrderProfit(), 2 );
                    _BuySwap       = NormalizeDouble( OrderSwap(), 2 );
                    _BuyCommission = NormalizeDouble( OrderCommission(), 
                                                      2 );
                    _BuyComment    = OrderComment();
                    break;
                case OP_SELL:
                    _SellTicket     = OrderTicket();
                    _SellLots       = NormalizeDouble( OrderLots(), 1 );
                    _SellOpenPrice  = NormalizeDouble( OrderOpenPrice(), 
                                                      Digits );
                    _SellStopLoss   = NormalizeDouble( OrderStopLoss(), 
                                                      Digits );
                    _SellTakeProfit = NormalizeDouble( OrderTakeProfit(), 
                                                      Digits );
                    _SellOpenTime   = OrderOpenTime();
                    _SellProfit     = NormalizeDouble( OrderProfit(), 2 );
                    _SellSwap       = NormalizeDouble( OrderSwap(), 2 );
                    _SellCommission = NormalizeDouble(OrderCommission(), 
                                                      2 );
                    _SellComment    = OrderComment();
                    break;
                case OP_BUYSTOP:
                    _BuyStopTicket     = OrderTicket();
                    _BuyStopLots       = NormalizeDouble( OrderLots(), 1 );
                    _BuyStopOpenPrice  = NormalizeDouble( OrderOpenPrice(), Digits );
                    _BuyStopStopLoss   = NormalizeDouble( OrderStopLoss(), Digits );
                    _BuyStopTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits );
                    _BuyStopOpenTime   = OrderOpenTime();
                    _BuyStopComment    = OrderComment();
                    _BuyStopExpiration = OrderExpiration();
                    break;
                case OP_SELLSTOP:
                    _SellStopTicket     = OrderTicket();
                    _SellStopLots       = NormalizeDouble( OrderLots(), 1 );
                    _SellStopOpenPrice  = NormalizeDouble( OrderOpenPrice(), Digits );
                    _SellStopStopLoss   = NormalizeDouble( OrderStopLoss(), Digits );
                    _SellStopTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits );
                    _SellStopOpenTime   = OrderOpenTime();
                    _SellStopComment    = OrderComment();
                    _SellStopExpiration = OrderExpiration();
                    break;
                case OP_BUYLIMIT:
                    _BuyLimitTicket     = OrderTicket();
                    _BuyLimitLots       = NormalizeDouble( OrderLots(), 1 );
                    _BuyLimitOpenPrice  = NormalizeDouble( OrderOpenPrice(), Digits );
                    _BuyLimitStopLoss   = NormalizeDouble( OrderStopLoss(), Digits );
                    _BuyLimitTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits );
                    _BuyLimitOpenTime   = OrderOpenTime();
                    _BuyLimitComment    = OrderComment();
                    _BuyLimitExpiration = OrderExpiration();
                    break;
                case OP_SELLLIMIT:
                    _SellLimitTicket     = OrderTicket();
                    _SellLimitLots       = NormalizeDouble( OrderLots(), 1 );
                    _SellLimitOpenPrice  = NormalizeDouble( OrderOpenPrice(), Digits );
                    _SellLimitStopLoss   = NormalizeDouble( OrderStopLoss(), Digits );
                    _SellLimitTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits );
                    _SellLimitOpenTime   = OrderOpenTime();
                    _SellLimitComment    = OrderComment();
                    _SellLimitExpiration = OrderExpiration();
                    break;
            }
        }
    }
}
 

Jetzt schließen wir die Funktion zum Experten an:

extern int    _MagicNumber = 1123;
 
extern double Lot          = 0.1;
extern int    StopLoss     = 60;    
// der Absand bis zum Stop-Loss in Punkten (0 -  Ausschalten)
extern int    TakeProfit   = 100;   
// der Absand bis zum TakeProfit in Punkten (0 - Ausschalten)
extern int    TrailingStop = 50;    
// die Größe Trailing-Stops in Punkten (0 - Ausschalten)
 
extern int    Luft         = 20;    
// der Absand bis zum Level, in dem die Pending Order gesetzt wird
 
#include <OneTypeOrdersControl.mq4>
 
int start()
{
    int _GetLastError = 0;
 
    //---- Merken wir uns die Parameter der geöffneten Position (wenn sie es gibt)
    OneTypeOrdersInit( _MagicNumber );
 
    //---- Wenn wir beide Pending Orders haben, dann Verlassen wir es, 
    //---- Es muss abgewartet sein, bevor eine von ihnen signalisiert 
    if ( _BuyStopTicket > 0 && _SellStopTicket > 0 ) return(0);
 
    //---- wenn eine geöffnete Buy-Position gibt,
    if ( _BuyTicket > 0 )
    {
        //---- Wenn die Sellstop-Order noch nicht gelöscht wurde, Löschen Wir Sie:
        if ( _SellStopTicket > 0 )
        {
            if ( !OrderDelete( _SellStopTicket ) )
            {
                Alert( "OrderDelete Error #", GetLastError() );
                return(-1);
            }
        }
        //---- Überprüfen Wir, soll die Stop-Loss zurückgesetzt werden:
        //---- wenn die Größe Trailing-Stops nicht zu klein ist,
        if ( TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL ) )
        {
            //---- wenn das Gewinn der Position als die Punkten der TrailingStop mehr ist,
            if ( NormalizeDouble( Bid - _BuyOpenPrice, Digits ) > 
                  NormalizeDouble( TrailingStop*Point, Digits ) )
            {
                //---- wenn der neue Stopp-Loss-Level höher ist,als jetzt bei der Position
                //---- (oder wenn die Position keine Stop-Loss hat),
                if ( NormalizeDouble( Bid - TrailingStop*Point, 
                    Digits ) > _BuyStopLoss
                      || _BuyStopLoss <= 0.0 )
                {
                    //---- Modifizieren die Order
                    if ( !OrderModify( _BuyTicket, _BuyOpenPrice, 
                          NormalizeDouble( Bid - TrailingStop*Point, 
                                           Digits ), 
                          _BuyTakeProfit, 0 ) )
                    {
                        Alert( "OrderModify Error #", 
                              GetLastError() );
                        return(-1);
                    }
                }                    
            }
        }
 // Wenn eine geöffnete Position gibt, Verlassen wir es -da gibt es nichts mehr zu tun 
        return(0);
    }
 
// Der nächste Block ist voll gleich dem Block der Bearbeitung der Buy-Positionen,
// deshalb wurden keine Kommentaren damit eingetragen...
    if ( _SellTicket > 0 )
    {
        if ( _BuyStopTicket > 0 )
        {
            if ( !OrderDelete( _BuyStopTicket ) )
            {
                Alert( "OrderDelete Error #", GetLastError() );
                return(-1);
            }
        }
        if ( TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL ) )
        {
            if ( NormalizeDouble( _SellOpenPrice - Ask, Digits ) > 
                  NormalizeDouble( TrailingStop*Point, Digits ) )
            {
                if ( NormalizeDouble( Ask + TrailingStop*Point, 
                     Digits ) < _SellStopLoss
                      || _SellStopLoss <= 0.0 )
                {
                    if ( !OrderModify( _SellTicket, _SellOpenPrice, 
                          NormalizeDouble( Ask + 
                          TrailingStop*Point, Digits ), 
                          _SellTakeProfit, 0 ) )
                    {
                        Alert( "OrderModify Error #", 
                              GetLastError() );
                        return(-1);
                    }
                }                    
            }
        }
        return(0);
    }
 
 
//+----------------------------------------------------------------------------------------------------+
//| Wenn die Ausführung bis zu diesem Punkt gekommen ist, heißt es, dass es keine Pending Positionen   |
//| und geöffneten Positionen gibt                                                                     |
//+----------------------------------------------------------------------------------------------------+
//---- Platzieren wir Byu-Stop und Sell-Stop der Order:
    double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel;
    _OpenPriceLevel = NormalizeDouble( Ask + Luft*Point, Digits );
 
    if ( StopLoss > 0 )
      _StopLossLevel = NormalizeDouble( _OpenPriceLevel - 
                       StopLoss*Point, Digits );
    else
      _StopLossLevel = 0.0;
 
    if ( TakeProfit > 0 )
      _TakeProfitLevel = NormalizeDouble( _OpenPriceLevel + 
                         TakeProfit*Point, Digits );
    else
      _TakeProfitLevel = 0.0;
 
    if ( OrderSend ( Symbol(), OP_BUYSTOP, Lot, _OpenPriceLevel, 
        5, _StopLossLevel, 
                          _TakeProfitLevel, "", _MagicNumber ) < 0 )
    {
        Alert( "OrderSend Error #", GetLastError() );
        return(-1);
    }
 
 
    _OpenPriceLevel = NormalizeDouble( Bid - Luft*Point, Digits );
 
    if ( StopLoss > 0 )
      _StopLossLevel = NormalizeDouble( _OpenPriceLevel + 
                       StopLoss*Point, Digits );
    else
      _StopLossLevel = 0.0;
 
    if ( TakeProfit > 0 )
      _TakeProfitLevel = NormalizeDouble( _OpenPriceLevel - 
                         TakeProfit*Point, Digits );
    else
      _TakeProfitLevel = 0.0;
 
    if ( OrderSend ( Symbol(), OP_SELLSTOP, Lot, _OpenPriceLevel, 
        5, _StopLossLevel, 
                   _TakeProfitLevel, "", _MagicNumber ) < 0 )
    {
        Alert( "OrderSend Error #", GetLastError() );
        return(-1);
    }

    return(0);
}
    Hier ist der Unterschied zwischen dem Anfangsexperte und dem geänderten Experte sehr auffälliger - der Position-Konntrollblock ist ganz einfach und klar.

    Nun kommt es in der Reihe die schwerste Experten - welche keine Begrenzung über die geöffneten Positionen haben.

 

4. Die Kontrolle über den allen Positionen

Wenn es zuerst die Verwendung der Variablen genug war, um einen Parameter einer Order zu speichern, nun brauchen wir ein paar Arrays einzustellen - je eines auf jeden Parameter. Und sonst so ist das Prinzip der Funktion sehr ähnlich:

  • Am Start setzen wir alle Arrays auf 0 zurück;
  • Danach sortieren wir alle Orders, und wir schreiben in Arrays nur solche Parameter ein, deren Symbol dem grafischen Symbol entspricht, und deren MagicNumber mit dem Parameter der Funktion magic gleich ist;
  • Um die Verwendung zu vereinfachen, Fügen wir noch eine globale Variable ein, die die Gesamtmenge der Orders speichern wird, die Orders gehören zum Experten und wenn Arrays aufgerufen werden, wird diese Variable sehr hilfreich.

Fangen wir direkt an, die Funktion zu schreiben:

// Die Variable,die die Gesamtmenge der Orders speichern wird , 
// die zum Experten gehören:
int _ExpertOrdersTotal = 0;
 
// Die Arrays, in den die Parameter der Orders gespeichert werden:
int _OrderTicket[], _OrderType[];
double _OrderLots[], _OrderOpenPrice[], _OrderStopLoss[], 
_OrderTakeProfit[];
double _OrderProfit[], _OrderSwap[], _OrderCommission[];
datetime _OrderOpenTime[], _OrderExpiration[];
string _OrderComment[];
 
void AllOrdersInit( int magic )
{
    int _GetLastError = 0, _OrdersTotal = OrdersTotal();
 
    // Je nach der aktuellen Anzahl der Positionen, änderen wir die Größe der Arrays
    // (wenn _OrdersTotal = 0 ist, dann ändern wir die Größe der Arrays um 1)
    int temp_value = MathMax( _OrdersTotal, 1 );
    ArrayResize( _OrderTicket,     temp_value );
    ArrayResize( _OrderType,       temp_value );
    ArrayResize( _OrderLots,       temp_value );
    ArrayResize( _OrderOpenPrice,  temp_value );
    ArrayResize( _OrderStopLoss,   temp_value );
    ArrayResize( _OrderTakeProfit, temp_value );
    ArrayResize( _OrderOpenTime,   temp_value );
    ArrayResize( _OrderProfit,     temp_value );
    ArrayResize( _OrderSwap,       temp_value );
    ArrayResize( _OrderCommission, temp_value );
    ArrayResize( _OrderComment,    temp_value );
    ArrayResize( _OrderExpiration, temp_value );
 
    // Setzen wir Arrays auf 0 zurück
    ArrayInitialize( _OrderTicket,     0 );
    ArrayInitialize( _OrderType,       0 );
    ArrayInitialize( _OrderLots,       0 );
    ArrayInitialize( _OrderOpenPrice,  0 );
    ArrayInitialize( _OrderStopLoss,   0 );
    ArrayInitialize( _OrderTakeProfit, 0 );
    ArrayInitialize( _OrderOpenTime,   0 );
    ArrayInitialize( _OrderProfit,     0 );
    ArrayInitialize( _OrderSwap,       0 );
    ArrayInitialize( _OrderCommission, 0 );
    ArrayInitialize( _OrderExpiration, 0 );
 
    _ExpertOrdersTotal = 0;
    for ( int z = _OrdersTotal - 1; z >= 0; z -- )
    {
        if ( !OrderSelect( z, SELECT_BY_POS ) )
        {
            _GetLastError = GetLastError();
            Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - 
                   Error #", _GetLastError );
            continue;
        }
        if ( OrderMagicNumber() == magic && OrderSymbol() == 
             Symbol() )
        {
            //Füllen die Arrays
            _OrderTicket[_ExpertOrdersTotal] = OrderTicket()
            _OrderType[_ExpertOrdersTotal] = OrderType();
            _OrderLots[_ExpertOrdersTotal] = NormalizeDouble( 
                                             OrderLots(), 1 );
            _OrderOpenPrice[_ExpertOrdersTotal] = NormalizeDouble( 
                                       OrderOpenPrice(), Digits );
            _OrderStopLoss[_ExpertOrdersTotal] = NormalizeDouble( 
                                        OrderStopLoss(), Digits );
            _OrderTakeProfit[_ExpertOrdersTotal] = NormalizeDouble( 
                                        OrderTakeProfit(), Digits );
            _OrderOpenTime[_ExpertOrdersTotal] = OrderOpenTime();
            _OrderProfit[_ExpertOrdersTotal] = NormalizeDouble( 
                                             OrderProfit(), 2 );
            _OrderSwap[_ExpertOrdersTotal] = NormalizeDouble( 
                                             OrderSwap(), 2 );
            _OrderCommission[_ExpertOrdersTotal] = NormalizeDouble( 
                                            OrderCommission(), 2 );
            _OrderComment[_ExpertOrdersTotal] = OrderComment();
            _OrderExpiration[_ExpertOrdersTotal] = OrderExpiration();
            _ExpertOrdersTotal++;
        }
    }
 
// Je nach der Anzahl der Positionen, die zum Experten gehören, ändern wir die Größe der Arrays
// (wenn _ExpertOrdersTotal = 0 ist, dann ändern wir die Größe der Arrays um 1)
    temp_value = MathMax( _ExpertOrdersTotal, 1 );
    ArrayResize( _OrderTicket,     temp_value );
    ArrayResize( _OrderType,       temp_value );
    ArrayResize( _OrderLots,       temp_value );
    ArrayResize( _OrderOpenPrice,  temp_value );
    ArrayResize( _OrderStopLoss,   temp_value );
    ArrayResize( _OrderTakeProfit, temp_value );
    ArrayResize( _OrderOpenTime,   temp_value );
    ArrayResize( _OrderProfit,     temp_value );
    ArrayResize( _OrderSwap,       temp_value );
    ArrayResize( _OrderCommission, temp_value );
    ArrayResize( _OrderComment,    temp_value );
    ArrayResize( _OrderExpiration, temp_value );
}
 

Um das Arbeitsprinzip der Funktion zu begreifen, Lassen Sie uns einen Experte schreiben, der das Ziel hat, die Information über alle Positionen, die vom Experte eröffnet wurden, auf das Bildschirm zu liefern.

Sein Code ist ziemlich einfach:

extern int _MagicNumber    = 0;
 
#include <AllOrdersControl.mq4>
 
int start()
{
    AllOrdersInit( _MagicNumber );
    
    if ( _ExpertOrdersTotal > 0 )
    {
        string OrdersList = StringConcatenate(Symbol(), ", 
                      MagicNumber ", _MagicNumber, ":\n");
        for ( int n = 0; n < _ExpertOrdersTotal; n ++ )
        {
            OrdersList = StringConcatenate( OrdersList, 
                        "Order № ", _OrderTicket[n], 
                ", Gewinn/Verlust: ", 
                  DoubleToStr( _OrderProfit[n], 2 ), 
                " ", AccountCurrency(), "\n" );            
        }
        Comment( OrdersList );
    }
 
    return(0);
}

Wenn die _MagicNumber = 0 eingestellt wird, wird der Experte die Positionen-Liste darstellen, die manuell geöffnet wurden:

 

5. Abschluss

Im letzten Teil dieses Artikels würde ich die Schnelligkeit der Experten vergleichen, welche selbst ihre Orders und Experten sortieren und welche Funktionen benutzten. Dafür wurden beide Versionen in "jedem Tick" 10 mal hintereinander getestet (die Optimierung über dem Parameter _MagicNumber). Die Zeitmessung beim Test hat selbst Meta Trader durchgeführt - es wurde während der Optimierung die verbrauchte Zeit automatisch gemessen.

Also, Ergebnisse:

Der Experte

Die verbrauchte Zeit für 10 Testen (mm:ss)

CrossMACD_beta (ohne Funktion)

07:42

CrossMACD

11:37

DoublePending_beta (ohne Funktion)

08:18

DoublePending

09:42

 

Wie Sie aus der Tabelle sehen können, die Experte, welche die Funktion anwenden, funktionieren langsamer (mindestens, im Testlauf). Das ist aber nur ein kleiner Preis für die Bequemlichkeit und Leichtigkeit des Schreibens des Anfangscodes des Expertes.

       Jedenfalls die Entscheidung, ob es sich lohnt, sie anzuwenden - trifft jeder selbst.

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/1404

Charts ohne "Gaps" (Lücken) Charts ohne "Gaps" (Lücken)
Der Artikel widmet sich der Realisierung der Charts ohne verpasste Bars.
Die Orders-Berechnung in einem großen Programm Die Orders-Berechnung in einem großen Programm
Betrachtet werden allgemeine Grundlagen der Orders-Berechnung in einem komplizierten Programm.
Informationsspeicherung und Informations-Darstellung Informationsspeicherung und Informations-Darstellung
Der Artikel ist den bequemen und praktischen Speichermethoden und der Informations-Darstellung gewidmet. Hier werden Alternativen zur Standard-Log-Datei des Terminals und der Funktion Comment() betrachtet.
Die Arbeit mit Daten. Das Beispiel für Visualisierung der wichtigen Marktereignisse Die Arbeit mit Daten. Das Beispiel für Visualisierung der wichtigen Marktereignisse
Der Artikel betrachtet die Perspektive für die Verwendung MQL4, um eine produktive Arbeit im Markt Forex zu leisten.