Fragen von Neueinsteigern zu MQL4 und MQL5, Hilfe und Diskussion über Algorithmen und Codes - Seite 614

 
Vitaly Muzichenko:

Nun, Sie haben die unkritischen Fehler aufgezeigt.

Wie die Funktion funktioniert, haben Sie selbst beantwortet:


Im Testgerät ist es in Ordnung. So funktioniert es in der Praxis.
Dateien:
yOXZsAXZ-X4.jpg  479 kb
 
Tigerfreerun:
Im Testgerät ist es in Ordnung. So funktioniert es in der Praxis.

In diesem Fall müssen Sie sich mit dem Code befassen, alle Werte ausdrucken( Print(...) ) und sehen, wo der Fehler herkommt

 
Tigerfreerun:
Im Testgerät ist es in Ordnung. So funktioniert es in der Praxis.

Sie haben Ihre Antwort:

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Alle Fragen von Anfängern zu MQL4, Hilfe und Diskussion über Algorithmen und Codes

Alexey Viktorov, 2018.09.06 21:00

Richtung zum Nachdenken: Wenn der Gewinn kleiner als Null ist... Wie groß wird das Feld beim Sortieren sein?

Und wie groß ist das Feld, wenn es überhaupt keine Aufträge gibt?
Überlegen Sie, wie groß das sortierbare Feld a[][2] in der ersten Dimension wäre, wenn alle Gewinne NICHT größer als Null sind.
 

Guten Tag, der EA heißt "Rollover", aber er funktioniert nicht wie geplant. Er verdoppelt das Lot, wenn er im Minus schließt, aber das anschließende Schließen des TP erlaubt es aus irgendeinem Grund nicht, Minusgeschäfte zurückzugeben, die vorher geschlossen wurden. Bitte sagen Sie mir, was los ist, ich kann es nicht herausfinden. Ich möchte meine Frage in meiner Mailbox stellen.

extern string TimeStart    = "04:00";  //Время начала контрольного периода
extern string TimeEnd      = "09:00";  //Время окончания контрольного периода
extern string TimeCloseOrder = "23:30";//Время в которое происходит закрытие всех ордеров
extern double LOT          = 0.1;
extern int    Magic        = 777;
extern double K_martin     = 2;
extern bool   No_Loss      = true;
int slippage = 3;
double marga,Lot,SL,TP;
int tip,Orders,tipOrders,TradeDey;
//-------------------------------------------------------------------+
int init()
{
   if (Digits==5 || Digits==3) slippage = 30;
}
int start()
{
   datetime Time_Start      = StrToTime(StringConcatenate(Day(),".",Month(),".",Year()," ",TimeStart,     ":00"));
   datetime Time_End        = StrToTime(StringConcatenate(Day(),".",Month(),".",Year()," ",TimeEnd,       ":00"));
   datetime Time_CloseOrder = StrToTime(StringConcatenate(Day(),".",Month(),".",Year()," ",TimeCloseOrder,":00"));

   if (Time_CloseOrder>Time_End) if (CurTime()>=Time_CloseOrder) CLOSEORDERS();

   int tip;
   if (Orders>OrdersTotal()) tip=CloseOrder();
   Orders=OrdersTotal();

   if (ORDERS(0)==0 && tip==0 && (CurTime()<Time_CloseOrder || Time_CloseOrder<=Time_End) && TradeDey!=TimeDay(CurTime()))
   {
      int BarStart = iBarShift(NULL,0,Time_Start,false);
      int BarEnd   = iBarShift(NULL,0,Time_End  ,false);
      double Max_Price=iHigh(NULL,0,iHighest(NULL,0,MODE_HIGH,BarStart-BarEnd,BarEnd));
      double Min_Price=iLow (NULL,0,iLowest (NULL,0,MODE_LOW, BarStart-BarEnd,BarEnd));
   
      if (TimeCurrent()>Time_End && ObjectFind("bar0"+Time_End)==-1)
      {
         ObjectCreate("bar0"+Time_End, OBJ_RECTANGLE, 0, 0,0, 0,0);
         ObjectSet   ("bar0"+Time_End, OBJPROP_STYLE, STYLE_SOLID);
         ObjectSet   ("bar0"+Time_End, OBJPROP_COLOR, Blue);
         ObjectSet   ("bar0"+Time_End, OBJPROP_BACK,  true);
         ObjectSet   ("bar0"+Time_End, OBJPROP_TIME1 ,Time_Start);
         ObjectSet   ("bar0"+Time_End, OBJPROP_PRICE1,Max_Price);
         ObjectSet   ("bar0"+Time_End, OBJPROP_TIME2 ,Time_End);
         ObjectSet   ("bar0"+Time_End, OBJPROP_PRICE2,Min_Price);
      }
      
      if (Bid>Max_Price) OrderSend(Symbol(),OP_BUY,LOT,Bid,slippage,Min_Price,
         NormalizeDouble(Ask + Max_Price-Min_Price,Digits),"BreakdownLevel",Magic,Blue);
      if (Bid<Min_Price) OrderSend(Symbol(),OP_SELL,LOT,Bid,slippage,Max_Price,
         NormalizeDouble(Bid - Max_Price+Min_Price,Digits),"BreakdownLevel",Magic,Blue);
      return;
   }
   if (No_Loss) No_Loss();
   if (tip==1 && TradeDey!=TimeDay(CurTime()))
   {
      Lot=Lot*K_martin;
      if (tipOrders==0) OrderSend(Symbol(),OP_SELL,Lot,Bid,slippage,SL,TP,"Nevalyashka",Magic,Blue);
      if (tipOrders==1) OrderSend(Symbol(),OP_BUY ,Lot,Ask,slippage,SL,TP,"Nevalyashka",Magic,Blue);
   }
   return(0);
}
//-------------------------------------------------------------------+
int CloseOrder()
{
   string txt;
   double loss;
   int i=OrdersHistoryTotal()-1;
   if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      if (OrderSymbol()==Symbol() && Magic==OrderMagicNumber())
      {
         tipOrders=OrderType();
         Lot=OrderLots();
         loss = MathAbs(OrderProfit()/MarketInfo(Symbol(),MODE_TICKVALUE)/Lot/K_martin);
         if (tipOrders==0)
         {
            TP=NormalizeDouble(Bid - loss*Point,Digits);
            SL=NormalizeDouble(Ask + loss*Point,Digits);
         }
         if (tipOrders==1)
         {
            SL=NormalizeDouble(Bid - loss*Point,Digits);
            TP=NormalizeDouble(Ask + loss*Point,Digits);
         }
         if (OrderClosePrice()==OrderTakeProfit() || OrderProfit()>=0) TradeDey=TimeDay(CurTime());
         if (OrderClosePrice()==OrderStopLoss()) return(1);
      }
   }  
   return(0);
}
//+-----------------------------------------------------------------+
int ORDERS(int tip)
{
   int N_Sell,N_Buy;
   for (int i=0; i<OrdersTotal(); i++)
   {                                               
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
      {
         if (OrderSymbol()==Symbol() && Magic==OrderMagicNumber())
         {
            if (OrderType()==OP_BUY ) N_Buy++;
            if (OrderType()==OP_SELL) N_Sell++;
         }
      }   
   }
if (tip== 0) return(N_Buy+N_Sell);
if (tip== 1) return(N_Buy);
if (tip==-1) return(N_Sell);
}                  
//-------------------------------------------------------------------+
void No_Loss()
{
   int tip;
   double TP,OOP;
   for (int i=OrdersTotal()-1; i>=0; i--) 
   {
      if (OrderSelect(i, SELECT_BY_POS)==true)
      {
         tip = OrderType();
         if (tip<2 && OrderSymbol()==Symbol())
         {
            if (OrderMagicNumber()!=Magic) continue;
            TP = OrderTakeProfit();
            OOP = OrderOpenPrice();
            if (tip==0) //Bay               
            {  
               if (OrderStopLoss()>OrderOpenPrice()+Ask-Bid) return;
               if ((TP-OOP)/2+OOP<=Bid)
               OrderModify(OrderTicket(),OOP,NormalizeDouble(OOP+Ask-Bid,Digits),TP,0,White);
            }                                         
            if (tip==1) //Sell               
            {                                         
               if (OrderStopLoss()<OrderOpenPrice()-Ask+Bid) return;
               if (OOP-(OOP-TP)/2>=Ask)
               OrderModify(OrderTicket(),OOP,NormalizeDouble(OOP-Ask+Bid,Digits),TP,0,White);
            } 
         }
      }
   }
}
//------------------------------------------------------------------+
void CLOSEORDERS()
{
   bool error;
   int err;
   while (true)
   {  error=true;
      for (int i=OrdersTotal()-1; i>=0; i--)
      {                                               
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
         {
            if (OrderSymbol()!=Symbol()||Magic!=OrderMagicNumber()) continue;
            if (OrderType()==OP_BUY)
               error=OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);
            if (OrderType()==OP_SELL)
               error=OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);
         }   
      }
      if (!error) {err++;Sleep(2000);RefreshRates();}
      if (error || err >5) return;
   }
}
//-------------------------------------------------------------------+
 
Tigerfreerun:
Ich verstehe nicht ganz, was genau diese Funktion bewirkt. Aber, wie der Autor schon sagte, ist es sein Ziel, verlorene Aufträge mit gewinnbringenden Aufträgen zwischen den Symbolen zu decken. Ich würde mich freuen, wenn Sie mir helfen könnten, die Funktion zu korrigieren und zu verstehen
void MaxMinProfit()
{
int i, N, MaxTic, MinTic;
double   MinProf=0, MaxProf=0, OP, g, a[][2];
string MinSym, MaxSym;
ArrayResize(a, 0);
 
for (i=OrdersTotal()-1; i>=0; i--) 
  {    
   if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) 
    { 
     if (OrderType()==OP_SELL ||  OrderType()==OP_BUY )
      {
       OP = NormalizeDouble(OrderProfit()+OrderSwap()+OrderCommission(),2);
       
      if (MinProf>OP) 
      {
       
          MinProf=OP;
          MinTic=OrderTicket();
          MinSym=OrderSymbol();
          
         }
         
      if (OP>0) 
      {
       
          N++;
            ArrayResize(a, N);
            a[N-1][0]=OP;
            a[N-1][1]=OrderTicket();
          
         }
         
         }
         }
         
         }
         
      ArraySort(a, WHOLE_ARRAY, 0, MODE_DESCEND);//MODE_ASCEND);
      
      for (i=0; i<Level; i++) 
       {
     
     g+=a[i][0];
     //int ti=a[i-2][1];
     }
         
         
     
     if(MinProf <0 && (g+MinProf)>=ProcMax)
      {
       for (i=0; i<Level; i++) 
       {
       if (OrderSelect(a[i][1], SELECT_BY_TICKET, MODE_TRADES))
        {
        //Alert(a[i][1]);
         if (OrderType()== OP_BUY)
         {
          OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(),MODE_BID), Slip, CLR_NONE);
          }
          if (OrderType()== OP_SELL)
           {
           OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(),MODE_ASK), Slip, CLR_NONE);
           }
          }
         }
          
          
          
          if (OrderSelect(MinTic, SELECT_BY_TICKET, MODE_TRADES))
        {
         if (OrderType()== OP_BUY)
         {
          OrderClose(MinTic, OrderLots(), MarketInfo(OrderSymbol(),MODE_BID), Slip, CLR_NONE);
          }
          if (OrderType()== OP_SELL)
           {
          OrderClose(MinTic, OrderLots(), MarketInfo(OrderSymbol(),MODE_ASK), Slip, CLR_NONE);
           }
          }}       
return;
}

Sie verstehen nicht, und ich will nicht verstehen, was diese Funktion bewirkt. Sie benutzen es. Sie haben es sich selbst ausgesucht. Wie kann man etwas benutzen, ohne zu wissen, wozu es gut ist?

Ich habe Ihnen gerade gesagt, woher der Fehler kommt und aus welchem Grund.

Eine weitere Klarstellung:

Ein Array wird deklariert. Sie ist grün hervorgehoben. Sie hat in der ersten Dimension die Länge Null. Die blaue Linie ist nicht eindeutig. Wenn Sie die Größe des Arrays zurücksetzen wollen, gibt es ArrayFree(). Aber auch diese Funktion ist nutzlos, da das gerade deklarierte dynamische Array die Länge Null hat.

2. Wenn es keine Aufträge gibt, wird der rot markierte Code nicht ausgeführt. Daher bleibt die Größe des Arrays gleich Null.

3. Die Array-Sortierung erfolgt bei jedem Tick. Dies ergibt sich aus dem Kodex. Und was kann man in einer leeren Tasche sortieren? Es sei denn, es sind zwei Wachteleier...?


Und hier ist der Fehlertext... Was soll ich sagen? Die Entwickler haben nicht vorausgesehen, dass jemand versuchen könnte, ein leeres Feld zu sortieren. Dafür haben sie sich keine besondere Botschaft einfallen lassen.

ArrayFree - Операции с массивами - Справочник MQL4
ArrayFree - Операции с массивами - Справочник MQL4
  • docs.mql4.com
При написании скриптов и индикаторов необходимость в использовании функции ArrayFree() может возникнуть не часто: так как при завершении работы скрипта вся использованная память сразу же освобождается, а в пользовательских индикаторах основная работа с массивами представляет собою доступ к индикаторным буферам, размеры которых автоматически...
 
Alexey Viktorov:

Sie verstehen nicht, und ich will nicht verstehen, was diese Funktion bewirkt. Sie benutzen es. Sie haben es sich selbst ausgesucht. Wie kann man etwas benutzen, ohne zu wissen, wozu es gut ist?

Ich habe Ihnen gerade gesagt, woher der Fehler kommt und aus welchem Grund.

Eine weitere Klarstellung:

1. Ein Array wird deklariert. Sie ist im Code grün hervorgehoben. Sie hat in der ersten Dimension die Länge Null. Die blau unterlegte Linie ist nicht eindeutig. Wenn wir die Größe des Arrays zurücksetzen wollen, gibt es ArrayFree() , aber auch diese Funktion wird nutzlos sein, da das dynamische Array, das wir gerade deklariert haben, eine Länge von Null hat.

2. Wenn es keine Aufträge gibt, wird der rot markierte Code nicht ausgeführt. Daher bleibt die Größe des Arrays gleich Null.

3. Die Array-Sortierung erfolgt bei jedem Tick. Das ergibt sich aus dem Kodex. Und was kann man in einer leeren Tasche sortieren? Es sei denn, es sind 2 Wachteleier...?


Und hier ist der Fehlertext... Was soll ich sagen? Die Entwickler haben nicht vorausgesehen, dass jemand versuchen könnte, ein leeres Feld zu sortieren. Dafür haben sie sich keine besondere Botschaft einfallen lassen.

Alexey, du irrst dich. ArrayFree() dient dazu, Speicher aus dem Array freizugeben, wenn er nicht mehr benötigt wird, was sehr selten der Fall ist, und schon gar nicht in diesem Fall.

ZeroMemory(a), ArrayInitialize(a,xxx) sollte verwendet werden, um das Array auf Null zu setzen, und ArrayResize(a,xxx) sollte verwendet werden, um die Größe in der ersten Dimension zu ändern.

Diese Änderung ändert jedoch nichts an Ihrer Argumentation - sie ist richtig.

 
Artyom Trishkin:

Alexey, das ist nicht richtig. ArrayFree() wird verwendet, um Speicher von einem Array freizugeben, wenn dieses Array nicht mehr benötigt wird, was sehr selten vorkommt, und definitiv nicht in diesem Fall.

ZeroMemory(a), ArrayInitialize(a,xxx) sollte verwendet werden, um das Array auf Null zu setzen, und ArrayResize(a,xxx) sollte verwendet werden, um die Größe in der ersten Dimension zu ändern.

Diese Änderung hat jedoch keinen Einfluss auf Ihre Argumentation - sie ist korrekt.

Laut der Dokumentation

ArrayFree .

gibt den Puffer eines beliebigen dynamischen Arrays frei und setzt die Größe der Null-Dimension auf 0.

Vielleicht habe ich mich nicht richtig ausgedrückt und Sie haben mich missverstanden.
 
Alexey Viktorov:

Laut der Dokumentation

Vielleicht habe ich mich nicht richtig ausgedrückt und Sie haben mich missverstanden.

Und weiter hinten:


Hinweis

Die Verwendung der Funktion ArrayFree() in Skripten und Indikatoren ist nicht sehr oft notwendig, da der gesamte verwendete Speicher sofort freigegeben wird, wenn das Skript aufhört zu arbeiten. In benutzerdefinierten Indikatoren wird bei den meisten Operationen mit Arrays auf Indikatorpuffer zugegriffen, deren Größe automatisch vom Exekutivsubsystem des Client-Terminals verwaltet wird.

Wenn ein Programm den Speicher unter komplexen dynamischen Bedingungen unabhängig verwalten muss, ermöglicht die Funktion ArrayFree() die explizite und sofortige Freigabe des von einem unnötigen dynamischen Array belegten Speichers.


Gibt den Puffer eines beliebigen dynamischen Arrays frei und setzt die Größe der Null-Dimension auf 0

Verstehen Sie das? Sie haben den zweiten Teil gelesen und den ersten - wichtigen - Teil überlesen? Er gibt den für das Array reservierten Speicher frei. Es ist... weg... Der für das Array zugewiesene Speicherplatz wird freigegeben und kann dann mit anderen Daten belegt werden. Warum sollte bei jedem erneuten Aufruf der Funktion diesem Array erneut Speicher zugewiesen werden? Sie sind derjenige, der sie befreien soll. Alles, was Sie tun müssen, ist, die Größe zu ändern - ArrayResize() oder das Array auf Null zu setzen - ArrayInitialize(), ZeroMemory(). Und der Speicherplatz für das Array wird nicht freigegeben, sondern bleibt für dieses Array reserviert, bis das Programm beendet ist.

 
Artyom Trishkin:

Und dann ist da noch das Gleiche:


Hinweis

Die Verwendung des Befehls ArrayFree() in Skripten und Indikatoren ist nicht sehr oft notwendig, da der gesamte verwendete Speicher sofort nach Abschluss der Operation freigegeben wird. In benutzerdefinierten Indikatoren wird bei den meisten Operationen mit Arrays auf Indikatorpuffer zugegriffen, deren Größe automatisch vom Ausführungssubsystem des Client-Terminals verwaltet wird.

Wenn ein Programm den Speicher unter komplexen dynamischen Bedingungen unabhängig verwalten muss, ermöglicht die Funktion ArrayFree() die explizite und sofortige Freigabe des von einem unnötigen dynamischen Array belegten Speichers.


Es gibt den Puffer eines dynamischen Arrays frei und setzt die Größe der Null-Dimension auf 0

Verstehen Sie das? Sie haben den zweiten Teil gelesen und den ersten wichtigen Teil verpasst, nicht wahr? Es gibt den für das Array zugewiesenen Speicher frei. Das ist alles... weg... Der für das Array zugewiesene Speicherplatz wird freigegeben und kann weiter mit anderen Daten belegt werden. Warum sollte bei jedem erneuten Aufruf der Funktion diesem Array erneut Speicher zugewiesen werden? Sie sind derjenige, der sie befreien soll. Alles, was Sie tun müssen, ist, die Größe zu ändern - ArrayResize() oder das Array auf Null zu setzen - ArrayInitialize(), ZeroMemory(). Und der Speicherplatz für das Array wird nicht freigegeben, sondern bleibt für dieses Array reserviert, bis das Programm beendet ist.

Also... Und wenn ein lokales Array bei jedem Funktionsaufruf oder, was sehr unwahrscheinlich ist, bei jedem Tick deklariert wird... Der Speicher für das Array wird jedoch jedes Mal zugewiesen, wenn das Array definiert wird. Ist es nicht so? Und es spielt keine Rolle, ob der Speicher freigegeben wird oder nicht, aber der Speicher wird jedes Mal neu zugewiesen...

Mein Hauptgedanke war, dass man das nicht tun sollte... und wenn Sie das tun, sollten Sie es besser über ArrayFree() tun.

Interessant ist Folgendes: Wenn ein lokales Array bei jedem Funktionsaufruf deklariert wird, wird dementsprechend jedes Mal Speicher dafür reserviert. Aber welche Adressen werden dabei verwendet? Dasselbe wie bei der ersten Deklaration des Arrays, oder was wird verwendet?

 
Denis Danilov:

Guten Tag, der EA heißt "Rollover", aber er funktioniert nicht wie geplant. Er verdoppelt das Lot, wenn er im Minus schließt, aber das anschließende Schließen des TP erlaubt es aus irgendeinem Grund nicht, Minusgeschäfte zurückzugeben, die vorher geschlossen wurden. Bitte sagen Sie mir, was los ist, ich kann es nicht herausfinden. Ich möchte mich im Voraus bei allen bedanken, die einen Kommentar abgegeben haben.

Versuchen Sie, die Verdoppelung vor der ersten Partie zu überprüfen. Beobachten Sie die Schließung nach der Zeit.