Anfänger fragen zu HistorySelect

Aleksi-Trader  

Hallo, da ich noch am Programmieren lernen bin habe ich ein neues "Lern-Projekt" gestartet welches das Ziel hat bei erreichen eines von 2 Werten den handel zu stoppen / unterbinden.

Der erste Wert ist das Tagesziel und der 2. der maximale Tagesverlust.

dies wird auch erfolgreich umgesetzt.

Nach ablauf des Tages (Aktuelles Datum um Mitternacht) sollte die Tagesauswertung insofern keine Einträge ab dieser Zeit in der Historie sind auf 0 stehen und den Algohandel wieder freigeben.

Leider Bleibt dieser aber nach erreichen des Wertes bestehen so das der Handel nicht freigegeben wird.

Wie kann ich dieses Problem lösen?


Hinweis: Variablen wie Gewinn ,Trades usw sind global festgelegt da diese an anderer stelle noch benötigt werden.

void AuswertungTag()
  {
   string JahrundDatum =TimeToString(ServerTime,TIME_DATE);
   datetime last=StringToTime(JahrundDatum);
   datetime Tagesanfang=StringToTime(JahrundDatum+" "+"00:00:00");
   datetime Tagesende=StringToTime(JahrundDatum+" "+"23:59:59");


//--- request in the cache of the program the needed interval of the trading history
   HistorySelect(Tagesanfang,Tagesende);
//--- obtain the number of deals in the history
   int deals=HistoryDealsTotal();
   int winreturns=0;
   int lossreturns=0;
   double profit=0;
   double swap=0;
   double commission=0;
   double loss=0;
   double mathloss=0;


//--- scan through all of the deals in the history
   for(int i=0; i<deals; i++)
     {
      //--- obtain the ticket of the deals by its index in the list
      ulong deal_ticket=HistoryDealGetTicket(i);
      if(deal_ticket>0) // obtain into the cache the deal, and work with it
        {
         string symbol             =HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
         datetime time             =HistoryDealGetInteger(deal_ticket,DEAL_TIME);
         ulong order               =HistoryDealGetInteger(deal_ticket,DEAL_ORDER);
         ulong order_magic          =HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
         long pos_ID               =HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
         ENUM_DEAL_ENTRY entry_type=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
         //--- result of fixation
         double result=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
         double resultswap=HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
         double resultcommission=HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);

         //Auswertung beschränken auf das Chartsymbol
         if(_Symbol==symbol)
           {
            if(result>0)
              {
               //--- calculate the losses and profits with a fixed results
               if(entry_type==DEAL_ENTRY_OUT)
                 {
                  //--- increase the number of deals
                  winreturns++;

                  //--- input the positive results into the summarized profit
                  profit+=result;
                  swap+=resultswap;
                  commission+=resultcommission;
                 }
              }

            if(result<0)
              {
               //--- calculate the losses and profits with a fixed results
               if(entry_type==DEAL_ENTRY_OUT)
                 {
                  //--- increase the number of deals
                  lossreturns++;

                  //--- input the positive results into the summarized profit
                  loss+=result;
                  swap+=resultswap;
                  commission+=resultcommission;
                 }
              }

           }
        }
      //--- output the results of the calculations
      GewinnTotal=NormalizeDouble(loss+profit+swap+commission,2); //Netto
      Tradestotal=winreturns+lossreturns;
      mathloss=MathAbs(loss);
      if(lossreturns && winreturns>0)
        {
         ProfitFactor=(profit/winreturns)/(mathloss/lossreturns);
         ProfitFactor=NormalizeDouble(profit/mathloss,2);
         ExpectedPayoff=(winreturns / Tradestotal) * (profit / winreturns) - (lossreturns / Tradestotal) * (mathloss/ lossreturns);
         Gewinntrades=winreturns;
         Gewinn=NormalizeDouble(profit,2);
         Verlusttrades=lossreturns;
         Verlust=loss;
         Swap=NormalizeDouble(swap,2);
         Kommission=commission;
        }
      if(Tradestotal>0)
         Trefferquote=100*winreturns/Tradestotal;
     }
   if(GewinnTotal>Tagesziel)
     {
      StatusTagesauswertung=1;
     }
   else
     {
      StatusTagesauswertung=0;
     }
   if(GewinnTotal<=MaxTagesverlust-(MaxTagesverlust*2))
     {
      StatusTagesauswertung=1;
     }

}
Aleksi-Trader  
Carl Schreiber:

Ohne den gesamten Code schwierig, da nicht klar ist, was wo welchen Wert hat, aber nicht haben sollte.
Versuch es mal mit zwei Variablen für die Tagesauswertung, eine für den letzten abgeschlossenen Tag (in der Schleife) und eine für den nächsten (vor und nach der Schleife).

 Hallo Carl Schreiber im Prinzip kann nicht viel falsch sein da die Variable der Tagesauswertung global angegeben ist und dann in der OnTick Funktion abgefragt wird mittels.
int StatusTagesauswertung=0; //globale Variable
void OnTick()
  {
   ServerTime=TimeCurrent();
   AuswertungTag();
   
   if(StatusTagesauswertung==0)
     {
     StrategieHATrippleEMA();
     Tradestatus="Tagesziel in arbeit";
     }
   if(StatusTagesauswertung==1)
     {
      Tradestatus="Zu hohe Verluste";
     }
   if(StatusTagesauswertung==2)
     {
      Tradestatus="Tagesziel erreicht/Stop";
     }

  }

Das Problem äußert sich in dem die Strategie bzw die string Variable Tradestatus nach erreichen von Status 1 oder 2 nicht mehr auf Tradestatus "Tagesziel n arbeit" zurückschaltet sobald ein neuer Tag ist.

Da ich davon ausgehe das um 00:00:00 ja kein Eintrag in der Historie für den neuen Tag ist, und somit der Tagesprofit / Verlust  auf 0 Euro sein sollte.

Oder wenigstens falls es ein Eintrag gibt noch nicht den maximalen Verlust oder Tagesziel erreicht hat und somit die Variable Int StatusTagesauswertung 0 entsprechen muss.

Oder habe ich da ein Denkfehler?
Carl Schreiber  
Aleksi-Trader:
 Hallo Carl Schreiber im Prinzip kann nicht viel falsch sein da die Variable der Tagesauswertung global angegeben ist und dann in der OnTick Funktion abgefragt wird mittels.

Das Problem äußert sich in dem die Strategie bzw die string Variable Tradestatus nach erreichen von Status 1 oder 2 nicht mehr auf Tradestatus "Tagesziel n arbeit" zurückschaltet sobald ein neuer Tag ist.

Da ich davon ausgehe das um 00:00:00 ja kein Eintrag in der Historie für den neuen Tag ist, und somit der Tagesprofit / Verlust  auf 0 Euro sein sollte.

Oder wenigstens falls es ein Eintrag gibt noch nicht den maximalen Verlust oder Tagesziel erreicht hat und somit die Variable Int StatusTagesauswertung 0 entsprechen muss.

Oder habe ich da ein Denkfehler?
Prüf es doch einmal mit dem Debugger, da siehst Du wann die entscheidenden Variablen welchen Wert annehmen.
amando  

Prüfe mal deine Datumseingaben ordentlich im Debugger, ich glaub da hats einen Fehler

Den Status Tagesauswertung musst du zuerst in der OnInit abfragen, sonst macht der EA was ohne das vorher zu prüfen.

und zur Klammersetzung

if(GewinnTotal<=MaxTagesverlust-(MaxTagesverlust*2))

Punkt vor Strichrechnung kann MQL5 ;-)

wobei mir nicht ganz klar ist was die Rechnung soll.

Wenn der Max Tagesverlust als positiver Wert ist, dann brauchst ja nur *-1 rechnen, dann hast ihn auch negativ

wobei du solltest den Part sowieso überarbeiten

   if(GewinnTotal>Tagesziel)
     {
      StatusTagesauswertung=1;
     }
   else
     {
      StatusTagesauswertung=0;
     }
   if(GewinnTotal<=MaxTagesverlust-(MaxTagesverlust*2))
     {
      StatusTagesauswertung=1;
     }

// nehm an das sollte so sein  

  if(GewinnTotal>Tagesziel)
     {
      StatusTagesauswertung=1;
     }
   else if(GewinnTotal<=MaxTagesverlust*-1
     {
      StatusTagesauswertung=1;
     }
   else
     {
      StatusTagesauswertung=0;
     }

du fragst in den if Bedingungen ab ob was eintrifft

und wenn nichts davon eintrifft, dann nimmt er die else

Aleksi-Trader  

Hallo amando,

Ja du hast es korrekt gesehen die Berechnung geht auch mit *-1. Daran hatte ich ehrlich gesagt erst nicht gedacht.

Die Datumsangabe habe ich noch mal geändert nach dem ich mir den Artikel https://www.mql5.com/de/articles/599#time_from_day_start

angesehen habe. Daher habe ich die Tagesauswertung wiefolgt geändert:

void AuswertungTag()
  {
   datetime Tagesanfang=TimeCurrent();
   Tagesanfang=(Tagesanfang/86400)*86400;
   datetime Tagesende=Tagesanfang+86399;

//--- request in the cache of the program the needed interval of the trading history
   HistorySelect(Tagesanfang,Tagesende);
.....

Die Abfragebn der Bedingungen und den  dazugehörigen Status zu setzen habe ich dein Beispiel genommen.

Der Debugger hatte mir gezeigt dass das Programm zwar richtig Ausführt und der Status 0 zu 1 geändert wird.

Danach jedoch springt es in die OnTick funktion zurück und prüft nur in Dauerschleife die Abfragen. Springt aber nicht zurück in die Auswertung um dort zu prüfen ob ein neuer tag ist bzw Mitternacht erricht ist.

Daraus werd ich icht schlau, außer der Annahme das es nur daran liegen kann das der Tagesanfang oder Tagesende immer noch nicht korrekt zu sein scheint.

Was mich aber verwundert ist, wenn ich die 2 Zeiten mir ausgeben lasse zb über ein Label wird Tagesanfang/ende korrekt angezeigt was mich vermuten lässt das es ja dann doch nicht falsch ist.

Programmierungsgrundlagen für MQL5 Zeit
Programmierungsgrundlagen für MQL5 Zeit
  • www.mql5.com
Dieser Beitrag konzentriert sich auf Standard MQL5-Funktionen zur Arbeitsweise mit Zeit sowie Programmiertechniken und praktisch sinnvolle Funktionen zur Arbeitsweise mit Zeit, die für die Erzeugung von Expert Advisors und Indikatoren erforderlich sind. Besondere Aufmerksamkeit wird auf die allgemeine Theorie der Zeitmessung gelegt. Dieser Beitrag sollte vor allem für Anfänger unter den MQL5-Programmierern von großem Interesse sein.
Carl Schreiber  

Den Tagesanfang (Brokerzeit 00:00:00) lässt sich (bis auf Wochenende!) einfach erkennen (ungetestet!):

static int prevSek = TimeCurrent()%86400;
bool Moin = (TimeCurrent()%86400) < prevSek) ? true : false;
prevSek = TimeCurrent()%86400;
amando  
Aleksi-Trader:

Hallo amando,

Ja du hast es korrekt gesehen die Berechnung geht auch mit *-1. Daran hatte ich ehrlich gesagt erst nicht gedacht.

Die Datumsangabe habe ich noch mal geändert nach dem ich mir den Artikel https://www.mql5.com/de/articles/599#time_from_day_start

angesehen habe. Daher habe ich die Tagesauswertung wiefolgt geändert:

Die Abfragebn der Bedingungen und den  dazugehörigen Status zu setzen habe ich dein Beispiel genommen.

Der Debugger hatte mir gezeigt dass das Programm zwar richtig Ausführt und der Status 0 zu 1 geändert wird.

Danach jedoch springt es in die OnTick funktion zurück und prüft nur in Dauerschleife die Abfragen. Springt aber nicht zurück in die Auswertung um dort zu prüfen ob ein neuer tag ist bzw Mitternacht erricht ist.

Daraus werd ich icht schlau, außer der Annahme das es nur daran liegen kann das der Tagesanfang oder Tagesende immer noch nicht korrekt zu sein scheint.

Was mich aber verwundert ist, wenn ich die 2 Zeiten mir ausgeben lasse zb über ein Label wird Tagesanfang/ende korrekt angezeigt was mich vermuten lässt das es ja dann doch nicht falsch ist.

weis ja nicht wo er hinspringen soll, 

aber wenn Du dir 

void AuswertungTag()
  {

das als double definierst statt als void, dann kannst Du als return wert den Profit ausweisen und den dann weiter verarbeiten.

Aleksi-Trader  

Vielen Dank für die Antworten das Problem ist gelöst, die  Lösung war tatsächlich die Tagesauswertung von void auf double zu ändern. und entsprechend abzufragen.

dadurch entfällt auch das setzen und lesen der Variable "StatusTagesauswertung" da ich direkt bei dem Abfragen der Bedingungen entsprechende Befehle ausführen lassen kann um den Handel zu stoppen.

Grund der Beschwerde: