
MQL5用スキャルピングオーダーフロー
はじめに
このエキスパートアドバイザー(EA)は、スキャルピングオーダーフローテクニックを使用するMetaTrader 5 (MQL5)用の洗練されたアルゴリズム取引システムの例です。
「スキャルピングオーダーフロー」とは、リアルタイムの注文フローを分析し、市場での最適なエントリーポイントやエグジットポイントを特定することに焦点を当てた短期取引戦略です。この戦略では、取引高、価格動向、オーダーブックデータの調査を組み合わせ、迅速かつ精度の高い取引判断をおこないます。通常、ポジションは非常に短期間(数秒から数分程度)で決済されます。
このEAは、多様なテクニカル指標と市場分析手法を駆使し、注文フローの不均衡をもとに取引機会を発見します。また、トレーリングストップ、ポジションの部分決済、動的ポジションサイジングといった高度なリスク管理機能を備えています。さらに、重要なニュースイベント時の取引回避機能や連続損失の制限設定など、リスク軽減を目的とした設計も組み込まれています。
リアルタイムのオーダーブックデータとボリューム動向を分析して短期的な価格変動を予測することが、オーダーフロー取引の基本的な考え方です。このEAは、この手法を確立されたテクニカル分析指標と組み合わせ、高確率の取引機会を精密に特定するためのハイブリッド戦略を実現しています。
特にこのEAはリスク管理を重視しており、これはスキャルピング戦略を活用する際に非常に重要な要素です。不安定な外国為替市場で資本を保護し、可能なリターンを最適化するために、このシステムにはトレーリングストップ、ポジションの部分決済、および動的ポジションサイジングなどの機能が含まれています。
柔軟な設計により、トレーダーはEAのパラメータを自由に調整し、自身の取引スタイルやリスク許容度に合わせることが可能です。例えば、取引量の閾値や指標の期間など、システムのさまざまな側面を取引目標や市場の見通しに応じてカスタマイズできます。
このEAは完全自動で取引をおこないますが、「設定して放置する」だけのソリューションではない点に留意する必要があります。ユーザーは、外国為替取引の基本、オーダーフローに基づく戦略、およびEAに組み込まれた特定の指標について十分な理解を持つことが重要です。EAがさまざまな市場状況で最適に機能するよう、定期的な監視と必要に応じた調整をおこなうことをお勧めします。
コード
このEAはMetaTrader 5用に設計され、高度なリスク管理機能を備えた高度なオーダーフロースキャルピング戦略を実装しています。OnInit()関数内でさまざまなテクニカル指標を初期化し、入力パラメータを検証することから始めます。移動平均、ADX、ATR、RSI、ボリンジャーバンドなどの指標のハンドルを設定します。
#include <Trade\Trade.mqh> #include <Trade\PositionInfo.mqh> // Input parameters input int VolumeThreshold = 35000; // Volume threshold to consider imbalance input int OrderFlowPeriod = 30; // Number of candles to analyze order flow input double RiskPercent = 1.0; // Risk percentage per trade input int ADXPeriod = 14; // ADX Period input int ADXThreshold = 25; // ADX threshold for strong trend input int MAPeriod = 200; // Moving Average Period input ENUM_TIMEFRAMES Timeframe = PERIOD_M15; // Timeframe for analysis input double MaxLotSize = 0.1; // Maximum allowed lot size input int ATRPeriod = 14; // ATR Period input double ATRMultiplier = 2.0; // ATR Multiplier input int RSIPeriod = 14; // RSI Period input int RSIOverbought = 70; // RSI Overbought level input int RSIOversold = 30; // RSI Oversold level input int MAFastPeriod = 10; // Fast Moving Average Period input int MASlowPeriod = 30; // Slow Moving Average Period input int BollingerPeriod = 20; // Bollinger Bands Period input double BollingerDeviation = 2.5; // Bollinger Bands Standard Deviation input int MaxConsecutiveLosses = 1; // Maximum number of consecutive losses before pausing input int MinBarsBetweenTrades = 1; // Minimum number of bars between trades // Global variables CTrade trade; CPositionInfo positionInfo; int maHandle, adxHandle, atrHandle, rsiHandle, maFastHandle, maSlowHandle, bollingerHandle; int consecutiveLosses = 0; datetime lastTradeTime = 0; int barsSinceLastTrade = 0; // New global variables for statistics int totalTrades = 0; int winningTrades = 0; double totalProfit = 0;
int OnInit() { // Logging initialization Print("Starting Order Flow EA v13..."); // Verify trading permissions if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Error: Automated trading is not allowed in the terminal."); return INIT_FAILED; } if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { Print("Error: Automated trading is not allowed for this EA."); return INIT_FAILED; } // Initialize trading object trade.SetExpertMagicNumber(123456); trade.SetMarginMode(); trade.SetTypeFillingBySymbol(_Symbol); trade.SetDeviationInPoints(10); // 1 pip deviation allowed Print("Trading object initialized."); // Initialize indicators maHandle = iMA(_Symbol, Timeframe, MAPeriod, 0, MODE_SMA, PRICE_CLOSE); adxHandle = iADX(_Symbol, Timeframe, ADXPeriod); atrHandle = iATR(_Symbol, Timeframe, ATRPeriod); rsiHandle = iRSI(_Symbol, Timeframe, RSIPeriod, PRICE_CLOSE); maFastHandle = iMA(_Symbol, Timeframe, MAFastPeriod, 0, MODE_EMA, PRICE_CLOSE); maSlowHandle = iMA(_Symbol, Timeframe, MASlowPeriod, 0, MODE_EMA, PRICE_CLOSE); bollingerHandle = iBands(_Symbol, Timeframe, BollingerPeriod, 0, BollingerDeviation, PRICE_CLOSE); // Verify indicator initialization if(maHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE || rsiHandle == INVALID_HANDLE || maFastHandle == INVALID_HANDLE || maSlowHandle == INVALID_HANDLE || bollingerHandle == INVALID_HANDLE) { Print("Error initializing indicators:"); if(maHandle == INVALID_HANDLE) Print("- Invalid MA"); if(adxHandle == INVALID_HANDLE) Print("- Invalid ADX"); if(atrHandle == INVALID_HANDLE) Print("- Invalid ATR"); if(rsiHandle == INVALID_HANDLE) Print("- Invalid RSI"); if(maFastHandle == INVALID_HANDLE) Print("- Invalid Fast MA"); if(maSlowHandle == INVALID_HANDLE) Print("- Invalid Slow MA"); if(bollingerHandle == INVALID_HANDLE) Print("- Invalid Bollinger Bands"); return INIT_FAILED; } Print("All indicators initialized successfully."); // Verify input parameters if(VolumeThreshold <= 0 || OrderFlowPeriod <= 0 || RiskPercent <= 0 || RiskPercent > 100 || ADXPeriod <= 0 || ADXThreshold <= 0 || MAPeriod <= 0 || MaxLotSize <= 0 || ATRPeriod <= 0 || ATRMultiplier <= 0 || RSIPeriod <= 0 || RSIOverbought <= RSIOversold || MAFastPeriod <= 0 || MASlowPeriod <= 0 || BollingerPeriod <= 0 || BollingerDeviation <= 0 || MaxConsecutiveLosses < 0 || MinBarsBetweenTrades < 0) { Print("Error: Invalid input parameters."); return INIT_FAILED; } Print("Input parameters validated."); // Initialize global variables consecutiveLosses = 0; lastTradeTime = 0; barsSinceLastTrade = MinBarsBetweenTrades;
主な取引ロジックはOnTick()関数内で実行され、各価格ティックごとに呼び出されます。まず、新しいバーが形成され、取引が許可されているかどうかを確認します。そして、指定された期間の買いと売りの取引高を比較することで、注文の流れを分析します。EAは、トレンドの強さ(ADX)、移動平均線に対する価格の位置、RSIレベルなど、取引シグナルを確認するために複数のテクニカル指標を使用します。
void OnTick() { if(!IsNewBar()) return; Print("Current state - Consecutive losses: ", consecutiveLosses, ", Bars since last trade: ", barsSinceLastTrade); if(!IsTradeAllowed()) { Print("Trading not allowed. Check EA configuration and account permissions."); return; } // Check if there's an open position and manage it if(PositionExists()) { ManageOpenPositions(); return; // Exit if there's an open position } barsSinceLastTrade++; // Increment only if there's no open position if(!IsRiskAcceptable()) { Print("Risk not acceptable."); return; } double buyVolume = 0, sellVolume = 0; AnalyzeOrderFlow(buyVolume, sellVolume); double adxValue[], maValue[], atrValue[], rsiValue[], maFastValue[], maSlowValue[], bollingerUpper[], bollingerLower[]; if(!GetIndicatorData(adxValue, maValue, atrValue, rsiValue, maFastValue, maSlowValue, bollingerUpper, bollingerLower)) return; bool strongTrend = (adxValue[0] > ADXThreshold); bool aboveMA = (SymbolInfoDouble(_Symbol, SYMBOL_LAST) > maValue[0]); bool fastAboveSlow = (maFastValue[0] > maSlowValue[0]); int dynamicSL = (int)(atrValue[0] * ATRMultiplier / SymbolInfoDouble(_Symbol, SYMBOL_POINT)); int dynamicTP = dynamicSL * 3; // Risk/Reward ratio of 1:3 double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // Conditions for a buy trade if(strongTrend && aboveMA && fastAboveSlow && buyVolume > sellVolume + VolumeThreshold && rsiValue[0] < RSIOverbought && currentPrice < bollingerUpper[0] && barsSinceLastTrade >= MinBarsBetweenTrades) { Print("Buy conditions met. Attempting to open position..."); if(ExecuteTrade(ORDER_TYPE_BUY, dynamicSL, dynamicTP)) { Print("Buy position opened successfully."); barsSinceLastTrade = 0; } } // Conditions for a sell trade else if(strongTrend && !aboveMA && !fastAboveSlow && sellVolume > buyVolume + VolumeThreshold && rsiValue[0] > RSIOversold && currentPrice > bollingerLower[0] && barsSinceLastTrade >= MinBarsBetweenTrades) { Print("Sell conditions met. Attempting to open position..."); if(ExecuteTrade(ORDER_TYPE_SELL, dynamicSL, dynamicTP)) { Print("Sell position opened successfully."); barsSinceLastTrade = 0; } } }
リスク管理のために、EAは口座残高のパーセンテージと現在の市場ボラティリティ(ATRを使用)に基づいた動的なポジションサイジングを実装しています。また、利益を確定するためのトレーリングストップ機構とポジションの部分決済機能も備えています。最大連続損失数と最小取引間隔バー数を強制することでリスクを制限します。
bool IsRiskAcceptable() { if(IsHighImpactNews()) { Print("Risk not acceptable: High impact news detected."); return false; } if(consecutiveLosses >= MaxConsecutiveLosses) { Print("Risk not acceptable: Maximum consecutive losses reached (", consecutiveLosses, "/", MaxConsecutiveLosses, ")."); return false; } if(barsSinceLastTrade < MinBarsBetweenTrades) { Print("Risk not acceptable: Not enough bars since last trade (", barsSinceLastTrade, "/", MinBarsBetweenTrades, ")."); return false; } double equity = AccountInfoDouble(ACCOUNT_EQUITY); double balance = AccountInfoDouble(ACCOUNT_BALANCE); double drawdown = (balance - equity) / balance * 100; if(drawdown > 20) // Increased from 10% to 20% { Print("Risk not acceptable: Excessive drawdown (", DoubleToString(drawdown, 2), "%)."); return false; } Print("Risk acceptable. Consecutive losses: ", consecutiveLosses, ", Bars since last trade: ", barsSinceLastTrade, ", Current drawdown: ", DoubleToString(drawdown, 2), "%"); return true; }
CalculateLotSize()関数は、口座残高、リスク割合、および現在の市場状況に基づいて、適切なポジションサイズを決定します。ManageOpenPositions()関数は、既存の取引を処理し、トレーリングストップと部分決済を実装します。
double CalculateLotSize(double stopLossDistance) { double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double maxRiskAmount = accountBalance * (RiskPercent / 100); double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if(tickValue == 0 || stopLossDistance == 0) { Print("Error: Tick value or Stop Loss distance is 0"); return 0; } double lotSize = NormalizeDouble(maxRiskAmount / (stopLossDistance * tickValue), 2); lotSize = MathFloor(lotSize / lotStep) * lotStep; double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); lotSize = MathMax(MathMin(lotSize, maxLot), minLot); lotSize = MathMin(lotSize, MaxLotSize); double margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE); double requiredMargin = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL) * lotSize; if(requiredMargin > margin) { Print("Not enough free margin to open this position. Required: ", requiredMargin, " Available: ", margin); return 0; } Print("Calculated lot size: ", lotSize, " Risk: $", NormalizeDouble(lotSize * stopLossDistance * tickValue, 2)); return lotSize; }
エラー処理は、HandleTradingErrors()関数を通じて包括的に対処され、取引に関連する様々なエラーに関する詳細なフィードバックを提供します。取引統計を記録する機能と、影響の大きいニュースイベントをチェックする機能も含まれています(ただし、後者はユーザーが実装できるようにプレースホルダーとして残されている)。
//+------------------------------------------------------------------+ //| Function for error handling | //+------------------------------------------------------------------+ void HandleTradingErrors(int errorCode) { switch(errorCode) { case TRADE_RETCODE_REQUOTE: Print("Error: Requote"); break; case TRADE_RETCODE_REJECT: Print("Error: Request rejected"); break; case TRADE_RETCODE_CANCEL: Print("Error: Request cancelled by trader"); break; case TRADE_RETCODE_PLACED: Print("Order placed successfully"); break; case TRADE_RETCODE_DONE: Print("Request completed"); break; case TRADE_RETCODE_DONE_PARTIAL: Print("Request partially completed"); break; case TRADE_RETCODE_ERROR: Print("Request processing error"); break; case TRADE_RETCODE_TIMEOUT: Print("Error: Request cancelled by timeout"); break; case TRADE_RETCODE_INVALID: Print("Error: Invalid request"); break; case TRADE_RETCODE_INVALID_VOLUME: Print("Error: Invalid volume in request"); break; case TRADE_RETCODE_INVALID_PRICE: Print("Error: Invalid price in request"); break; case TRADE_RETCODE_INVALID_STOPS: Print("Error: Invalid stops in request"); break; case TRADE_RETCODE_TRADE_DISABLED: Print("Error: Trading is disabled"); break; case TRADE_RETCODE_MARKET_CLOSED: Print("Error: Market is closed"); break; case TRADE_RETCODE_NO_MONEY: Print("Error: Not enough money to complete request"); break; case TRADE_RETCODE_PRICE_CHANGED: Print("Error: Prices changed"); break; case TRADE_RETCODE_PRICE_OFF: Print("Error: No quotes to process request"); break; case TRADE_RETCODE_INVALID_EXPIRATION: Print("Error: Invalid order expiration date"); break; case TRADE_RETCODE_ORDER_CHANGED: Print("Error: Order state changed"); break; case TRADE_RETCODE_TOO_MANY_REQUESTS: Print("Error: Too many requests"); break; case TRADE_RETCODE_NO_CHANGES: Print("Error: No changes in request"); break; case TRADE_RETCODE_SERVER_DISABLES_AT: Print("Error: Autotrading disabled by server"); break; case TRADE_RETCODE_CLIENT_DISABLES_AT: Print("Error: Autotrading disabled by client terminal"); break; case TRADE_RETCODE_LOCKED: Print("Error: Request locked for processing"); break; case TRADE_RETCODE_FROZEN: Print("Error: Order or position frozen"); break; case TRADE_RETCODE_INVALID_FILL: Print("Error: Invalid order filling type"); break; case TRADE_RETCODE_CONNECTION: Print("Error: No connection to trading server"); break; case TRADE_RETCODE_ONLY_REAL: Print("Error: Operation allowed only for live accounts"); break; case TRADE_RETCODE_LIMIT_ORDERS: Print("Error: Pending orders limit reached"); break; case TRADE_RETCODE_LIMIT_VOLUME: Print("Error: Volume limit for orders and positions reached"); break; default: Print("Unknown error: ", errorCode); break; } }
全体として、このEAは、注文フロー分析と伝統的なテクニカル指標および高度なリスク管理手法を組み合わせた複雑な取引システムを表しています。経験豊富なトレーダー向けに設計されており、本番運用の前に十分にテストする必要があります。
ただし、 影響の大きいニュースイベントをチェックする機能は実装されていません。完成させるのは読者にお任せします。
バックテスト
このEAは、5分、15分、30分の期間で機能します。
EAを使って取引することを検討する前に、すべての期間をよく分析し、EAを最適化する必要があります。
以下は15分間の結果です。
このバックテスト調査では、15分チャートのデータを使用して、2000年から2025年までのEURUSD通貨ペアにおける取引戦略のパフォーマンスを分析しました。 レバレッジ比率は1:100で、開始預金額は3000米ドルです。この場合、口座サイズは比較的小さく、レバレッジが高いため、利益と損失の両方が大きく変動する可能性があります。 バックテスト期間中、このアプローチにより、最初の3000米ドルの預金に対して控えめながら4.19%の収益が得られ、総純利益は125.83米ドルとなりました。
この戦略では、1ドルの損失に対して1.13ドルの利益を生み出しており、利益率1.13が示すように、全体的にわずかに利益を上げる結果となりました。合計で364件の取引が実行され、その内訳は167件がロング取引、197件がショート取引でした。ショート取引の勝率は73.60%、ロング取引の勝率は86.23%と高く、取引選択が比較的適切であったことを示しています。
ただし、この方法では、勝ち取引1件あたりの平均利益(3.71米ドル)が負け取引1件あたりの平均損失(-12.62米ドル)を大きく下回っており、利益は小さいものの、不利な取引では大きな損失を被る可能性があることが分かります。 最大で連続15件の勝ち取引と、最大5件の負け取引が記録されました。利益をもたらした最大の取引は50.22米ドルであったのに対し、最大損失は-66.10米ドルでした。
この戦略による資産曲線の最大ドローダウン(資産減少率)は5.63%であり、許容可能な損失の範囲内であることを示しています。 また、シャープ比率は1.83と算出されており、想定されるリスクを十分に上回るリターンを得られたことを示しています。
総合的に、この手法は小規模な取引で高い成功率を維持しつつ、時折大きな損失を許容する高頻度スキャルピング戦略といえます。 勝率が高く利益率が低いことからも、この戦略には一定の弱点が見られ、市場の状況が変化した場合には大きな損失を被るリスクがあると考えられます。慎重なリスク管理が引き続き重要であると言えるでしょう。
5分間
このバックテスト研究では、5分足チャートのデータを用いて、2000年1月1日から2025年2月1日までの期間におけるEURUSD通貨ペアの取引戦略のパフォーマンスを検証しました。 この戦略は、レバレッジ1:100の条件下で3,000米ドルの初期預金を使用しており、比較的小さな口座サイズと高いレバレッジを特徴としています。このため、利益が拡大する可能性がある一方で、損失も大きくなるリスクが伴います。
バックテストの結果、初期預金3,000米ドルに対して、合計150.32米ドルの純利益が得られ、25年間で控えめな5.01%の収益率を記録しました。 この戦略では、合計1,732件の取引が行われ、その内訳は1,023件のショート取引と709件のロング取引で構成されていました。ショート取引の勝率は81.82%、ロング取引の勝率は81.95%といずれも高く、両方向での取引選択が優れていたことが示されています。
一方、この手法では、小さな利益を積み重ねる一方で、取引が失敗した場合には大きな損失を被る傾向があることがわかりました。これは、勝ち取引1件あたりの平均利益(2.27米ドル)が、負け取引1件あたりの平均損失(-9.79米ドル)を大きく下回っていることからも明らかです。 損失1米ドルに対して利益が1.05米ドルであったため、利益率1.05が示すように、全体としてわずかに利益を上げたに過ぎません。 さらに、この戦略による資産曲線の最大ドローダウンは9.95%であり、妥当な範囲といえるものの、リスク管理の面で改善の余地があるかもしれません。
このアプローチは、シャープ比率0.92が示すように、発生したリスクをわずかに相殺する程度の収益を生み出しました。 資産曲線は全体的に上昇傾向を示しているものの、顕著な変動や下降も見られます。
また、この戦略のパラメータには、ADX、RSI、移動平均、ボリンジャーバンドなどのテクニカル指標を用いた複雑なマルチファクターアプローチが含まれ、取引判断の精度を高めることを推奨しています。 総合的に、この手法は小規模な取引で高い成功率を維持しつつ、時折大きな損失を許容する高頻度スキャルピング戦略といえます。勝率が高いにもかかわらず利益率が低いため、長期的に大きな利益を得るのは難しいと考えられ、不利な市場状況においては大きなドローダウンの影響を受けやすい可能性があります。
結論
このMetaTrader 5エキスパートアドバイザー(EA)は、最先端のリスク管理ツールを活用し、複雑なオーダーフロースキャルピング手法を適用しています。さまざまなテクニカル指標、オーダーフロー分析、そして動的ポジションサイズ管理を組み合わせることで、高確率の外国為替取引の機会を特定します。EURUSD通貨ペアを対象に、特に15分足と5分足の時間枠でバックテストを行った結果、このEAの潜在的な可能性が示されました。
しかしながら、結果は長所と短所の両面を浮き彫りにしています。この戦略は高い勝率を誇る一方で、収益性は控えめであり、利益率が低いことが課題となっています。テスト期間が長期に及ぶ場合、利益は比較的小さく、戦略単体で大きな利益を生み出すことは難しい可能性があります。頻繁に小さな勝利を積み重ねる一方で、散発的に大きな損失を被る傾向があるため、市場状況が不利な場合には、大幅なドローダウンの影響を受けやすい点にも注意が必要です。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15895




- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索