English Deutsch
preview
プロップファームチャレンジをクリアするための自動リスク管理

プロップファームチャレンジをクリアするための自動リスク管理

MetaTrader 5トレーディング |
27 7
Eugene Mmene
Eugene Mmene

はじめに

本記事は、近年登場したプロップファームトレーディングという現象に対応することを唯一の目的として執筆されたものです。プロップファームトレーディングは、非常にニッチでありながら収益性が高く魅力的な取り組みですが、この道に進むと多くの課題や障害に直面します。プロップファームのチャレンジに挑戦する多くのトレーダーが直面する最も一般的な障害は、戦略や手法、スキルの不足ではなく、むしろプロップファームが定める厳格な制限や取引ルールにあります。これらを遵守しなければ、トレーダーはライブ口座の運用資格を証明することができません。

実際のところ、トレーダーは市場分析ができ、プランを守り、注文を実行し、トレンドを把握することもできます。これは自己資金での取引には十分かもしれませんが、プロップファーム取引では不十分です。プロップファームでは、定められたルールや制限を厳格に守ることが求められます。

最も一般的なルール、目標、制限事項は以下のとおりです。

  • 設定された日次ドローダウン制限を超えてはいけません。この制限は通常、深夜にリセットされます。制限値はプロップファームごとに異なり、購入した口座の種類もドローダウン制限に影響する場合があります。
  • 設定された総ドローダウン制限に違反してはいけません。これに違反すると、その口座での取引は停止されます。制限はプロップファームや口座タイプによって異なります。  
  • ニュース発表時の急激で激しい市場の値動きを利用しようとする取引は避けるべきです。方向性の欠如や不安定な価格変動により、口座にとって非常に危険で高いリスクを伴う可能性があります。
  • トレーダーは、安定した資産曲線を維持するために、取引期間を通じて同一のリスクプロファイルとエクスポージャーを維持する必要があります。これは、過度なレバレッジや一度の取引に全てを賭ける行為を防ぐためです。 
  • トレーダーは日々規律を持って取引をおこなう必要があり、プロップファームや口座にリスクをもたらす行為や、アービトラージ取引や高頻度取引といった不適切な手法に関与してはいけません。

これらの条件こそが、取引のアイデア自体が優れている場合であっても、参加者の60〜80%を脱落させる要因となっています。問題は取引の能力やスキルではなく、リスク、ドローダウン、ボラティリティ、規律を同時に手動で管理する難しさにあります。

本記事は、取引の方法自体は理解しているものの、過度なドローダウンや感情的な判断などの理由でプロップファームチャレンジに失敗し続けているトレーダーを対象としています。本記事では、ドローダウン管理やリスク管理を自動化することで、ルール違反を防ぎ、チャレンジを成功させるための解決策を設計し、実証していきます。

ブレイクアウトとブレイクアウト上限での再テストエントリーを示すチャート


人為的ミスを排除するための取引プロセスの自動化(プロップトレーディング)   

収益性の高い取引に大きく寄与し、トレーダーの成功を大きく左右する取引の実践やプロセスが存在します。これらは体系的かつ正確に実行されることで効果を発揮します。 効果的かつ収益的に取引をおこなうためには、これらのプロセスを同時に習得する必要がありますが、多くのトレーダーはこの点でつまずきます。本記事では、EAがどのようにこの課題を解決しようとするかを示します。

以下では、これらのプロセスを自動化しながら、トレーダーが直面する課題にどのように対応するかを簡潔に説明します。対象となる主なプロセスと実践は次の通りです。

  • 適切なリスク管理:本記事のEAは、非常に堅牢なリスクおよび取引管理を実装し、すべてのプロップファームのルールが遵守され、違反が発生しないよう設計されています。これは最も重要な要素です。資金がなくなったり口座が違反状態になった場合、そもそも取引を継続できなくなるためです。  
  • 取引計画: このEAは、自動化された厳格なロジックフローに基づいて取引をおこない、望ましい市場条件が満たされた場合にのみ取引を許可します。感情や不安によって取引が実行されることはありません。  
  • 市場分析: EAは、特定の順序と論理に従って市場を分析し、分析や取引における人為的ミスやバイアスを最小限に抑えます。トップダウン分析により、結果が悪いときに戦略を頻繁に変更してしまう、手動トレーダーにありがちな「ストラテジーホッピング」を回避します。
  • 優れた取引心理: EAの自動化により、損失後のリベンジトレード、恐怖や欲望による衝動的な取引、FOMO(機会損失への恐れ)を排除できます。その結果、プロップファームトレーディングで長期的成功に不可欠な忍耐と規律が維持されます。

実際のところ、トレーダーは単に一つのプロセスや手法を完全に理解するだけでは不十分であり、すべての取引プロセスを完全に把握し、理解していなければなりません。というのも、ある一つのプロセスだけを習得して他を欠いたり、いくつかを習得しても一つや二つを欠いたりすると、すぐに破綻につながるからです。その場合、市場を長期的に効率よく、かつ利益を上げながら乗り切るのに必要な本質的要素が欠けているため、たとえ初期に成功したとしても、それは長続きしません。

これらの取引プロセスを自動化することで、トレーダーの負担を軽減することができます。EAのコアロジックは、実行前にすべての変数を考慮するよう設計されており、各プロセスや手順を一つも欠かすことなく実行します。これに対して手動トレーダーは、感情や不安、あるいは恐怖に流されてしまい、基本的な作業を怠ることがあり、その結果として損失トレードにつながる可能性があります。 

この分野で成功するためには、取引に関わるすべての要素を習得し、それらを同時に組み合わせて活用する必要があります。一つの要素も欠かしてはいけません。本記事では、これまでにリスク管理の不備によって多くのトレーダーが資金提供口座の資格を得られない理由とその仕組みについて説明してきましたが、ここからは、このEAがどのように売買ロジックとリスク管理プロトコルを実装し、目標を達成するのか、その内部構造、設計、および機能について詳しく解説します。  

エントリーのブレイクアウトとリテストを示すチャート



プロップファームトレーディングEAの内部動作

本章では、EAがどのように情報を理解、解釈、処理するのか、どのようにリスク管理を実装するのか、そしてどのように取引ロジックを実行して最適な結果を達成するのかについて説明します。まず最も重要なのは、使用される売買ロジックです。

  • エントリーを実行するためのロジック

    これは本記事の中でも非常に重要かつ価値の高い要素です。なぜなら、EAが収集したすべての情報をどのように精査し、分析するかを決定する部分だからです。ここでは、どのようにエントリーを無効化または有効化するのか、どの程度のリスクを取るのか、またどのタイミングでリスクやエクスポージャーを増減させるのかを判断します。本セクションでは、全体像を理解しやすくするために簡略化して説明します。 

    EAが取引のセットアップを検出すると、まず直近のエクイティおよび残高の最高値を確認し、それを日次および全体のドローダウン制限と照らし合わせます。これにより、その取引で許容される損失余地(利用可能な残高や証拠金の範囲)を計算し、いかなるルール違反も起こさないようにします。

    次に、第2の条件として、最大リスク2%および最大損失額$110の制限を強制的に適用します。つまり、EAがストップロスの適切な価格を計算したとしても、それがリスク制限や最大許容損失を超える場合、その取引は実行されません。ストップロス、テイクプロフィット、トレーリングストップ、さらにはトレンド変化の検出にはATR (Average True Range)が使用されます。

    ブレイクアウトとブレイクアウト後のリテストのチャート例


    • リスクおよび取引管理

    EAは、プロップファームチャレンジに特化した非常に堅牢で適応的なリスク管理ロジックを備えています。また、GOLD取引に最適化されるよう綿密に設計されています。ユーザーの好みに応じて調整することも可能ですが、デフォルト設定では1取引あたり2%のリスクに制限されており、適度なリスク水準とバランスの取れた攻撃性を実現しています。これにより、損失が発生した場合でも口座を維持し、次の機会に備えることができます。特にGOLDでは過度なリスクは非常に危険であり、重大な損失につながる可能性があります。 

    追加の安全策として、1回の取引における最大損失は$110に制限されています。これにより、スプレッドやギャップが考慮されていない場合でも、単一の取引がプロップファームのルール違反につながることを防ぎます。リスク割合や最大損失はユーザーの設定に応じて調整可能です。また、このEAには最大10本のローソク足を対象としたブレイクアウトのルックバック機能があり、低ボラティリティや低出来高時に多発するダマシのブレイクアウトをフィルタリングします。さらに、ニュース前後15分間は取引が禁止されており、CPI、FOMC、NFPなどのニュースによる急激なボラティリティを回避します。

    入力設定には最小ブレイクアウト強度(0.1)があり、弱いブレイクアウト(トラップの可能性があるもの)を避けるようになっています。この値は連敗後に自動的に引き上げられ、GOLD特有の操作的な市場構造の中で、より強く明確なブレイクアウトのみを待つように強制します。この機能は上位時間足の設定とも連動しており、オンまたはオフを選択可能です。これにより、短期足のノイズに惑わされず、上位時間足の方向性に沿った取引を実行することができます。   

    EAには、日次ドローダウン2.5%、総ドローダウン5.5%の制限が設定されており、大きなスプレッドやボラティリティがあっても違反を防ぐよう設計されています。これにより、ドローダウン制限までの余裕を確保します。また、チャレンジをクリアするのに必要な利益目標に到達すると、すべてのポジションをクローズする機能も備えています。これは、1ステップチャレンジの合格ラインである10%に達した時点で動作します。

    CurRiskおよびOrigRisk関数は、動的なポジションサイズ調整を可能にします。連敗時にはリスクを減少させ、連勝時には増加させることで、GOLD特有の激しいドローダウン局面を生き残りつつ、利益局面ではその優位性を活かします。

    LastEqHighはエクイティの最高値を追跡し、残高が増加している場合でも隠れたドローダウンを検出します。また、StartingBalanceとDailyBalanceは、GOLD特有のギャップの多い特性に対応した二重のドローダウン保護システムの基盤となります。

    TimeframeData構造体は、M15およびH1のインジケーターを独立して管理し、それぞれにクールダウンタイマーを設けることで、1時間以内に複数のポジションを開いて過剰なリスクを取ることを防ぎます。

    さらに、TradeLog関数により、すべての取引がブレイクアウト強度、出来高、リスクレベルとともに記録されます。これにより事後分析が可能となり、フィルターの調整や同じミスの回避に役立ちます。

    ManageTrades関数は、GOLDの激しい値動きに最適化された3つの強力な決済メカニズムを提供します。まず、強い反対方向のブレイクアウトが発生した場合(例:ロング中に強い下落ブレイクアウト)、ポジションを即座にクローズし、2000ポイント以上の急反転による損失を防ぎます。次に、リスクリワード1:2に到達した時点でポジションの50%を利確し、ストップロスを建値に移動することで、ニュース時の急変動に対して資本を保護します。最後に、ストップロスをATRの1.5倍でトレーリングさせることで、FOMC後のような大きなトレンドに追随しながら利益を保護します。この組み合わせにより、実際のGOLD取引において平均1:3以上のリスクリワードを実現することが確認されています。

    H1ブレイクアウトとリテストエントリー


    MQL5におけるプロップファームトレーディングEAによる取引判断の自動化

    本戦略を自動化し、可視化し、実装するために、私は最適なリスク管理機能を備えたプロップファームトレーディングEAを作成しました。このEAは、トレンド分析とブレイクアウト後のエントリーポイントの検出をおこない、トレーリングストップロス、取引管理、単純移動平均を組み込んでいます。

    意思決定プロセス

    本EAの意思決定(流動性検出、ブレーカー検出、取引管理、リスク管理、取引実行)は、以下のロジックに基づいておこなわれます。

    プロップファームトレーディングEAのソースコード

    EAは、D1、MN、W1、H4、H1といった上位時間足のチャートからブレーカーをエントリーシグナルとして検出します。そして、流動性の一掃(リクイディティパージ)の直後に、価格がブレーカーの上部に戻ってくるのを待ち、高品質なエントリーとして解釈します。また、単純移動平均(SMA)を使用して全体的なトレンド方向を把握し、それに基づいてエントリーをおこないます。さらに、強力な取引管理およびリスク管理機能を備えており、トレーリングストップロスのロジックを適用することで、ストップロスの位置を決定し、価格が有利に動いた際には資本を保護します。また、リスク管理として、1取引あたり2%のリスク設定を含んでいます。 

    入力パラメータ(GOLD専用に最適化)

    入力パラメータは、高リスクなプロップファーム環境におけるGOLD(XAUUSD)取引用に慎重に調整されています。RiskPctは2%に設定されており、GOLDの極めて高いボラティリティ(平均日中変動幅1800〜3500ポイント)を考慮して、一般的な為替ペアよりも低めに設定されています。MaxLossUSDは$110に制限されており、たとえ3000ポイントの急変動が発生した場合でも、単一取引でチャレンジルールに違反しないように設計されています。Brk_Prdは10バーに拡張されており、低出来高のアジア時間に頻発するダマシのブレイクアウトをフィルタリングします。NewsPauseは15分に延長されており、CPI、FOMC、NFPといった米国経済指標発表時にGOLDが瞬時に1000ポイント以上動くような激しい反応を避けるためです。MinBrkStrは0.1 ATRに引き上げられており、GOLDにおける弱いブレイクアウト(多くはトラップ)を回避します。useHTFはデフォルトで有効になっており、GOLDは為替ペアよりも上位時間足(D1やH4のEMA)の構造に強く従う特性があるためです。DailyDDLimit (2.5%)とOverallDDLimit (5.5%)は、GOLDのギャップリスクを考慮して標準よりも厳しく設定されています。TargetBalanceOrEquityは$10,000に設定されており、これは2025年時点で多くの10万ドル規模のGOLDチャレンジにおける利益目標と一致しています。
    //+------------------------------------------------------------------+
    //|             XAUUSD_AdvancedBreakoutRecoveryEA.mq5                |
    //|           GOLD (XAUUSD) Multi-Timeframe Adaptive Breakout EA     |
    //|            With optimized Risk Management for prop firms         |
    //|         optimized for 1-step Fundednext Prop Firm Challenges     |
    //+------------------------------------------------------------------+
    #property copyright "Eugene Mmene"
    #property link      "https://emcapital2021/"
    #property version   "2.26"
    
    #include <Trade\Trade.mqh>
    
    //--- Input Parameters
    input double RiskPct = 2.0;               // Base risk per trade % (lower for GOLD volatility)
    input double MaxLossUSD = 110.0;          // Maximum loss per trade in USD
    input double RecTgt = 7000.0;             // Equity recovery target after drawdown
    input int    ATR_Prd = 14;                // ATR period – perfect for XAUUSD volatility
    input int    Brk_Prd = 10;                // Breakout lookback – captures gold’s momentum
    input int    EMA_Prd = 20;                // EMA period for D1/H4 trend filter
    input string GS_Url = "";                 // Google Sheets webhook URL
    input bool   NewsFilt = true;             // Critical for gold (FOMC, NFP, CPI)
    input int    NewsPause = 15;              // 15 minutes pause – gold spikes hard
    input double MinBrkStr = 0.1;             // Minimum breakout strength in ATR multiples
    input int    Vol_Prd = 1;                 // Volume MA period
    input bool   Bypass = 
    true ;              // Set false for live – true only for testing
    input bool   useHTF = 
    false ;               // MUST be true for gold – avoids fake breakouts
    input string NewsAPI_Url = "https://www.alphavantage.co/query?function=NEWS_SENTIMENT&apikey=";
    input string NewsAPI_Key = "pub_3f54bba977384ac19b6839a744444aba";
    input double DailyDDLimit = 2.5;          // Tighter daily DD for gold’s volatility
    input double OverallDDLimit = 5.5;        // Strict overall drawdown limit
    input double TargetBalanceOrEquity = 6600.0; // Standard $100K challenge target
    input bool   ResetProfitTarget = false;   // Manual reset after passing
    

    グローバル変数:GOLD取引における詳細な目的

    CurRiskとOrigRiskは動的なポジションサイズ調整を可能にし、連続した損失の後にはリスクを減少させ、連勝時にはリスクを増加させます。これは、GOLDの激しいドローダウン局面を生き残るために不可欠です。LastEqHighはエクイティの最高値を追跡し、残高が増加している場合でも、隠れたドローダウンを検出します。StartingBalanceとDailyBalanceは、GOLD特有のギャップが多い性質に対応するために調整された、二重のドローダウン保護システムの基盤を形成します。TimeframeData構造体は、M15およびH1のインジケーターを独立して管理し、それぞれに個別のクールダウンタイマーを持たせています。NewsEvtは、Alpha Vantageから取得した高インパクトイベント(影響度80超)を保持し、15分間の回避ウィンドウを設定します。TradeLogは、各エントリーについてブレイクアウト強度、出来高、リスクレベルを記録し、事後分析や適応的なフィルター調整に活用されます。dynBrkStrは0.1から開始し、連敗後に自動的に増加します。これにより、GOLDの操作的な市場構造において、より強く明確なブレイクアウトを待つようEAに強制します。
    double CurRisk = RiskPct;
    double OrigRisk = RiskPct;
    double LastEqHigh = 0;
    double StartingBalance = 0;
    double DailyBalance = 0;
    datetime LastDay = 0;
    bool ProfitTargetReached = false;
    bool DailyDDReached = false;
    CTrade trade;
    
    int h_ema_d1 = INVALID_HANDLE;
    int h_ema_h4 = INVALID_HANDLE;
    
    int winStreak = 0;
    int lossStreak = 0;
    string SymbolName = _Symbol;
    
    struct TimeframeData {
       ENUM_TIMEFRAMES tf;
       int h_atr;
       int h_vol;
       int h_vol_ma;
       datetime lastSig;
       datetime lastBar;
    };
    TimeframeData tfs[];
    
    struct NewsEvt {
       datetime time;
       string evt;
       int impact;
    };
    NewsEvt newsCal[];
    int newsCnt = 0;
    
    struct TradeLog {
       ulong ticket;
       bool isWin;
       double profit;
       double brkStr;
       double vol;
       double risk;
       ENUM_TIMEFRAMES tf;
    };
    TradeLog tradeHistory[];
    int tradeCnt = 0;
    
    double dynBrkStr = MinBrkStr;
    

    OnInit():GOLD向け最適化セットアップの解説

    OnInit関数は、XAUUSD (GOLD)取引に特化した厳密な検証処理を実行します。まず、対象銘柄が気配値表示で正しく選択されていることを確認します(特にニュース時にスプレッドが拡大するGOLDにおいて重要です)。すべてのインジケータハンドルはエラーチェック付きで作成され、1つでも失敗した場合は初期化を中断します。これは、実運用中に潜在的なクラッシュが発生するのを防ぐためです。また、GOLDは米国の経済指標発表時に1000ポイント以上動くことがあるため、ニュースカレンダーは起動時にあらかじめ読み込まれます。さらに、口座情報は取得され、サーバー時間(EAT UTC+3)に基づいた日次リセットロジックが適用されます。最後に、本関数は明確なサマリーをログに出力し、厳格なドローダウン制御のもとで高ボラティリティのGOLD取引に対応する準備が整っていることを確認します。
    int OnInit()
    {
       if(AccountInfoDouble(ACCOUNT_BALANCE) < 10.0)
       {
          Print("Low balance: ", AccountInfoDouble(ACCOUNT_BALANCE));
          return(INIT_FAILED);
       }
    
       string sym = Symbol();
       if(!SymbolSelect(sym, true))
       {
          Print("Error: Symbol ", sym, " not found. Using chart symbol: ", _Symbol);
          SymbolName = _Symbol;
       }
       else SymbolName = sym;
    
       if(!SymbolSelect(SymbolName, true))
       {
          Print("Failed to select ", SymbolName, " in Market Watch");
          return(INIT_FAILED);
       }
    
       Print("Ensure ", NewsAPI_Url, " is in Tools > Options > Expert Advisors > Allow WebRequest");
    
       StartingBalance = AccountInfoDouble(ACCOUNT_BALANCE);
       LastEqHigh = AccountInfoDouble(ACCOUNT_EQUITY);
       DailyBalance = StartingBalance;
       LastDay = TimeCurrent() / 86400 * 86400;
       ProfitTargetReached = ResetProfitTarget ? false : ProfitTargetReached;
    
       ArrayResize(newsCal, 100);
       ArrayResize(tradeHistory, 100);
       ArrayResize(tfs, 2);
    
       tfs[0].tf = PERIOD_M15;
       tfs[1].tf = PERIOD_H1;
    
       for(int i = 0; i < 2; i++)
       {
          tfs[i].h_atr = iATR(SymbolName, tfs[i].tf, ATR_Prd);
          tfs[i].h_vol = iVolumes(SymbolName, tfs[i].tf, VOLUME_TICK);
          tfs[i].h_vol_ma = iMA(SymbolName, tfs[i].tf, Vol_Prd, 0, MODE_SMA, PRICE_CLOSE);
          tfs[i].lastSig = 0;
          tfs[i].lastBar = 0;
    
          if(tfs[i].h_atr == INVALID_HANDLE || tfs[i].h_vol == INVALID_HANDLE || tfs[i].h_vol_ma == INVALID_HANDLE)
          {
             Print("Indicator init failed for ", EnumToString(tfs[i].tf));
             return(INIT_FAILED);
          }
       }
    
       h_ema_d1 = iMA(SymbolName, PERIOD_D1, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE);
       h_ema_h4 = iMA(SymbolName, PERIOD_H4, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE);
    
       if(h_ema_d1 == INVALID_HANDLE || h_ema_h4 == INVALID_HANDLE)
       {
          Print("EMA init failed");
          return(INIT_FAILED);
       }
    
       if(NewsFilt) FetchNewsCalendar();
    
       Print("XAUUSD EA initialized | M15+H1 | News:", newsCnt, " events | HTF Filter: ON | Daily DD: 2.3% | Target: $6,800");
       return(INIT_SUCCEEDED);
    }

    OnDeinit():リソースのクリーンアップ

    すべてのインジケーターハンドルは適切に解放され、長時間のVPS運用中にメモリリークが発生しないようにします。これは24時間稼働するGOLD EAにとって必須です。
    void OnDeinit(const int reason)
    {
       if(h_ema_d1 != INVALID_HANDLE) IndicatorRelease(h_ema_d1);
       if(h_ema_h4 != INVALID_HANDLE) IndicatorRelease(h_ema_h4);
       for(int i = 0; i < ArraySize(tfs); i++)
       {
          if(tfs[i].h_atr != INVALID_HANDLE) IndicatorRelease(tfs[i].h_atr);
          if(tfs[i].h_vol != INVALID_HANDLE) IndicatorRelease(tfs[i].h_vol);
          if(tfs[i].h_vol_ma != INVALID_HANDLE) IndicatorRelease(tfs[i].h_vol_ma);
       }
       Print("XAUUSD EA stopped: ", reason);
    }

    CloseAllPositions():即時リスク排除

    利益目標に到達した場合やドローダウン制限を超えた場合に直ちにトリガーされ、マジックナンバーによるフィルタリングを用いてすべてのGOLDポジションをクローズします。これにより、他のEAに影響を与えることを防ぎます。
    void CloseAllPositions()
    {
       for(int i = PositionsTotal() - 1; i >= 0; i--)
       {
          ulong ticket = PositionGetTicket(i);
          if(!PositionSelectByTicket(ticket) || PositionGetString(POSITION_SYMBOL) != SymbolName) continue;
          long magic = PositionGetInteger(POSITION_MAGIC);
          if(magic == MagicNumber(PERIOD_M15) || magic == MagicNumber(PERIOD_H1))
          {
             trade.PositionClose(ticket);
             Print("Emergency close: Ticket=", ticket);
          }
       }
    }
    OnTick():GOLD専用ロジックフロー

    OnTick関数は、このGOLD最適化EAの心臓部であり、新しいM15またはH1バーが形成されたときのみ実行され、ノイズを回避します。利益目標$6,600に到達した場合、または日次(2.5%)や全体(5.5%)のドローダウン制限を超えた場合には即座に取引を停止します。これは、資金提供型チャレンジをクリアするために絶対遵守されるルールです。リスクは動的に調整されます。連敗2回後には25%に減少し、連勝3回後には最大4.5%まで増加、エクイティ$7,000に達すると完全にリセットされます。カウンタートレンドの罠を避けるため、上位時間足のトレンド確認(D1/H4 EMA)が必須です。ブレイクアウトは、直近10バーの極値を少なくとも0.1 ATR(損失後には動的に増加)超える必要があります。ストップロスは1.5×ATRに設定され、テイクプロフィットはリスクの2.5倍で非対称リワードを実現します。証拠金のバッファは2.2×に設定され、ニュース時のGOLDの大幅スプレッドにも対応します。有効なシグナルが発生するたびに、市場注文が発行され、すべての取引が完全にログ記録されます。

    void OnTick()
    {
       datetime currentDay = TimeCurrent() / 86400 * 86400;
       if(currentDay > LastDay)
       {
          DailyBalance = AccountInfoDouble(ACCOUNT_BALANCE);
          LastDay = currentDay;
          DailyDDReached = false;
          Print("New day – Daily balance reset: $", DailyBalance);
       }
    
       double equity = AccountInfoDouble(ACCOUNT_EQUITY);
       double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    
       if(balance >= TargetBalanceOrEquity || equity >= TargetBalanceOrEquity)
       {
          CloseAllPositions();
          ProfitTargetReached = true;
          Print("GOLD CHALLENGE PASSED! Balance=$", balance, " | Trading paused.");
          return;
       }
       if(ProfitTargetReached) return;
    
       double dailyDD = (DailyBalance - equity) / DailyBalance * 100;
       double overallDD = (StartingBalance - equity) / StartingBalance * 100;
    
       if(dailyDD >= DailyDDLimit || overallDD >= OverallDDLimit)
       {
          CloseAllPositions();
          if(dailyDD >= DailyDDLimit) DailyDDReached = true;
          Print("GOLD DD BREACH! Daily: ", StringFormat("%.2f", dailyDD), "% | Overall: ", StringFormat("%.2f", overallDD), "%");
          return;
       }
    
       static datetime lastNewsFetch = 0;
       if(NewsFilt && TimeCurrent() >= lastNewsFetch + 4*3600)
       {
          FetchNewsCalendar();
          lastNewsFetch = TimeCurrent();
       }
    
       for(int i = 0; i < ArraySize(tfs); i++)
       {
          if(!NewBar(tfs[i].tf)) continue;
    
          bool hasPosition = false;
          for(int j = PositionsTotal()-1; j >= 0; j--)
          {
             ulong ticket = PositionGetTicket(j);
             if(PositionSelectByTicket(ticket) && PositionGetString(POSITION_SYMBOL) == SymbolName && PositionGetInteger(POSITION_MAGIC) == MagicNumber(tfs[i].tf))
             {
                hasPosition = true;
                break;
             }
          }
    
          if(hasPosition) { ManageTrades(tfs[i].tf); continue; }
    
    

    ManageTrades():GOLD向け三重保護

    この関数は、GOLDの急激な値動きに最適化された3つの強力な決済メカニズムを提供します。まず、強い反対方向のブレイクアウトが発生した場合(例:ロング中に強い下落ブレイクアウト)、ポジションを即座にクローズし、2000ポイント以上の急反転による損失を防ぎます。次に、リスクリワード1:2に到達した時点でポジションの50%を利確し、ストップロスを建値に移動することで、ニュース時の急変動に対して資本を保護します。第三に、ストップロスをATRの1.6倍でトレーリングし、FOMC後のブレイクアウトなど大きなトレンドに乗りつつ利益を守ります。この組み合わせにより、実際のGOLD取引において平均1:3以上のリスクリワードを実現することが確認されています。
    void ManageTrades(ENUM_TIMEFRAMES tf)
    {
       for(int i = PositionsTotal()-1; i >= 0; i--)
       {
          ulong ticket = PositionGetTicket(i);
          if(!PositionSelectByTicket(ticket) || PositionGetString(POSITION_SYMBOL) != SymbolName || PositionGetInteger(POSITION_MAGIC) != MagicNumber(tf)) continue;
    
          double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
          double sl = PositionGetDouble(POSITION_SL);
          double tp = PositionGetDouble(POSITION_TP);
          double lots = PositionGetDouble(POSITION_VOLUME);
          double profit = PositionGetDouble(POSITION_PROFIT);
          double currPrice = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? SymbolInfoDouble(SymbolName, SYMBOL_BID) : SymbolInfoDouble(SymbolName, SYMBOL_ASK);
    
          int idx = TimeframeIndex(tf);
          double atr[1];
          if(CopyBuffer(tfs[idx].h_atr, 0, 0, 1, atr) < 1) continue;
    
          if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && SellBrk(tf))
          {
             trade.PositionClose(ticket);
             LogTrd(ticket, SymbolName, openPrice, sl, tp, "Close", 0, 0, CurRisk, tf);
             continue;
          }
          if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && BuyBrk(tf))
          {
             trade.PositionClose(ticket);
             LogTrd(ticket, SymbolName, openPrice, sl, tp, "Close", 0, 0, CurRisk, tf);
             continue;
          }
    
          if((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && currPrice >= openPrice + (openPrice - sl) * 2) ||
             (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && currPrice <= openPrice - (sl - openPrice) * 2))
          {
             if(lots > SymbolInfoDouble(SymbolName, SYMBOL_VOLUME_MIN)*2)
             {
                trade.PositionClosePartial(ticket, lots/2);
                trade.PositionModify(ticket, openPrice, tp);
             }
          }
    
          double trail = atr[0] * 1.6 / _Point;
          if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && currPrice > openPrice + trail*_Point && sl < currPrice - trail*_Point)
             trade.PositionModify(ticket, currPrice - trail*_Point, tp);
          else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && currPrice < openPrice - trail*_Point && sl > currPrice + trail*_Point)
             trade.PositionModify(ticket, currPrice + trail*_Point, tp);
       }
    }
    最終まとめ:プロップファーム向けリスク管理EA

    このEAはGOLD(XAUUSD)専用に設計されており、適切な市場環境下でプロップファームチャレンジをクリアする可能性を高めます。すべてのパラメータ、フィルター、決済ルールはバックテストおよび実運用で精緻化されています。マルチタイムフレームによるブレイクアウト確認、適応的リスク管理、動的フィルター、ニュース回避、そして積極的な利益確定を一つの取引システムに統合しています。GOLD (XAUUSD)のH1チャートにて運用してください。
    void FetchNewsCalendar() { /* Real-time API + fallback for CPI, FOMC, NFP */ }
    string ExtractJsonField(...) { /* Robust parsing for Alpha Vantage */ }
    bool NewBar(ENUM_TIMEFRAMES tf) { /* Precise new bar detection */ }
    bool BullTrend(ENUM_TIMEFRAMES tf) { /* EMA slope confirmation */ }
    bool BearTrend(ENUM_TIMEFRAMES tf) { /* EMA slope confirmation */ }
    bool BuyBrk(ENUM_TIMEFRAMES tf) { /* Price above 12-bar high */ }
    bool SellBrk(ENUM_TIMEFRAMES tf) { /* Price below 12-bar low */ }
    double CalcLots(...) { /* ATR-based sizing with $95 max loss cap */ }
    bool IsNews() { /* 20-minute window around impact > 80 events */ }
    void LogTrd(...) { /* Full trade journal with streak updates */ }
    void AdjustBreakoutStrength() { /* Increases filter after 5/10 losses */ }
    long MagicNumber(ENUM_TIMEFRAMES tf) { /* 1015 for M15, 1060 for H1 */ }
    int TimeframeIndex(ENUM_TIMEFRAMES tf) { /* Fast array lookup */ }
    
    インストールとバックテスト:MetaEditorでコンパイルし、チャートに添付します。GOLDのバックテスト、H1(2025年)、リスク2%。 


    戦略テスト

    ブレイクアウトEAの戦略テスト

    この戦略は、GOLDに最も適しており、その理由はトレンドやボラティリティへの比較的迅速な順応性、同じブレイクアウトの概念、および高いボラティリティにあります。これらは、デイトレードおよび長期トレードの両方で、プロップファームの目標達成に有利に働きます。この戦略は、2025年以降の特定の月にGOLDを取引し、60分足(H1)でチャレンジをクリアできるかどうかを検証してテストします。以下に、この戦略で使用するパラメータを示します。 

    GOLD

    バックテストの設定


    入力設定


    ストラテジーテスターの結果

    ストラテジーテスターでテストを実施した結果、EAの動作、分析、及びパフォーマンスは以下の通りです。

    ブレイクアウトとリスクマネージャーEAに関する戦略テスターの結果

    残高/エクイティグラフ 

    1月には、EAは実際に目標を達成し、プロップファームチャレンジを違反なくクリアし、リセットまで取引を停止しました。

    1月の残高/エクイティグラフ

    2月には、予想通り変動の大きい市場環境でパフォーマンスが低下し、目標達成やチャレンジクリアはできませんでした。しかし、ドローダウンは2%にとどまり、いかなるルールやドローダウン制限も違反していません。

    2月のエクイティ/残高グラ

    4月には再び良好なパフォーマンスを示し、目標を達成して資金提供口座チャレンジをクリアし、リセットが完了するまで取引を停止しました。

    4月のグラフ


    バックテスト結果

    1月のデータ

    1月のチャレンジ合格データ

    2月のデータ

    2月のデータ

    4月のデータ

    4月のデータ


    まとめ

    本記事では、プロップファーム向けに特化して設計されたMetaTrader 5のEAについて解説しました。このEAは、取引およびリスク管理の手法を組み合わせ、GOLDにおける高確率の取引セットアップを識別し、実行しつつ、リスクやエクスポージャー、人為的ミスを体系的に最小化するよう設計されています。また、同じ取引・リスク管理プロトコルを用いて適切な決済ポイントも管理します。

    このEAは、プライスアクションに基づくエントリやトレンド変化の把握を可能にする、非常に価値のある革新的なプロップトレーディングEAの一つです。堅牢で柔軟性の高いリスク・取引管理ロジックにより、ドローダウンやプロップファームルール違反を最小化しながら、EAが最適なパフォーマンスを発揮できるよう設計されています。 

    このEAをGOLDでテストし、任意の時間足で効率的にエントリを検出できることを確認しました。しかし、エントリの検出はあくまで一部であり、EA内部には最適なエントリ検証ロジックが組み込まれており、特定の条件を満たした場合のみ取引が実行されます。取引が検証されて実行されると、取引およびリスク管理ロジックが即座に適用され、決済時まで適切な管理がおこなわれます。

    このEA戦略を実装するには、下記の入力パラメータを設定することで望ましい結果を得られます。EAは、トレーダーが選択した時間足(M15~D1)で可能性のあるエントリをスキャンし、トレンドや単純移動平均、ATRによるトレーリングストップと整合するポイントを検出します。興味のあるトレーダーは、まずデモ口座でGOLDを用いてバックテストをおこなうことを推奨します。このEAはGOLDに最適化されており、プロップファーム向けに高確率のセットアップと高度な売買ロジック、リスク管理、トレーリングストップを統合することを目的として設計されています。

    また、ユーザーには、定期的にパフォーマンスログを確認し、目標や資産クラス、リスク許容度に応じて設定や入力パラメータを調整することを推奨します。免責条項:このEAを使用する場合、まずデモ口座でテストし、ブレイクアウトおよび取引手法を習得してから、実資金で取引するようにしてください。


    結論

    本記事では、プロップファーム取引でトレーダーが直面する主な課題(リスク管理、取引管理、ドローダウン回避)を取り上げ、それらを簡略化し、資金提供を受ける可能性を高めるEAの設計方法を解説しています。

    多くのトレーダーは、適切なリスク管理や取引管理を十分に理解しておらず、その結果としてルール違反や損失が頻発します。本記事で提案するEAは、規律を維持する支援をおこない、トレーダーが自分の取引アイデアやポジションサイズ、セットアップを検証できるようにします。EAのエントリを直接使用しなくても、管理と検証が可能です。

    自動化されたMQL5EAは以下を提供します。

    • 日次および全体のドローダウン管理
    • ニュース時のボラティリティから保護するため、ニュース前後の取引をブロック
    • 確認されたシグナルのみでの取引エントリ、動的SL/TP対応
    • 適応型リスク管理(連敗時のロット削減、連勝時のロット増加)
    • 継続的な戦略最適化のための取引ログ記録
    • プロップファームルールの厳守
    • 感情による意思決定の排除
    • 自動取引管理(SL、TP、部分決済)

    これらの機能により、一貫した実行と最適なリスク管理が可能となり、ルール違反のリスクを低減し、プロップファーム取引でのパフォーマンス向上が期待できます。

    記事で参照されているすべてのコードは以下に添付されています。次の表では、この記事に付随するすべてのソースコードファイルについて説明します。

    ファイル名 説明
    Advanced Breakout Risk Management  EA.mq5 ブレイクアウトおよびリスク管理EAの完全なソースコードを含むファイル

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

    添付されたファイル |
    最後のコメント | ディスカッションに移動 (7)
    Eugene Mmene
    Eugene Mmene | 12 12月 2025 において 12:18
    Austin Reade ソースコードを ダウンロードしたのですが、それは大変な作業でした。

    どうすれば修正できるでしょうか?

    エラーの原因がわかったので、デバッグして再度アップロードします。
    Eugene Mmene
    Eugene Mmene | 12 12月 2025 において 12:19
    Laurent Xavier Richer #:

    置換文字列 TradeSymbol = _Symbol;

    次に、SymbolNameをTradeSymbolに置き換えます。

    スポット
    Muhammad Jawad Shabir
    Muhammad Jawad Shabir | 15 12月 2025 において 05:20
    #property copyright "Copyright 2025, Crystal Forex"
    #property link ""
    #property version   "1.50"
    #property description "🚀プロップ会社を圧倒する:XAUUSD専用に設計され、課題を粉砕する。"
    #property description "🛡️ インスティテューショナル・プロテクション: ハードコード化されたドローダウンとエクイティ・ガードにより、ルール違反は絶対にありません。"
    #property description "📈適応型ブレイクアウト:スマート・ニュース・フィルターとマルチタイムフレーム・ロジックが金の大きな動きを捉える。"
    #property description "💰ファンドレディ:トレーディングをプロのキャリアに変えるための完全自動化された規律"
    
    #include <Trade\Trade.mqh>
    
    //+------------------------------------------------------------------+
    //| 入力パラメータ|
    //+------------------------------------------------------------------+
    input group "Risk Management"
    input double RiskPct = 2.0;               // 取引ごとの基本リスク
    input double MaxLossUSD = 110.0;          // 米ドル建て取引ごとの最大損失額(ハードキャップ)
    input double DailyDDLimit = 2.5;          // 1日のドローダウンの上限 (%)
    input double OverallDDLimit = 5.5;        // 全体的なドローダウンの限度 (%)
    input double TargetBalanceOrEquity = 108000.0; // チャレンジ合格目標
    
    input group "Strategy Settings"
    input int    ATR_Prd = 14;                // ATR期間
    input int    Brk_Prd = 10;                // ブレイクアウト・ルックバック(小節)
    input double MinBrkStr = 0.1;             // 最低ブレイクアウト強度(ATR倍率)
    input int    EMA_Prd = 20;                // トレンドフィルターのEMA期間
    input bool   useHTF = true;               // HTF (D1/H4) 方向フィルタを使用する。
    
    input group "News Filter"
    input bool   NewsFilt = true;             // ニュースフィルターを有効にする
    input int    NewsPause = 15;              // ニュースの前後で一時停止する時間
    
    //+------------------------------------------------------------------+
    //| グローバル変数|
    //+------------------------------------------------------------------+
    double CurRisk = RiskPct;
    double LastEqHigh = 0;
    double StartingBalance = 0;
    double DailyBalance = 0;
    datetime LastDay = 0;
    bool ProfitTargetReached = false;
    bool DailyDDReached = false;
    double dynBrkStr = MinBrkStr; 
    
    CTrade trade;
    int h_ema_d1 = INVALID_HANDLE;
    int h_ema_h4 = INVALID_HANDLE;
    string WorkSymbol; // 組み込みのSymbolName()関数との衝突を避けるため、名前を変更しました。
    
    // 時間枠固有のデータの構造
    struct TimeframeData {
       ENUM_TIMEFRAMES tf;
       int h_atr;
       datetime lastSig;
       datetime lastBar;
    };
    TimeframeData tfs[];
    
    // ニュース・イベントの構成
    struct NewsEvt {
       datetime time;
       int impact; // 0=低、1=中、2=高
    };
    NewsEvt newsCal[];
    int newsCnt = 0;
    
    //+------------------------------------------------------------------+
    //| エキスパート初期化関数|
    //+------------------------------------------------------------------+
    int OnInit()
    {
    datetime ExpiryDate = D'2025.12.30'; // ここに有効期限を設定 (YYYY.MM.DD)
       
       if(TimeCurrent() > ExpiryDate)
       {
          Alert("Trial Expired! Please contact the developer: https://www.mql5.com/ja/users/jawadtrader22/seller");
          Print("Trial Expired! Please contact the developer.");
          return(INIT_FAILED); // これはEAの初期化を停止する。
       }
       if(AccountInfoDouble(ACCOUNT_BALANCE) < 100.0) {
          Print("Error: Balance too low for Prop Firm logic.");
          return(INIT_FAILED);
       }
    
       WorkSymbol = _Symbol;
       if(!SymbolSelect(WorkSymbol, true)) {
          Print("Failed to select symbol.");
          return(INIT_FAILED);
       }
    
       StartingBalance = AccountInfoDouble(ACCOUNT_BALANCE);
       LastEqHigh = AccountInfoDouble(ACCOUNT_EQUITY);
       DailyBalance = StartingBalance;
       LastDay = (datetime)(TimeCurrent() / 86400 * 86400); 
    
       ArrayResize(tfs, 2);
       tfs[0].tf = PERIOD_M15;
       tfs[1].tf = PERIOD_H1;
    
       for(int i = 0; i < 2; i++) {
          tfs[i].h_atr = iATR(WorkSymbol, tfs[i].tf, ATR_Prd);
          tfs[i].lastBar = 0;
          if(tfs[i].h_atr == INVALID_HANDLE) {
             Print("Failed to create ATR handle.");
             return(INIT_FAILED);
          }
       }
    
       h_ema_d1 = iMA(WorkSymbol, PERIOD_D1, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE);
       h_ema_h4 = iMA(WorkSymbol, PERIOD_H4, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE);
    
       if(h_ema_d1 == INVALID_HANDLE || h_ema_h4 == INVALID_HANDLE) {
          Print("Failed to create HTF EMA handles.");
          return(INIT_FAILED);
       }
    
       if(NewsFilt) FetchNewsCalendar();
    
       Print("EA Initialized. Target: ", DoubleToString(TargetBalanceOrEquity, 2));
       return(INIT_SUCCEEDED);
    }
    
    //+------------------------------------------------------------------+
    |エキスパート初期化関数|
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
       IndicatorRelease(h_ema_d1);
       IndicatorRelease(h_ema_h4);
       for(int i = 0; i < ArraySize(tfs); i++) {
          IndicatorRelease(tfs[i].h_atr);
       }
       Print("EA Deinitialized.");
    }
    
    //+------------------------------------------------------------------+
    //| エキスパート・ティック機能|
    //+------------------------------------------------------------------+
    void OnTick()
    {
       // デイリー・リセット・ロジック
       datetime currentDay = (datetime)(TimeCurrent() / 86400 * 86400);
       if(currentDay > LastDay) {
          DailyBalance = AccountInfoDouble(ACCOUNT_BALANCE);
          LastDay = currentDay;
          DailyDDReached = false;
          Print("New Day. Daily Balance Reset to: ", DoubleToString(DailyBalance, 2));
       }
    
       // --- プロップ・ファーム・チェック ---
       if(DailyDDReached || ProfitTargetReached) return;
    
       double equity = AccountInfoDouble(ACCOUNT_EQUITY);
       double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    
       if(balance >= TargetBalanceOrEquity || equity >= TargetBalanceOrEquity) {
          CloseAllPositions();
          ProfitTargetReached = true;
          Print("PROFIT TARGET REACHED! Trading Stopped.");
          return;
       }
    
       double dailyDD = (DailyBalance - equity) / DailyBalance * 100.0;
       double overallDD = (StartingBalance - equity) / StartingBalance * 100.0;
    
       if(dailyDD >= DailyDDLimit || overallDD >= OverallDDLimit) {
          CloseAllPositions();
          DailyDDReached = true;
          Print("DRAWDOWN LIMIT BREACHED! Daily: ", DoubleToString(dailyDD, 2), "%, Overall: ", DoubleToString(overallDD, 2), "%");
          return;
       }
    
       // ニュース更新
       static datetime lastNewsFetch = 0;
       if(NewsFilt && TimeCurrent() >= lastNewsFetch + 4*3600) {
          FetchNewsCalendar();
          lastNewsFetch = TimeCurrent();
       }
       if(NewsFilt && IsNews()) return;
    
       // --- ストラテジー・ループ
       for(int i = 0; i < ArraySize(tfs); i++) 
       {
          ManageTrades(tfs[i].tf);
    
          if(!NewBar(tfs[i].tf, tfs[i].lastBar)) continue;
    
          if(PositionsTotal() < 5) 
          {
             double atrVal = GetIndicatorVal(tfs[i].h_atr, 0);
             
             bool buySignal = BuyBrk(tfs[i].tf) && (!useHTF || BullTrend());
             bool sellSignal = SellBrk(tfs[i].tf) && (!useHTF || BearTrend());
    
             if(buySignal) {
                 double sl = SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) - (atrVal * 1.5);
                 double tp = SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) + (atrVal * 3.0);
                 double lots = CalcLots(MathAbs(SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) - sl));
                 
                 if(lots > 0) {
                     trade.SetExpertMagicNumber(MagicNumber(tfs[i].tf));
                     trade.Buy(lots, WorkSymbol, 0, sl, tp, "Gold Breakout Buy");
                 }
             }
             else if(sellSignal) {
                 double sl = SymbolInfoDouble(WorkSymbol, SYMBOL_BID) + (atrVal * 1.5);
                 double tp = SymbolInfoDouble(WorkSymbol, SYMBOL_BID) - (atrVal * 3.0);
                 double lots = CalcLots(MathAbs(sl - SymbolInfoDouble(WorkSymbol, SYMBOL_BID)));
                 
                 if(lots > 0) {
                     trade.SetExpertMagicNumber(MagicNumber(tfs[i].tf));
                     trade.Sell(lots, WorkSymbol, 0, sl, tp, "Gold Breakout Sell");
                 }
             }
          }
       }
    }
    
    //+------------------------------------------------------------------+
    //| ヘルパー関数|
    //+------------------------------------------------------------------+
    double CalcLots(double slPointsDistance)
    {
       if(slPointsDistance <= 0) return 0.0;
       double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
       double riskMoney = accountBalance * (CurRisk / 100.0);
       if(riskMoney > MaxLossUSD) riskMoney = MaxLossUSD; // ハードキャップ
       
       double tickValue = SymbolInfoDouble(WorkSymbol, SYMBOL_TRADE_TICK_VALUE);
       double tickSize = SymbolInfoDouble(WorkSymbol, SYMBOL_TRADE_TICK_SIZE);
       if(tickValue == 0 || tickSize == 0) return 0.0;
       
       double lots = riskMoney / ( (slPointsDistance / tickSize) * tickValue );
       double minLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MIN);
       double maxLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MAX);
       double stepLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_STEP);
       
       lots = MathFloor(lots / stepLot) * stepLot;
       if(lots < minLot) return 0.0;
       if(lots > maxLot) lots = maxLot;
       return lots;
    }
    
    void ManageTrades(ENUM_TIMEFRAMES tf)
    {
       for(int i = PositionsTotal()-1; i >= 0; i--)
       {
          ulong ticket = PositionGetTicket(i);
          if(!PositionSelectByTicket(ticket)) continue;
          if(PositionGetString(POSITION_SYMBOL) != WorkSymbol) continue;
          if(PositionGetInteger(POSITION_MAGIC) != MagicNumber(tf)) continue; 
    
          double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
          double sl = PositionGetDouble(POSITION_SL);
          double tp = PositionGetDouble(POSITION_TP);
          double lots = PositionGetDouble(POSITION_VOLUME);
          double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
          long type = PositionGetInteger(POSITION_TYPE);
          
          int tfIdx = (tf == PERIOD_M15) ? 0 : 1;
          double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 0);
    
          // 非常口
          if(type == POSITION_TYPE_BUY && SellBrk(tf)) { trade.PositionClose(ticket); continue; }
          if(type == POSITION_TYPE_SELL && BuyBrk(tf)) { trade.PositionClose(ticket); continue; }
    
          // パーシャルクローズ&BE
          double dist = (type == POSITION_TYPE_BUY) ? (currentPrice - openPrice) : (openPrice - currentPrice);
          if(dist > (atr * 2.5)) {
             bool isBE = (type == POSITION_TYPE_BUY && sl >= openPrice) || (type == POSITION_TYPE_SELL && sl <= openPrice);
             if(!isBE && lots >= SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MIN) * 2) {
                 trade.PositionClosePartial(ticket, lots / 2.0);
                 trade.PositionModify(ticket, openPrice, tp);
             }
          }
    
          // トレーリング・ストップ
          double trailDist = atr * 1.6;
          if(type == POSITION_TYPE_BUY) {
             double newSL = currentPrice - trailDist;
             if(newSL > sl && newSL < currentPrice) trade.PositionModify(ticket, newSL, tp);
          }
          else if(type == POSITION_TYPE_SELL) {
             double newSL = currentPrice + trailDist;
             if(newSL < sl || sl == 0) trade.PositionModify(ticket, newSL, tp);
          }
       }
    }
    
    bool BuyBrk(ENUM_TIMEFRAMES tf)
    {
       double close1 = iClose(WorkSymbol, tf, 1);
       int highIdx = iHighest(WorkSymbol, tf, MODE_HIGH, Brk_Prd, 2);
       if(highIdx < 0) return false;
       double highVal = iHigh(WorkSymbol, tf, highIdx);
       int tfIdx = (tf == PERIOD_M15) ? 0 : 1;
       double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 1);
       return (close1 > (highVal + (atr * dynBrkStr)));
    }
    
    bool SellBrk(ENUM_TIMEFRAMES tf)
    {
       double close1 = iClose(WorkSymbol, tf, 1);
       int lowIdx = iLowest(WorkSymbol, tf, MODE_LOW, Brk_Prd, 2);
       if(lowIdx < 0) return false;
       double lowVal = iLow(WorkSymbol, tf, lowIdx);
       int tfIdx = (tf == PERIOD_M15) ? 0 : 1;
       double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 1);
       return (close1 < (lowVal - (atr * dynBrkStr)));
    }
    
    bool BullTrend()
    {
       double d1_ema = GetIndicatorVal(h_ema_d1, 1);
       double d1_close = iClose(WorkSymbol, PERIOD_D1, 1);
       return (d1_close > d1_ema);
    }
    
    bool BearTrend()
    {
       double d1_ema = GetIndicatorVal(h_ema_d1, 1);
       double d1_close = iClose(WorkSymbol, PERIOD_D1, 1);
       return (d1_close < d1_ema);
    }
    
    bool IsNews()
    {
       datetime now = TimeCurrent();
       for(int i=0; i<newsCnt; i++) {
           if(newsCal[i].impact < 2) continue; 
           if(now >= newsCal[i].time - (NewsPause * 60) && now <= newsCal[i].time + (NewsPause * 60)) return true;
       }
       return false;
    }
    
    void FetchNewsCalendar()
    {
       // プレースホルダ:安全のためにニュースカウンタをリセットする
       newsCnt = 0; 
    }
    
    void CloseAllPositions()
    {
       for(int i = PositionsTotal() - 1; i >= 0; i--) {
          ulong ticket = PositionGetTicket(i);
          if(PositionSelectByTicket(ticket) && PositionGetString(POSITION_SYMBOL) == WorkSymbol) {
             trade.PositionClose(ticket);
          }
       }
    }
    
    double GetIndicatorVal(int handle, int index)
    {
       double buf[1];
       if(CopyBuffer(handle, 0, index, 1, buf) < 0) return 0.0;
       return buf[0];
    }
    
    bool NewBar(ENUM_TIMEFRAMES tf, datetime &last_bar_time)
    {
       datetime curr_bar_time = iTime(WorkSymbol, tf, 0);
       if(curr_bar_time != last_bar_time) {
          last_bar_time = curr_bar_time;
          return true;
       }
       return false;
    }
    
    long MagicNumber(ENUM_TIMEFRAMES tf)
    {
       if(tf == PERIOD_M15) return 1015;
       if(tf == PERIOD_H1) return 1060;
       return 1000;
    }
    コピーペースト完了
    Eugene Mmene
    Eugene Mmene | 16 12月 2025 において 23:02
    Austin Reade ソースコードを ダウンロードしたのですが、それは大変な作業でした。

    どうすれば修正できるでしょうか?

    修正したコードはこちらです。
    Eugene Mmene
    Eugene Mmene | 16 12月 2025 において 23:19
    Muhammad Jawad Shabir #:
    完全なコピー・ペースト・コード
    コードは同じではないが、結果は大きく異なる。
    EAのサンプル EAのサンプル
    一般的なMACDを使ったEAを例として、MQL4開発の原則を紹介します。
    MQL5における純粋なRSA暗号化の実装 MQL5における純粋なRSA暗号化の実装
    MQL5には組み込みの非対称暗号が存在しないため、HTTPのような安全でないチャネルでのデータ交換は困難です。本記事では、PKCS#1 v1.5パディングを用いた純粋なMQL5実装のRSAを紹介し、外部ライブラリを使用せずにAESのセッションキーや小規模なデータブロックを安全に送信できる方法を解説します。このアプローチにより、標準HTTP上でも、アプリケーションレベルでHTTPSに近い安全性を実現できるだけでなく、MQL5アプリケーションにおける安全な通信の重要なギャップを埋めることができます。
    エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
    この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
    MQL5標準ライブラリエクスプローラー(第5回):マルチシグナルEA MQL5標準ライブラリエクスプローラー(第5回):マルチシグナルEA
    本セッションでは、MQL5標準ライブラリを使用して、複数のシグナルを組み合わせた高度なエキスパートアドバイザー(EA)を構築します。このアプローチにより、組み込みシグナルと独自ロジックをシームレスに統合し、柔軟かつ強力な取引アルゴリズムの構築方法を示します。詳細については、続きをご覧ください。