If-Schleife wird ausgeführt, obwohl die Bedingung nicht erfüllt ist

 

Hallo,


ich habe folgenden Code, der eigentlich immer beim Wechsel der EMA20 und EMA50 Linie den letzten Trade schließen soll und einen neuen aufmacht.
#include<Trade\Trade.mqh>
CTrade trade;
bool steigend = false;
bool fallend = false;
double letztekerze;
ulong meinticket;
uint insgesamt;

void OnTick()
{
   //Print("test");
   //Print("---- Wie DBL_MAX sieht aus -----");
   double MAA20[],MAA50[];
   int definition20 = iMA (_Symbol,_Period,20,0,MODE_EMA,PRICE_CLOSE);
   int definition50 = iMA (_Symbol,_Period,50,0,MODE_EMA,PRICE_CLOSE);
   ArraySetAsSeries(MAA20,true);
   ArraySetAsSeries(MAA50,true);
   CopyBuffer(definition20,0,0,3,MAA20);
   CopyBuffer(definition50,0,0,3,MAA50);
   if((MAA20[0]>MAA50[0])&&(MAA20[1]<MAA50[1])) // wenn der kurs anfängt zu steigen
   {
       Comment(steigend,":steigen");
      if((steigend=false))
      {
         steigend = true;
         Comment(steigend,":steigen");
         
         //fallend = false;
         insgesamt=PositionsTotal();
         for(uint i=0;i<insgesamt;i++)
         {
             //--- erhalten wir Orderticket in Bezug auf seine Position in der Liste 
            if((meinticket=PositionGetTicket(i))>0)
            {
               //--- erhlaten wir Ordereigenschaften 
               trade.PositionClose(meinticket,5);
               Print("geschlossen");
               Comment("Ticket geschlossen");
            }
         }
      }

      if(!trade.Buy(0.01))
     {
      //--- failure message
      //Comment("Sell() method failed. Return code=",trade.ResultRetcode(),
      //      ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      //Comment("Sell() method executed successfully. Return code=",trade.ResultRetcode(),
      //      " (",trade.ResultRetcodeDescription(),")");
     }
   } 
   if((MAA20[0]<MAA50[0])&&(MAA20[1]>MAA50[1])) // wenn der kurs anfängt zu fallen
   {
      //int menge = OrdersTotal();
     //Comment("es geht los");
      Comment(steigend,":fallen");
     if((steigend=true))
      {
         steigend = false;
         
         //fallend = true;
         insgesamt=PositionsTotal();
         for(uint i=0;i<=insgesamt;i++)
         {
             //--- erhalten wir Orderticket in Bezug auf seine Position in der Liste 
            if((meinticket=PositionGetTicket(i))>0)
            {
               //--- erhlaten wir Ordereigenschaften 
               trade.PositionClose(meinticket,5);
               Print("geschlossen");
               Comment("Ticket geschlossen");
            }
         }
      }

      if(!trade.Sell(0.01))
     {
      //--- failure message
      Comment("Sell() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Comment("Sell() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }
   }   
   //if (equity >= balance)
   //   trade.Buy(0.01,NULL,ask,0,(ask+100 * _Point),NULL);
     }

Nun ist es aber so, dass der er bei jedem Tick nach dem Wechsel einen Trade auf und wieder zumacht.

Das habe ich versucht mit dem "steigend" wert zu verhindern.

Meine idee: wenn der Kurs von fallend zu steigend wechselt, wird steigend auf true gesetzt.

Wenn jetzt der kurs wieder anfängt zu fallen, ist beim ersten Tick die Bedingung steigend=true erfüllt, und alle Positionen werden geschlossen.

Dabei wird dannn der Wert steigend sofort auf false gesetzt, dadurch sollte ja

if((steigend=true))

falsch sein und die Positionen, die danach geöffnet werden, offen bleiben.


Dem ist aber nicht so, er macht bei jedem Tick die letzte Position zu und eine neue auf, als ob die zeile mit der Bedingung garnicht da wäre.


was mach ich falsch?

 

Das macht die 2te if schleife, die setzt dir den wert wieder zurück. Das problem, der ma ändert bei jedem tick seinen wert. Du kannst zb warten bis die kerze geschlossen ist, dann sinds weniger fehlsignale aber verhindern kannst das so nicht


 btw, in der for schleife reicht eine normale int,  rauchst keine uint

 

Hallo,


wie kann ich halbswegs komfortabel warten, bis die kerze zuende ist?

die andere If-schleife sollte doch garnicht aktiv sein, da der kurs ja entweder steigend oder fallend ist (bezogen auf die beiden MAs.

 

Zuerst gehört mal die indicator handle und arraysetasseries in die on int, nur die copy buffer in die on tick, sonst rufst du das ganze bei jedem tick auf


wenn du im englischen form suchst, da gibts eine Funktion für eine neue bar erkennen

Alternativ kannst auch die ontimer funktion verwenden bzw auch einen mindestabstand zwischen den ma oder mindestabstand kurs zu ma
 

Nimm Dir ein Beispiel (F1) an iMA() oder an den Beispielen, die mit dem MT5 mitkommen!

Es ist ganz bestimmt keine gute Idee mit jedem Tick die iMA() neu aufzumachen:

void OnTick() {
...
   int definition20 = iMA (_Symbol,_Period,20,0,MODE_EMA,PRICE_CLOSE);
   int definition50 = iMA (_Symbol,_Period,50,0,MODE_EMA,PRICE_CLOSE);

Das gehört in OnInit()!!

Such Dir lieben einen EA in der Codebase, der das Kreuzen zweier MA handelt - es gibt sichre Dutzende - dann vergleiche die Zeit des Suchens mit der die Du für Deine fehlerhafte erste Lösung benötigst hast!!

 

Oh jeh, schon wieder ein Opfer von diesem 'YT-Guru', dem das Handwerk gelegt gehört. Ich erkenn das am Code.

Der löscht immer alles oberhalb der OnTick(), anscheinend weiß er mit der OnInit() nix anzufangen.

Das läuft dann wie Autofahren auf der Autobahn im ersten Gang, Vollgas, mit angezogener Handbremse.

 

Hallo Follast,

versuche es doch mal, Syntaktisch eine if Abfrage nicht mit

if((steigend=true))

sondern
if((steigend==true))
abzuändern.
Denn ein Gleichheitszeichen setzt steigend gleich tru, und dann ist die if(..) Abfrage sinnlose - oder?
 
if(steigend)
   {
      // ........
   }
wäre perfekt.
 

Ich bin noch halbswegs neu im Programmieren mit MQL5, ich hab bisher nur mit einer anderen Sprache erfahrung gesammelt, und da hat ein einfaches = gut funktioniert.

Aber wenn das hier nur die zuweisung ist, und nicht der vergleich, dann erklärt das einiges.


jetzt nochmal für mein Verständnis:


im Kopf (oder bei OnInit()) initialisere ich die Arrays double MAA20[],MAA50[];

in der OnInit schreibe ich ausserdem ArraySetAsSeries(MAA20,true); und int definition20 = iMA (_Symbol,_Period,20,0,MODE_EMA,PRICE_CLOSE);

und nur CopyBuffer muss in die OnTick? also ist CopyBuffer erst der Moment, in der die Berechnung ausgeführt wird?

Ich dachte, iMA führt die Berechnung des MA durch, darum reicht es nicht, diesen nur einmal im Kopf zu laden.


noch eine andere Frage: ich lese und höre hier öfter, dass man Ressourcenschonend programmieren soll... aber ist rechenleistung heutzutage wirklich das Problem?

Also, bremst es einen durchschnitts-PC wirklich signifikant aus, wenn man bei jedem Tick das Array initialisiert?


Vielen Dank für die Hilfe.

 

Bedenke eines, es gibt fast nichts, was nicht schon für MT4/5 programmiert wurde! Es ist besonders für Newbies viel(!!) schneller sich in der CodeBase oder unter den Artikeln etwas zu suchen, was so ähnlich ist und das zu ändern, anstatt alle Fehler auf die harte Tour selber auszuprobieren!

Bei der Suche oben rechts erst auf Englisch stellen und dann suchen mit englischen Termini - bringt mehr Treffer, ist leider so.

Der Hauptunterschied bei ressourcenschonend oder nicht zeigt sich eher bei der Optimierung. Und - auch ganz lehrreich - bei einem Indikator, der weit in der Vergangenheit (MetaQuotes Demo geht zurück bis 1971) beginnt zu seine Werte zu den Charts zu berechnen und der zu jeder Bar einen Comment() auf den Chart schreibt. Man vergleiche mal die Zeit bis der Chart da ist, einmal mit und einmal ohne Comment(). Bei graphischen Objekten ist das ähnlich.

Sonst im Realbetrieb merkt man das nicht, weil der EA mit seinen Indis rechnet bis er fertig ist und dann erst neue, aktuelle Ticks kriegt oder nachfragt. Wir erinnern uns, Geschwindigkeit ist relativ. ;)

Die Ticks dazwischen werden ausgelassen - meist kein Problem.