English Deutsch
preview
データサイエンスとML(第41回):YOLOv8を用いた外国為替および株式市場のパターン検出

データサイエンスとML(第41回):YOLOv8を用いた外国為替および株式市場のパターン検出

MetaTrader 5トレーディングシステム |
32 0
Omega J Msigwa
Omega J Msigwa

内容


はじめに

金融市場におけるパターン検出は、機械学習やAIにとって大きな挑戦です。人間にとっては直感的に容易に見えるかもしれませんが、機械にとっては手間のかかる作業です。その理由は、取引でよく扱う表形式(二次元の表形式)データとは異なり、パターン検出には二次元の画像データを扱う必要があるからです。これらは通常、.pngや.jpgといった形式で保存されています。

実際、市場にはプライスアクションや特定のチャートパターンに依存する戦略を使うトレーダーが数多く存在します。以下は例です。

  • 階段状の上昇および階段状の下降
  • アセンディングトライアングル(上昇型トライアングル)
  • ディセンディングトライアングル(下降型トライアングル)
  • シンメトリカルトライアングル(均衡型トライアングル)
  • フラッグ 
  • ウェッジ
  • ダブルトップ
  • ダブルボトム
  • 三尊
  • ラウンドトップとラウンドボトム
  • カップ&ハンドル(カップウィズハンドル)
  • その他多数

プログラミングの観点では、ローソク足パターンやインジケーターの反応など、比較的シンプルなコードで検出できるものもあります。しかし、上記のチャートパターンは非常に複雑です。

たとえば「Wボトム」のようなシンプルなパターンを検出するだけでも、洗練された最適化済みのコードが必要になります。であれば、この退屈な作業をAIに手伝わせてはどうでしょうか。

この問題を解決するために、本記事ではhuggingface.coで見つけた非常に興味深いモデル「YOLOv8」について解説します。

このモデルは、画像やチャートからチャートパターンを比較的高い精度で検出することができます。

なお、本記事の内容を十分に理解するためには、機械学習Pythonプログラミング言語に関する基礎的な知識が必要です。


YOLOv8とは何か

公式ドキュメントによると:

YOLOv8sはYOLO (You Only Look Once)フレームワークに基づく物体検出モデルです。このモデルは、株式市場の取引データをスクリーンキャプチャした画像から、さまざまなチャートパターンをリアルタイムに検出するよう設計されています。

このモデルは、チャートパターンの分析を自動化することでトレーダーや投資家を支援し、タイムリーな洞察を提供して意思決定をサポートします。

また、このモデルは多様なデータセットでファインチューニングされており、実際の取引シナリオにおいて株式市場のパターンを高精度に検出・分類することが可能です。

現時点で、このモデルはいくつかのパターンを正確に予測することができます。

三尊

三尊

パターンの簡単な説明

このパターンは、市場において反転が起こる可能性を示しています。

トレーダーは、3つの山と谷のセット(中央の山が最も大きいもの)が現れると、株価が下落を開始すると考えます。

「ネックライン」は、弱気のトレーダーが売り始めるポイントを表します。詳細はこちら

逆三尊

これは三尊の反対です。

M字型パターン

M字型パターン

パターンの簡単な説明

ダブルトップとも呼ばれるこのパターンは、2つの連続した丸みを帯びたトップから形成されます。

これらの丸みを帯びたトップは、長期にわたる強気の上昇トレンドの後に現れることが多く、弱気への反転を示すシグナルとなることがあります。

ダブルトップが発生した場合、2つ目の丸みを帯びたトップは通常、1つ目のトップのピークよりわずかに低く現れ、抵抗線および買い疲れを示します。

ダブルトップは比較的まれにしか出現しませんが、その形成は投資家が強気トレンドから最終的な利益を得ようとしていることを示している場合があります。詳細はこちら

W字型パターン

W字型

これは、M字型パターンと同じように機能しますが、逆になります。詳細はこちら

ストックライン

ドキュメントやオンラインで参照が見つからなかったので、今はスキップしましょう。

トライアングルパターン

これらのパターンは、検証された場合には継続パターンとなり、失敗した場合には強力な反転パターンとなる可能性があります。

トレーダーはトライアングルを使って、上昇トレンドや下降トレンドの後に株式や証券の取引レンジが収束するタイミングを特定します。詳細はこちら


MetaTrader 5からチャートパターンを取得する

YOLOv8は画像(画像データ)を扱うため、テストやモデルの実験に使用できる高品質な画像を大量に抽出する必要があります。

幸いなことに、MetaTrader 5とMQL5プログラミング言語は、任意のチャートや銘柄からスクリーンショットを撮影する機能を提供しています。スクリプトを使って、いくつかの画像を収集してみましょう。

ファイル: 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);
}

この関数は、現在のチャートから複数のスクリーンショットを取得します。対象範囲は1000本のバー(デフォルト)で、各スクリーンショットは前回の位置から50本のバー(デフォルト)分だけ過去にシフトしてキャプチャされます。

スクリーンショットを取得する関数を呼び出す前に、チャートをできる限りクリーンな状態にしておく必要があります。グリッドラインやティックボリュームといったわずかなノイズでも、モデルがチャート上に現れる主要なパターンを検出する際に妨げとなる可能性があります。

    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  

すべての画像はMQL5\Files\Screenshotsフォルダに保存されます。


YOLOv8を用いたパターン検出

    公式ドキュメントによると、以下のコードがこのモデルを実行し、予測結果を受け取るための最小限のサンプルとなります。

    インストールをおこないます。

    $pip install ultralytics

    はじめます。

    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)

    ただし、このコードをそのまま実行するとエラーが出る可能性があります。というのも、現在の環境にはultralyticsのYOLOv8が存在せず、公式ドキュメントがやや古くなっているためです。以下の手順が正しい方法になります。

    まず最初に、YOLOオブジェクトをインポートし、タスクに応じて学習済みモデルを読み込む必要があります。

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

    ファイルmodel.ptこちらにあります。ファイルをダウンロードしたら、現在作業しているディレクトリのModelsサブフォルダに保存します。

    その後、モデルオブジェクトからpredictメソッドを呼び出して、画像名を解析する必要があります。これで、予測された結果が得られます :)。

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

    save=Trueの場合、モデルはパターンがハイライトされた結果画像を保存します。

    しかし、これだけでは単純すぎて不十分です。そこで、スクリーンショットが保存されたフォルダ内の複数画像を分析・予測できる、信頼性の高い堅牢なコードにするために、専用のクラスを作成してみましょう。

    さらに、予測結果を扱いやすくし、視覚的に確認するための最適な方法も考慮する必要があります。

    単一画像でのパターン検出

    このクラスのコンストラクタは、YOLOモデルオブジェクトと、MetaTrader 5から取得したスクリーンショットが格納されている画像フォルダを受け取ります。

    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

    また、クラス内には指定フォルダ内のすべての画像を取得する関数も必要です。

    この関数は、複数画像に対して予測をおこなう際に便利です。フォルダ内の画像数やファイル名を把握でき、Pythonのリストとして名前を返すと同時に、画像の総数もタプルで取得できます。

    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

    次に、予測関数を拡張して、単一画像の予測にも対応できるようにしましょう。この関数では、検出されたパターンと、それぞれのパターンに対する信頼度も確認できるようにします。

    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.")
    

    YOLOv8のpredict関数は、検出されたパターンを囲むボックス情報を含む辞書を返します。このボックスは、特定のチャートパターンを検出した領域を囲み、その信頼度も表示します。

    この情報を取得した後、Pythonコンソールやコマンドプロンプト(CMD)に出力して確認できます。

    関数の最後では、histがFalseに設定されている場合、cv2モジュールを使用して予測結果をウィンドウ上に表示します。

    これは、モデルによって検出されたパターンがハイライトされた画像を視覚的に確認したいときに便利な機能です。

    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)
    

    今回は、Screenshotsフォルダ内にあるEURUSD.PERIOD_H1から取得した画像を用意しました。この画像には番号「11」がマークされています。 

    以下が元の画像です。

    以下は、予測関数を実行した後にモデルが生成した画像です。画像は別ウィンドウのダイアログで表示されます。

    複数の画像にわたるパターンの検出

    Screenshotsフォルダから画像を取得したら、すべての画像を順番にループ処理し、先ほど作成したpredict_images関数にそれぞれ渡して予測をおこないます。

    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)

    では、先ほど作成した関数を使って、収集した複数の画像を予測してみましょう。これはバックテストに似た手法です。過去に収集した複数の画像をモデルに渡すことで、このモデルがどの程度精度の高い予測をおこなえるかどうかを確認できます。

    pattern_detector.predict_images()
    出力

    すべての予測結果と、このモデルが生成した画像は、現在の作業ディレクトリのruns\predict*フォルダに保存されています。

    上記の通り、モデルはいくつか良好な予測を出しています。しかし、これまでに作られたどの機械学習モデルと同様に、弱点や限界も存在します。以下にそのいくつかを挙げます。


    YOLOv8のバイアス、リスク、限界

    01:チャートスタイル、画面解像度、市場状況の違いによる性能への影響

    チャート上のローソク足の色はなるべく分かりやすく設定します。背景色とローソク足の色は明確に区別されている方が、より良い結果が得られます。

    チャートのスケールも重要です。MetaTrader 5で大きなスケールを使うとパターンが一部しか見えない場合があり、小さすぎるとノイズが増える可能性があります。

    適切なチャートスケールと画像サイズのバランスを見つけることが重要です。

    02:急激な市場変動や取引データのノイズによる精度への影響

    急な変動は誤ったブレイクアウトや奇妙なパターンを生むことがあります。このモデルは、そのようなチャートや市場で誤検出をおこなう可能性があります。

    03:学習データで十分に表現されていない市場特有のパターンの検出が困難

    不確実なパターンが存在する市場や時間足を避け、適切な市場でモデルを運用することが、モデルの性能を最大限に引き出す最善の方法です。


    YOLOv8を用いたMetaTrader 5におけるチャートパターン検出

    改めて言うと、YOLOv8モデルは画像を扱い、予測結果も画像形式で出力されます。そのため、ネイティブのMQL5言語だけでは直接読み取って解釈することはできません。しかし、MQL5にはBMP形式のビットマップ画像を扱う機能があるため、ここから始めるのは良いアプローチです。

    MQL5では、画像ベースのオブジェクトを作成したり、MetaTrader 5のチャートの背面に画像を埋め込んだりすることが可能で、実際にこれまでに何度もおこなわれています。そこで、YOLOv8が生成したチャートパターン検出画像を、チャートの背面に配置して表示してみましょう。この記事で紹介されている方法と同じです。

    画像をチャートの背景として追加したら、現在表示されているローソク足(前景)を非表示にし、ローソク足を含むチャート全体を画像として更新することができます。

    これを実現するために、Pythonクラスのいくつかの部分を修正する必要があります。まずは予測関数を改良し、予測結果を含むすべての画像を特定のディレクトリ(同じフォルダ)に保存できるようにするところから始めましょう。

    ファイル名: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.")
    
    

    予測関数を使って画像を指定フォルダに保存できるようになったので、MQL5ファイルの親フォルダ内にYOLOv8 Imagesというサブフォルダを作成して、すべての画像をそこに保存することができます。

    YOLOv8はJPEGまたはJPG形式で画像を出力しますが、MetaTrader 5で使用する場合はBitmap形式(BMP)に変換する必要があります。以下に、その変換をおこなう関数を示します。

    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

    ここで、単一の画像で利用可能なパターンを検出して予測する方法を説明します。

    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)

    このプロセスは自動化できます。数分が経過したら、スクリプトでMQL5\Files\Screenshotsから画像を読み取り、予測をおこない、画像をMQL5\Files\YOLOv8 Imagesに保存します。

    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)

    では次に、MetaTrader 5のチャート上でBitmap (.BMP)形式の画像を表示するための環境を整えましょう。

    まずは、タイマー処理用の関数を初期化します。これにより、スクリーンショットの取得や、予測(検出)パターンを含む画像でチャートを自動的に更新するプロセスを自動化することができます。

    ファイル名: 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);
      }

    showBarsという関数は、チャート上のスクリーンショットを撮るための適切な環境をクリーンアップして準備する役割を担います。

    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();
     }

    この関数をfalseの値で呼び出すと、チャートのすべてのプロパティ(ローソク足の色を含む)がチャートの背景色と同じ色に設定され、すべてを見えなくする処理がおこなわれます。

    これは、チャートの背景に画像を配置するために必要な手順です。前景のローソク足が残っていると、画像上で表示され、視覚的に混乱を招く可能性があるためです。

    以下に、Bitmap (.BMP)形式の画像をオブジェクトに変換し、現在のチャートの背景として割り当てる関数を示します。

    //+------------------------------------------------------------------+
    //|       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;
    }

    最後に、スクリーンショットを自動で取得してScreenshotsフォルダに保存し、Pythonスクリプトで読み込めるようにするプロセスを自動化しましょう。さらに、YOLOv8が出力した予測画像をYOLOv8 Imagesフォルダから自動で読み込み、MetaTrader 5のチャートに描画するプロセスも自動化します。

    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);
      }

    最後に、エキスパートアドバイザー(EA)をEURUSD、PERIOD_H1にアタッチしました(Pythonスクリプトと同じ設定です)。Pythonスクリプトは稼働中で、タイマーは6秒に設定されています。

    EURUSDチャートで60秒が経過すると、MetaTrader 5はモデルから生成された画像を受信しました。


    すごいですね。

    ただし、上で紹介したチャートの背景として画像を配置する方法は簡易的なもので、チャートサイズが一定であること、あるいは少なくともタイマーで設定した時間の間は変わらないことを前提としています。

    そのため、チャートのサイズを変更すると、画像をチャート上に描画するプロセスが一時的に中断される可能性があります。より堅牢に画像をチャート背景として表示したい場合は、こちらで紹介した方法を参考に、安定して表示できる方法を採用することをおすすめします。


    最後に

    私の意見では、YOLOv8は非常に印象的なモデルです。もちろん他の機械学習モデルと同様に限界や欠点はありますが、先ほど紹介したチャートパターンの検出に関しては、いくつかのパターンを正しく検出しており、開発者の方々に敬意を表したいと思います。過去に同じタスク用のモデルを自分で作ろうとしたことがありますが、うまくいかず苦労した経験があります。

    AIモデルを使って取引戦略を自動化することは一般的ですが、このモデルは現時点では画像を出力するだけで、人間が読む必要があるため、アルゴリズム取引には実用的ではありません。しかし、裁量トレーダーがパターンを検出するための面白い方法としては十分に活用できます。アルゴリズム取引に利用したい場合は、PythonとMetaTrader間で通信を確立し、モデルの状態やpredictメソッドの予測結果をテキストやJSON形式で送信する方法を考える必要があります。

    ご一読、誠にありがとうございました。

    今後の更新にもご注目ください。こちらのGitHubリポジトリで、MQL5言語向けの機械学習アルゴリズムの開発にぜひ貢献してください。


    添付ファイルの表


    ファイル名とパス
    説明と使用法
    Experts\YOLOv8 EA.mq5 チャートからスクリーンショットを収集し、YOLOv8による予測画像を現在のチャートに追加するEA
    Include\errordescription.mqh MetaTrader 5およびMQL5で生成されたエラーコードを整数から人間が読める文字列に変換するためのライブラリ
    Scripts\ChartScreenshots.mq5 MetaTrader 5の指定されたチャートから履歴的に複数のスクリーンショットを撮るためのスクリプト
    YOLOv8 Proj\test.py 複数の画像にわたってYOLOv8モデルをテストするためのPythonスクリプト
    YOLOv8 Proj\deploy.py YOLOv8モデルを継続的に展開および実行するためのPythonスクリプト
    YOLOv8 Proj\requirements.txt プロジェクトで使用されるすべてのPython依存関係とそのバージョン番号


    MetaQuotes Ltdにより英語から翻訳されました。
    元の記事: https://www.mql5.com/en/articles/18143

    添付されたファイル |
    Attachements.zip (1023.22 KB)
    データサイエンスとML(第42回):PythonでARIMAを用いた外国為替時系列予測、知っておくべきことすべて データサイエンスとML(第42回):PythonでARIMAを用いた外国為替時系列予測、知っておくべきことすべて
    ARIMAは自己回帰和分移動平均(Auto Regressive Integrated Moving Average)の略称で、強力な従来の時系列予測モデルです。このモデルは、時系列データ内の急上昇や変動を検出する機能により、次の値を正確に予測できます。この記事では、ARIMAが何であるか、どのように機能するか、市場での次の価格を高い精度で予測する際に何ができるかなどについて説明します。
    MQL5 Algo Forgeへの移行(第1回):メインリポジトリの作成 MQL5 Algo Forgeへの移行(第1回):メインリポジトリの作成
    MetaEditorでプロジェクトを進める際、開発者はしばしばコードのバージョンを管理する必要に直面します。MetaQuotesは最近、Gitへの移行と、コードのバージョン管理や共同作業を可能にするMQL5 Algo Forgeの立ち上げを発表しました。本記事では、新しく導入されたツールと既存のツールを、より効率的に活用する方法について解説します。
    エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
    この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
    プライスアクション分析ツールキットの開発(第23回):Currency Strength Meter プライスアクション分析ツールキットの開発(第23回):Currency Strength Meter
    通貨ペアの方向性を本当に決定しているのは何でしょうか。それは各通貨自体の強さです。本記事では、通貨の強さを、その通貨が含まれるすべてのペアを順に分析することで測定します。この洞察により、各通貨ペアが相対的な強さに基づいてどのように動くかを予測することができます。詳しくは本稿をご覧ください。