English 日本語
preview
Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten

Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten

MetaTrader 5Handelssysteme |
33 0
Omega J Msigwa
Omega J Msigwa

Inhalt


Einführung

Die Erkennung von Mustern auf den Finanzmärkten ist eine anspruchsvolle Aufgabe im Bereich des maschinellen Lernens und der KI. So mühelos es uns Menschen auch erscheinen mag, für eine Maschine erfordert es einige Arbeit, diese Muster zu erkennen und zu interpretieren, denn im Gegensatz zu den zweidimensionalen (tabellarischen) Daten, die wir im Handel häufig verwenden, erstreckt sich die Mustererkennung auf zweidimensionale Bilddaten, die in der Regel in Formaten wie .png, .jpg usw. gespeichert sind.

Es gibt eine große Anzahl von Händlern mit Strategien, die sich auf Preisaktionen und bestimmte Chartmuster auf den Märkten stützen, wie z.B.:

  • Aufsteigende und absteigende Stufen
  • Aufsteigendes Dreieck
  • Absteigendes Dreieck
  • Symmetrisches Dreieck
  • Fahne 
  • Keil
  • Doppelspitze
  • Doppelter Boden
  • Kopf und Schultern
  • Runde Spitze oder Boden
  • Tasse und Henkel
  • und viele mehr.

Wenn es um die Programmierung von Mustern wie Kerzen-Mustern und Indikatorreaktionen geht, die auch ohne ausgefeilte Codezeilen identifiziert werden können, sind die oben genannten Chartmuster recht komplex.

Es bedarf eines ausgeklügelten, gut geschriebenen und optimierten Codes, um selbst ein einfaches Muster wie das W unten zu erkennen. Warum also nicht KI einsetzen, um uns bei dieser langweiligen Aufgabe zu helfen?

Um dieses Problem mit Hilfe von Künstlicher Intelligenz (KI) zu lösen, werden wir in diesem Artikel ein sehr faszinierendes Modell namens YOLOv8 diskutieren, auf das ich auf huggingface.co gestoßen bin.

Dieses Modell hilft dabei, Chartmuster in Bildern und Charten mit einer angemessenen Genauigkeit zu erkennen.

Ein grundlegendes Verständnis von maschinellem Lernen und der Programmiersprache Python ist erforderlich, um den Inhalt dieses Artikels vollständig zu verstehen.


Was ist YOLOv8?

In der Dokumentation heißt es dazu.

YOLOv8s ist ein Objekterkennungsmodell, das auf dem YOLO (You Only Look Once) Framework basiert. Dieses Modell wurde entwickelt, um verschiedene Chartmuster in Echtzeit aus den am Bildschirm erfassten Börsendaten zu erkennen.

Das Modell hilft Händlern und Anlegern, indem es die Analyse von Chartmustern automatisiert und zeitnahe Erkenntnisse für fundierte Entscheidungen liefert.

Das Modell wurde anhand einer Vielzahl von Daten optimiert und erreicht eine hohe Genauigkeit bei der Erkennung und Klassifizierung von Aktienmarktmustern in Live-Handelsszenarien.

Zum gegenwärtigen Zeitpunkt kann dieses Modell eine Reihe von Mustern genau vorhersagen, unter anderem.

Kopf und Schultern oben

Kopf und Schultern oben

Eine kurze Beschreibung des Musters

Dieses Muster deutet darauf hin, dass eine Umkehrung des Marktes möglich ist.

Händler gehen davon aus, dass drei Gruppen von Höchst- und Tiefstständen, mit einem größeren Höchststand in der Mitte, darauf hinweisen, dass der Kurs einer Aktie zu fallen beginnen wird.

Die Nackenlinie stellt den Punkt dar, an dem Händler, zu verkaufen beginnen. Mehr dazu hier.

Kopf und Schultern Unten

Dies ist das Gegenteil des Kopf und Schultern Oben.

M Kopfmuster:

M Kopfmuster

Eine kurze Beschreibung des Musters

Dieses auch als Doppeltop bekannte Muster besteht aus zwei aufeinanderfolgenden runden Spitzen.

Diese runden Spitzen können oft ein Indikator für eine Abwärtsumkehr sein, da sie oft nach einer ausgedehnten Aufwärtsbewegung auftreten.

Bei einer Doppelspitze liegt die zweite runde Spitze in der Regel leicht unter der Spitze der ersten runden Spitze, was auf Widerstand und Erschöpfung hindeutet.

Doppelspitzen sind seltene Erscheinungen, da ihre Bildung oft darauf hindeutet, dass die Anleger versuchen, letzte Gewinne aus einem Aufwärtstrend zu erzielen. Mehr dazu hier.

W-Muster des Bodens:

W-BodentitlealtW-Bodenalt

Die Funktionsweise ist dieselbe wie beim M-Muster der Spitzen, nur umgekehrt, Mehr dazu hier.

Aktienlinie

Ich konnte weder in der Dokumentation noch online Hinweise darauf finden, also lassen wir das erst einmal weg.

Dreiecksmuster:

Diese Muster können entweder ein Fortsetzungsmuster sein, wenn sie sich bestätigen, oder ein starkes Umkehrmuster, wenn sie scheitern.

Händler verwenden Dreiecke, um festzustellen, wann die Verengung der Handelsspanne einer Aktie oder eines Wertpapiers nach einem Abwärts- oder Aufwärtstrend eintritt. Mehr dazu hier.


Abrufen von Chartmustern aus MetaTrader 5

Da YOLOv8 mit Bildern (Bilddaten) arbeitet, müssen wir eine Vielzahl von qualitativ hochwertigen Bildern extrahieren, die wir zum Testen und Spielen mit dem Modell verwenden können.

Glücklicherweise bieten der MetaTrader 5 und die Programmiersprache MQL5 eine Funktion, mit der man von jedem beliebigen Chart und Symbol einen Screenshot machen kann. Lassen Sie uns ein paar Bilder mit Hilfe eines Skripts sammeln.

Datei: ChartScreenshots.mq5

#property script_show_inputs 

input uint BarsToCapture = 1000; //Total Bars
input uint BarsShift = 50; //Bars Shift
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Save current chart position

    long firstVisibleBar = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
    long chartShift = ChartGetInteger(0, CHART_SHIFT);
    double priceMax = ChartGetDouble(0, CHART_PRICE_MAX);
    double priceMin = ChartGetDouble(0, CHART_PRICE_MIN);
    
//--- Set chart properties for clean screenshots

    ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true);
    ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true);
    ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images
    ChartSetInteger(0, CHART_SHOW_VOLUMES, false);
    ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false);
    ChartSetInteger(0, CHART_AUTOSCROLL, false);  // prevent scrolling  
    
    int steps = (int)MathCeil((double)BarsToCapture / BarsShift);
    
    for(int i = 0; i < steps; i++)
    {
        // Shift chart view
        int shift = i * (int)BarsShift;
        ChartNavigate(0, CHART_END, -shift);
        
        // Wait a moment for the chart to update
        Sleep(500);
        
        // Take screenshot
        string filename = StringFormat("Screenshots\\%s.%s.%d.png", Symbol(), EnumToString(Period()), i+1);
        
        FileDelete(filename); //we delete a previous screenshot with the same name
        if(!ChartScreenShot(0, filename, 640, 480, ALIGN_CENTER))
         {
            printf("Failed to take screenshot #:%d Error = %d", i+1, GetLastError());
            continue;
         }
        else
         {
            printf("Screenshot saved: %s", filename);
         }
    }

//--- Restore original chart position

    ChartNavigate(0, CHART_END, -(int)firstVisibleBar);
    ChartSetDouble(0, CHART_PRICE_MAX, priceMax);
    ChartSetDouble(0, CHART_PRICE_MIN, priceMin);
    ChartSetInteger(0, CHART_SHIFT, chartShift);
}

Diese Funktion erstellt mehrere Screenshots des aktuellen Charts für 1000 Balken (Standard), wobei 50 Balken (Standard) rückwärts vom vorherigen Screenshot verschoben werden.

Bevor wir eine Funktion aufrufen, um einen Screenshot aufzunehmen, müssen wir sicherstellen, dass das Chart so sauber wie möglich ist. Selbst einige Geräusche, wie z. B. die Gitternetzlinien und Tickvolumina, könnten die Modelle davon ablenken, wichtige Muster im Chart zu erkennen.

    ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true);
    ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); // Showing the timescale on a chart
    ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images
    ChartSetInteger(0, CHART_SHOW_VOLUMES, false); //Prevent displaying the tick volumes
    ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false); //Prevent drawing arrows that displays trading history
    ChartSetInteger(0, CHART_AUTOSCROLL, false);  // prevent scrolling  

Alle Bilder werden unter dem Pfad MQL5\Files\Screenshots gespeichert.


Verwendung von YOLOv8 für die Mustererkennung

    Laut der Dokumentation des Unternehmens ist der folgende Mindestcode erforderlich, um dieses Modell auszuführen und das vorhergesagte Ergebnis zu erhalten.

    Installation

    $pip install ultralytics

    Die ersten Schritte.

    from ultralytics import YOLOvv8
    
    model = YOLOvv8.from_pretrained("foduucom/stockmarket-pattern-detection-yolov8")
    source = 'http://images.cocodataset.org/val2017/000000039769.jpg'
    model.predict(source=source, save=True)

    Aber dieser Code wird in Ihrer Umgebung zu Fehlern führen, da es derzeit kein YOLOvv8 von ultralytics gibt (die Dokumentation ist irgendwie veraltet), unten ist der richtige Weg.

    Zunächst müssen wir das YOLO-Objekt importieren und es mit einem trainierten Modell für die Aufgabe bestücken.

    from ultralytics import YOLO
    import os
    
    model = YOLO(os.path.join('Models','model.pt'))

    Die Datei model.pt, kann von hier abgerufen werden. Nachdem Sie die Datei heruntergeladen haben, speichern Sie sie in einem Unterordner namens Models in Ihrem aktuellen Arbeitsverzeichnis.

    Danach müssen wir die Methode Predict von einem Modellobjekt aufrufen und einen Bildnamen parsen, und schon haben wir das vorhergesagte Ergebnis :).

    model.predict("image_name.png", save=True)

    Wenn save=True, speichert das Modell das resultierende Bild, das hervorgehobene Muster enthält.

    Dies ist jedoch zu einfach und unzureichend. Lassen Sie uns eine Klasse für diesen Prädiktor erstellen, um sicherzustellen, dass wir einen zuverlässigen und robusten Code für die Analyse und Vorhersage mehrerer Bilder aus einem Ordner haben, der unsere Screenshots enthält.

    Außerdem brauchen wir die beste Methode, um die Vorhersagen zu verarbeiten und das Ergebnis zu visualisieren.

    Erkennung von Mustern in einem einzelnen Bild

    Unser Klassenkonstruktor nimmt das YOLO-Modellobjekt und den Bilderordner, der alle Screenshots von MetaTrader 5 enthält.

    class YOLOv8deploy:
        
        def __init__(self, model: YOLO, images_folder: str):
            
            """A simple class for deploying YOLOv8 model for detecting trading patterns in chart images
    
            Args:
                model (YOLO): YOLO model object
                images_folder (str): A path where images will be imported from
            """
            
            self.model = model
            self.images_folder = images_folder

    Wir brauchen auch eine Funktion in der Klasse, um alle Bilder im angegebenen Ordner zu erhalten.

    Diese Funktion ist praktisch, wenn mehrere Vorhersagen gemacht werden, da sie uns die Anzahl der in einem Ordner verfügbaren Bilder mitteilt, indem sie ein Tupel zurückgibt, das die Gesamtzahl der Bilder und ihre Namen in einer Python-Liste enthält.

    def _get_images(self, folder: str, img_extensions: list=['*.png', '*.jpg', '*.jpeg']) -> tuple: 
            
       """ A function to help us detect the number of images present in a folder
    
       Args:
           folder (str): A path where images are located
           img_extensions (list, optional): Image filenames extensions. Defaults to ['*.png', '*.jpg', '*.jpeg'].
    
       Returns:
           tuple: Returns the number of images present in a folder and their names
       """
            
       image_files = []
       for ext in img_extensions:
           image_files.extend(glob.glob(os.path.join(folder, ext)))
    
       return (len(image_files), image_files) # Get the number of images and their names

    Erweitern wir die Vorhersagefunktion so, dass sie ein einzelnes Bild vorhersagen kann, sollte diese Funktion uns auch die erkannten Muster und den Vertrauensgrad für diese Muster mitteilen.

    def predict_image(self, img_name: str, hist: bool=True):
            
       """This function predicts a single image
    
       Args:
           img_name (str): name of the image
           hist (bool, optional): When set to false it means the function isn't predicting multiple instances and the outcome will be displayed.
                
           Defaults to True.
       """
            
       if os.path.exists(img_name) == False: # Check if an image exists
           print(f"Failed to detect patterns, {img_name} not found")
           return
            
       results = self.model.predict(source=img_name, save=True) # Predict an image 
    
       # Loop through the results
       for result in results:
           boxes = result.boxes  # Contains bounding boxes and confidence
           names = result.names  # Class index to name mapping
    
           if boxes is not None and len(boxes) > 0:
               for box in boxes:
                   cls_id = int(box.cls[0])  # class id
                   conf = box.conf[0].item()  # confidence score
                   label = names[cls_id]
                        
                   print(f"Detected: {label} (confidence: {conf:.2f})")
                        
                   # Open the saved image if this is a single (non-historical) run
                        
               if not hist:
                   base_name = os.path.splitext(os.path.basename(img_name))[0] + ".jpg"
                   saved_path = os.path.join(result.save_dir, base_name)
                        
                   print("saved path: ",saved_path)
                        
                   if os.path.exists(saved_path):
                       print(f"Opening detected image: {saved_path}")
                       img = cv2.imread(saved_path)
                       cv2.imshow("Detected Patterns", img)
                       cv2.waitKey(0)
                       cv2.destroyAllWindows()
           else:
               print("No detections.")
    

    Die von YOLOv8 angebotene Vorhersagefunktion liefert ein Wörterbuch mit Informationen über die Box, die dann in einem Bild angezeigt wird. Diese Box ist um ein erkanntes Muster herumgewickelt, gefolgt von der Vertrauensstufe für ein bestimmtes erkanntes Chartmuster.

    Nachdem wir diese Informationen extrahiert haben, drucken wir sie in einer Python-Konsole oder einer Eingabeaufforderung (CMD) aus.

    Am Ende der Funktion, wenn hist auf False gesetzt ist, verwendet diese Funktion das Modul cv2, um das vorhergesagte Ergebnis in einem Dialogfenster anzuzeigen.

    Dies ist praktisch, wenn Sie das resultierende Bild mit den vom Modell erzeugten Mustern visualisieren möchten.

    Beispiel.

    images_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files\Screenshots" # Change this for to the right path on your pc :)
    symbol = "EURUSD"
    timeframe = "PERIOD_H1"
    imgs = 100
    
    pattern_detector = YOLOv8deploy(model=model, images_folder=images_path)
    
    pattern_detector.predict_image(img_name=os.path.join(images_path, f"{symbol}.{timeframe}.{11}.png"), 
                                   hist=False)
    

    Wir haben ein Bild von EURUSD.PERIOD_H1 mit einer markierten Nummer 11 im Ordner Screenshots, das wir visualisieren wollen. 

    Originalbild.

    Nachfolgend sehen Sie das vom Modell nach der Vorhersagefunktion erzeugte Bild in einem separaten Dialogfenster.

    Erkennung von Mustern über mehrere Bilder hinweg

    Nachdem wir die Bilder aus dem Ordner „Screenshots“ erhalten haben, gehen wir sie in einer Schleife durch und übergeben jedes Bild an die Funktion predict_image, die wir gerade oben erstellt haben.

    def predict_images(self):
       
       _, image_names = self._get_images(self.images_folder) # Get all images from a folder
    
       for image_name in image_names:
           self.predict_image(img_name=image_name)

    Rufen wir nun diese Funktion auf, um mehrere Bilder vorherzusagen, die wir gesammelt haben. Dies ist vergleichbar mit einem Backtest, bei dem wir anhand mehrerer historisch gesammelter Bilder prüfen können, ob das Modell geeignet ist oder nicht.

    pattern_detector.predict_images()
    Ausgabe:

    Alle vorhergesagten Ergebnisse und Bilder, die von diesem Modell erzeugt wurden, finden Sie im aktuellen Arbeitsverzeichnis unter runs\predict*

    Wie Sie oben sehen können, hat das Modell einige gute Vorhersagen gemacht, aber wie jedes maschinelle Lernmodell, das jemals entwickelt wurde, hat es einige Schwächen und Einschränkungen. Nachfolgend sind einige von ihnen aufgeführt.


    Verzerrungen, Risiken und Beschränkungen von YOLOv8

    01: Die Leistung kann durch unterschiedliche Chartstile, Bildschirmauflösungen und Marktbedingungen beeinträchtigt werden.

    Es ist von entscheidender Bedeutung, dass die Farben Ihrer Kerzen auf dem Chart weniger verwirrend sind; die Farben des Hintergrunds und der Kerzen sollten sich deutlich voneinander unterscheiden, um bessere Ergebnisse zu erzielen.

    Die Skalierung des Charts spielt ebenfalls eine Rolle. Eine größere Skalierung des Charts in MetaTrader 5 könnte dazu führen, dass unvollständige Muster zu sehen sind, während eine kleinere Skalierung verrauscht sein könnte.

    Sie müssen das richtige Gleichgewicht zwischen dem Maßstab der Karte und der Bildgröße finden.

    02: Schnelle Marktschwankungen und Rauschen in den Handelsdaten können die Genauigkeit beeinträchtigen.

    Fluktuationen können zu falschen Durchbrüchen und seltsamen Mustern führen. Dieses Modell ist bei solchen Charts und Märkten zu Fehlern gezwungen.

    03: Marktspezifische Muster, die in den Trainingsdaten nicht gut repräsentiert sind, können eine Herausforderung für die Erkennung darstellen.

    Sie müssen Märkte und Zeitrahmen mit unsicheren Mustern vermeiden. Der Einsatz des Modells auf dem/den richtigen Markt/Märkten ist der beste Weg, um sicherzustellen, dass Sie das Beste aus dem Modell herausholen.


    Erkennung von Chartmustern in MetaTrader 5 mit YOLOv8

    Auch hier arbeitet das Modell YOLOv8 mit Bildern und erzeugt das vorhergesagte Ergebnis im Bildformat, das in der ursprünglichen MQL5-Sprache nicht gelesen und interpretiert werden kann. Die Sprache ist jedoch in der Lage, mit Bildern im Bitmap-Format .BMP zu arbeiten, was einen guten Ausgangspunkt darstellt.

    Da es möglich ist, ein bildbasiertes Objekt zu erstellen oder ein Bild auf der Rückseite des MetaTrader 5-Charts mit MQL5 einzubetten, wie es bereits mehrfach geschehen ist. Öffnen wir diese von YOLOv8 erzeugten Bilder, die Chartmuster enthalten, die im MetaTrader 5 auf der Rückseite des Charts erkannt wurden, so wie wir das in diesem Artikel getan haben.

    Nachdem wir ein Bild auf der Rückseite des Charts (Hintergrund) hinzugefügt haben, können wir die aktuellen Balken im Vordergrund ausblenden und den Chart als Bild mit Kerzen aktualisieren.

    Um dies zu erreichen, müssen wir einige Dinge in unserer Python-Klasse ändern, beginnend mit der Verbesserung der Vorhersagefunktion, sodass sie alle Bilder, die Vorhersagen enthalten, in einem bestimmten/gleichen Verzeichnis (Ordner) speichern kann.

    Dateiname: deploy.py

    def predict_image(self, img_name: str, save_path: str):
            
        """This function predicts a single image
    
        Args:
           img_name (str): name of the image
           hist (bool, optional): When set to false it means the function isn't predicting multiple instances and the outcome will be displayed.
                
           Defaults to True.
       """
            
       if os.path.exists(img_name) == False: # Check if an image exists
           print(f"Failed to detect patterns, {img_name} not found")
           return
            
       results = self.model.predict(source=img_name, 
                                    save=True,
                                    project=save_path,
                                    name="YOLOv8 Images",
                                    exist_ok=True
                                    ) # Predict an image 
                        
       # Loop through the results
       for result in results:
           boxes = result.boxes  # Contains bounding boxes and confidence
           names = result.names  # Class index to name mapping
    
           # Convert a jpg image to bmp suitable for MQL5 diplay purposes
                
           base_name = os.path.splitext(os.path.basename(img_name))[0] + ".jpg"
           saved_path = os.path.join(result.save_dir, base_name)        
    
           convert_jpg_to_bmp(saved_path, os.path.join(result.save_dir, os.path.splitext(os.path.basename(img_name))[0] + '.bmp'))
    
           if boxes is not None and len(boxes) > 0:
               for box in boxes:
                   cls_id = int(box.cls[0])  # class id
                   conf = box.conf[0].item()  # confidence score
                   label = names[cls_id]
                        
                   print(f"Detected: {label} (confidence: {conf:.2f})")
           else:
               print("No detections.")
    
    

    Angesichts dieser Möglichkeit, die Bilder in einem bestimmten Ordner mit der Funktion predict zu speichern, können wir alle Dateien in einem Unterordner namens YOLOv8 Images speichern, der unter dem übergeordneten Pfad der MQL5-Dateien erstellt wurde.

    YOLOv8 erzeugt ein Bild im JPEG- oder JPG-Format. Wenn wir dieses Bild in MetaTrader 5 verwenden wollen, müssen wir es in ein Bitmap-Format (BMP) umwandeln. Nachfolgend finden Sie die Funktion für die Aufgabe.

    def convert_jpg_to_bmp(jpg_path, bmp_path):
        """
        Convert a JPG image to 24-bit RGB BMP format
        
        Args:
            jpg_path (str): Path to input JPG file
            bmp_path (str): Path to save output BMP file
        """
        try:
            # Open the JPG image
            with Image.open(jpg_path) as img:
                # Convert to RGB if not already (handles CMYK, grayscale, etc.)
                if img.mode != 'RGB':
                    img = img.convert('RGB')
                
                # Save as 24-bit BMP
                img.save(bmp_path, 'BMP')
                
            print(f"Successfully converted {jpg_path} to {bmp_path}")
            return True
        
        except Exception as e:
            print(f"Conversion failed: {str(e)}")
            return False

    Im Folgenden wird erläutert, wie wir die auf einem einzelnen Bild vorhandenen Muster erkennen und vorhersagen können.

    files_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files"
    images_path = os.path.join(files_path, "Screenshots") # Change this for to the right path on your pc :)
    
    # ....
    # ....
    
    pattern_detector = YOLOv8deploy(model=model, images_folder=images_path)
    pattern_detector.predict_image(img_name=image_filename, save_path=files_path)

    Wir können diesen Prozess automatisieren. Nachdem einige Minuten vergangen sind, soll unser Skript ein Bild aus MQL5\Files\Screenshots lesen, Vorhersagen treffen und ein Bild in MQL5\Files\YOLOv8 Images speichern.

    files_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files"
    images_path = os.path.join(files_path, "Screenshots") # Change this for to the right path on your pc :)
    symbol = "EURUSD"
    timeframe = "PERIOD_H1"
    
    def scheduledYOLOv8Run():
            
        now = datetime.now() # Get the current local date and time
    
        # Extract current day and hour
    
        date = now.day
        current_day = now.weekday()  # e.g., 'Wednesday'
        current_hour = now.strftime("%H")  # e.g., '14' for 2 PM in 24-hour format
    
        image_filename = os.path.join(images_path, f"{symbol}.{timeframe}.{date}.{current_day+1}.{current_hour}.png")
    
        pattern_detector = YOLOv8deploy(model=model, images_folder=images_path)
    
        pattern_detector.predict_image(img_name=image_filename, 
                                        save_path=files_path)
    
        print(f"Processed image at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        
    
    # Schedule the pattern detection after every minute(s)
    
    schedule.every(1).minutes.do(scheduledYOLOv8Run)
    
    print("Scheduler started. Press Ctrl+C to stop.")
    
    # Run forever
    while True:
        schedule.run_pending()
        time.sleep(1)

    Bereiten wir nun die richtige Umgebung für den Einsatz des erzeugten Bildes im Bitmap-Format (.BMP) in einem MetaTrader 5-Chart vor.

    Wir beginnen mit der Initialisierung der Timer-Funktion, die uns hilft, den Prozess der Aufnahme eines Screenshots und der Aktualisierung des Charts mit dem Bild, das die vorhergesagten (erkannten) Muster enthält, zu automatisieren.

    Dateiname: YOLOv8 EA.mq5

    input uint chart_scale = 3;
    input uint timer_seconds = 60;
    
    int chart_width, chart_height;
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //---
       
       if (!EventSetTimer(timer_seconds))
         {
           printf("%s failed to set the timer, Error = %d",__FUNCTION__,GetLastError());
           return INIT_FAILED;
         }
    
        showBars(true);   
             
    //---
    
       return(INIT_SUCCEEDED);
      }

    Die Funktion showBars ist für die Reinigung und Vorbereitung der richtigen Umgebung auf dem Chart für die Aufnahme eines Screenshots verantwortlich.

    void showBars(bool show=true)
     { 
    //--- Cleaning the chart
    
        ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true);
        ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true);
        ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images
        ChartSetInteger(0, CHART_SHOW_VOLUMES, false);
        ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false);
        ChartSetInteger(0, CHART_AUTOSCROLL, true);  // prevent scrolling  
        ChartSetInteger(0, CHART_SHIFT, true);
        
        if (ChartGetInteger(0, CHART_SCALE) != chart_scale)
             ChartSetInteger(0, CHART_SCALE, chart_scale);
       
       if (show)
         {
             ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite);
             ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack);
             ChartSetInteger(0, CHART_COLOR_CHART_UP, clrTomato);
             ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrTomato);
             ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrLightSeaGreen);
             ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrLightSeaGreen);
             ChartSetInteger(0, CHART_SHOW_ASK_LINE, true);
             ChartSetInteger(0, CHART_SHOW_BID_LINE, true);
             ChartSetInteger(0, CHART_COLOR_ASK, clrTurquoise);
         }
       else
         {
             ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite);
             ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack);
             
             ChartSetInteger(0, CHART_COLOR_CHART_UP, clrWhite);
             ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrWhite);
             ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrWhite);
             ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrWhite);
             ChartSetInteger(0, CHART_SHOW_ASK_LINE, true);
             ChartSetInteger(0, CHART_SHOW_BID_LINE, true);
             ChartSetInteger(0, CHART_COLOR_ASK, clrTurquoise);
         }
         
       ChartRedraw();
     }

    Wenn diese Funktion mit einem falschen Wert aufgerufen wird, werden alle Eigenschaften des Charts (einschließlich der Kerzen-Farben) auf dieselbe Farbe wie der Hintergrund des Charts gesetzt, um alles unsichtbar zu machen.

    Dies ist notwendig, da wir das aktuelle Chart mit einem Bild im Hintergrund auffüllen werden. Wir wollen also nicht, dass die Balken im Vordergrund auf unserem Bild erscheinen, da sie eine verwirrende Umgebung schaffen können.

    Nachfolgend finden Sie die Funktion, mit der Sie ein Bitmap-Bild (.BMP) in ein Objekt umwandeln und es dann dem Hintergrund des aktuellen Charts zuweisen können.

    //+------------------------------------------------------------------+
    //|       Function to set a BMP image as chart background            |
    //+------------------------------------------------------------------+
    bool chartBackGroundSet(string filename, int width, int height)
    {
        string obj_name = "background-img";
            
       if(!ObjectCreate(0,obj_name,OBJ_BITMAP_LABEL,0,0,0)) 
         { 
          printf("%s failed to create a bitmap in the chart window! Error = %s",__FUNCTION__,ErrorDescription(GetLastError())); 
          return(false); 
         } 
         
    //--- set the path to the image file 
       if(!ObjectSetString(0,obj_name,OBJPROP_BMPFILE, filename)) 
         { 
          printf("%s failed to load the image! Error = %s",__FUNCTION__,ErrorDescription(GetLastError())); 
          return(false); 
         } 
    
    //--- Position the image to cover the entire chart
    
        ObjectSetInteger(0, obj_name, OBJPROP_XDISTANCE, 0);
        ObjectSetInteger(0, obj_name, OBJPROP_YDISTANCE, 0);
        ObjectSetInteger(0, obj_name, OBJPROP_XSIZE, width);
        ObjectSetInteger(0, obj_name, OBJPROP_YSIZE, height);
        
    //--- Send the image to the background
    
        ObjectSetInteger(0, obj_name, OBJPROP_BACK, true);
        ObjectSetInteger(0, obj_name, OBJPROP_ZORDER, -1);
        
    //--- Make sure the object is visible
        ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(0, obj_name, OBJPROP_HIDDEN, true);
        
    //--- Redraw the chart to see changes
    
        ChartRedraw(0);    
    //---
       return true;
    }

    Schließlich automatisieren wir den Prozess der Aufnahme von Screenshots und senden sie an den Screenshot-Pfad, um von unserem Python-Skript gelesen zu werden. Wir automatisieren auch den Prozess des Lesens der vorhergesagten Bilder aus dem Ordner YOLOv8 Images und den Prozess des Malens des Bildes auf dem MetaTrader 5 Chart.

    void OnTimer(void)
      {   
    //---
    
        showBars(true); //explicitly show the bars
        
        // Clear the objects before taking a screenshot
        ObjectsDeleteAll(0);
        ObjectsDeleteAll(0,0);
        
        if (takeScreenShot())
         {
           Print("Screen shot taken: ",TimeCurrent());
           Sleep(100);
         }
         
        chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
        chart_height = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
               
    //--- Take screenshot
        
        MqlDateTime time_struct;
        TimeToStruct(TimeLocal(), time_struct);
       
        string filename = StringFormat("\\Files\\YOLOv8 Images\\%s.%s.%d.%d.%d.bmp",Symbol(),EnumToString(Period()),time_struct.day, time_struct.day_of_week, time_struct.hour);
        string fileshort_name = filename;
        
        bool checkfile = false;
        if (StringReplace(fileshort_name, "\\Files\\","")>0)
          checkfile = true; //If the parent folder was removed we can proceed to check if a file exists before drawing an object
          
        if (checkfile)
         while (!FileIsExist(fileshort_name)) 
           {
             printf("%s not found",fileshort_name);
             return;
           }
            
    //--- Set the image with patterns detected to a chart
    
        if (!chartBackGroundSet(filename, chart_width, chart_height))
            return;
            
        showBars(false);
      }

    Schließlich wurde ein Expert Advisor (EA) auf EURUSD gestartet, PERIOD_H1 (wie im Python-Skript). Das Python-Skript lief, und der Timer war auf 60 Sekunden eingestellt.

    Nachdem 60 Sekunden im EURUSD-Chart vergangen waren, erhielt MetaTrader 5 ein Bild vom Modell.


    So cool!

    Die Methode zum Anhängen eines Bildes als Hintergrund des oben verwendeten Charts ist grob und setzt voraus, dass die Größe des Charts konstant ist oder für eine gewisse Zeit gleich bleibt (zumindest für die Zeit, die in der Timer-Funktion eingestellt ist).

    Die Anpassung der Chartgröße unterbricht also den Prozess des Zeichnens eines Bildes auf dem Chart für einige Zeit. Ich empfehle die hier beschriebene Methode, um eine robuste Methode zur Visualisierung des Bildes als Hintergrund eines Charts zu erhalten.


    Abschließende Überlegungen

    YOLOv8 ist meiner Meinung nach ein beeindruckendes Modell. Wie jedes andere maschinelle Lernmodell hat es seine Grenzen und Nachteile, aber wenn es um die Erkennung der zuvor besprochenen Chartmuster geht, trifft es einige Muster richtig, also Hut ab vor seinen Autoren, denn ich habe in der Vergangenheit versucht, ein ähnliches Modell für diese Aufgabe zu erstellen und habe schlechte Ergebnisse erzielt.

    Wir verwenden zwar immer KI-Modelle, um unsere Handelsstrategien zu automatisieren, aber dieses Modell ist für den algorithmischen Handel nicht geeignet, da es Bilder erzeugt, die vorerst nur ein Mensch lesen kann. Es ist eher eine coole Art, Muster für manuelle Trader zu erkennen. Um es für algorithmische Strategien zu nutzen, können Sie eine Verbindung zwischen Python und MetaTrader herstellen, um Rohinformationen in Text- oder JSON-Formaten über den Zustand des Modells und die Vorhersagen zu senden, die von der Methode Predict dieses Modells angeboten werden.

    Mit freundlichen Grüßen.

    Bleiben Sie dran und tragen Sie zur Entwicklung von Algorithmen für maschinelles Lernen für die Sprache MQL5 in diesem GitHub Repository bei.


    Tabelle der Anhänge


    Dateiname & Pfad
    Beschreibung und Verwendung
    Experts\YOLOv8 EA.mq5 Ein Expert Advisor zum Sammeln von Screenshots aus dem Chart und Hinzufügen des von YOLOv8 vorhergesagten Bildes zum aktuellen Chart.
    Include\errordescription.mqh Eine Bibliothek zum Konvertieren von Fehlercodes, die in MetaTrader 5 und MQL5 erzeugt werden, von Ganzzahlen in sprechenden Zeichenketten.
    Scripts\ChartScreenshots.mq5 Ein Skript, um mehrere Screenshots historisch von einem bestimmten Chart in MetaTrader 5 zu machen.
    YOLOv8 Proj\test.py Ein Python-Skript zum Testen des YOLOv8-Modells über mehrere Bilder hinweg.
    YOLOv8 Proj\deploy.py Ein Python-Skript für die kontinuierliche Bereitstellung und Ausführung des YOLOv8-Modells.
    YOLOv8 Proj\requirements.txt Enthält alle im Projekt verwendeten Python-Abhängigkeiten und deren Versionsnummer.


    Übersetzt aus dem Englischen von MetaQuotes Ltd.
    Originalartikel: https://www.mql5.com/en/articles/18143

    Beigefügte Dateien |
    Attachements.zip (1023.22 KB)
    Umstellung auf MQL5 Algo Forge (Teil 1): Erstellen des Haupt-Repositorys Umstellung auf MQL5 Algo Forge (Teil 1): Erstellen des Haupt-Repositorys
    Bei der Arbeit an Projekten in MetaEditor stehen Entwickler oft vor der Notwendigkeit, Codeversionen zu verwalten. MetaQuotes kündigte kürzlich die Migration zu GIT und die Einführung von MQL5 Algo Forge mit Codeversionierung und Kollaborationsfunktionen an. In diesem Artikel wird erörtert, wie die neuen und bereits vorhandenen Tools effizienter genutzt werden können.
    Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker
    Die Preisaktion ist ein grundlegender Ansatz zur Identifizierung profitabler Handels-Setups. Die manuelle Überwachung von Kursbewegungen und -mustern kann jedoch schwierig und zeitaufwändig sein. Deshalb entwickeln wir Tools, die das Kursgeschehen automatisch analysieren und rechtzeitig Signale geben, wenn sich potenzielle Chancen ergeben. In diesem Artikel wird ein robustes Tool vorgestellt, das fraktale Ausbrüche zusammen mit dem EMA 14 und dem EMA 200 nutzt, um zuverlässige Handelssignale zu generieren, die Händlern helfen, fundierte Entscheidungen mit größerer Zuversicht zu treffen.
    Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
    In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
    MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel
    In diesem Artikel bauen wir ein Multi-Timeframe-Scanner-Dashboard in MQL5, um Handelssignale in Echtzeit anzuzeigen. Wir planen eine interaktive Gitterschnittstelle, implementieren Signalberechnungen mit mehreren Indikatoren und fügen eine Schaltfläche zum Schließen hinzu. Der Artikel schließt mit Backtests und strategischen Handelsvorteilen