English Русский 中文 Español Deutsch Português
preview
Candlestick Trend Constraintモデルの構築(第8回):エキスパートアドバイザー(EA)の開発 (II)

Candlestick Trend Constraintモデルの構築(第8回):エキスパートアドバイザー(EA)の開発 (II)

MetaTrader 5テスター | 25 10月 2024, 12:42
126 0
Clemence Benjamin
Clemence Benjamin

内容

  1. はじめに
  2. EAの作成
  3. テスター
  4. 結論


    はじめに

    前回の記事では、Trend Constraint V1.09指標と、リスクとリターンの矩形を配置するための手動実行型Trend Constraint R-Rスクリプトを使用してEAを作成する方法を検討しました。この設定は、洞察に富んだ取引シグナルや高度な可視化を提供しつつ、手動での介入を必要とする部分がありました。しかし、取引環境が高速で進行する中、より効率的なソリューションの必要性が明らかになりました。多くのトレーダーは、常時の監視や手動での実行を減らすために、自律的に機能する統合システムを求めています。

    本記事では、Trend Constraint V1.09のトレンド分析機能に加え、リスクリワード機能をEAに直接統合した、独立したEAの開発プロセスを紹介します。私たちの目標は、MetaTrader 5プラットフォーム上でMQL5を使用して、トレーダーを支援するオールインワンの自動化ソリューションを提供し、市場のニーズに応えるシームレスな運用を実現することです。

    そのために、これまで第1回第2回第3回で取り上げた基本的なステップを再確認し、EAが取引タスクを実行するために必要なロジックを組み込みます。次に、それらの要素を組み合わせて、実際にEAを作成します。

    以下は、MQL5で実装された指標でシグナルが発生した条件をまとめたものです。

    買い(ロング)状態

    1. D1ローソク足は強気でなければなりません。
    2. 強気D1ローソク足内の下位時間枠では、シグナルの合流が必要です。具体的には、相対力指数(RSI)のような内蔵指標が売られ過ぎの状態を示し、高速移動平均線が低速移動平均線を上回らなければなりません。

    売り(ショート)の状態

    1. D1ローソク足は強気でなければなりません。
    2. 弱気D1ローソク足内の下位時間枠では、シグナルが合流する必要があります。具体的には、相対力指数(RSI)などの内蔵指標が買われすぎの状 態を示し、高速移動平均線が低速移動平均線を下回らなければなりません。


    EAの作成

    MetaEditorアプリを使ってMQL5 EAプログラムを書いきます。最も重要なのは、土台を念頭に置くことです。以下は、EAの構造を要約したものです。

    ほとんどのEAプログラムのアーキテクチャ概要:

    • 初期化(OnInit):必要な指標と変数を設定します。
    • メインループ(OnTick):受信したティックを処理して市場の状況を評価し、取引の意思決定をおこないます。
    • 取引管理(OnTrade):取引関連のイベントを扱います。
    • テスト(OnTesterおよび関連関数):ストラテジーテスターでEAのパフォーマンスを最適化し、評価するための仕組みを提供します。
    • ユーザーインタラクション(OnChartEvent):オプションですが、チャートイベントを通じてEAとのインタラクションを可能にします。

    以下のブロック図の下書きが、私たちが望む結果を明確にし、理解しやすくするのに役立つと思います。

    Trend Constraint EA

    EAの各部分の大まかなブロック図と、部分間の連携の仕方

    このような構造により、私たちのEAはよく組織化され、取引戦略を実行するために必要なさまざまなタスクを効果的に処理することができます。開発プロセスをいくつかの項目に分けて説明しますが、上級開発者は(i)と(ii)の段階を飛ばして(iii)の項目に直接進むことができます。

    (i) MetaEditorでデフォルトのEA(テンプレート)を起動します

    (ii) テンプレートをカスタマイズします

    (iii) 作成したテンプレートTrend Constraint EAのロジックを記述します


    (i) EAテンプレートの起動

    MetaEditorでCtrl + Nキーを押して新規ファイルを立ち上げ、下図のように「エキスパートアドバイザ(テンプレート)」を選択します。

    EAの起動(テンプレート)

    新しいエキスパートアドバイザ(テンプレート)の起動

    私のコンピューターには以前のプロジェクトがあるため、新しいプロジェクトを立ち上げると、著者の詳細とリンクがすでに利用可能になっています。自分用にカスタマイズすることもできます。


    (ii) テンプレートのカスタマイズ

    この文章を書いた意図は、私のコーディング能力を示すだけでなく、プロセスを理解し始めたばかりの人たちに影響を与え、習得したスキルを将来応用できるようにするためでもあります。この時点ではテンプレートを見ているのですが、初心者には意味がないように思えるかもしれません。スケルトンテンプレートへのコーディングを始める前に、必要な最も重要な機能を抜き出して簡単に説明しましょう。その後、ニーズに合わせてEAコードを書きながら、詳細を詰めていきます。このやり方は、今注目していることとは別の自分のプロジェクトを無理なく始めることができるようになるので、非常に重要です。

    このスケルトンは、後にEAのロジックを構築するための土台となります。

    以下はMetaEditorから生成されたテンプレートです。

    //+------------------------------------------------------------------+
    //|                                      Trend Constraint Expert.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/ja/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/ja/users/billionaire2024/seller"
    #property version   "1.00"
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //---
       
    //---
       return(INIT_SUCCEEDED);
      }
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Trade function                                                   |
    //+------------------------------------------------------------------+
    void OnTrade()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Tester function                                                  |
    //+------------------------------------------------------------------+
    double OnTester()
      {
    //---
       double ret=0.0;
    //---
    
    //---
       return(ret);
      }
    //+------------------------------------------------------------------+
    //| TesterInit function                                              |
    //+------------------------------------------------------------------+
    void OnTesterInit()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| TesterPass function                                              |
    //+------------------------------------------------------------------+
    void OnTesterPass()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| TesterDeinit function                                            |
    //+------------------------------------------------------------------+
    void OnTesterDeinit()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    

     テンプレートから、EAに不可欠な主要機能について説明します。

    • OnInit()関数:この関数は、EAが初期化されるときに一度だけ実行され、操作に必要な指標、変数、リソースを設定します。適切な初期化により、EAが市場データの処理を開始する前に、必要なリソースがすべて準備できていることが保証されます。Trend Constraint EAの場合、RSI指標やその他の重要な変数は通常ここで初期化されます。

    • OnDeinit()関数:この関数は、EAがチャートから削除されたときや端末がシャットダウンされたときなど、EAが初期化解除されたときに呼び出されます。メモリリークやその他の問題を防ぐために、指標ハンドルの解放やファイルのクローズなど、リソースのクリーンアップに使われます。

    • OnTick()関数:このメイン関数は、EAがアタッチされている銘柄の新しいティック(価格更新)を受信するたびにトリガーされます。Trend Constraint EAでは、D1トレンドやRSIレベルなどの相場状況を確認し、ポジションを建てたり決済するなどの売買判断をおこなうロジックが含まれます。

    • OnTrade()関数:注文の発注、変更、決済などの取引イベントが発生したときに呼び出されるこの関数は、取引ステータスを監視し、変化に対応するために不可欠です。例えば、いつ取引が開始されたかを追跡し、それに応じてEAの動作を調整するために使用することができます。

    • OnTester()関数:この関数は戦略のテスト中に使用され、最適化のためのカスタム基準として機能するdouble値を返します。ストラテジーテスターでテストする際にEAのパフォーマンスを評価するために、プロフィットファクターやドローダウンなどのカスタムメトリックを定義することができます。

    • OnTesterInit()、OnTesterPass()、 OnTesterDeinit()関数:これらの関数は、ストラテジーテスターにおけるテストの開始、進行中のパス、終了を管理する、戦略テストと最適化のためのものです。リソースの初期化、データの収集、テスト後の後始末をおこなうことで、テストプロセスの制御性を高めることができます。

    • OnChartEvent()関数:この関数は、マウスクリックやキー押下のようなチャートイベントを処理し、EAの実行中にEAとのインタラクションを可能にします。EAにパラメータの変更やチャートイベントによるアクションのトリガーなど、ユーザーとのインタラクションが含まれる場合、この関数は不可欠です。

    これらの関数を理解すれば、その中でどのようにロジックを構成すればよいかがわかります。しかし、テンプレートが提供する関数は、ここで開発しようとしているEAの複雑さには十分ではないかもしれません。追加の関数が必要な場合もあります。Trend Constraint EAの具体的な要件を満たすために、その関数が含まれていることを正当化し、説明する必要があります。

    以下は、EAテンプレートには含まれていないが、私たちのプロジェクトに必要な追加関数です。

    • 指標関数(iRSIなど):取引戦略に不可欠な RSI などの指標を計算するために使用します。
    • 取引関数(CTradeクラス):売買注文の発注、ストップロスの設定、ポジションの変更など、注文やポジションの管理に使用します。
    特定の適切な関数の中でEAに使わせたいロジックを概説しました。これは、私がEAに盛り込もうと考えている機能の骨格となるレイアウトであり、この開発において各機能がどのように不可欠であるかをコードにコメントを付けて説明しました。
    //+------------------------------------------------------------------+
    //|                               Trend Constraint Expert Advisor.mq5|
    //|                                 Copyright 2024, Clemence Benjamin|
    //|              https://www.mql5.com/ja/users/billionaire2024/seller|
    //+------------------------------------------------------------------+
    
    
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
       // Initialization code here
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       // Any other initialization tasks
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
       // Cleanup code here
       IndicatorRelease(rsi_handle);  // Release RSI indicator handle
       // Any other deinitialization tasks
      }
    
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
       // Main trading logic goes here
       
       // Determine market conditions (e.g., daily trend, RSI levels)
       
       // Check for trade conditions and execute orders if necessary
    
       // Implement trailing stop logic if necessary
      }
    
    //+------------------------------------------------------------------+
    //| Trade event function                                             |
    //+------------------------------------------------------------------+
    void OnTrade()
      {
       // Handle trade events (e.g., order placement, modification, closure)
      }
    
    //+------------------------------------------------------------------+
    //| Tester function                                                  |
    //+------------------------------------------------------------------+
    double OnTester()
      {
       double ret = 0.0;
       // Custom optimization criteria (if any) go here
       return(ret);
      }
    
    //+------------------------------------------------------------------+
    //| TesterInit function                                              |
    //+------------------------------------------------------------------+
    void OnTesterInit()
      {
       // Initialization for testing (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| TesterPass function                                              |
    //+------------------------------------------------------------------+
    void OnTesterPass()
      {
       // Actions after each optimization pass (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| TesterDeinit function                                            |
    //+------------------------------------------------------------------+
    void OnTesterDeinit()
      {
       // Cleanup after testing (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| Chart event function                                             |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
       // Handle chart events (e.g., mouse clicks, key presses) here
      }
    
    //+------------------------------------------------------------------+
    


    (iii) Trend Constraint EAロジックの記述 

    次に、EAを構成する各関数のロジックを書いていきます。ステップごとにプログラムを組み立てていきましょう。

    取引ライブラリをインクルードする

    まず、取引ライブラリをインクルードします。このライブラリ内のCTradeクラスは、ポジションのオープン、変更、クローズなどの取引操作を実行するために必要な関数を提供するため、取引ライブラリが必要になります。このライブラリをインクルードすることで、EAがマーケットと対話し、プログラム的に取引を管理できるようになります。

    #include <Trade\Trade.mqh>  // Include the trade library
    

    入力パラメータの定義

    次に、入力パラメータを定義し、ユーザーが自分の取引の好みに合わせて調整できるようにします。これらのパラメータには、RSI期間、買われすぎと売られすぎのレベル、ロットサイズ、ストップロス、テイクプロフィット、トレイリングストップが含まれます。これらの入力行を記述することで、EAをさまざまな市場環境に合わせてカスタマイズできるようにしています。プログラムは、これらの値を使用して、いつ取引を開始し、終了するかを決定します。

    // Input parameters
    input int    RSI_Period = 14;            // RSI period
    input double RSI_Overbought = 70.0;      // RSI overbought level
    input double RSI_Oversold = 30.0;        // RSI oversold level
    input double Lots = 0.1;                 // Lot size
    input double StopLoss = 100;             // Stop Loss in points
    input double TakeProfit = 200;           // Take Profit in points
    input double TrailingStop = 50;          // Trailing Stop in points
    

    グローバル変数の宣言

    RSI_valueやRS1_handleといったグローバル変数を宣言し、それぞれRSI値やハンドル、CTradeクラスのインスタンスを格納します。これらの変数を宣言することで、EAがさまざまな関数にまたがって状態を維持できるようになり、プログラムが動作中に必要に応じてこれらの値にアクセスし、変更できるようになります。

    // Global variables
    double rsi_value;
    int rsi_handle;
    CTrade trade;  // Declare an instance of the CTrade class
    

    EAの初期化

    OnInit関数で、iRSI関数を使用してRSI指標ハンドルを作成します。プログラムは各ティック中にRSI値を取得するためにこのハンドルを必要とするので、このステップは非常に重要です。ハンドルが作成できない場合にINIT_FAILEDを返すようにプログラムを記述し、この重要なコンポーネントなしでEAが実行されないようにしています。これにより、市場データの分析に必要な機能が完全に装備されている場合にのみ、プログラムが実行されるようになります。

    int OnInit()
      {
       // Create an RSI indicator handle
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       return(INIT_SUCCEEDED);
      }
    

    EAの初期化解除

    リソースを効率的に管理するために、EAがチャートから削除されたときにRSI指標のハンドルを解放するOnDeinit関数を実装します。このクリーンアップコードを書くことで、メモリリークを防ぎ、リソースが適切に解放されるようにします。プログラムは初期化解除時にこのクリーンアップを自動的に実行し、最適なパフォーマンスを維持します。

    void OnDeinit(const int reason)
      {
       // Release the RSI indicator handle
       IndicatorRelease(rsi_handle);
      }
    

    コア取引ロジックの導入

    核となる取引ロジックはOnTick関数にあり、市場のティックごとに実行されるように設計されています。まず、日足の始値と終値を比較して、現在の日足トレンドを判断するコードを書きます。この分析により、プログラムは市場が強気か弱気かを識別することができ、これは十分な情報に基づいた取引判断を下すために不可欠です。

    void OnTick()
      {
       // Determine current daily trend (bullish or bearish)
       double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
       double daily_close = iClose(_Symbol, PERIOD_D1, 0);
    
       bool is_bullish = daily_close > daily_open;
       bool is_bearish = daily_close < daily_open;
    

    RSI値の取得

    次に、CopyBufferと先に作成したRSIハンドルを使ってRSI値を取得します。これを書くことで、プログラムが市場が買われすぎか売られすぎかを評価できるようにします。プログラムはこのRSI値を意思決定プロセスに使用し、取引に入る条件を満たしているかどうかを判断します。

       // Get the RSI value for the current bar
       double rsi_values[];
       if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
         {
          Print("Failed to get RSI value");
          return;
         }
       rsi_value = rsi_values[0];
    

    トレンドの変化に応じてポジションを閉じる

    また、市場のトレンドが変化した場合に、未決済のポジションを決済するロジックも組み込んでいます。例えば、トレンドが強気から弱気に転換した場合、EAは買いポジションを決済し、その逆も同様です。このセーフガードを設定することで、リスクを最小限に抑えるために重要な、一般的な市場センチメントとの整合性を維持することを保証します。

       // Close open positions if the trend changes
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             int position_type = PositionGetInteger(POSITION_TYPE);
             ulong ticket = PositionGetInteger(POSITION_TICKET);  // Get the position ticket
    
             if ((position_type == POSITION_TYPE_BUY && is_bearish) ||
                 (position_type == POSITION_TYPE_SELL && is_bullish))
               {
                trade.PositionClose(ticket);  // Use the ulong variable directly
               }
            }
         }
    

    売買条件の確認

    売買条件については、買い注文の場合は強気トレンドと売られ過ぎのRSIの組み合わせを、ショート注文の場合は弱気トレンドと買われ過ぎのRSIの組み合わせを確認するロジックを書きます。これらの条件をプログラムすることで、トレンドとモメンタムの両指標が一致したときのみEAが取引を開始するようにします。このプログラムは、これらの状況を監視し、それに応じて取引を実行し、取引への規律あるアプローチを保証します。

       // Check for buy condition (bullish trend + RSI oversold)
       if (is_bullish && rsi_value < RSI_Oversold)
         {
          // No open positions? Place a buy order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
             double sl = price - StopLoss * _Point;
             double tp = price + TakeProfit * _Point;
    
             // Open a buy order
             trade.Buy(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Buy");
            }
         }
    
       // Check for sell condition (bearish trend + RSI overbought)
       if (is_bearish && rsi_value > RSI_Overbought)
         {
          // No open positions? Place a sell order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
             double sl = price + StopLoss * _Point;
             double tp = price - TakeProfit * _Point;
    
             // Open a sell order
             trade.Sell(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Sell");
            }
         }
    

    トレーリングストップメカニズムの導入

    最後に、トレーリングストップの仕組みを導入し、マーケットがポジションに有利に動くときに利益を守ります。このトレーリングストップのロジックを記述することで、EAが動的にストップロスを調整して利益を確定する一方、市場が有利な状態が続く限り取引を継続できるようにします。プログラムは自動的にトレーリングストップを管理し、利益を最大化し、損失を最小化するために市場の動きに確実に対応します。

       // Apply trailing stop
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             double price = PositionGetDouble(POSITION_PRICE_OPEN);
             double stopLoss = PositionGetDouble(POSITION_SL);
             double current_price;
    
             if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                if (current_price - price > TrailingStop * _Point)
                  {
                   if (stopLoss < current_price - TrailingStop * _Point)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
             else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                if (price - current_price > TrailingStop * _Point)
                  {
                   if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
            }
         }
      }

    以下は、ヘッダーとその他のプロパティを持つ最終プログラムです。

    //+------------------------------------------------------------------+
    //|                                      Trend Constraint Expert.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/ja/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/ja/users/billionaire2024/seller"
    #property version   "1.00"
    #property description "A System that seeks to Long D1 Bullish sentiment and short D1 Bearish sentiment"
    #property strict
    
    
    #include <Trade\Trade.mqh>  // Include the trade library
    
    // Input parameters
    input int    RSI_Period = 14;            // RSI period
    input double RSI_Overbought = 70.0;      // RSI overbought level
    input double RSI_Oversold = 30.0;        // RSI oversold level
    input double Lots = 0.1;                 // Lot size
    input double StopLoss = 100;             // Stop Loss in points
    input double TakeProfit = 200;           // Take Profit in points
    input double TrailingStop = 50;          // Trailing Stop in points
    
    // Global variables
    double rsi_value;
    int rsi_handle;
    CTrade trade;  // Declare an instance of the CTrade class
    
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
       // Create an RSI indicator handle
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
       // Release the RSI indicator handle
       IndicatorRelease(rsi_handle);
      }
    
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
       // Determine current daily trend (bullish or bearish)
       double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
       double daily_close = iClose(_Symbol, PERIOD_D1, 0);
    
       bool is_bullish = daily_close > daily_open;
       bool is_bearish = daily_close < daily_open;
    
       // Get the RSI value for the current bar
       double rsi_values[];
       if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
         {
          Print("Failed to get RSI value");
          return;
         }
       rsi_value = rsi_values[0];
    
       // Close open positions if the trend changes
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             int position_type = PositionGetInteger(POSITION_TYPE);
             ulong ticket = PositionGetInteger(POSITION_TICKET);  // Get the position ticket
    
             if ((position_type == POSITION_TYPE_BUY && is_bearish) ||
                 (position_type == POSITION_TYPE_SELL && is_bullish))
               {
                trade.PositionClose(ticket);  // Use the ulong variable directly
               }
            }
         }
    
       // Check for buy condition (bullish trend + RSI oversold)
       if (is_bullish && rsi_value < RSI_Oversold)
         {
          // No open positions? Place a buy order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
             double sl = price - StopLoss * _Point;
             double tp = price + TakeProfit * _Point;
    
             // Open a buy order
             trade.Buy(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Buy");
            }
         }
    
       // Check for sell condition (bearish trend + RSI overbought)
       if (is_bearish && rsi_value > RSI_Overbought)
         {
          // No open positions? Place a sell order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
             double sl = price + StopLoss * _Point;
             double tp = price - TakeProfit * _Point;
    
             // Open a sell order
             trade.Sell(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Sell");
            }
         }
    
       // Apply trailing stop
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             double price = PositionGetDouble(POSITION_PRICE_OPEN);
             double stopLoss = PositionGetDouble(POSITION_SL);
             double current_price;
    
             if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                if (current_price - price > TrailingStop * _Point)
                  {
                   if (stopLoss < current_price - TrailingStop * _Point)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
             else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                if (price - current_price > TrailingStop * _Point)
                  {
                   if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
            }
         }
      }
    //+------------------------------------------------------------------+
    //HAPPY DEVELOPING!

    この段階まで来れば、プログラムのテストに進むことができます。以下に私のテスト経験を記します。


    テスター

    MetaTrader 5のストラテジーテスターでTrend Constraintt EAをテストするために、まずEAのパフォーマンスを評価するために過去のデータを使ってバックテストを設定します。このプロセスによって、さまざまな市場条件下での取引戦略をシミュレーションすることができ、収益性、リスク管理、総合的な有効性の分析に役立てることができます。希望の時間枠(この場合はM1時間枠)、入力パラメータ、取引環境を選択し、EAがトレンドフォローのロジックとRSIの条件にどれだけ忠実であるかを観察する必要があります。このテストは、実取引を検討する前にEAを微調整するために極めて重要です。私はBoom 500 Indexのファンで、この美しいペアのEAをテストするのが大好きでした。

    ストラテジーテスター

    ストラテジーテスターの設定Trend Constraint EA

    テスターパフォーマンス

    テスターにおけるTrend constraintのパフォーマンス

    テスター結果

    テスター結果(01/2023~12/2023)



    結論

    この有意義なチュートリアルの議論が終わりを迎えたことを嬉しく思います。今回の目標は、特定の指標を別途インストールすることなく機能する、独立したEAを作成することでした。この議論が、EA開発の基本構造を理解する良いきっかけとなり、確かな出発点となったことを願っています。基本的な概念に重点を置き、できる限りわかりやすく解説しました。これにより、さまざまな要素を調整してEAをカスタマイズし、最適な設定を探し出すことが可能になります。

    最初のアイデアに基づいた実用的なEAの開発は成功し、テスターを用いて注文の執行を確認できる段階に達しました。ただし、改善の余地はまだ残されています。特にエントリ条件において、Trend Constraint EAは、1日のトレンドに沿った収益性をさらに向上させるための改良が必要です。今回、マジックナンバーを設定しなかったため、デモ口座でテストした際に、EAが既に発注した他の注文に影響を与える場面が見られました。

    今回の開発の大きな利点の1つは、指標に依存せず、ポータブルな単一ファイルとして動作する点です。これまでの努力が無駄だったわけではなく、むしろ貴重な学びを得た結果です。今後も、より良い成果を得るためにEAを改良し続けることが私たちの目標です。

    次回は、マジックナンバーを実装し、エントリー技術を強化することで、さらなる創意工夫を加えていきます。取引をお楽しみください。

    ファイル 詳細
    Trend Constraint Expert.mq5 ソースコード

    トップに戻る

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

    添付されたファイル |
    ダイナミックマルチペアEAの形成(第1回):通貨相関と逆相関 ダイナミックマルチペアEAの形成(第1回):通貨相関と逆相関
    ダイナミックマルチペアEAは、相関戦略と逆相関戦略の両方を活用し、取引パフォーマンスの最適化を図ります。リアルタイムの市場データを分析することで、通貨ペア間の相関関係や逆相関関係を特定し、それらを取引に活かします。
    MQL5で取引管理者パネルを作成する(第1回):メッセージングインターフェイスの構築 MQL5で取引管理者パネルを作成する(第1回):メッセージングインターフェイスの構築
    この記事では、システム管理者を対象に、プラットフォーム内で他のトレーダーと直接コミュニケーションを図るための、MetaTrader 5用メッセージングインターフェイスの作成について説明します。ソーシャルプラットフォームとMQL5との最近の統合により、さまざまなチャンネルに素早くシグナルをブロードキャストことができるようになりました。YESかNOのどちらかをクリックするだけで、送られてきたシグナルを検証できることをご想像ください。詳しくは本稿をご覧ください。
    MQL5のパラボリックSARトレンド戦略による取引戦略の自動化:効果的なEAの作成 MQL5のパラボリックSARトレンド戦略による取引戦略の自動化:効果的なEAの作成
    この記事では、MQL5を使用してパラボリックSAR戦略を基にした取引戦略を自動化する方法について説明します。効果的なエキスパートアドバイザー(EA)を創り出します。このEAは、パラボリックSAR指標によって識別されたトレンドに基づいて取引を実行します。
    知っておくべきMQL5ウィザードのテクニック(第33回):ガウス過程カーネル 知っておくべきMQL5ウィザードのテクニック(第33回):ガウス過程カーネル
    ガウス過程カーネルは正規分布の共分散関数であり、予測において役割を果たす可能性があります。MQL5のカスタムシグナルクラスで、このユニークなアルゴリズムを探求し、プライムエントリシグナルやエグジットシグナルとして活用できるかを検証しました。