English
preview
ダイナミックマルチペアEAの形成(第5回):スキャルピングとスイングトレードの切替設計

ダイナミックマルチペアEAの形成(第5回):スキャルピングとスイングトレードの切替設計

MetaTrader 5 |
37 9
Hlomohang John Borotho
Hlomohang John Borotho

目次

  1. はじめに
  2. システムの概要
  3. 導入手順
  4. バックテスト結果
  5. 結論


はじめに

市場状況に応じて最適な取引手法を選択することは非常に難しいです。相場が急速に動く場合、スイング戦略は遅すぎると感じられ、変動の激しい時間帯ではスキャルピングの小さなターゲットがすぐにストップアウトしてしまうことがあります。このジレンマにより、トレーダーは短期的に高確率なチャンスを逃すか、または不適切な相場で過剰取引してしまい、利益が不安定になることがあります。さらに、ある資産や時間足で有効なシステムが、他の資産や時間足では機能しない場合もあります。

この課題は、スキャルピングとスイングトレードの両モードを統合したダイナミックマルチペアエキスパートアドバイザー(EA)を開発することで解決できます。トレーダーが市場のボラティリティや構造に応じてモードを手動または自動で切り替えられるようにすることで、EAはエントリーロジック、ストップレベル、取引時間足を動的に調整できるようになります。これにより、短期的な即時利益と長期的な高品質のスイングトレードとのバランスを保ちながら、さまざまな市場条件で安定的に利益を狙うことが可能です。


システムの概要

スキャルピングは、短時間(数秒〜数分)で非常に小さな価格変動を狙う取引手法です。このスタイルでは、トレーダーは1日を通して複数のポジションを開閉し、市場のマイクロフラクチュエーションから利益を狙います。大きな方向性の値動きではなく、小さな値動きを効率的に取るため、精度、高速な注文処理、そして厳格なルール遵守が求められます。スプレッドやスリッページ、手数料が利益に大きく影響するため、注意が必要です。スキャルパーは主に1分足や5分足などの短期足チャートを使用し、移動平均線、ボリュームスパイク、モメンタムオシレーターなどのテクニカル指標を駆使して、エントリーとエグジットのタイミングを高精度で判断します。

一方、スイングトレードは、数時間から数日、場合によっては数週間単位での比較的大きな価格変動を狙う手法です。市場のトレンドや押し目と戻り売り、サポートとレジスタンスの重要レベルに反応して生じる自然な値動き(スイング)を捉えることを重視します。スイングトレーダーは、テクニカル分析、市場構造や、場合によってはファンダメンタルズ分析も組み合わせて高確率のエントリーポイントと有利なリスクリワード設定を判断します。この手法は取引回数が少なく、画面に張り付く必要も低いため、戦略的かつ分析的に市場を観察するトレーダーに適しています。

項目 スキャルピング スイングトレード 
取引期間数秒から数分数時間から数日(場合によっては数週間)
取引頻度1日あたり数十回から数百回週1~10回(平均)
目標小さく頻繁な値動きを狙う(50〜100pips、貴金属で$0.50〜1)大きな市場スイングを捉える(数百pips)
時間的コミット高い、画面に張り付く必要がある中程度、分析中心
市場環境高ボラティリティ・高流動性市場で有効(例:XAUUSDや主要FXペア)トレンド相場やレンジ拡張相場で有効
損切り/利確タイトなSL(50〜150pips)/小さなTP(40〜100pips)広めのSL(200pips以上)/大きなTP(1000pips以上)
ポジションサイズ通常は大きめ(ターゲットが小さいため)通常は小さめ(ターゲットが広いため)


導入手順

//+------------------------------------------------------------------+
//|                                            Scalps and Swings.mq5 |
//|                        GIT under Copyright 2025, MetaQuotes Ltd. |
//|                     https://www.mql5.com/ja/users/johnhlomohang/ |
//+------------------------------------------------------------------+
#property copyright "GIT under Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/ja/users/johnhlomohang/"
#property version   "1.00"
#property description "Dual-mode EA for Scalping and Swing Trading"
#include <Trade/Trade.mqh>

いつも通り、まずはエキスパートアドバイザー(EA)が注文を実行しポジションを管理するために必要な取引ライブラリをインポートします。

//+------------------------------------------------------------------+
//| Input Parameters                                                 |
//+------------------------------------------------------------------+
enum ENUM_MODE
{
   MODE_SCALP,  // Scalping
   MODE_SWING   // Swing Trading
};

input ENUM_MODE          TradeMode = MODE_SCALP;          // Trading Mode
input string             TradePairs = "XAUUSD,BTCUSD,US100,GBPUSD"; // Trading Pairs (comma separated)
input bool               UseATR = false;                  // Use ATR for SL/TP

// Scalping Parameters
input double             LotSize_Scalp = 0.1;             // Scalp Lot Size
input int                StopLoss_Scalp = 50;             // Scalp Stop Loss (pips)
input int                TakeProfit_Scalp = 30;           // Scalp Take Profit (pips)
input int                ScalpTrailingStop = 15;          // Scalp Trailing Stop (pips)
input ENUM_TIMEFRAMES    ScalpTimeframe = PERIOD_M5;      // Scalping Timeframe
input int                Scalp_EMA_Fast = 5;              // Scalp Fast EMA
input int                Scalp_EMA_Slow = 20;             // Scalp Slow EMA
input int                Scalp_RSI_Period = 14;           // Scalp RSI Period
input int                Scalp_RSI_Overbought = 55;       // Scalp RSI Overbought
input int                Scalp_RSI_Oversold = 45;         // Scalp RSI Oversold

// Swing Trading Parameters
input double             LotSize_Swing = 0.1;             // Swing Lot Size
input int                StopLoss_Swing = 200;            // Swing Stop Loss (pips)
input int                TakeProfit_Swing = 400;          // Swing Take Profit (pips)
input int                SwingTrailingStop = 100;         // Swing Trailing Stop (pips)
input ENUM_TIMEFRAMES    SwingTimeframe = PERIOD_H4;      // Swing Timeframe
input int                Swing_Lookback = 20;             // Swing Lookback Period
input double             Fib_Level = 0.618;               // Fibonacci Retracement Level
input bool               UseHigherTFConfirmation = true;  // Use D1 Confirmation
input ENUM_TIMEFRAMES    HigherTF = PERIOD_D1;            // Higher Timeframe

// Risk Management
input int                MaxOpenPositions = 4;            // Max Open Positions per Pair
input int                MagicNumber = 12345;             // Magic Number
input int                Slippage = 3;                    // Slippage (points)

まず、スキャルピングとスイングトレードの両方をサポートするマルチモード取引システムの入力パラメータを定義します。最初のセクションではENUM_MODEという列挙型を紹介しており、ユーザーはMODE_SCALPとMODE_SWINGのどちらかを選択できます。この入力により、EAの挙動(短期のデイトレードか、長期のスイングトレードか)を制御します。さらに、TradePairs入力により複数の銘柄(例:XAUUSD、BTCUSD、US100、GBPUSD)を柔軟に指定でき、UseATRオプションを有効にすると、固定のpips値ではなくボラティリティに応じた可変型のストップロス/テイクプロフィットを設定することが可能です。

スキャルピング用のパラメータは、高速・高頻度環境でのEAの挙動を定義します。ここでは、ストップロスおよびテイクプロフィットの距離を小さく設定し、短い時間足(例:M5)を使用します。また、5期間と20期間のEMAに加えて14期間のRSIを組み合わせた反応速度の高い指標を用います。RSIの閾値は55と45に設定されており、微妙なモメンタムの変化を検出できるようにしています。トレーリングストップの値も小さく設定し、日中のボラティリティに柔軟に対応します。これらの設定により、短期間の価格変動を効率的に捉えつつ、長時間の市場ノイズにさらされるリスクを抑えた迅速な取引サイクルを実現します。

一方、スイングトレード用のパラメータはより大きな市場の動きに対応するよう調整されています。EAは、より長期の時間足ボラティリティとトレンド継続を考慮して、ストップロスおよびテイクプロフィットの距離を広めに設定します。直近20本のバーを対象とするルックバック期間やフィボナッチリトレースメント(0.618)を用いて、潜在的な反転のための重要な修正ゾーンを特定します。さらに、上位時間足(通常はD1)での確認をおこなうことで、逆トレンドの取引を避けるためのトレンド検証を追加します。最後に、MaxOpenPositions、MagicNumber、Slippageといったリスク管理入力により、取引数量、識別、注文精度を厳密に制御でき、EAがすべての通貨ペアや市場状況で一貫性と安全性を保つように設計されています。

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
string   SymbolList[];
int      TotalPairs;
datetime LastTickTime = 0;
color    TextColor = clrWhite;
CTrade   trade;

int handleEmaFast_Scalp, handleEmaSlow_Scalp, handleRsi_Scalp;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Initialize trade object
    trade.SetExpertMagicNumber(MagicNumber);
    trade.SetDeviationInPoints(Slippage);

    // Split trading pairs
    SplitString(TradePairs, ",", SymbolList);
    TotalPairs = ArraySize(SymbolList);

    // Validate symbols
    for(int i = 0; i < TotalPairs; i++)
    {
        if(!SymbolInfoInteger(SymbolList[i], SYMBOL_TRADE_MODE))
        {
            Print("Error: Symbol ", SymbolList[i], " is not available for trading");
            return(INIT_FAILED);
        }
    }

    // Create indicator handles for scalping mode
    handleEmaFast_Scalp = iMA(NULL, ScalpTimeframe, Scalp_EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
    if(handleEmaFast_Scalp == INVALID_HANDLE)
    {
        Print("Failed to create handle for fast EMA (Scalp)");
        return(INIT_FAILED);
    }
    handleEmaSlow_Scalp = iMA(NULL, ScalpTimeframe, Scalp_EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
    if(handleEmaSlow_Scalp == INVALID_HANDLE)
    {
        Print("Failed to create handle for slow EMA (Scalp)");
        return(INIT_FAILED);
    }
    handleRsi_Scalp = iRSI(NULL, ScalpTimeframe, Scalp_RSI_Period, PRICE_CLOSE);
    if(handleRsi_Scalp == INVALID_HANDLE)
    {
        Print("Failed to create handle for RSI (Scalp)");
        return(INIT_FAILED);
    }

    Print("EA initialized successfully with ", TotalPairs, " pairs");
    Print("Trading Mode: ", EnumToString(TradeMode));

    return(INIT_SUCCEEDED);
}

次に、EAのグローバル変数と初期化ルーチンを定義します。グローバル変数では、取引銘柄のリスト、ペアの総数、取引実行を扱うCTradeクラスのインスタンスといった主要コンポーネントを宣言します。さらに、スキャルピングモード用のインジケーターハンドル(高速EMA、低速EMA、RSI)も用意されており、後にシグナル生成のためにリアルタイムデータを取得する際に使用されます。LastTickTime変数はティック処理の効率化を目的とし、TextColorはチャート上のテキスト要素(可視化やログ表示用)のデフォルト色を定義します。

OnInit()関数では、EAが取引環境をセットアップします。まず、一意のマジックナンバーとスリッページ許容値をCTradeオブジェクトに割り当て、注文管理の一貫性を確保します。入力文字列TradePairsはカスタム関数SplitString()を用いて配列に分割され、EAがどの銘柄で稼働するかを決定します。各銘柄は取引可能かどうか検証され、有効でない場合は処理を進めません。その後、スキャルピングモード用の高速EMA、低速EMA、RSIの指標ハンドルを作成します。各ハンドルの有効性もチェックされ、無効なインジケーターハンドルでEAが起動することを防ぎます。すべての検証が完了すると、初期化成功メッセージが表示されます。このメッセージには、アクティブなペアの数と選択された取引モードが示され、EAが実行準備完了であることを確認できます。

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Comment(""); // Clear chart comment
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Avoid multiple processing in the same tick
   if(LastTickTime == iTime(_Symbol, _Period, 0)) return;
   LastTickTime = iTime(_Symbol, _Period, 0);
   
   // Process each trading pair
   for(int i = 0; i < TotalPairs; i++)
   {
      string symbol = SymbolList[i];
      
      if(TradeMode == MODE_SCALP)
      {
         ScalpModeHandler(symbol);
         
         if(IsNewBar(symbol, ScalpTimeframe))
         {
            ExecuteScalpTrade(symbol);
         }
         
         ManageScalpTrades(symbol);
      }
      else if(TradeMode == MODE_SWING)
      {
         if(SwingSignal(symbol))
         {
            if(IsNewBar(symbol, SwingTimeframe))
            {
               ExecuteSwingTrade(symbol);
            }
         }
         ManageSwingTrades(symbol);
      }
   }
   
   // Update dashboard
   UpdateDashboard();
}

//+------------------------------------------------------------------+
//| Check if new bar formed                                          |
//+------------------------------------------------------------------+
bool IsNewBar(string symbol, ENUM_TIMEFRAMES timeframe)
{
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(symbol, timeframe, 0);
   
   if(currentBarTime != lastBarTime)
   {
      lastBarTime = currentBarTime;
      return true;
   }
   return false;
}

ご存知の通り、OnTick()関数はEAのコア実行ループとして機能し、新しいティックが到着するたびに呼び出されます。まず、現在のティックの時刻が前回処理されたティックと同じかどうかを確認し、同じティック内での冗長な処理を防ぎます。その後、EAはSymbolListに定義されたすべての取引ペアを順番に処理し、選択されたTradeModeに応じてスキャルピングまたはスイングトレードのロジックを動的に扱います。スキャルピングモードでは、ScalpModeHandler()を呼び出してシグナルを評価し、新しいバーで取引を実行し、既存のスキャルプポジションを管理します。スイングモードでは、有効なスイングシグナルを検出し、適切に取引を配置し、ManageSwingTrades()を通じて進行中のポジションを更新します。最後に、関数は画面上のダッシュボードを更新し、リアルタイムで取引状況やパフォーマンスを表示します。これにより、EAはすべてのアクティブなペアにおいて効率的かつ適応的に動作できるようになります。

//+------------------------------------------------------------------+
//| Scalping Signal Function                                         |
//+------------------------------------------------------------------+
void ScalpModeHandler(string symbol)
{
    // Define arrays to hold indicator values
    double emaFastArr[2], emaSlowArr[2], rsiArr[2];

    // Copy values: current and previous
    if(CopyBuffer(handleEmaFast_Scalp, 0, 0, 2, emaFastArr) < 2) return;
    if(CopyBuffer(handleEmaSlow_Scalp, 0, 0, 2, emaSlowArr) < 2) return;
    if(CopyBuffer(handleRsi_Scalp,     0, 0, 2, rsiArr)     < 2) return;

    // Assign named values
    double emaFastCurr = emaFastArr[0];
    double emaFastPrev = emaFastArr[1];
    double emaSlowCurr = emaSlowArr[0];
    double emaSlowPrev = emaSlowArr[1];
    double rsiCurr     = rsiArr[0];

    // Validate (avoid zero or invalid)
    if(emaFastCurr == 0 || emaSlowCurr == 0 || rsiCurr == 0) return;

    // Check open positions for this symbol
    if(CountOpenPositions(symbol) >= MaxOpenPositions) return;

    // BUY signal condition
    if(emaFastCurr > emaSlowCurr && emaFastPrev <= emaSlowPrev && rsiCurr > Scalp_RSI_Overbought)
    {
        ExecuteAdaptiveTrade(ORDER_TYPE_BUY, symbol, LotSize_Scalp);
        Print("Scalp BUY Signal executed for ", symbol);
    }
    // SELL signal condition
    else if(emaFastCurr < emaSlowCurr && emaFastPrev >= emaSlowPrev && rsiCurr < Scalp_RSI_Oversold)
    {
        ExecuteAdaptiveTrade(ORDER_TYPE_SELL, symbol, LotSize_Scalp);
        Print("Scalp SELL Signal executed for ", symbol);
    }
}

//+------------------------------------------------------------------+
//| Swing Trading Signal Function                                    |
//+------------------------------------------------------------------+
bool SwingSignal(string symbol)
{
   int swingHighBar = iHighest(symbol, SwingTimeframe, MODE_HIGH, Swing_Lookback, 1);
   int swingLowBar  = iLowest(symbol, SwingTimeframe, MODE_LOW, Swing_Lookback, 1);
   if(swingHighBar == -1 || swingLowBar == -1) return false;

   double swingHigh     = iHigh(symbol, SwingTimeframe, swingHighBar);
   double swingLow      = iLow(symbol, SwingTimeframe, swingLowBar);
   double currentClose  = iClose(symbol, SwingTimeframe, 0);
   double range         = swingHigh - swingLow;
   if(range == 0) return false;

   double fib618_Up     = swingHigh - Fib_Level * range;
   double fib618_Down   = swingLow + Fib_Level * range;

   bool higherTFBullish = true;
   bool higherTFBearish = true;

   if(UseHigherTFConfirmation)
   {
      int handleEMA = iMA(symbol, HigherTF, 20, 0, MODE_EMA, PRICE_CLOSE);
      if(handleEMA == INVALID_HANDLE) return false;

      double emaVal[1];
      if(CopyBuffer(handleEMA, 0, 0, 1, emaVal) < 1) return false;

      double htEMA20 = emaVal[0];
      double htClose = iClose(symbol, HigherTF, 0);
      higherTFBullish = htClose > htEMA20;
      higherTFBearish = htClose < htEMA20;
   }

   // --- Buy Signal
   if(currentClose <= fib618_Down && currentClose > swingLow && higherTFBullish)
      return true;

   // --- Sell Signal
   if(currentClose >= fib618_Up && currentClose < swingHigh && higherTFBearish)
      return true;

   return false;
}

ScalpModeHandler()関数は、スキャルピングモードにおける短期売買シグナルの生成と実行を担当します。事前に初期化されたインジケーターハンドルからCopyBuffer()を用いて、高速EMA、低速EMA、RSIの最新値と前回値を取得します。これらの値を使用して、クロスオーバーやモメンタムの状態を検出し、スキャルプトレードのシグナルを生成します。具体的には、買いシグナルは、高速EMAが低速EMAを上抜けし、RSIが買われすぎ閾値を超えた場合に発生し、上昇モメンタムを示唆します。逆に、売りシグナルは、高速EMAが低速EMAを下抜けし、RSIが売られすぎ閾値を下回った場合に発生し、下降モメンタムを示唆します。取引を実行する前に、関数は指標データの有効性を確認し、対象銘柄の最大ポジション数を超えていないことをチェックします。これにより、効率的で適切に管理された取引運用が可能になります。

SwingSignal()関数は、上位時間足で市場の大きな反転やトレンド継続を特定します。指定されたルックバック期間内の最新のスイングハイとスイングローを取得し、取引レンジを算出します。さらに、フィボナッチリトレースメントレベルを計算して、価格の反応が起こりやすいゾーンを特定します。この情報を用いて、現在の市場価格が反転の可能性を示す主要なリトレースメントレベルに一致するかを確認します。上位時間足確認が有効になっている場合、追加のEMAフィルタにより、上位時間足のトレンドに沿った取引のみが実行されます。関数は、有効な買いまたは売りセットアップが検出された場合はtrue、そうでなければfalseを返します。このように、短期(スキャルピング)と長期(スイング)のロジックを分離することで、EAは市場状況に応じて戦略を動的に適応させることが可能になります。

//+------------------------------------------------------------------+
//| Execute Scalp Trade                                              |
//+------------------------------------------------------------------+
void ExecuteScalpTrade(string symbol)
{
   if(CountOpenPositions(symbol) >= MaxOpenPositions) return;

   int handleEmaFast = iMA(symbol, ScalpTimeframe, Scalp_EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
   int handleEmaSlow = iMA(symbol, ScalpTimeframe, Scalp_EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
   int handleRSI     = iRSI(symbol, ScalpTimeframe, Scalp_RSI_Period, PRICE_CLOSE);

   double emaFast[1], emaSlow[1], rsi[1];
   if(CopyBuffer(handleEmaFast, 0, 0, 1, emaFast) < 1) return;
   if(CopyBuffer(handleEmaSlow, 0, 0, 1, emaSlow) < 1) return;
   if(CopyBuffer(handleRSI, 0, 0, 1, rsi) < 1) return;

   double emaF = emaFast[0];
   double emaS = emaSlow[0];
   double rsiV = rsi[0];

   if(emaF > emaS && rsiV > Scalp_RSI_Overbought)
      ExecuteTrade(ORDER_TYPE_BUY, symbol, LotSize_Scalp, StopLoss_Scalp, TakeProfit_Scalp);
   else if(emaF < emaS && rsiV < Scalp_RSI_Oversold)
      ExecuteTrade(ORDER_TYPE_SELL, symbol, LotSize_Scalp, StopLoss_Scalp, TakeProfit_Scalp);
}

//+------------------------------------------------------------------+
//| Execute Swing Trade                                              |
//+------------------------------------------------------------------+
void ExecuteSwingTrade(string symbol)
{
   if(CountOpenPositions(symbol) >= MaxOpenPositions) return;
   
   // Determine trade direction (simplified logic)
   int swingHighBar = iHighest(symbol, SwingTimeframe, MODE_HIGH, Swing_Lookback, 1);
   int swingLowBar = iLowest(symbol, SwingTimeframe, MODE_LOW, Swing_Lookback, 1);
   
   if(swingHighBar != -1 && swingLowBar != -1)
   {
      double swingHigh = iHigh(symbol, SwingTimeframe, swingHighBar);
      double swingLow = iLow(symbol, SwingTimeframe, swingLowBar);
      double currentClose = iClose(symbol, SwingTimeframe, 0);
      double range = swingHigh - swingLow;
      double fib618_Down = swingLow + Fib_Level * range;
      double fib618_Up = swingHigh - Fib_Level * range;
      
      if(currentClose <= fib618_Down && currentClose > swingLow)
      {
         ExecuteTrade(ORDER_TYPE_BUY, symbol, LotSize_Swing, StopLoss_Swing, TakeProfit_Swing);
      }
      else if(currentClose >= fib618_Up && currentClose < swingHigh)
      {
         ExecuteTrade(ORDER_TYPE_SELL, symbol, LotSize_Swing, StopLoss_Swing, TakeProfit_Swing);
      }
   }
}

//+------------------------------------------------------------------+
//| Execute trade with dynamic stop/TP adaption per symbol           |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE tradeType, string symbol, double lotSize, int stopLossPips, int takeProfitPips)
{
   //--- Symbol info
   double point  = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int digits    = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);

   double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
   double price = (tradeType == ORDER_TYPE_BUY) ? ask : bid;

   //--- Detect pip size automatically (handles forex, gold, crypto, indices)
   double pipSize;
   if(StringFind(symbol, "JPY") != -1)              // JPY pairs (2/3 digits)
      pipSize = (digits == 3) ? point * 10 : point;
   else if(StringFind(symbol, "XAU") != -1 || StringFind(symbol, "GOLD") != -1)  // Metals
      pipSize = 0.10;
   else if(StringFind(symbol, "BTC") != -1 || StringFind(symbol, "ETH") != -1)   // Cryptos
      pipSize = point * 100.0;
   else if(StringFind(symbol, "US") != -1 && digits <= 2)                         // Indices
      pipSize = point;
   else
      pipSize = (digits == 3 || digits == 5) ? point * 10 : point;                // Default Forex

   //--- Convert SL/TP from pips to price distances
   double sl_distance = stopLossPips * pipSize;
   double tp_distance = takeProfitPips * pipSize;

   //--- Determine broker minimum stop levels
   double minStopPoints = 0.0;
   if(SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) > 0)
      minStopPoints = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   else if(SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) > 0)
      minStopPoints = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   else
      minStopPoints = 30; // fallback default (points)

   double minStop = minStopPoints * point;

   //--- Ensure SL/TP distances are greater than min stop level
   if(sl_distance < minStop) sl_distance = minStop;
   if(tp_distance < minStop) tp_distance = minStop;

   //--- Calculate final SL/TP prices
   double sl = (tradeType == ORDER_TYPE_BUY) ? price - sl_distance : price + sl_distance;
   double tp = (tradeType == ORDER_TYPE_BUY) ? price + tp_distance : price - tp_distance;

   //--- Normalize prices
   sl = NormalizeDouble(sl, digits);
   tp = NormalizeDouble(tp, digits);
   price = NormalizeDouble(price, digits);

   //--- Safety validation (correct SL/TP relation)
   if((tradeType == ORDER_TYPE_BUY && (sl >= price || tp <= price)) ||
      (tradeType == ORDER_TYPE_SELL && (sl <= price || tp >= price)))
   {
      Print("Invalid SL/TP detected for ", symbol, " — auto-adjusting...");
      if(tradeType == ORDER_TYPE_BUY)
      {
         sl = NormalizeDouble(price - minStop, digits);
         tp = NormalizeDouble(price + minStop * 2, digits);
      }
      else
      {
         sl = NormalizeDouble(price + minStop, digits);
         tp = NormalizeDouble(price - minStop * 2, digits);
      }
   }

   //--- Try executing trade
   if(trade.PositionOpen(symbol, tradeType, lotSize, price, sl, tp, "Adaptive Multi-Pair EA"))
   {
      PrintFormat("%s opened on %s | Lot: %.2f | SL: %.5f | TP: %.5f | TickValue: %.2f",
                  EnumToString(tradeType), symbol, lotSize, sl, tp, tickValue);
   }
   else
   {
      int err = GetLastError();
      PrintFormat("Failed to open %s on %s | Error %d: %s",
                  EnumToString(tradeType), symbol, err, err);
      ResetLastError();      
   }
}
ExecuteScalpTrade()関数とExecuteSwingTrade()関数は、2つの異なる実行ロジックを定義しています。1つは短期の精密エントリー用、もう1つは高時間足スイング用のセットアップ用です。スキャルピングのロジックは、高いモメンタム環境での迅速なエントリーに焦点を当てています。高速EMAと低速EMA、RSIの閾値を用いて短期的なトレンドを検出し、高速EMAが低速EMAをクロスし、RSIが買われすぎ・売られすぎ条件に到達した瞬間に即座にトレードを実行します。これにより、ボラティリティの高い値動きに迅速に対応できます。一方、スイングトレードの関数は、より大きな市場構造を特定します。直近のスイングハイとスイングローを分析し、フィボナッチリトレースメントレベルを計算して、リトレースメントに基づく最適なエントリーゾーンを特定します。これにより、EAは中期的な反転やトレンド継続を広範なトレンド内で捉えることが可能です。

ExecuteTrade()関数は、EAのコア実行エンジンとして機能し、各市場銘柄に応じてピップサイズを計算し、ブローカーの制約を確認し、価格を正規化して安全に取引を配置できるようにします。ストップロス(SL)やテイクプロフィット(TP)のレベルも、銘柄の特性(FX、ゴールド、暗号資産、株価指数など)に応じて動的に調整され、各取引がブローカーの最小ストップレベルを尊重しつつ論理的なSL/TP距離を維持できるようになっています。これらの機能により、ExecuteScalpTrade()、ExecuteSwingTrade()、ExecuteTrade()の3つの関数が一体となり、高速および低速の市場環境の両方に適応可能な堅牢な実行システムを形成し、複数の資産クラスにおいて精度、安全性、一貫性の高い取引を実現します。
//+------------------------------------------------------------------+
//| Execute trade with adaptive SL/TP by symbol type                 |
//+------------------------------------------------------------------+
void ExecuteAdaptiveTrade(ENUM_ORDER_TYPE type, string symbol, double lotSize)
{
   double point  = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int digits    = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   double ask    = SymbolInfoDouble(symbol, SYMBOL_ASK);
   double bid    = SymbolInfoDouble(symbol, SYMBOL_BID);
   double price  = (type == ORDER_TYPE_BUY) ? ask : bid;

   //--- Determine adaptive pip scale per asset
   double pipScale;
   if(StringFind(symbol, "XAU") != -1 || StringFind(symbol, "GOLD") != -1)
      pipScale = 1.0;          // Gold → 1 dollar movement = 1 pip
   else if(StringFind(symbol, "BTC") != -1)
      pipScale = 50.0;         // Crypto → 50-point unit for volatility
   else if(StringFind(symbol, "US") != -1 && digits <= 2)
      pipScale = 10.0;         // Indices (US100, US30)
   else if(StringFind(symbol, "JPY") != -1)
      pipScale = 0.1;          // Yen pairs
   else
      pipScale = 0.0001;       // Standard Forex

   ENUM_TIMEFRAMES tf = ScalpTimeframe;

   //--- Calculate SL/TP dynamically
   double atr = iATR(symbol, tf, 14);
   if(atr <= 0) atr = pipScale * 30;  // Fallback default

   double slDistance = atr * 1.5;     // SL = 1.5x ATR
   double tpDistance = atr * 3.0;     // TP = 3x ATR

   //--- Validate broker min stop distance
   double minStop = 0;
   if(SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) > 0)
      minStop = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;
   else if(SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) > 0)
      minStop = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;
   else
      minStop = atr * 0.5;

   if(slDistance < minStop) slDistance = minStop;
   if(tpDistance < minStop) tpDistance = minStop * 2;

   //--- Final price calculation
   double sl = (type == ORDER_TYPE_BUY) ? price - slDistance : price + slDistance;
   double tp = (type == ORDER_TYPE_BUY) ? price + tpDistance : price - tpDistance;

   sl = NormalizeDouble(sl, digits);
   tp = NormalizeDouble(tp, digits);

   //--- Trade execution
   if(trade.PositionOpen(symbol, type, lotSize, price, sl, tp, "Scalp-Mode"))
   {
      PrintFormat("%s %s | Lot: %.2f | SL: %.5f | TP: %.5f | ATR: %.5f",
                  EnumToString(type), symbol, lotSize, sl, tp, atr);
   }
   else
   {
      int err = GetLastError();
      PrintFormat("Trade failed on %s | Error %d: %s",
                  symbol, err, GetLastError());
      ResetLastError();
   }
}

//+------------------------------------------------------------------+
//| Dashboard Functions                                              |
//+------------------------------------------------------------------+
void UpdateDashboard()
{
   string dashboardText = "";
   string newLine = "\n";
   
   dashboardText += "=== MULTI-PAIR TRADING EA ===" + newLine;
   dashboardText += "Trading Mode: " + EnumToString(TradeMode) + newLine;
   dashboardText += "Active Pairs: " + IntegerToString(TotalPairs) + newLine;
   dashboardText += "Account Balance: " + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + newLine;
   dashboardText += "=================================" + newLine;
   
   // Show status for each pair
   for(int i = 0; i < TotalPairs; i++)
   {
      string symbol = SymbolList[i];
      int positions = CountOpenPositions(symbol);
      
      dashboardText += symbol + ":" + newLine;
      dashboardText += "  Positions: " + IntegerToString(positions) + newLine;
      
      // Add signal status with detailed info
      if(TradeMode == MODE_SCALP)
      {
         //bool signal = ScalpModeHandler(symbol);
         double emaFast = iMA(symbol, ScalpTimeframe, Scalp_EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
         double emaSlow = iMA(symbol, ScalpTimeframe, Scalp_EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
         double rsi = iRSI(symbol, ScalpTimeframe, Scalp_RSI_Period, PRICE_CLOSE);
         
         //dashboardText += "  Scalp Signal: " + (signal ? "ACTIVE" : "INACTIVE") + newLine;
         dashboardText += "  EMA Fast: " + DoubleToString(emaFast, 5) + newLine;
         dashboardText += "  EMA Slow: " + DoubleToString(emaSlow, 5) + newLine;
         dashboardText += "  RSI: " + DoubleToString(rsi, 1) + newLine;
      }
      else
      {
         bool signal = SwingSignal(symbol);
         dashboardText += "  Swing Signal: " + (signal ? "ACTIVE" : "INACTIVE") + newLine;
      }
      dashboardText += newLine;
   }
   
   Comment(dashboardText);
}
//+------------------------------------------------------------------+

ExecuteAdaptiveTrade()関数は、各資産の独自のボラティリティプロファイルに基づいてストップロス(SL)およびテイクプロフィット(TP)の距離を動的に調整するインテリジェントな取引実行メカニズムを導入します。対象銘柄がゴールド、暗号資産、株価指数、JPYペア、または標準FXであるかを判別し、それぞれに適したピップスケールを適用したうえで、ATR (Average True Range)インジケーターを用いて適応型SL/TPレベルを計算します。これにより、ボラティリティの高い市場でトレードがタイトになりすぎたり、安定した市場で広すぎたりすることを防ぎ、リスクとリワードのバランスをリアルタイムで最適化します。関数にはブローカーの最小ストップ距離の保護や自動補正メカニズムも組み込まれており、マルチ資産環境においても正確かつボラティリティに対応した取引配置が可能です。

UpdateDashboard()関数は、適応型トレードロジックを補完し、リアルタイムでのパフォーマンスの透明性を提供します。各取引ペアのアクティブポジション、主要なテクニカル指標(EMA値、RSI、またはスイングシグナル)、およびEAの全体的な動作モードを表示し、トレーダーがチャート上から直接意思決定の流れやシステムの状態を視覚的に監視できるようにします。これらのコンポーネントにより、ボラティリティに応じた適応型実行とライブダッシュボードによる監視がシームレスに連携し、トレーダーは複数ペアを自信を持って効率的に管理し、さまざまな市場状況下でのシステム挙動を明確に理解しながら運用できる環境が整います。


バックテスト結果

スキャルピングパラメータ
入力変数パラメータ 
 SL/TPにATRを使用True
 ロットサイズ0.35
 SL(pips単位)950
 TP(pips単位)30
 トレーリングストップ 15
 時間足3分
 高速EMA20
 低速EMA50
 RSI期間14
 RSI買われ過ぎ55
 RSI売られ過ぎ45

スイングトレードのパラメータ

入力変数 パラメータ
ロットサイズ0.45
SL(pips単位)200
TP(pips単位)1800
トレーリングストップ(pips単位)100
時間足4時間
ルックバック期間20
フィボナッチリトレースメントレベル0.618
D1確認を使用true
上位時間足1日



結論

スキャルピングとスイングトレードの両方に切り替え可能で、ゴールド、FX、暗号資産、株価指数などのさまざまな資産に適応できるダイナミックマルチペアEAを開発しました。このシステムは、EMAクロスオーバー、RSIフィルタ、フィボナッチリトレースメント、ATRベースのボラティリティ測定などのテクニカルモデルを統合し、取引方向とポジション管理をインテリジェントに判断します。適応型SL/TPレベルと堅牢なマルチシンボル構造を実装することで、EAはリスク管理を最適化し、効率的な実行を実現し、多様な市場条件において一貫したロジックを適用できます。これにより、短期スキャルプでも長期スイングセットアップでも最適な運用が可能となります。

結論として、このフレームワークはトレーダーに市場のボラティリティ、銘柄特性、取引目標に動的に適応する多機能かつ自動化された取引ソリューションを提供します。ユーザーは1つのEAで積極的なスキャルピングと忍耐強いスイング戦略の両方をシームレスに運用でき、手動介入を最小化できます。この統一設計により、実行精度とリスク管理が向上し、市場適応力が強化されます。これは、複数の資産クラスにおいて一貫性と拡張性を求めるトレーダーにとって大きな利点となります。 

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

添付されたファイル |
最後のコメント | ディスカッションに移動 (9)
Ryan L Johnson
Ryan L Johnson | 11 11月 2025 において 20:19

スキャルピングの画像に単なる誤植があると思います:

タイポ

Hlomohang John Borotho
Hlomohang John Borotho | 12 11月 2025 において 10:47
Mohammed Altaf Ahmed #:
ダウンロードしましたが、バックテストに失敗しました。

入力記号に注意してください。例えば、"EURUSD.m "は接尾辞".m "を持っています。もし、あなたのブローカーのシンボルに接尾辞や接頭辞がある場合は、入力シンボルに入力してください。

hemantto
hemantto | 13 11月 2025 において 07:46

こんにちは、


デモMt5で実行しましたが、バックテストは失敗しました。

YDILLC
YDILLC | 21 11月 2025 において 06:07
このEAは素晴らしい!このEAは素晴らしい!!!!これからもよろしくお願いします。一つ質問があります!バックテストはどのペアですか?
Hlomohang John Borotho
Hlomohang John Borotho | 21 11月 2025 において 11:53
YDILLC #:
このEAは素晴らしい!このEAは素晴らしい!!!!これからもよろしくお願いします。一つ質問があります!バックテストはどのペアですか?

フィードバックありがとう。

バックテストはデフォルトの入力シンボル設定で行っています:

"XAUUSD,BTCUSD,US100,GBPUSD"
古典的な戦略を再構築する(第18回):ローソク足パターンの探索 古典的な戦略を再構築する(第18回):ローソク足パターンの探索
この記事は、新しいコミュニティメンバーが自分自身でローソク足パターンを検索し、発見する手助けを目的としています。ローソク足パターンを記述することは簡単ではなく、手動で探索し、創造的に改善点を見つけ出す必要があります。ここでは、包み線パターンを紹介し、より利益につながる取引応用のためにどのように改善できるかを示します。
MQL5における市場ポジショニング戦略の体系(第2回): Nvidia向けマルチパターンのビット単位学習 MQL5における市場ポジショニング戦略の体系(第2回): Nvidia向けマルチパターンのビット単位学習
管理可能なテスト期間において、特定の資産を特定の取引方向で検証する市場ポジショニングに関する新連載を継続します。前回の記事では、Nvidia Corp (NVDA)の株を対象に、RSIとDeMarkerオシレーターの組み合わせから5つのシグナルパターンを検証しました。本記事では残りの5パターンを取り上げ、さらに複数パターンの組み合わせにも踏み込みます。これには、10パターンすべての自由な組み合わせや、特定のペアのみを組み合わせる特殊パターンも含まれます。
MQL5での取引戦略の自動化(第39回):信頼区間とダッシュボードを備えた統計的平均回帰 MQL5での取引戦略の自動化(第39回):信頼区間とダッシュボードを備えた統計的平均回帰
統計的平均回帰取引用のMQL5エキスパートアドバイザー(EA)を開発します。指定期間における平均、分散、歪度、尖度、ジャック=ベラ統計量などのモーメントを算出し、非正規分布を特定するとともに、適応的な閾値を用いた信頼区間に基づいて売買シグナルを生成します。
MQL5における二変量コピュラ(第2回):MQL5でのアルキメデスコピュラの実装 MQL5における二変量コピュラ(第2回):MQL5でのアルキメデスコピュラの実装
連載第2回では、二変量アルキメデスコピュラの特性と、それらをMQL5で実装する方法について解説します。また、コピュラを活用したシンプルなペアトレード戦略の開発についても取り上げます。