Partieller Take Profit - Seite 2

 
 MqlTick tick;                                               // nur gültig für das aktuelle Symbol
   if(!SymbolInfoTick(Symbol(),tick)) GetLastError();
Ingo Christ
:

Ist es wohl okay, wenn ich den Code nochmal im englischsprachigen Forum poste und frage, ob jemand einen Fehler findet?

Also ctrade tptrade würde ich mal im allgemeinen teil schreiben

es reicht aber die ctrade einmal reinzunehmen, quasi


ctrade. Trade im allgemeinen teil


das symbolinfo double würde ich mit

 MqlTick tick;                                               // nur gültig für das aktuelle Symbol
   if(!SymbolInfoTick(Symbol(),tick)) GetLastError();


Aus der ontick übergeben


weiters ticket niemals mit tick abkürzen, das führt zu verwirrung


Dann hast du beim schliessen die deviation mit -1, da gehört ein realer wert hin, also 10 für 1 pip, 20 für 2 weil es sind ja immer points. Ich hab das bei mir in einer variable namens slip im globalen bereich, weil die benötigst du auch fürs order setzen

Den position type musst du als POSITION_BUY schreben und nicht als 0 und 1, das kennt mql5 nicht immer


den indicator brauchst du nicht in der void, lass den copy buffer in der ontick und übergeb die werte ind die funktion, part mächtig code und funkt

Postitiom volume einmal auslesen


double volume = xxx

dann sparst du dir die viele Schreiberei

und geb das in den debugger , oder wird dir print aus damit du siehst was genau nicht geht

 
Ingo Christ:

Ist es wohl okay, wenn ich den Code nochmal im englischsprachigen Forum poste und frage, ob jemand einen Fehler findet?

Klar kannst Du, aber hast Du mal den Debugger versucht? Mit ihm kann man genau solche Fehler finden, warum bestimmte Dinge nicht so passieren wie gedacht.

Das liegt doch an der Schleife und den if in ihr. Übrigens hast Du nicht angegeben was nicht passiert bzw. was anders passiert als Du es willst!!

Kann es sein, dass Deine Ifs da falsch aufgestellt sind? Das sagt Dir aber der Debugger!

 
Carl Schreiber:

Klar kannst Du, aber hast Du mal den Debugger versucht? Mit ihm kann man genau solche Fehler finden, warum bestimmte Dinge nicht so passieren wie gedacht.

Das liegt doch an der Schleife und den if in ihr. Übrigens hast Du nicht angegeben was nicht passiert bzw. was anders passiert als Du es willst!!

Kann es sein, dass Deine Ifs da falsch aufgestellt sind? Das sagt Dir aber der Debugger!

Werde aus dem Debugger in diesem Fall leider nicht schlau :-(
Ich will, dass der Code prüft, ob Positionen offen sind und wenn der Kurs ein Vielfaches der ATR(14) über/unter (je nachdem ob Buy-/Sellposition) einen Teil der Position schließt.
Er soll auch noch prüfen, ob die Position ihr ursprüngliches Volumen hat. 
Nur dann soll er einen Teil der Position schließen. Der Teil wird durch den Input TPDivisor bestimmt. Der geschlossene Teil der Position soll dann 1/TPDivisor sein. 
Habe den Code nochmal angepasst und in den Hauptquellcode getan, wo dann CTrade schon als trade initialisiert ist. 
Leider ohne Erfolg.

void TakeProfitFunction(bool UseTP1,int TPDivisor1,int ATRHandle1, double TPATRMultiplier1)
{
if(UseTP1==true&&PositionsTotal()>0)
  {
   ulong ticket;
   
   double ATRArray1[];
   CopyBuffer(ATRHandle1,0,0,3,ATRArray1);
   ArraySetAsSeries(ATRArray1,true);
   
   for (int i=0; i<PositionsTotal();i++)
      {
      tick=PositionGetTicket(i);
      PositionSelectByTicket(ticket);
      OrderSelect(ticket);
      
      if(OrderGetDouble(ORDER_VOLUME_INITIAL)==PositionGetDouble(POSITION_VOLUME) 
         && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY
         && (SymbolInfoDouble(_Symbol,SYMBOL_BID)>PositionGetDouble(POSITION_PRICE_OPEN)+(ATRArray1[1]*TPATRMultiplier1))) 
        {        
         double Vol=PositionGetDouble(POSITION_VOLUME);
         double CloseVol = NormalizeDouble(Vol/TPDivisor1,2);
         trade.PositionClosePartial(ticket,CloseVol,20);              
        }

      if(OrderGetDouble(ORDER_VOLUME_INITIAL)==PositionGetDouble(POSITION_VOLUME)
         && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL
         && (SymbolInfoDouble(_Symbol,SYMBOL_ASK)<PositionGetDouble(POSITION_PRICE_OPEN)-(ATRArray1[1]*TPATRMultiplier1))) 
        {        
         double Vol=PositionGetDouble(POSITION_VOLUME);
         double CloseVol = NormalizeDouble(Vol/TPDivisor1,2);
         trade.PositionClosePartial(ticket,CloseVol,20);      
        }
   
      }
 }

}
 
Werde aus dem Debugger in diesem Fall leider nicht schlau :-(
Ich will, dass der Code prüft, ob Positionen offen sind und wenn der Kurs ein Vielfaches der ATR(14) über/unter (je nachdem ob Buy-/Sellposition) einen Teil der Position schließt.
Er soll auch noch prüfen, ob die Position ihr ursprüngliches Volumen hat. 
Nur dann soll er einen Teil der Position schließen. Der Teil wird durch den Input TPDivisor bestimmt. Der geschlossene Teil der Position soll dann 1/TPDivisor sein. 
Habe den Code nochmal angepasst und in den Hauptquellcode getan, wo dann CTrade schon als trade initialisiert ist. 
Leider ohne Erfolg.

Naja, all das, was Du willst und nicht funktioniert, könnte Dir der Debugger zeigen!

Er würde Dir auch helfen Deine Fehler zu erkennen, was mir auf Grund der gezeigten Funktion schwer fällt bzw. unmöglich ist.

Ich selber würde mir meine eigene Logik, wenn sie nicht tut, was sie soll auch so prüfen.

Ich wüsste zB. nicht, weil ich das immer wieder durcheinander bringe, ob ArraySetAsSeries() da richtig ist - also frage ich den Debugger ...

Außerdem Du machst überhaupt keine Fehlerabfragen...

 
Carl Schreiber:

Naja, all das, was Du willst und nicht funktioniert, könnte Dir der Debugger zeigen!

Er würde Dir auch helfen Deine Fehler zu erkennen, was mir auf Grund der gezeigten Funktion schwer fällt bzw. unmöglich ist.

Ich selber würde mir meine eigene Logik, wenn sie nicht tut, was sie soll auch so prüfen.

Ich wüsste zB. nicht, weil ich das immer wieder durcheinander bringe, ob ArraySetAsSeries() da richtig ist - also frage ich den Debugger ...

Außerdem Du machst überhaupt keine Fehlerabfragen...

Das kann der Debugger? Ich dachte er kann nur Anzeigen welchen Wert eine Variable an einer Bestimmten Stelle des Code-Durchlaufs hat. 
Gibt es da ein Tutorial zu? 
Habe nur dieses gefunden: https://www.mql5.com/de/articles/654 und daraus werde ich irgendwie nicht schlau. 

Zur Fehlerbehebung von MQL5-Programmen (Debugging)
Zur Fehlerbehebung von MQL5-Programmen (Debugging)
  • www.mql5.com
Dieser Artikel richtet sich primär an Programmierer, die die Sprache zwar bereits gelernt haben, die allerdings noch keine Meister ihres Fachs sind. Dabei geht der Artikel auf die wichtigste Elemente ein, mit denen sich Entwickler auseinandersetzen müssen, wenn sie ein Programm debuggen wollen. Was also verstehen wir unter Fehlerbehebung...
 

Was mir da so aufgefallen ist: (leider gibt es hier keine Zeilennummern auf die ich mich beziehen kann)

1. CTrade TPTrade;

    Das ist eine Programmbremse sondergleichen. das gehört entweder mit static definiert(eher Sonderfall) oder in den globalen Teil des Programms.

2. Eine Variablenbezeichnung tick für Ticket ist eher 'patschert' weil ein Tick was anderes ist als ein Ticket.

3. Die Definition double ATRArray1[]; und anschließendes ArraySetAsSeries(ATRArray1,true); gehört auch in den allgemeinen Programmteil

4. Die Unterscheidung von Buy und Sell würde ich mit einer switch-Anweisung machen. und POSITION_TYPE mit den vordefinierten Werten, nicht mit 0 und 1

5. if(UseTP1==true) grausliche formulierung if(UseTP1) ist besser.

6. Die Abfrage PositionsTotal()>0 erscheint mit überflüssig, da in der for-Schleife impliziert.

Hier der umgeschriebene Code, so könnte ich mir das vorstellen. Ist nicht getestet!

#include <Trade/Trade.mqh>

input bool   inp_UseTP1      = true;   // Use TP1
input int    inp_ATR_Period  =   14;   // ATR Period
input int    inp_TPDivisor1  =    1;   // TPDivisor1
input double inp_TPATRMult1  =  1.0;   // TPATRMultiplier1

CTrade Trade;
int    ATRhandle;
double ATRbuffer[];
int    toCopy=2;

int OnInit()
{
   ArraySetAsSeries(ATRbuffer,true);
   ATRhandle=iATR(_Symbol,_Period,inp_ATR_Period);
   if(ATRhandle==INVALID_HANDLE)
      return(INIT_FAILED);
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   if(CopyBuffer(ATRhandle,0,0,toCopy,ATRbuffer)!=toCopy) return;
   
   if(inp_UseTP1)
      TakeProfitFunction(inp_TPDivisor1,inp_TPATRMult1);
}

void TakeProfitFunction(int TPDivisor1, double TPATRMultiplier1)
{
   ulong ticket;
   int i,total=PositionsTotal();

   for(i=0; i<total; i++)
      {
         ticket=PositionGetTicket(i);
         PositionSelectByTicket(ticket);
         if(OrderSelect(ticket))
            switch((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE))
              {
               case POSITION_TYPE_BUY:
                     if(OrderGetDouble(ORDER_VOLUME_INITIAL)==PositionGetDouble(POSITION_VOLUME) 
                        && PositionGetDouble(POSITION_PRICE_OPEN)+ATRbuffer[1]*TPATRMultiplier1<=SymbolInfoDouble(_Symbol,SYMBOL_BID))
                       {        
                        double Vol=PositionGetDouble(POSITION_VOLUME);
                        Trade.PositionClosePartial(ticket,NormalizeDouble(Vol/TPDivisor1,2),-1);      
                       }
                 break;

               case POSITION_TYPE_SELL:
                     if(OrderGetDouble(ORDER_VOLUME_INITIAL)==PositionGetDouble(POSITION_VOLUME)
                        && PositionGetDouble(POSITION_PRICE_OPEN)-(ATRbuffer[1]*TPATRMultiplier1)>=SymbolInfoDouble(_Symbol,SYMBOL_ASK))
                       {        
                        double Vol=PositionGetDouble(POSITION_VOLUME);
                        Trade.PositionClosePartial(ticket,NormalizeDouble(Vol/TPDivisor1,2),-1);      
                       }
   
                 break;
               }
      }
}

Als Basis zum weiterarbeiten.
 

Ganz vielen Herzlichen Dank Leute!

Ihr habt mir viel weiterhgeholfen.  
Der letztendlich Fehler lag darin, dass man anscheinend güfullte Orders über HistoryOrderSelect(ticket) und nicht über OrderSelect(ticket) aufrufen muss.
Hier ist nun, der Vollständigkeit halber, der funktionierende Code. Er muss natürlich noch geschwindigkeitstechnisch optimiert werden. 

void TakeProfitFunction(bool UseTP1,int TPDivisor1,int ATRHandle1, double TPATRMultiplier1)
{
if(UseTP1)
   {
   ulong ticket;
   
   double ATRArray1[];
   CopyBuffer(ATRHandle1,0,0,3,ATRArray1);
   ArraySetAsSeries(ATRArray1,true);
   int i,total=PositionsTotal();
   
   for (i=0; i<total;i++)
      {
      ticket=PositionGetTicket(i);
      PositionSelectByTicket(ticket);
      
      if(HistoryOrderSelect(ticket))
         {
          switch((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE))
            {
             case POSITION_TYPE_BUY :
               if(NormalizeDouble(OrderGetDouble(ORDER_VOLUME_INITIAL),2)==NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2) //Normalize neccessary because sometimes MT5 sets the volume wrong
                  && (SymbolInfoDouble(_Symbol,SYMBOL_BID)>PositionGetDouble(POSITION_PRICE_OPEN)+(ATRArray1[1]*TPATRMultiplier1)))
                     {
                     double Vol=NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2);
                     double CloseVol = NormalizeDouble(Vol/TPDivisor1,2);
                     trade.PositionClosePartial(ticket,CloseVol,20);
                     }
               break;
               
               case POSITION_TYPE_SELL :
                  if(NormalizeDouble(OrderGetDouble(ORDER_VOLUME_INITIAL),2)==NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2) 
                  && (SymbolInfoDouble(_Symbol,SYMBOL_ASK)<PositionGetDouble(POSITION_PRICE_OPEN)-(ATRArray1[1]*TPATRMultiplier1))) 
                     {
                     double Vol=NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2);
                     double CloseVol = NormalizeDouble(Vol/TPDivisor1,2);
                     trade.PositionClosePartial(ticket,CloseVol,20);      
                     }      
               break;
             }
      
         }
        }
   }
}
 

Sieht doch schon viel besser aus ;)

Und das mit dem Optimieren wird schon.