expert advisor - verschiedene Fragen - Seite 24

 

Das ist bereits im Beispiel enthalten.

Wenn Sie den Auftrag schließen, verwenden Sie den booleschen Rückgabewert der Funktion OrderClose(), und wenn die Funktion erfolgreich war, können Sie die mit dem Auftrag verbundenen Objekte entfernen.

                           bool close=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,clrBlue);
                             {
                              if(close==0)
                                {
                                 Alert(" Order Close Error! # "+IntegerToString(OrderTicket()));
                                }
                              if(close==1)
                                {
                                 Alert(" Order: "+IntegerToString(OrderTicket())+" Closed due to TP Profit = "+DoubleToString(OrderProfit(),2));
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
                                }
                             }
 
Marco vd Heijden:

Das ist bereits im Beispiel enthalten.
Wenn Sie den Auftrag schließen, verwenden Sie den booleschen Rückgabewert der Funktion OrderClose(), und wenn die Funktion erfolgreich war, können Sie die mit dem Auftrag verbundenen Objekte entfernen.

Ich weiß es schon, ich habe es schon versucht. Vielleicht habe ich etwas falsch gemacht. Ich werde es noch einmal versuchen, aber vorher möchte ich fragen, ob ich OrderClose() verwenden möchte. (manchmal schließe ich Aufträge manuell)
F: Also, kann ich Order-Objekte löschen, nachdem die Order ohne OrderClose() geschlossen wurde?

Vielen Dank im Voraus.

 

Nun, der Rückgabewert der Funktion Order Close() entscheidet, ob die Aktion erfolgreich war oder nicht. Wenn Sie also die Bestellung manuell schließen, müssen Sie einen etwas anderen Mechanismus entwickeln und verwenden.

Sie können eine Schattenkopie der Auftragsliste erstellen und diese mit der aktuellen Liste vergleichen. Wenn sich etwas ändert, weil Sie einen Auftrag manuell geschlossen haben, suchen Sie nach den Änderungen und entfernen Sie diese Objekte.

Einfacher ist es jedoch, zu prüfen, ob das OrderTicket() noch im aktiven Auftragspool vorhanden ist, so dass die Objekte automatisch entfernt werden, wenn es verschwindet, weil Sie den Auftrag manuell geschlossen haben.

Es hängt also davon ab, wie Sie es einrichten wollen.

An diesem Punkt würde ich sagen, dass Sie versuchen sollten, darüber hinaus zu schauen, was Sie letztendlich damit machen wollen, weil die Richtung, die Sie einschlagen, etwas mit zusätzlichen Aufgaben zu tun hat, die Sie vielleicht später hinzufügen wollen.


Da die Erstellung von Objekten bereits vollständig automatisiert ist, schlage ich vor, dass Sie das Gleiche für das Entfernen von Objekten tun, damit Sie sich in Zukunft nicht mehr darum kümmern müssen.

Hierfür können Sie einfach die Funktion

OrdersHistoryTotal()

Und der Historienpool

MODE_HISTORY

Es ist ganz einfach, der Auftragshistorien-Pool wird gescannt, und bei jedem Zyklus wird der Code nachsehen, ob irgendwelche Objekte mit Bezug zur OrderTicket()-Nummer existieren, und wenn es eine Übereinstimmung gibt, werden die Objekte automatisch gelöscht.

Dazu müssen Sie nur eine weitere Schleife hinzufügen, diesmal aber über den History-Pool.

Siehe Beispiel.

//+------------------------------------------------------------------+
//|                                                ObjectsRemove.mq4 |
//|      Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

static input int takeprofit=500;// Take Profit
static input int stoploss=500;  // Stop Loss
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   for(int order=OrdersTotal(); order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS);
        {
         if(selected==1)
           {
            if(Symbol()==OrderSymbol()) // only for current chart symbol
              {
               switch(OrderType())
                 {
                  case OP_BUY: // for buy order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()+takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()-stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;

                  case OP_SELL: // for sell order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()+stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;
                 }
              }
           }
        }
     }
//+------------------------------------------------------------------+
//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
              }
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
              }
           }
        }
     }
//+------------------------------------------------------------------+    
  } // end OnTimer() function
//+------------------------------------------------------------------+

So haben Sie nun das vollautomatische Hinzufügen von virtuellen Take-Profit- und Stop-Loss-Linien und auch das vollautomatische Entfernen dieser Linien.

Natürlich wird in diesem Beispiel der History-Pool kontinuierlich durchsucht...

Zusätzlich könnten Sie einen Integer hinzufügen, der die Anzahl der Orders enthält, die dann mit OrdersTotal() verglichen wird, und wann immer sich etwas ändert, führen Sie den Code zum Entfernen der Objekte aus.

Oder Sie könnten einen einfachen Zähler (60) hinzufügen, dann wird das Codestück nur einmal pro Minute prüfen, ob etwas entfernt werden muss.

 

Hey Mann! Das funktioniert perfekt! Vielen Dank an dieser Stelle!

Ich habe nur wenig geändert. Bis jetzt funktioniert es ohne Probleme.

//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            ObjectsDeleteAll( 0, "#" + IntegerToString( OrderTicket() ) ); // for arrows
            ObjectsDeleteAll( 0, _prefix + " #" + IntegerToString( OrderTicket() ) ); // order, sl, tp, price objects
           }
        }
     }

Sollte etwas nicht stimmen, bitte ich um Rückmeldung.
Nochmals vielen Dank Mann!

 

Vielleicht versteht niemand meine Frage. Aber ich brauche trotzdem einen guten Kommentar dafür. Deshalb versuche ich jetzt, meine Frage mit einem Bild zu verdeutlichen.
Frage: Auch Stop Loss, Take Profit Linien vor den Trade Panel Objekten. Ich weiß, dass dies durch das letzte Mal erstellte Objekt verursacht wurde. Aber wenn Sie mich verstehen, lassen Sie mich bitte wissen, wie ich Trade Panel Objekt sollte vor allen anderen Objekten ohne "Stop Loss und Take Profit" Linien sein.

Gemischte Objekte

Ich weiß, dass ich OBJPROP_BACK verwenden kann, aber ich möchte es nicht verwenden. Ich muss nur Zeile und Preis wie beide sehen. Ich hoffe, dass ich dafür gute Kommentare bekomme.


Öffnen, Stop Loss, Take Profit, Preislinien "Erstellen und Löschen", dass alle von ihnen in einer Funktion. So gerade jetzt versuche ich, es zu teilen, weil ich diese Funktion in OnChartEvent() setzen müssen. Aber bevor ich fragen muss.
F: Wenn ich diese Funktion in OnChartEvent() - so dass die Funktion konnte nicht Auswirkungen auf meine manuell Bestellungen?

Ich arbeite jetzt daran.

Bitte helfen Sie mir, vielen Dank im Voraus.

 

Nein, Onchartevent() führt den Code nur aus, wenn ein Diagrammereignis eintritt, nicht so wie die Funktion OnTImer().

Sie müssen also genau wissen, was Sie tun.

Wenn Sie zum Beispiel den Scan-Code verwenden:

if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))

Um zu prüfen, ob der Preis Ihre Linie überschritten hat, wird dies nicht in OnChartEvent() funktionieren.

Auch wenn Sie das automatisierte Beispiel verwenden möchten

if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
   {
     ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
     ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
   }

Dies wird nicht funktionieren oder die Objekte erstellen.

Sie werden den Code neu schreiben müssen.

Sie können auch die H_LINE-Objekte auf OBJPROP_BACK setzen. Das ist kein Problem, Sie werden sie immer noch sehen und sie werden unter Ihrem Panel sein.

 

Wirklich netter und nützlicher Kommentar, jetzt weiß ich sicher, dass ich es zumindest einmal versuchen sollte, um zu wissen, was ich zusätzlich tun könnte.

Danke für Ihre schnelle Antwort und Ihren hilfreichen Kommentar.

 
Marco vd Heijden:

Du wirst den Code neu schreiben müssen.

(Ich habe Ihren Kommentar schon aufmerksam gelesen, aber ich wollte es nur einmal versuchen - schließlich funktioniert es, wie Sie sagten, nicht wie der OnTimer(). )

Omg! Soll ich alles in diesem Code des Blocks ändern?
Jetzt habe ich vier Funktionen. Ich versuche gerade, sie in OnChartEvent() einzufügen. Ich habe bereits versucht, ich sehe nur eine Sache aktualisiert dies ist nur Print() für Stop Loss, Take Profit Preise.
OrderModify() funktioniert nicht in ihm.

Ich werde beginnen, etwas zu versuchen, wieder für dieses Problem in 8 - 10 Stunden.
Ich brauche nur wirklich gute Kommentare, ich hoffe, ich werde es bekommen.

Vielen Dank im Voraus.

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG) // I already tried with take profit object - there was not any effects
     {
      SL_TPcreateobjects();
      SL_TPdrags();
      SL_TPmodify();
      deleteobjs();
     }
  }
// if objects not found - create them
SL_TPcreateobjects()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
        {
         ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,takeprofit);
        }
     }
  }
// if objects exist
SL_TPdrags()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
        {
         if(TP_Price!=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
           {
            TP_drag=1;
            TP_Price=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0);
           }
         if(TP_drag==1)
           {
            if(TP_Price==ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
              {
               Print("Take Profit Price:",DoubleToString(TP_Price,Digits));
               TP_drag=0;
              }
           }
        }
     }
  }
// order closed - delete junks
deleteobjs()
{
  for(int i=OrdersHistoryTotal()-1; i>=0; i--)
    {
     bool Selected=OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(Selected==1)
       {
        ObjectsDeleteAll(0,"#"+IntegerToString(OrderTicket())+"-TP");
       }
    }
}
// ordermodify()
SL_TPmodify()
{
  Order_Modify=OrderModify(OrderTicket(),OrderOpenPrice(),SL_Price,TP_Price,0,CLR_NONE);
}
//+------------------------------------------------------------------+
 

Diese Funktionen werden nur ausgeführt, wenn ein Zeichenereignis eintritt.

Zumindest ist es das, was Sie hier zeigen.

Chartevent ist nur ein Auslöser für eine Unterbrechungsroutine, wenn jemand eine Schaltfläche oder etwas anderes auf dem Diagramm drückt.

Jetzt haben Sie das vollautomatische Beispiel genommen und unter eine Schaltfläche gelegt, es wird nichts passieren, wenn niemand die Schaltfläche drückt.

 
Marco vd Heijden:

Diese Funktionen werden nur ausgeführt, wenn ein Zeichenereignis eintritt.
Zumindest ist es das, was Sie hier zeigen.
Ein Chart-Ereignis ist nur ein Auslöser für eine Interrupt-Routine, wenn jemand eine Schaltfläche oder etwas anderes auf dem Chart drückt.
Jetzt haben Sie das vollautomatische Beispiel unter eine Schaltfläche gelegt, und wenn niemand auf die Schaltfläche drückt, wird nichts passieren.

Es ist möglich, dass Ihr letzter Kommentar sieht aus wie so einfach, aber eigentlich, dass Kommentar zeigte mir den richtigen Weg.
So jetzt löse ich mein Problem, die ich versuchen, ziehen zu verwenden.

Und jetzt fange ich an, über einige andere grafische Objekte zu recherchieren, die sich mit diesem HLine-Objekt bewegen.

Vielen Dank mehr Mann!
Alles Gute für Sie!


honest_knave:

Überlegen Sie auch, wie oft Sie die Linie bewegen. Ist es einmal pro Sekunde? Wahrscheinlich nicht.
Fügen Sie Ihren Code in OnChartEvent() ein:

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line
Vielen Dank Mann! Also das dein Kommentar mir wirklich sehr geholfen hat!