English Русский 中文 Español Deutsch Português
preview
Candlestick Trend Constraintモデルの構築(第9回):マルチ戦略エキスパートアドバイザー(I)

Candlestick Trend Constraintモデルの構築(第9回):マルチ戦略エキスパートアドバイザー(I)

MetaTrader 5トレーディングシステム |
221 0
Clemence Benjamin
Clemence Benjamin

コアコンテンツ



はじめに

この連載が始まった当初から、EAを日足(D1)の優勢なセンチメントに合わせることに重点を置いてきました。D1ローソク足の形は、主要な指針となっています。しかし、D1市場内のエントリレベルを特定するためには、より下位の時間枠にスケールダウンする必要がありました。例えば、M1時間枠では、相対力指数(RSI)が極端なレベルに達し、EAが潜在的な取引のシグナルを出すようにします。この初期段階では、初心者にわかりやすい内容にするため、あまり多くの戦略を紹介しませんでした。

しかし、Trend Constraint EAのアルゴリズムに研究し、統合するための戦略の膨大なコレクションがあります。今日は、私が「市場の父」と呼ぶ、取引界で影響力のある人物たちが開発した有名な戦略を詳しく見ていきましょう。この段階での議論は、タイトルの本来のテーマを保ちつつ、理解を深めることになるでしょう。また、主にRSIと制約ロジックに焦点を当てた前回の開発で議論された戦略の限界にも対処します。さらに、EAに新しい戦略を組み込む方法を探ります。

7つのトップ戦略を深く掘り下げる前に、コードの制約ロジックを巻き戻して復習しておきましょう。 

 MQL5の強気ローソク足の状態

void OnTick()
{
    // Determine current daily trend (bullish )
    double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
    double daily_close = iClose(_Symbol, PERIOD_D1, 0);

    bool is_bullish = daily_close > daily_open;
}

MQL5の弱気ローソク足の状態

void OnTick()
{
    // Determine current daily trend (bearish)
    double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
    double daily_close = iClose(_Symbol, PERIOD_D1, 0);

    
    bool is_bearish = daily_close < daily_open;
}

上記のコードでは、上位時間枠のセンチメントが制約要因となっています。この場合はD1時間枠を選択しました。

制約条件の実装

日足の弱気と強気のセンチメントが確立されたので、エントリ条件のロジックと一緒にif()文を利用することができます。 

強気な日足

 if (is_bullish)
    {
        // Logic for bullish trend
        Print("The daily trend is bullish.");

   // You can add your trading logic here, for example:
        // if (OrderSelect(...)) { /* Place buy order */ }
    }

弱気な日足

 if (is_bearish)
    {
        // Logic for bearish trend
        Print("The daily trend is bearish.");
        // You can add your trading logic here, for example:
        // if (OrderSelect(...)) { /* Place sell order */ }
    }

このディスカッションが終わる頃には、以下について分かるでしょう。

1. その他の戦略とその背後にいる男

2. EAの既存モジュールに新しい戦略を組み込む

3. マジックナンバーの実装

まとめると、上記の3つのポイントは、トレーダーに様々な戦略とその背後にある動機についての理解を深めるだけでなく、新しい戦略を既存のコードに統合するためにMQL5を実装するための洞察を提供します。

メインコードの開発を始める前に、次のセグメントでは、私の調査に基づくこれらの戦略について議論することに集中しましょう。特に市場が常に進化しているため、EA戦略を拡大する必要性がお分かりいただけるでしょう。これらの複合戦略は、あらゆる市場シナリオに適応するために不可欠です。ある戦略が失敗しても、必ず別の戦略があります。各戦略を支える数学的側面を明らかにするよう、あらゆる努力を払ってきました。これらの数学的機能は、効率的なアルゴリズム開発の基礎となる要素だからです。

お気づきになったかもしれませんが、最近のEAを見直した後、いくつかの警告エラーに遭遇しました。下の画像をご覧ください。

警告エラー

コンパイル警告

そのエラーは78行目と28列目にあり、以下で強調表示されています。

警告

78行目、列28の警告

この警告は自明であるため、修正するのが最も簡単なものの一つです。以下は修正したコードスニペットです。

long position_type = PositionGetInteger(POSITION_TYPE);

上記の修正では、intlongに置き換えました。

最新のTrend Constraint EAのソースコードはこちらで提供していますが、前の記事でもご覧になれます。新機能を実装する前に、上記でおこなったようにコードのデバッグを練習しておいてください。

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


7つの有名戦略

外国為替市場での取引には、スキルと戦略の融合が必要です。長年にわたり、トレーダーが成功する可能性を最大化するのに役立つ様々なアプローチが登場してきました。ここでは、影響力のある経済学者やトレーダーによって開発された本質的な数学的原理と理論に基づいた、7つの効果的なFX取引戦略を簡単に掘り下げてみます。戦略が頭に入ってくれば、コーディングのスキルを実装し、戦略のアルゴリズムを作成することが容易になります。

(i)トレンドフォロー戦略

トレンドフォロー戦略は、19世紀後半(1896年)にダウ理論を提唱したチャールズ・ダウの原則に基づいています。ダウは、市場はトレンドの中で動いており、そのトレンドを見極めることで大きな取引機会を得ることができると考えていました。トレンドフォローの背後にある数学は、トレーダーが価格の変動を滑らかにするために単純移動平均(SMA)を使用し、多くの場合、移動平均を採用しています。

単純移動平均(SMA)の実際の計算式は以下の通りです。

SMA

ここで

  • Nは期間(またはデータポイント)の数
  • (P_i)は(i番目の)期間における価格(または価値)

この式は、N期間の平均価格を計算します。1980年代のリチャード・デニスと彼の「タートルズ」による実験のような裏付けとなる研究は、トレンドフォローが、特に強いトレンドの市場で、大きな利益をもたらすことを示しています。

(ii)レンジ取引

レンジ取引は、テクニカル分析に不可欠な支持レベルと抵抗レベルの概念に基づいています。これらのコンセプトは J. Welles Wilder(英語)の著書『New Concepts in Technical Trading Systems』(1978年)でよく文書されています。トレーダーは、買いの関心が下落を防ぎ、抵抗が価格上昇を妨げる価格レベルをサポートと認識します。これらのレベルを特定するための一般的な方法であるピボットポイントを計算するための数学的基礎は、次式で与えられます。

ピボットポイント(PP)の実際の計算式は以下の通りです。

ピボット

ここで

  • Highは前取引期間の最高値
  • Lowは前取引期間の最安値
  • Closeは前取引期間の終値

この計算式は、テクニカル分析で使用されるセントラルピボットポイントを計算し、次の取引期間の潜在的な支持線と抵抗線を決定します。ジョン・マーフィーによる『Technical Analysis of the Financial Markets』(1986年)のような研究では、支持線と抵抗線はしばしば、トレーダーが十分な情報に基づいた意思決定をおこなうのに役立つ心理的指標として機能することが強調されています。

(iii)ブレイクアウト取引

ブレイクアウト取引は、価格が確立された支持線または抵抗線を突破したときに大幅な値動きが発生するという信念を利用しています。Richard Donchian(英語)は、1950年代にこの戦略を導入し、彼のドンチアンチャネルの研究は、ボラティリティを使ってブレイクアウトポイントを特定することに重点を置いています。トレーダーは、指定された期間の最高値(HH)と最安値(LL)を使用してドンチアンチャネルを計算します。

(上限バンド=HH)

(下限バンド=LL)

ドンチャンチャンネル

ドンチャンチャンネル

行動ファイナンスの研究は、トレーダーはしばしば群れ行動によってブレイクアウトを追いかけ、ブレイクアウトの方向への勢いを強めるという考えを支持しています。Daniel Kahnemanとエイモス・トベルスキーが1979年に発表した論文「Prospect Theory:An Analysis of Decision under Risk」では、心理的要因がブレイクアウト時の取引行動にどのような影響を与えるかを明らかにしています。

(iv)キャリー取引

キャリー取引は、金利平価(IRP)の理論に基づき、2つの通貨間の金利差を活用します。この原則は、20世紀初頭に、特にPaul Samueltonなどの経済学者が『Foundations of Economic Analysis』(1947年)などの著作で定式化した経済理論に根ざしています。

キャリー取引の期待リターンを計算するための基本的な公式は次のようになります。

ER

ここで

  • i_highi_lowはそれぞれ、高利回り通貨と低利回り通貨の金利
  • Delta Sは為替レートの予想変化を表す 
 Kenneth Rogoffは1998年の論文で、金利平価からの乖離がいかに有益な取引機会を生み出すかを強調しています。

(v)スキャルピング

スキャルピングは、市場ミクロ構造理論(MMT)に裏打ちされた、小さな値動きを利用する高頻度取引戦略です。この理論は、Lawrence Harrisの『Market Making and the Financial Performance of Nasdaq Firms』(1998年)をはじめ、様々な研究者の研究によって発展してきました。スキャルパーは、短い時間枠の中で複数の取引を実行し、微細な価格変動から利益を得ようとします。

スキャルパーにとって重要な指標には、ビッドアスクスプレッドと注文フロー分析があり、多くの場合、次のようなさまざまな指標を通じて計算されます。

利益

ここで

  • Selling Priceは、資産の販売価格

  • Buying Priceは、その資産が最初に購入された価格

  • Transaction Costsは、売買プロセスに関連する手数料や費用(仲介手数料、税金など)

数回の不利な取引が大きな損失につながる可能性があるため、リスク管理は非常に重要になります。

(vi)ファンダメンタル分析

ファンダメンタル分析では、通貨評価に影響を与える経済指標や地政学的要因を調べます。ベンジャミン・グレアムDavid Doddが『Security Analysis』(1934年)で提唱したこのアプローチは、通貨の本質的価値を評価することの重要性を強調しています。トレーダーは、国内総生産(GDP)成長率や失業率など、さまざまな指標を活用して、情報に基づいた意思決定をおこないます。株式の株価収益率(P/E)のような数学的手法も適応できます。

P^E

ここで

  • Market Price per shareは、その会社の株式1株の現在の価格

  • Earnings per Share (EPS)は、発行済み普通株式1株当たりに配分される会社の利益

広範な調査により、特に市場の大幅な変動につながることが多い重要な経済レポートや中央銀行の発表の際には、ファンダメンタル分析の有効性が裏付けられています。


(vii)テクニカル指標の使用

テクニカル分析は、チャールズ・ダウらの考えに基づくもので、過去の値動きから将来の行動を洞察することができると仮定しています。相対力指数(RSI)のような様々なテクニカル指標は、市場のモメンタムを測定するために採用されます。RSIは式を使って計算されます。 

RSI

ここで

  • RSは一定期間の平均損益を表す

RS

Thomas Bulkowskiによる『Encyclopedia of Candlestick Charts』(2008年)のような裏付けとなる研究は、特定のパターンと指標が取引の精度を高め、トレーダーが過去の値動きに基づいて市場の動きを予測できることを示しています。これらの各戦略は、基礎的な理論、数学的原理、および外国為替市場におけるトレーダーの意思決定に役立つ広範な研究に支えられています。これらの戦略の複雑さを理解することは、トレーダーの複雑な外国為替取引をナビゲートする能力を大幅に向上させ、最終的には、より多くの情報に基づいた有益な取引結果につながります。これらの戦略を思慮深く採用することで、トレーダーは個々の好みやリスク許容度に合わせた強固な取引手法を開発することができます。


マジックナンバーの導入

MQL5のマジックナンバーは、EAが取引をマークするために使用するユニークなシグネチャのような、極めて重要な組織的ツールとして機能します。それぞれのEAが、取引を開始するたびにスタンプを押す、自分だけの識別子を持っていると考えてください。これは、EAが他の戦略からきれいに分離された運営を維持するのに役立つため、多数の戦略を同時に実行する口座で特に有用です。

マジックナンバーを入力パラメータとして定義することで、ソースコードに戻ることなくEAの設定を調整できる柔軟性が生まれます。EAがポジションをスキャンするとき、この数字を使用して、どの取引が自分のものかを素早く見つけます。

PositionGetInteger(POSITION_MAGIC)関数は、各取引に付けられたマジックナンバーを取得し、EAが次のステップ(ポジションを修正するか、監視するか、決済するか)を決定できるようにします。トレーダーや開発者にとっては、異なる戦略間の偶発的な干渉の心配が少なくなり、各取引をそのソース戦略まで遡ることができるため、デバッグが容易になります。このように、マジックナンバーを効果的に取り入れ、管理することで、金融市場における取引戦略の正確性と組織性を保つことができます。

以下は、組み込みを示すコードスニペットです。

input int MagicNumber = 12345678; // Define a unique magic number for the EA

// Within the OnTick() or relevant function
for (int i = 0; i < PositionsTotal(); i++) {
    if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i))) {
        long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

        if (currentMagicNumber == MagicNumber) { // Check if the position belongs to this EA
            // Perform actions on this position, like closing or modifying
        }
    }
}

// When opening a new trade
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = price - StopLoss * _Point;
double tp = price + TakeProfit * _Point;

if (trade.Buy(Lots, _Symbol, price, sl, tp, "TrendFollowing Buy")) {
    Print("Buy order placed with Magic Number: ", MagicNumber);
} else {
    Print("Error placing buy order: ", GetLastError());


トレンドフォロー戦略の実施

上記の選択した戦略のほとんどは、現時点では使用するために必要なデータが不足しているため、当社のプログラムに実装できません。たとえば、キャリートレードは金利差が関係するためこのコードだけでは実行できず、ファンダメンタル分析にはGDPや雇用率などの詳細な外部経済データフィードが必要です。将来のさらなる探求のために、最も実現可能な戦略に焦点を絞ります。

トレンドフォローは、トレンドの方向を確認するために移動平均線のようなテクニックを使用して、持続的な市場トレンドの方向を識別し、取引するアプローチです。ここでのEAコードでは、すでにRSIを使って買われすぎや売られすぎの状態を判断していますが、移動平均線を統合することで、判断プロセスをさらに洗練させることができます。ここでは、短期移動平均線(50期間)と長期移動平均線(200期間)を使ってトレンドの方向性を判断します。短期平均が長期平均を上回れば上昇トレンドのシグナル、逆に下回れば下降トレンドを示します。この手法の統合は、強気または弱気のトレンドの確認に役立ち、RSI条件と並行して取引エントリの精度を高めます。

 メインプログラムに統合する前の移動平均を計算するコードスニペットを以下に示します。

//Calculate moving averages
double ma_short = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma_long = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

//Determine the trend  direction
bool is_uptrend = ma_short > ma_long;
bool is_downtrend = ma_short < ma_long;

if (is_bullish && is_uptrend && rsi_value < RSI_Oversold)
{
   // Implement buy order logic here
}

if (is_bearish && is_downtrend && rsi_value > RSI_Overbought)
{
   // Implement sell order logic here
}

既存のEAにトレンドフォロー戦略を効果的に組み込むには、まずモジュール内の初期化と処理ロジックを強化することから始めます。OnInit()関数から始めて、iMA関数を使った2つの重要な指数移動平均(EMA)、典型的には短期トレンドのための50周期と長期トレンドのための200周期の計算を紹介します。

OnTick()メソッドに進むと、これらのEMAは新しい市場ティックごとに再計算され、EAが現在の市場トレンド方向を判断できるようになります。短期EMAが長期EMAより上に上昇するクロスオーバーは上昇トレンドを、下に下降するクロスオーバーは下降トレンドを示します。

これらのトレンドシグナルを既存のRSI分析と統合することで、RSIが売られ過ぎの上昇トレンドが確認されている間はアルゴリズムが買い注文を出し、RSIが買われ過ぎの下降トレンドの間はアルゴリズムが売り注文を出す条件を作り上げます。

約定にはCTradeクラスを使用し、ストップロス、テイクプロフィット、トレーリングストップのパラメーターを綿密に設定し、確実なリスク管理をおこないます。さらに、同じOnTick()ループ内で、特定されたトレンドが反転した場合に既存のポジションを潔くクローズするシステムが組み込まれているため、すべての取引が検証された市場の方向と一致します。これらの戦略的なアップデートを通じて、EAはトレンドフォロー戦略を採用するように巧みに調整され、現在の機能とシームレスに統合され、全体的な取引の有効性を高めています。

以下は、完全に統合されたプログラムです。

//+------------------------------------------------------------------+
//|                                      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 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
input int    MagicNumber = 12345678;     // Magic number for this EA

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

// Variables for moving averages
double ma_short;
double ma_long;

//+------------------------------------------------------------------+
//| 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()
  {
   // Calculate moving averages
   ma_short = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);
   ma_long  = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE);

   // Determine trend direction
   bool is_uptrend = ma_short > ma_long;
   bool is_downtrend = ma_short < ma_long;

   // 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 = 0; i < PositionsTotal(); i++) // Correct loop initialization
     {
      if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))  // Select position by symbol
        {
         long position_type = PositionGetInteger(POSITION_TYPE);
         long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);
         ulong ticket = PositionGetInteger(POSITION_TICKET);

         if (currentMagicNumber == MagicNumber) // Ensure only this EA's orders are checked
           {
            if ((position_type == POSITION_TYPE_BUY && is_downtrend) ||
                (position_type == POSITION_TYPE_SELL && is_uptrend))
              {
               trade.PositionClose(ticket);
              }
           }
        }
     }

   // Check for buy condition (uptrend + RSI oversold)
   if (is_uptrend && rsi_value < RSI_Oversold)
     {
      // No open positions? Place a buy order
      bool open_position = false;

      for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
        {
         if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))
           {
            long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

            if (currentMagicNumber == MagicNumber)
              {
               open_position = true;
               break;
              }
           }
        }

      if (!open_position)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double sl = price - StopLoss * _Point;
         double tp = price + TakeProfit * _Point;

         // Open a buy order
         if (trade.Buy(Lots, _Symbol, price, sl, tp, "TrendFollowing Buy"))
            Print("Buy order placed with Magic Number: ", MagicNumber);
         else
            Print("Error placing buy order: ", GetLastError());
        }
     }

   // Check for sell condition (downtrend + RSI overbought)
   if (is_downtrend && rsi_value > RSI_Overbought)
     {
      // No open positions? Place a sell order
      bool open_position = false;

      for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
        {
         if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))
           {
            long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

            if (currentMagicNumber == MagicNumber)
              {
               open_position = true;
               break;
              }
           }
        }

      if (!open_position)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double sl = price + StopLoss * _Point;
         double tp = price - TakeProfit * _Point;

         // Open a sell order
         if (trade.Sell(Lots, _Symbol, price, sl, tp, "TrendFollowing Sell"))
            Print("Sell order placed with Magic Number: ", MagicNumber);
         else
            Print("Error placing sell order: ", GetLastError());
        }
     }

   // Apply trailing stop
   for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
     {
      if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i))) // Select position by symbol
        {
         long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

         if (currentMagicNumber == MagicNumber) // Apply trailing stop only to this EA's positions
           {
            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));
                    }
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


テスト結果

B00M 500インデックスでEAをテストし、注文を観察しました。しかし、複数の注文が同時に発注されるのを防ぐには、まだやるべきことがたくさんあります。10,000ドルのデモ口座でのパフォーマンスはプラスの結果を示していますが、実際の口座や資金が少ない口座では同じ結果にはならないかもしれません。このシステムは利益を保証するものではなく、教育目的、実験、研究を目的としていることに注意することが重要です。

EA開始

EAをブーム500指数で開始

テスター

ブーム500指数テスター結果2019


結論

結論として、MQL5を使用したマルチ戦略EAの構築に関する議論は、既存のトップ戦略の起源を理解し、相対力指数(RSI)などの重要な要素とトレンドフォロー戦略を統合することに重点を置きました。トレンドフォローの構成要素は、市場のトレンド方向を決定するために移動平均を利用し、トレーダーは、多くの場合、より安定し、潜在的により収益性の高い長期的な動きに自分のポジションを合わせることができます。これらの移動平均を使用することにより、当社のシステムは上昇トレンドと下降トレンドを識別することができ、明確に定義された市場の方向性に基づいた情報に基づく取引判断を容易にします。

トレンドフォローの手法を戦略的に取り入れることで、買われすぎ、売られすぎの相場状況を見極めるのに不可欠なRSIの使用を補完しています。これらの要素を組み合わせることで、トレンドの勢いを捉え、本連載の基本概念である「Trend Constraint」に沿った、バランスの取れたアプローチが実現します。開発中におこなわれたもう1つの重要な機能強化は、マジックナンバーの統合です。マジックナンバーは、複数の戦略が存在する環境で正確な取引管理をおこなうために不可欠な機能であるが、当初はこの機能が欠けていました。マジックナンバーはユニークな識別子として機能し、戦略を分けて管理するのに役立ち、トレーダーはそれぞれの戦略を独立して追跡管理することができます。

検討した7つの戦略のうち、これまでに実装したのは1つだけであり、今後の検討には多くの潜在的な開発が残されています。添付のソースファイルをコンパイルしてテストし、そのパフォーマンスを評価し、ご自分自身のプロジェクトに実装するためのアイデアを集めてください。取引をお楽しみください。

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

添付されたファイル |
化学反応最適化(CRO)アルゴリズム(第1回):最適化におけるプロセス化学 化学反応最適化(CRO)アルゴリズム(第1回):最適化におけるプロセス化学
この記事の最初の部分では、化学反応の世界に飛び込み、最適化への新しいアプローチを発見します。化学反応最適化(CRO)は、熱力学の法則から導き出された原理を使用して効率的な結果をもたらします。この革新的な方法の基礎となった分解、合成、その他の化学プロセスの秘密を明らかにします。
ニューラルネットワークが簡単に(第93回):周波数領域と時間領域における適応予測(最終回) ニューラルネットワークが簡単に(第93回):周波数領域と時間領域における適応予測(最終回)
本稿では、時系列予測において2つのブロック(周波数と時間)の結果を適応的に組み合わせるATFNetモデルのアプローチの実装を継続します。
データサイエンスとML(第30回):株式市場を予測するパワーカップル、畳み込みニューラルネットワーク(CNN)と再帰型ニューラルネットワーク(RNN) データサイエンスとML(第30回):株式市場を予測するパワーカップル、畳み込みニューラルネットワーク(CNN)と再帰型ニューラルネットワーク(RNN)
本稿では、株式市場予測における畳み込みニューラルネットワーク(CNN)と再帰型ニューラルネットワーク(RNN)の動的統合を探求します。CNNのパターン抽出能力と、RNNの逐次データ処理能力を活用します。この強力な組み合わせが、取引アルゴリズムの精度と効率をどのように高めることができるかを見てみましょう。
初心者からエキスパートへ:MQL5での共同デバッグ 初心者からエキスパートへ:MQL5での共同デバッグ
問題解決は、MQL5でのプログラミングのような複雑なスキルを習得するための簡潔なルーチンを確立することができます。このアプローチでは、問題解決に集中しながら、同時にスキルアップを図ることができます。問題に取り組めば取り組むほど、高度な専門知識が脳に伝達されます。個人的には、デバッグはプログラミングをマスターするための最も効果的な方法だと思っています。今日は、コードクリーニングのプロセスを紹介し、乱雑なプログラムをクリーンで機能的なものに変えるための最善のテクニックについて解説します。この記事を読んで、貴重な洞察を発見してください。