Disfunktiuonaler Fehler im Skript EA

 

Hallo Gemeinde,


ich versuche mich gerade darin, einen EA gangbar zu machen. Ich habe als Rumpf also ein einfaches Skript geschrieben, was im MetaEditor erstmal ohne bugs funktioniert.

Im Backtest zeigen sich allerdings funktionale Probleme. Folgende Bedingungen soll das Skript beachten/ausführen:

1. If it's the first second of the day, reset the flags to allow trading

2. If the first opening price for the current day is higher than the high of the previous day, no long trade (round-trade) are allowed for the day.

3. If the first opening price for the current day is lower than the low of the previous day, no short trade (round-trade) are allowed for the day.

4. Only one buy-trade is allowed per day (round-trade).

5. Only one sell-trade is allowed per day (round-trade).

6. If the price reaches the high of the previous day for the first time, a buy-trade is opened.

7. If the price reaches the low of the previous day for the first time, a sell-trade is opened.

8. Take profit for a buy-trade is set at 10000 points above the entry price.

9. Stop loss for a buy-trade is set at 10000 points below the entry price.

10. Take profit for a sell-trade is set at 10000 points below the entry price.

11. Stop loss for a sell-trade is set at 10000 points above the entry price.

Was offenbar nicht funktioniert:

1. Der Reset funktioniert nicht wie erhofft. Im Backtest bekomme ich nur 2 Roundtrades, egal, welchen Zeitraum ich für den Test wähle. Gelegenheiten gäbe es genug, es liegt am Code.

2. Ein short-Trade wird auch ausgeführt, wenn z.B. die Eröffnung unter dem Vortages-low liegt und der Kurs die Lücke schließt (kann man näher beobachten, wenn mehr als 2 volle Trades aus dem Bachtest herauskommen)

3. Offenbar ist nur 1 Roundtrade (1x Kauf; 1x Verkauf) am Tag möglich. Nach der Logik sollten aber maximal 2 Roundtrades möglich sein (1xshort, 1xlong) 

Was ich noch nicht eingebaut habe: Schließen aller Positionen vor Börsenschluss.

Der Code sieht aktuell wie folgt aus:

//+------------------------------------------------------------------+
//|                                                My Expert Advisor |
//|                                          Copyright 2023, Me Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|1. If the opening price for the current day is higher than the    |
//|high of the previous day, no long trades are allowed for the day. |
//|                                                                  |
//|2. If the opening price for the current day is lower than the low |
//|of the previous day, no short trades are allowed for the day.     |
//|                                                                  |
//|3. Only one buy-trade is allowed per day.                         |
//|                                                                  |
//|4. Only one sell-trade is allowed per day.                        |
//|                                                                  |
//|5. If the price reaches the high of the previous day for the first| 
//|time, a buy-trade is opened.                                      |
//|                                                                  |
//|6. If the price reaches the low of the previous day for the first |
//|time, a sell-trade is opened.                                     |
//|                                                                  |
//|7. Take profit for a buy-trade is set at 10000 points above the   |
//|entry price.                                                      |
//|                                                                  |
//|8. Stop loss for a buy-trade is set at 10000 points below the     | 
//|entry price.                                                      |
//|                                                                  |
//|9.Take profit for a sell-trade is set at 10000 points below the   | 
//|entry price.                                                      |
//|                                                                  |
//|10. Stop loss for a sell-trade is set at 10000 points above the   |
//|entry price.                                                      |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Me Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include <Expert\Expert.mqh>
#include <Trade\Trade.mqh>
#include <Tools\DateTime.mqh>
#include <Indicators\TimeSeries.mqh>

bool allow_buy_today = true;
bool allow_sell_today = true;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    //---
    return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    //---
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
    double Point = SymbolInfoDouble(Symbol(), SYMBOL_POINT);

    // Buy if previous day's high is reached
    double prevHigh = iHigh(NULL, PERIOD_D1, 1);
    double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
    
    // Check if it's the first hour of the day
    MqlDateTime current_time;
    TimeToStruct(TimeCurrent(), current_time);
    if(current_time.hour == 0)
    {
        // Reset the flag to allow trading
        allow_buy_today = true;
        allow_sell_today = true;
    }

    // Buy if previous day's high is reached and it's the first trade of the day
    if (ask >= prevHigh && allow_buy_today) 
    {
        // Open a buy order
        double entry = ask;
        double tp = entry + 10000 * Point;
        double sl = entry - 10000 * Point;
        CTrade trade;
        if (trade.Buy(1.00, Symbol(), entry, sl, tp) == true) 
        {
            Print("Buy order opened at ", entry);
            Print("SL: ", sl);
            Print("TP: ", tp);

            // Set the flag to prevent further trading for today
            allow_buy_today = false;
        } 
        else 
        {
            Print("Error opening buy order: ", trade.ResultRetcode());
        }
    }

    // Sell if previous day's low is reached and it's the first trade of the day
    double prevLow = iLow(NULL, PERIOD_D1, 1);
    ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
    if (ask <= prevLow && allow_sell_today) 
    {
        // Open a sell order
        double entry = Bid;
        double tp = entry - 10000 * Point;
        double sl = entry + 10000 * Point;
        CTrade trade;
        if (trade.Sell(1.00, Symbol(), entry, sl, tp) == true) 
        {
            Print("Sell order opened at ", entry);
            Print("SL: ", sl);
            Print("TP: ", tp);

            // Set the flag to prevent further trading for today
            allow_sell_today = false;
        } 
        else 
        {
            Print("Error opening sell order: ", trade.ResultRetcode());
        }
    }
}
//+-----------------------------------------------------------+

Kann mir jemand sagen, was hier nicht so läuft, wie beabsichtigt?

Lieben Dank vorab, Christian

 

Offenbar sollte das ein Daily Breakout werden, da bist Du nicht der Erste (Es gibt fast nichts, das nicht schon für MT4/5 programmiert wurde!):
https://www.mql5.com/de/search#!keyword=daily%20breakout&module=mql5_module_codebase

Wenn ein EA nicht tut, was er soll ist der nächste Schritt, der zum Debugger:

    Zur Fehlerbehebung von MQL5-Programmen (Debugging) : https://www.mql5.com/de/articles/654
    Einführung in MQL5: Schreiben eines einfachen Expert Advisor und benutzerdefinierten Indikators, Siehe Ende: Starten und Debuggen     https://www.mql5.com/de/articles/35
    Die Fehlerverarbeitung und Protokollierung in MQL5:     https://www.mql5.com/de/articles/2041
    https://www.mql5.com/de/articles/272
    Fehler finden und Protokollierung     https://www.mql5.com/de/articles/150

Hier noch Hilfen für Anfänger:

Quickstart for newbies: https://www.mql5.com/de/articles/496
und: https://www.mql5.com/de/articles/100
(Schrittweiser Leitfaden für Anfänger zum Schreiben eines Expert Advisors in MQL5)
Kochbücher: https://www.mql5.com/de/search#!keyword=kochbuch

 

Hallo Carl,


danke dafür. Habe mich leider zu früh gefreut, als ich das Skript von Deinem Link gesehen habe. Hätte nur ein paar Sachen modifizieren müssen, so mein Gedanke.

Leider schmeißt mir der MetaEditor beim Kompilieren satte 65 Errors aus (MetaEditor 4). Im Umkehrschluß heist das, alles neu zu schreiben und ich lande dann wieder da, wo ich jetzt bin.

Kannst Du nicht mal über meinen Code schauen, vielleicht fällt Dir was offensichtliches auf.


Gruß Christian

 

Welches " Skript von Deinem Link ".

Es sind seitenweise Programme ...

Und den Debugger hast Du auch noch nicht benutzt.

Verzeih, offenbar hast Du den EA von irgendwo. Ist im Prinzip ok, aber entweder fragt man nach von wo er ist, oder man sollte es selber reparieren.

Meine Links enthalten überdies "seitenweise" EAs die funktionieren!

PS.:  ChatGPT  erzeugt nur Mist, es lohnt nicht das dann auszubessern.
 

Hallo Carl,


ich bezog mich auf das Skript "daily outbreak".

In der Debugging-Funktion sehe ich nur das, was ich auch schon im Journal sehe. Oder ich bin zu blöd, das richtig zu bedienen.

Ich habe schon ein Print-Command gesetzt, um zu sehen, ob der daily-reset der Flags funktioniert. Das tut er, jedoch nur einmal am Anfang.

Das Script ist schon selbst zusammengestammelt, eine Bedingung nach der anderen und immer wieder auf Fehler testen. Für mich ziemlicher Horror, bin da wirklich kein Experte. 

Wie beschrieben habe ich dann im Backtest gesehen, dass es Ausführungsprobleme gibt. Das Wesentlichste ist, dass der daily Reset nicht funktioniert.


Beste Grüße Christian

 

Hier: https://www.mql5.com/de/articles/9926

habe ich ua. gezeigt, den Tagesbeginn zu ermitteln:

#define BoD(t) ((t)-((t)%86400))     // Begin of day 17.5. 12:54 => 17.5. 00:00:00

Also der neue Tag wäre:

   datetime tC = TimeCurrent();
   static datetime tNxtDay = 0;
   if (tC > tNxtDay ) {
       tNxtDay = BoD(tC) + 86400; // 86400=24*60*60 
       ...
   }
Umgang mit Zeit (Teil 1): Die Grundlagen
Umgang mit Zeit (Teil 1): Die Grundlagen
  • www.mql5.com
Funktionen und Codeschnipsel, die den Umgang mit der Zeit, dem Broker-Offset und der Umstellung auf Sommer- oder Winterzeit vereinfachen und verdeutlichen. Genaues Timing kann ein entscheidendes Element beim Handel sein. Ist die Börse in London oder New York zur aktuellen Stunde bereits geöffnet oder noch nicht, wann beginnt und endet die Handelszeit für den Forex-Handel? Für einen Händler, der manuell und live handelt, ist dies kein großes Problem.
 

Hallo Carl,


ich habe das so noch garnicht betrachtet. Möglicherweise würde der flag-reset funktionieren. Das tut er aber nicht, weil die Funktion Ermittlung "neuer Tag" nicht funktioniert. Ich schau erstmal, ob ich hierzu mit einer Printausgabe was herausfinden kann. Womöglich kommt man so der Ursache auf die Schliche.

 
Leuchtfeuer #:

Hallo Carl,


ich habe das so noch garnicht betrachtet. Möglicherweise würde der flag-reset funktionieren. Das tut er aber nicht, weil die Funktion Ermittlung "neuer Tag" nicht funktioniert. Ich schau erstmal, ob ich hierzu mit einer Printausgabe was herausfinden kann. Womöglich kommt man so der Ursache auf die Schliche.

Mit einem richtig eingestellten Debugger geht das schneller.

 

Hallo Carl,


zum Debugger: Wahrscheinlich bin ich wirklich zu blöd, damit zu arbeiten. Ich sehe am Chart, dass was nicht stimmt, erkenne aber nicht warum. Deswegen die Prints um zu sehen, ob der Code die gewünschten Werte verarbeitet. Somit kann ich das Problem eingrenzen.

Du hast mich jedoch auf die richtige Spur gebracht. Es war die (nicht)Feststellung des neuen Tages, weswegen die flags nicht resettet wurden. Das läuft nun also soweit und Trades werden augeführt. Heißt aber nicht, dass alles klappt, wie gewollt.

Ich habe mich hier entgültig festgefahren, was die beiden nachfolgenden Bedingungen angeht, mal scheint das zu funktionieren, mal nicht:

1. Nur long-roundtrades eingehen, wenn die Eröffnung unterhalb des Vortages-Hoch liegt.

2. Nur short-roundtrades eingehen, wenn die Eröffnung oberhalb des Vortages-Tief liegt.

Als ich daran gescheitert bin, habe ich mich daran gemacht, over-night-trades zu verhindern. Offene Positionen sollten kurz vor Handelsschluss glattgestellt werden. Auch das war ein totales Desaster. Bin da auf keinen grünen Zweig gekommen, trotz verschiedener Ansätze.

In Summe habe ich hier was Halbgares und komme beim besten Willen nicht weiter. Eigentlich sollte das ne poplige Sache sein, nichts kompliziertes. Vielleicht wirfst Du mal ein Auge, vielleicht ist die Lösung ja ein Kinderspiel, nur ich weiß nicht wie.

//+------------------------------------------------------------------+
//|                                                My Expert Advisor |
//|                                          Copyright 2023, Me Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Me Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include <Expert\Expert.mqh>
#include <Trade\Trade.mqh>
#include <Tools\DateTime.mqh>
#include <Indicators\TimeSeries.mqh>

bool allow_buy_today = true;
bool allow_sell_today = true;
MqlDateTime current_time;
MqlDateTime prev_time;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Expert initialized successfully.");

    // Initialize current_time and prev_time
    TimeToStruct(TimeCurrent(), current_time);
    TimeToStruct(TimeCurrent(), prev_time);

    // Start the timer to update current_time every second
    EventSetTimer(1);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("Expert deinitialized.");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
    double Point = SymbolInfoDouble(Symbol(), SYMBOL_POINT);

    // Buy if previous day's high is reached
    double prevHigh = iHigh(NULL, PERIOD_D1, 1);
    double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

    // Check if it's a new day
    TimeToStruct(TimeCurrent(), current_time);
    if(current_time.day != prev_time.day) {
        // Print the current time
        Print("Current time: ", current_time.hour, ":", current_time.min);

        // Reset the flag to allow trading
        ResetTradingFlags();

        // Print a message to indicate that the flags have been reset
        Print("Trading flags reset.");

        // Update prev_time
        TimeToStruct(TimeCurrent(), prev_time);
    }

    // Buy if previous day's high is reached and it's the first trade of the day
    if (ask >= prevHigh && allow_buy_today) 
    {
        // Open a buy order
        double entry = ask;
        double tp = entry + 10000 * Point;
        double sl = entry - 10000 * Point;
        CTrade trade;
        if (trade.Buy(1.00, Symbol(), entry, sl, tp) == true) 
        {
            Print("Buy order opened at ", entry);
            Print("SL: ", sl);
            Print("TP: ", tp);

            // Set the flag to prevent further trading for today
            allow_buy_today = false;
        } 
        else 
        {
            Print("Error opening buy order: ", trade.ResultRetcode());
        }
    }

    // Sell if previous day's low is reached and it's the first trade of the day
    double prevLow = iLow(NULL, PERIOD_D1, 1);
    ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
    if (ask <= prevLow && allow_sell_today) 
    {
        // Open a sell order
        double entry = Bid;
        double tp = entry - 10000 * Point;
        double sl = entry + 10000 * Point;
        CTrade trade;
        if (trade.Sell(1.00, Symbol(), entry, sl, tp) == true) 
        {
            Print("Sell order opened at ", entry);
            Print("SL: ", sl);
            Print("TP: ", tp);

            // Set the flag to prevent further trading for today
            allow_sell_today = false;
        } 
        else 
        {
            Print("Error opening sell order: ", trade.ResultRetcode());
        }
    }
}

bool ResetTradingFlags()
{
    allow_buy_today = true;
    allow_sell_today = true;
    Print("Trading flags reset successfully.");
    return true;
}
//+-----------------------------------------------------------+
 
  1. iLow und iHigh liefern immer den tiefsten bzw. höchsten Bid-Preis, wenn eingestellt wurde, dass der Chart Bid-Preise zeigt.
  2. Kontrollieren mit iTime, auf welchen Tag sich die Preise beziehen - siehe die Zeitdarstellung in CopyRates().
  3. Ich würde CopyRates() verwenden (kann leichter kontrolliert werden):
       static MqlRates D1[];
    
       if (isNewDay) { 
          if ( CopyRates(_Symbol,PERIOD_D1,TimeCurrent(),3,D1) <3) return;
       }
    
    3 Werte: D1[2] = heute, D1[1] = gestern und  D1[0] = vorgestern, 0=ältester Wert, index Max = letzter Wert.

  4.  Static bedeutet, dass der Variablenwert nach dem Wiederauffruf der Funktion erhalten geblieben ist (wie bei einer globalen Variablen): Trick im Editor Kursor 'draufstellen und F1 drücken.
  5. Wieso funktioniert der Debugger nicht, ich arbeite sehr viel mit ihm, um zu kontrollieren, ob genau das passiert, was ich will! DebugBreak() einstreuen oder am linken Rand auf die Zeilennummer klicken.
  6. Zeig einmal Screenshots, was passiert und nicht passieren soll oder umgekehrt.
Dokumentation zu MQL5: Zugang zu Zeitreihen und Indikatoren / iTime
Dokumentation zu MQL5: Zugang zu Zeitreihen und Indikatoren / iTime
  • www.mql5.com
iTime - Zugang zu Zeitreihen und Indikatoren - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 

Hallo Carl,

anbei der Screenshot.

Schon bei der ersten Kerze hätte der short-trade nicht ausgelöst werden dürfen, weil das Vortages-low über der Eröffnung lag. Der Long-Trade passt komplett.

Die zweite Kerze passt.

Die dritte Kerze hätte nicht gehandelt werden dürfen, da das open über dem high vom Vortag liegt.

Vierte Kerze: Short-Position startet hier etwas zu spät bei 21009 (low Vortag 21023), kann aber an einer schnellen Kursbewegung liegen. Wird dann vorschriftsmäßig ausgestoppt. Die spätere long-Position passt vom Kurs her, wird aber ein overnight-trade (der nicht gehandelt werden soll, der code dazu fehlt mangels Umsetzungserfolg beim coden).

Wie man an weiteren Kerzen erkennt, wird manchmal auch gehandelt, obwohl der Vortageskurs nicht mal berührt wird. Das ist alles ziemlich verwirrend, da es manchmal passt, manchmal aber auch vollkommen daneben ist.

Was offenbar immer funktioniert ist die TP/SL-Einstellung, sowie die Erkennung des neuen Handelstages mit max. 1x Long-Trade/1xShort-Trade.

Wirst Du daraus schlau? Könnte zur Zuarbeit vielleicht noch Journalauszüge mit feinerem Chart für einen bestimmten Ausschnitt machen.

Gruß Christian

Dateien:
chart.PNG  48 kb
Grund der Beschwerde: