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

 
PolarSeaman:

Was für eine Wendung!)))

Auftrag 1 (von# nein, nach#2) -- > Auftrag2 (von#1, nach#3) -- >Auftrag3 (von#2, nach# nein)

Von hier aus können Sie die gesamte Kette finden.

Wir sehen uns den offenen Kommentar an, und wenn dort from#XXX steht, bedeutet das, dass er zuvor teilweise geschlossen wurde - suchen Sie nach dem Ticket XXX aus dem Kommentar und suchen Sie es in der Historie. Schauen Sie in den Kommentaren nach - wenn dort "from#YYY" steht, bedeutet dies, dass die Seite früher teilweise geschlossen wurde. Suchen Sie das Ticket YYY aus dem Kommentar und suchen Sie es in der Historie. Schauen Sie sich den Kommentar an - wenn dort von#ZZZZ steht, bedeutet das, dass er früher auch teilweise geschlossen war - wiederholen Sie die Suche. Wenn es kein from#... gibt, dann ist es das allererste der ganzen Kette.

 
Artyom Trishkin:

Reihenfolge 1 (von# nein, nach#2) -- > Reihenfolge2 (von#1, nach#3) -- > Reihenfolge3 (von#2, nach# nein)

Von hier aus können Sie die gesamte Kette finden.

Wir sehen uns den offenen Kommentar an, und wenn dort from#XXX steht, bedeutet das, dass er zuvor teilweise geschlossen wurde - suchen Sie nach dem Ticket XXX aus dem Kommentar und suchen Sie es in der Historie. Schauen Sie in den Kommentaren nach - wenn dort from#YYY steht, bedeutet dies, dass die Anfrage früher teilweise geschlossen wurde - suchen Sie das Ticket YYY aus dem Kommentar und suchen Sie es in der Historie. Schauen Sie sich den Kommentar an - wenn dort von#ZZZZ steht, bedeutet das, dass er früher auch teilweise geschlossen war - wiederholen Sie die Suche. Wenn es kein from#... gibt, dann ist es das allererste der ganzen Kette.

Danke, es kann auch einen Auftrag in der Gegenrichtung geben, den ich auch hacken werde. Ich habe Angst, verwirrt zu werden. Ich denke, es wäre einfacher, die Gewinnreihenfolge eines bestimmten Datums zu verwenden, natürlich nur, wenn wir in der Lage sind, herauszufinden, wann die Position eröffnet wurde, da sich das Datum ändert, wenn die Position teilweise geschlossen wird.

 
Artyom Trishkin:

Auftrag 1 (von# nein, nach#2) -- > Auftrag2 (von#1, nach#3) -- > Auftrag3 (von#2, nach# nein)

Von hier aus können Sie die gesamte Kette finden.

Achten Sie auf offene Kommentare, und wenn dort from#XXX steht, bedeutet das, dass er früher teilweise geschlossen wurde - suchen Sie nach dem Ticket XXX aus dem Kommentar und suchen Sie es im Verlauf. Sehen Sie sich den Kommentar dort an - wenn es von#YYY ist - also wurde er auch früher teilweise geschlossen - sehen Sie sich das Ticket YYY vom Kommentar aus an und suchen Sie es in der Historie. Schauen Sie sich den Kommentar an - wenn dort von#ZZZZ steht, bedeutet das, dass er früher auch teilweise geschlossen war - wiederholen Sie die Suche. Wenn es kein from#... gibt, dann ist es das erste der ganzen Kette.

Artyom, Sie wissen, dass dies nicht immer der Fall ist. Und um eine Kette nicht zu verfolgen, muss das Terminal nicht dreimal abgefragt werden - die Geschichte wird trotzdem in eigenen Arrays und Strukturen gefahren. Es unterscheidet sich nicht von der Pflege Ihrer eigenen Datenbank, abgesehen von den zusätzlichen Schritten

Das Terminal und seine API sind die niedrigste mögliche Ebene. Und um die Logik des Roboters umzusetzen, ist es logisch, die Buchhaltung in seinen Begriffen zu führen (Handel, Kette, Gruppe, Transaktion - jeder nennt es anders). Es ist nur vernünftig, sie getrennt zu halten und nicht bei jedem Niesen (Häkchen/Balken) zu versuchen, sie zu rekonstruieren.

 
Maxim Kuznetsov:

Du weißt, dass dies nicht immer der Fall ist, Artyom. So müssen Sie das Terminal nicht dreimal fragen, wenn Sie die Kette verfolgen - die Geschichte wird immer noch in ihre eigenen Arrays und Strukturen gesteuert. Es ist nicht anders als die Pflege Ihrer eigenen Datenbank, abgesehen von den zusätzlichen Schritten

Das Terminal und seine API sind die niedrigste mögliche Ebene. Und für die Verwirklichung der Roboterlogik ist es logisch, Konten in ihren Begriffen zu führen (Handel, Kette, Gruppe, Transaktion - jeder nennt es anders). Es ist nur vernünftig, sie getrennt zu halten und nicht bei jedem Niesen (Häkchen/Balken) zu versuchen, sie zu rekonstruieren.

Ich habe das alles schon lange erledigt - ich lese die Geschichte nicht jedes Mal - aber sie ist immer auf dem neuesten Stand, und ich kann dort alles, was ich brauche, leicht und sehr schnell finden. Aber um jemandem zu raten, das Gleiche zu tun, brauche ich zumindest ein paar Artikel. Und so habe ich die Logik der Suche nach der ganzen Kette geschrieben.

 
PolarSeaman:

Danke, vielleicht gibt es einen Auftrag in umgekehrter Richtung, den ich auch schreddern werde. Ich habe Angst, verwirrt zu werden. Ich denke, es wäre einfacher, die Funktion Profit zu verwenden, um eine Position ab einem bestimmten Datum zu schließen, natürlich nur, wenn Sie herausfinden können, wann die Position eröffnet wurde, denn bei einer teilweisen Schließung ändert sich das Datum

Um nach einer Kette zu suchen, reicht es aus, das Ticket der Bestellung zu kennen, deren gesamte Kette Sie kennen möchten - übergeben Sie das Ticket als Parameter an die Suchfunktion, und die Ausgabe - ein gefülltes Array oder Array von Strukturen mit allen Daten jeder Bestellung der gesamten Kette.

 
Artyom Trishkin:

Ein gefülltes Array oder ein Array von Strukturen mit allen Daten der einzelnen Aufträge der gesamten Kette.

Ich weiß nicht einmal annähernd, was Sie gerade gesagt haben.

Zeigen Sie mir wenigstens ein Beispiel, wie es sein sollte.

 
PolarSeaman:

Ich weiß nicht einmal annähernd, was Sie gerade gesagt haben.

Geben Sie mir wenigstens ein Beispiel dafür, wie es sein sollte.

Ich löse das Problem auf folgende Weise: Ich suche nach Ketten in der Geschichte. Nun, damit die Geschichte eindeutig verfügbar ist, verwende ich zwei Varianten:

  1. Wenn ohne DLL, dann gebe ich in der Programmbeschreibung in 24 fett )))) an, dass der Kontoverlauf immer vollständig geladen werden muss (Registerkarte Kontoverlauf des Terminalfensters, Kontextmenü - Gesamter Verlauf).
  2. Mit DLL - Expert Advisor bleibt die Registerkarte "Kontohistorie" auf dem neuesten Stand, unabhängig von den Aktionen des Benutzers.

Funktionen zur Bestimmung des übergeordneten Auftrags, wenn der aktuelle Auftrag nicht der primäre ist:

int GetSignOfPartialOrCloseByClose()
{
   string comment = OrderComment();
   if (comment == "")
      return 0;
   
   // Ордер образовался вследствии частичного закрытия
   int fromStart = StringFind(comment, "from #");
   if (fromStart >= 0)
      return GetTicketByPartialClose(comment, fromStart, OrderType(), OrderOpenTime());
   
   // Ордер образовался вследствии встречного закрытия
   if (StringFind(comment, "partial close") >= 0)
   {
      datetime openTime = OrderOpenTime();
      int type = OrderType();
      for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
      {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            continue;
            
         if (OrderOpenTime() != openTime)
            continue;
            
         if (OrderType() != type)
            continue;
            
         if (StringFind(OrderComment(), "partial close") < 0)
            continue;
            
         return OrderTicket();
      }
   }
   
   return 0;
}


int GetTicketByPartialClose(string comment, int fromStart, int orderType, datetime openTime)
{
   string sTicket = StringSubstr(comment, fromStart + 6);
   int iTicket = (int)StringToInteger(sTicket);
   int type = OrderType();
   if (!OrderSelect(iTicket, SELECT_BY_TICKET))
      return 0;
      
   if (OrderType() == type)                                                                        // Дочерний ордер указывает на родителя - уходим
      return iTicket;
      
   // Дочерний ордер указывает на противоположный ордер. Необходимо искать родительский
   for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
         
      if (OrderType() != orderType || OrderOpenTime() != openTime)
         continue;
         
      int iFind = StringFind(OrderComment(), "close hedge by #");
      if (iFind < 0)
         continue;
         
      sTicket = StringSubstr(OrderComment(), iFind + 16);
      int iNewTicket = (int)StringToInteger(sTicket);
      if (iNewTicket != iTicket)
         continue;
         
      return OrderTicket();
   }
   
   return 0;
}

Einfach zu bedienen:

   for (int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS))
         continue;

      ....         

      int nFromTicket = GetSignOfPartialOrCloseByClose();                // Обязательно последней строкой в теле цикла, т. к. может измениться текущий выбранный ордер
   }


 
Ihor Herasko:

Der gröbste Fehler ist hier die Angabe des Wertes 100 anstelle von ticket im Argument OrderDelete().

Der nächste Fehler ist nicht so grob, aber er hängt damit zusammen, dass der berechnete Wert des Stop Loss geprüft wird und nicht sein tatsächlicher Wert.

Auch die Auftragsart wird nicht geprüft. Was ist, wenn wir einen Marktauftrag gewählt haben? Wie kann man sie löschen? Das Auftragssymbol wurde nicht geprüft.

Unter Berücksichtigung dieser Fehler erhalten wir den Code für die Löschung des schwebenden Auftrags, wenn der Kurs seinen Stop Loss erreicht:

Außerdem wird in Ihrem Code der Stop-Loss sofort nach Eröffnung der Order überprüft. Es scheint, dass dieser Code nach der Eröffnung eines schwebenden Auftrags nicht mehr ausgeführt wird. Das heißt, Sie müssen die Ausführungszweige trennen. Der eine ist für die Festlegung der Reihenfolge zuständig, der andere für die Begleitung der Reihenfolge.

Vielen Dank für Ihre ausführliche Antwort!

Ihrem Rat folgend, habe ich die Zweige getrennt und alles funktioniert.

Dann habe ich mit dem Problem der gleichzeitigen Eröffnung von 10-15 schwebenden Aufträgen konfrontiert, ich habe dieses Problem gelöst, indem ich es nach Ihrem Code hinzugefügt:

if (OrdersTotal ()>0) return;

Ich bin sicher, dass es einen besseren Weg gibt.

Könnten Sie bitte anhand Ihres Codes erklären, was 1; i >=0; --i bedeutet?

for (int i = OrdersTotal() - 1; i >= 0; --i)
 

Bitte helfen Sie mir zu verstehen, wie man einen Indikator schreibt. Ich habe einen solchen Dummy gezeichnet. Wie kann ich die Länge des Indikators so einstellen, dass er ab dem Moment, in dem der Indikator auf dem Chart platziert wird, in Größenpunkten über dem aktuellen Bid gezeichnet wird? Vielleicht liegt der Fehler darin, dass ich dieses Feld in die falsche Richtung verschiebe?

Ich weiß, es ist "kanonisch", ohne prev_calculated usw., aber ich brauche es so


#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot 
#property indicator_label1  "myInd"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double buff[], Bid;
input int lenght = 50, size = 5;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   ArrayResize(buff, 50);
   ArrayInitialize(buff, 0);
   SetIndexBuffer(0, buff, INDICATOR_DATA);
   //--- установим метку для отображения в DataWindow
   PlotIndexSetString(0,PLOT_LABEL,"myInd");   
//--- установим имя для показа в отдельном подокне и во всплывающей подсказке
   IndicatorSetString(INDICATOR_SHORTNAME,"myInd");
//--- укажем точность отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS, _Point);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   for(int i = lenght-1; i>0; i--){
      buff[i] = buff[i-1];
   }
   buff[0] = Bid+size;
   


   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Roman Sharanov:

Bitte helfen Sie mir zu verstehen, wie man einen Indikator schreibt. Ich habe einen solchen Dummy gezeichnet. Wie kann ich die Länge des Indikators so einstellen, dass er ab dem Zeitpunkt, an dem der Indikator auf dem Chart platziert wird, in Größenpunkten über dem aktuellen Bid gezeichnet wird? Vielleicht liegt der Fehler darin, dass ich dieses Feld in die falsche Richtung verschiebe?

Ich weiß, dass es "kanonisch" ist, ohne prev_calculated und dergleichen.


Es gibt ein offizielles Dokument - es ist genau wie das Ihre.

1. Sie sollten die Serialisierung aller verwendeten Arrays innerhalb von OnCalculate festlegen.

2. bevor Sie in die Schleife einsteigen, geben Sie buff[length]=Bid+size ein; - Sie erhalten dann ungefähr das, was Sie wollen. Eine geschwungene Linie und am Ende ein "Visier" bei Bid+size

3. beobachten Sie die Array-Grenzen. Natürlich ist rates_total kaum < Länge, aber man kann nicht viel falsch machen :-)

4.
buff[i] = buff[i+1]; // если тайм-серия (а вы подразумеваете их) то +