MQL5 エラー完全ガイド|エラーコード一覧・原因・解決法・デバッグ

MQL5のEA開発で遭遇するエラーを網羅的にまとめました。EAが動かない時のチェックリスト、取引エラーの原因と解決法、コンパイルエラー対処法、エラーコード全一覧、エラーハンドリング実装、デバッグ手法まで、このページですべて解決できます。

目次

EAが動かない時のチェックリスト

EAをチャートに設置したのに何も起きない。ログにエラーも出ない。この状態の原因はほとんどの場合、コードのバグではなくMT5側の設定にあります。上から順に確認してください。

1. 自動売買ボタンがOFFになっている

MT5ツールバーの「アルゴリズム取引」ボタン(Algo Trading)を確認。これがOFFだと全EAが停止します。チャート右上のEA名の横にニコちゃんマークが表示されていればON、灰色アイコンならOFFです。

void OnTick()
  {
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      Print("エラー: ターミナルの自動売買が無効です");
      return;
     }
   if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
     {
      Print("エラー: このEAの自動売買が許可されていません");
      return;
     }
  }

2. EAのプロパティで取引が許可されていない

チャート上のEA名を右クリック → プロパティ → 「共通」タブ → 「自動売買を許可する」にチェック。WebRequestやDLLを使うEAは、それぞれの許可チェックも必要です。

3. 口座が取引可能な状態ではない

投資家パスワード(読み取り専用)でログインしている、デモ口座の有効期限が切れている、口座が無効化されている、のいずれかです。

int OnInit()
  {
   if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
     {
      Print("この口座では取引できません");
      Print("口座タイプ: ",
            EnumToString((ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE)));
     }
   return(INIT_SUCCEEDED);
  }

4. 市場が閉まっている

土日、祝日、メンテナンス時間帯はティックが配信されないため、OnTick()は一度も呼ばれません。MT5下部のステータスバーに接続状態が表示されます。

5. 通貨ペアまたは時間足が想定と違う

EAが特定の通貨ペアや時間足を前提にしている場合、違うチャートにセットしても想定通りに動きません。

int OnInit()
  {
   Print("通貨ペア: ", _Symbol, "  時間足: ", EnumToString(_Period));
   return(INIT_SUCCEEDED);
  }

6. エントリー条件が成立していない

コードに問題はなく、単に売買条件が発生していないだけのケースです。OnTick()の先頭にPrintを入れて、ティックが来ているか、条件判定のどこで止まっているかを確認してください。

void OnTick()
  {
   static int count = 0;
   count++;
   Print("Tick #", count);  // これが出力されればOnTickは呼ばれている
  }

7. スプレッドフィルターで弾かれている

早朝や指標発表前後はスプレッドが大きく広がります。EAにスプレッド制限を入れている場合、この時間帯はエントリーがブロックされます。

int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
Print("現在のスプレッド: ", spread, " point");

8. 時間フィルターで弾かれている

取引時間帯を制限している場合、サーバー時間とローカル時間のずれに注意。ブローカーによってサーバー時間のタイムゾーンが異なります。

Print("サーバー時間: ", TimeCurrent());
Print("GMT: ", TimeGMT());
Print("ローカル: ", TimeLocal());
Print("GMTオフセット: ", (int)(TimeCurrent() - TimeGMT()) / 3600, "時間");

9. 最大ポジション数に達している

EA側の制限またはブローカー側の制限でこれ以上ポジションを持てない状態です。

int myPositions = 0;
for(int i = 0; i < PositionsTotal(); i++)
  {
   ulong ticket = PositionGetTicket(i);
   if(PositionSelectByTicket(ticket))
     {
      if(PositionGetInteger(POSITION_MAGIC) == MagicNumber)
         myPositions++;
     }
  }
Print("このEAのポジション数: ", myPositions);

10. コンパイルしていない / 古い.ex5が動いている

ソースコード(.mq5)を修正しても、MetaEditorでコンパイル(F7)しないと変更は反映されません。コンパイル後、MT5側でEAを再読み込みする必要がある場合もあります。

よくある取引エラーの原因と解決

OrderSendが失敗したとき、MqlTradeResult.retcodeにエラーコードが格納されます。ここではEA開発で特に遭遇頻度が高いエラーを、原因と解決コード付きで解説します。

10016: TRADE_RETCODE_INVALID_STOPS — SL/TPが不正

EA開発で最も遭遇頻度が高いエラーです。SL/TPの位置が現在価格に近すぎる、または買い/売りの方向に対してSL/TPの位置が論理的に矛盾しています。

主な原因: ブローカーが定める最小ストップレベル(SYMBOL_TRADE_STOPS_LEVEL)より現在価格に近い位置にSL/TPを設定している。

// ❌ 10016になる例: SLが現在価格に近すぎる
request.sl = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - 1 * _Point;

// ✅ 最小ストップレベルを考慮した設定
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
int stopsLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
if(stopsLevel == 0) stopsLevel = 15;  // 0の場合は安全マージンを取る

double minDistance = stopsLevel * _Point;
double sl = NormalizeDouble(ask - MathMax(50 * _Point, minDistance), _Digits);
double tp = NormalizeDouble(ask + MathMax(50 * _Point, minDistance), _Digits);
  • SL/TPと現在価格の距離が SYMBOL_TRADE_STOPS_LEVEL × _Point 以上あるか
  • 買い注文: SL < Ask、TP > Ask になっているか
  • 売り注文: SL > Bid、TP < Bid になっているか
  • SL/TPの値が NormalizeDouble() で正規化されているか

10014: TRADE_RETCODE_INVALID_VOLUME — ロット数が不正

ロット数がブローカーの許容範囲外です。最小ロット未満、最大ロット超過、またはロットステップに合っていません。

double LotNormalize(string symbol, double lot)
  {
   double minLot  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
   double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);

   lot = MathMax(minLot, lot);
   lot = MathMin(maxLot, lot);
   lot = MathFloor(lot / lotStep) * lotStep;
   lot = NormalizeDouble(lot, 2);

   return lot;
  }

10019: TRADE_RETCODE_NO_MONEY — 資金不足

指定したロット数を建てるための証拠金が口座にありません。

double margin;
if(!OrderCalcMargin(ORDER_TYPE_BUY, _Symbol, lot, ask, margin))
  {
   Print("証拠金計算エラー");
   return;
  }

double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
if(margin > freeMargin)
  {
   Print("証拠金不足: 必要=", margin, " 利用可能=", freeMargin);
   return;
  }

10013: TRADE_RETCODE_INVALID — リクエストが不正

MqlTradeRequest構造体のフィールドに矛盾や不備があります。最も多い原因はactionフィールドの指定漏れ、またはtype_fillingの未指定です。

MqlTradeRequest request = {};
request.action       = TRADE_ACTION_DEAL;          // 必須: 成行注文
request.symbol       = _Symbol;                     // 必須: 通貨ペア
request.volume       = 0.1;                         // 必須: ロット数
request.type         = ORDER_TYPE_BUY;              // 必須: 売買方向
request.price        = SymbolInfoDouble(_Symbol, SYMBOL_ASK);  // 必須: 価格
request.deviation    = 10;                          // 推奨: 許容スリッページ
request.type_filling = ORDER_FILLING_FOK;           // 推奨: 充填タイプ
request.magic        = MagicNumber;                 // 推奨: EA識別用

10030: TRADE_RETCODE_INVALID_FILL — 充填タイプが不正

type_fillingに指定した充填タイプ(FOK/IOC/RETURN)を、そのブローカー・銘柄がサポートしていません。

ENUM_ORDER_TYPE_FILLING GetFillingType(string symbol)
  {
   int filling = (int)SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);

   if((filling & SYMBOL_FILLING_FOK) == SYMBOL_FILLING_FOK)
      return ORDER_FILLING_FOK;
   if((filling & SYMBOL_FILLING_IOC) == SYMBOL_FILLING_IOC)
      return ORDER_FILLING_IOC;

   return ORDER_FILLING_RETURN;
  }

10027: TRADE_RETCODE_CLIENT_DISABLES_AT — 自動取引が無効

MT5の「アルゴリズム取引」ボタンがOFFになっています。コードの問題ではなくMT5の設定の問題です。

int OnInit()
  {
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      Alert("自動売買を有効にしてください");
      return INIT_FAILED;
     }
   return INIT_SUCCEEDED;
  }

コンパイルエラー一覧と対処法

MetaEditorでF7を押してコンパイルした際に表示されるエラーです。コンパイルエラーがあるとEAは動作しません。

エラーは上から順に直してください。最初の1つを直すだけで後続のエラーが消えることが多いです。

構文エラー

エラーメッセージ原因対処
';' expectedセミコロン忘れエラー行の前の行の末尾を確認
')' expected閉じ括弧の不足if文やfor文の条件式の括弧を確認
'}' expected閉じ波括弧の不足Ctrl+, でインデント整形して対応を可視化
unexpected token予期しない文字前の行にセミコロン忘れがないか確認
expressions are not allowed on a global scope関数の外にコードがある実行文がOnTick等の関数内にあるか確認

変数・型エラー

エラーメッセージ原因対処
'xxx' - undeclared identifier変数が未宣言スペルミス(大文字小文字含む)か宣言忘れ
'xxx' - variable already defined同名変数が2回宣言同じスコープ内で重複していないか確認
implicit conversion数値→文字列の暗黙変換IntegerToString()DoubleToString()で明示変換
possible loss of data精度が失われる型変換(int)等で明示キャストすれば消える(警告)
constant variable cannot be modifiedconst変数への代入constを外すか別の変数に代入

関数エラー

エラーメッセージ原因対処
'xxx' - wrong parameters count引数の数が違うMQL4とMQL5で引数が変わった関数に注意
'xxx' - function not defined関数が存在しないスペルミスか、MQL4専用関数を使っていないか確認
not all control paths return a value一部のパスでreturnがないif/elseの全分岐でreturnを入れる
cannot open file 'xxx.mqh'インクルードファイルが見つからない<>はIncludeフォルダ、””はカレントフォルダ

取引リターンコード全一覧(ENUM_TRADE_RETCODE)

OrderSend / OrderSendAsync の実行結果として MqlTradeResult.retcode に格納されるコードの全一覧です。

コード定数名意味
10004TRADE_RETCODE_REQUOTEリクオート
10006TRADE_RETCODE_REJECTリクエスト拒否
10007TRADE_RETCODE_CANCELトレーダーによるキャンセル
10008TRADE_RETCODE_PLACED注文が発注された
10009TRADE_RETCODE_DONEリクエスト完了
10010TRADE_RETCODE_DONE_PARTIAL部分的に完了
10011TRADE_RETCODE_ERROR一般的な処理エラー
10012TRADE_RETCODE_TIMEOUTタイムアウト
10013TRADE_RETCODE_INVALID無効なリクエスト
10014TRADE_RETCODE_INVALID_VOLUME無効なロット数
10015TRADE_RETCODE_INVALID_PRICE無効な価格
10016TRADE_RETCODE_INVALID_STOPS無効なSL/TP
10017TRADE_RETCODE_TRADE_DISABLED取引無効
10018TRADE_RETCODE_MARKET_CLOSED市場閉鎖
10019TRADE_RETCODE_NO_MONEY資金不足
10020TRADE_RETCODE_PRICE_CHANGED価格変動
10021TRADE_RETCODE_PRICE_OFF気配値なし
10022TRADE_RETCODE_INVALID_EXPIRATION無効な有効期限
10023TRADE_RETCODE_ORDER_CHANGED注文状態が変更された
10024TRADE_RETCODE_TOO_MANY_REQUESTSリクエスト過多
10025TRADE_RETCODE_NO_CHANGES変更なし
10026TRADE_RETCODE_SERVER_DISABLES_ATサーバー側で自動取引無効
10027TRADE_RETCODE_CLIENT_DISABLES_ATクライアント側で自動取引無効
10028TRADE_RETCODE_LOCKEDリクエストがロック中
10029TRADE_RETCODE_FROZEN注文/ポジションが凍結
10030TRADE_RETCODE_INVALID_FILL無効な充填タイプ
10031TRADE_RETCODE_CONNECTION接続なし
10032TRADE_RETCODE_ONLY_REALリアル口座でのみ許可
10033TRADE_RETCODE_LIMIT_ORDERS待機注文数の上限
10034TRADE_RETCODE_LIMIT_VOLUMEボリューム上限
10035TRADE_RETCODE_INVALID_ORDER無効な注文タイプ
10036TRADE_RETCODE_POSITION_CLOSEDポジションは既にクローズ済み
10038TRADE_RETCODE_INVALID_CLOSE_VOLUME無効な決済ボリューム
10039TRADE_RETCODE_CLOSE_ORDER_EXIST既に決済注文が存在
10040TRADE_RETCODE_LIMIT_POSITIONSポジション数の上限
10041TRADE_RETCODE_REJECT_CANCELキャンセル拒否
10042TRADE_RETCODE_LONG_ONLY買いのみ許可
10043TRADE_RETCODE_SHORT_ONLY売りのみ許可
10044TRADE_RETCODE_CLOSE_ONLY決済のみ許可
10045TRADE_RETCODE_FIFO_CLOSEFIFO順の決済のみ許可

ランタイムエラー一覧

GetLastError() で取得できるランタイムエラーです。取引リターンコードとは別の体系です。

コード定数名意味
0ERR_SUCCESSエラーなし
4001ERR_INTERNAL_ERROR予期しない内部エラー
4003ERR_INVALID_PARAMETER関数のパラメータ不正
4004ERR_NOT_ENOUGH_MEMORYメモリ不足
4014ERR_FUNCTION_NOT_ALLOWEDシステム関数の呼び出し不可
4101ERR_WRONG_FILENAME無効なファイル名
4103ERR_CANNOT_OPEN_FILEファイルを開けない
4301ERR_UNKNOWN_SYMBOL不明なシンボル
4302ERR_INDICATOR_CANNOT_INITインジケーター初期化失敗
4303ERR_INDICATOR_CANNOT_CREATEインジケーター作成失敗
4401ERR_ARRAY_RESIZE_ERROR配列リサイズ失敗
5004ERR_WEBREQUEST_INVALID_ADDRESSWebRequestのURL不正
5200ERR_WEBREQUEST_TIMEOUTWebRequestタイムアウト
5201ERR_WEBREQUEST_REQUEST_FAILEDWebRequestリクエスト失敗

エラーハンドリングの実装方法

GetLastError / ResetLastError

GetLastError() は直前の関数呼び出しで発生したランタイムエラーのコードを返します。取引エラー(retcode)とは別の仕組みです。

int handle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE);
if(handle == INVALID_HANDLE)
  {
   int err = GetLastError();
   Print("iMA作成失敗: エラーコード=", err);
   return;
  }

// ResetLastError: エラーコードを0にリセット
// 複数の関数を連続して呼ぶ前にリセットしておくと
// どの関数でエラーが発生したか特定しやすい
ResetLastError();
double value[];
int copied = CopyBuffer(handle, 0, 0, 1, value);
if(copied <= 0)
  {
   int err = GetLastError();
   Print("CopyBuffer失敗: エラーコード=", err);
  }
注意

GetLastError() はエラーコードを返しますが、MQL5では自動リセットされません。エラーコードをリセットするには ResetLastError() を明示的に呼ぶ必要があります。複数の関数を連続して呼ぶ場合は、各呼び出しの前に ResetLastError() でリセットしてください。

リトライパターンの実装

リクオートや価格変動など、リトライで解決するエラーには自動リトライが有効です。ただしリトライすべきでないエラーを無限リトライすると問題になるので、エラー種別の判定が重要です。

// リトライ対象のエラーかどうか判定
bool IsRetryableError(uint retcode)
  {
   switch(retcode)
     {
      case TRADE_RETCODE_REQUOTE:
      case TRADE_RETCODE_PRICE_CHANGED:
      case TRADE_RETCODE_PRICE_OFF:
      case TRADE_RETCODE_TIMEOUT:
      case TRADE_RETCODE_CONNECTION:
         return true;
      default:
         return false;
     }
  }

// リトライ付き注文送信
bool OrderSendWithRetry(MqlTradeRequest &request, MqlTradeResult &result, int maxRetry = 3)
  {
   for(int attempt = 1; attempt <= maxRetry; attempt++)
     {
      // 成行注文の場合、毎回最新価格を取得
      if(request.action == TRADE_ACTION_DEAL)
        {
         if(request.type == ORDER_TYPE_BUY)
            request.price = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
         else if(request.type == ORDER_TYPE_SELL)
            request.price = SymbolInfoDouble(request.symbol, SYMBOL_BID);
        }

      if(!OrderSend(request, result))
        {
         Print("OrderSend失敗 (attempt ", attempt, "): ", GetLastError());
         return false;
        }

      if(result.retcode == TRADE_RETCODE_DONE
         || result.retcode == TRADE_RETCODE_PLACED)
        {
         Print("注文成功: ticket=", result.order);
         return true;
        }

      if(!IsRetryableError(result.retcode))
        {
         Print("リトライ不可: ", result.retcode, " ", result.comment);
         return false;
        }

      Print("リトライ (", attempt, "/", maxRetry, "): ", result.retcode);
      Sleep(300 * attempt);  // 間隔を徐々に広げる
     }

   Print("リトライ上限に達しました");
   return false;
  }

デバッグの方法

MQL5で最も基本的な3つのデバッグ手段です。出力先が異なります。

関数出力先用途
Print()操作履歴タブ / ログファイルメインのデバッグ手段。ログに残る
Comment()チャート左上リアルタイムの値をチャート上に表示
Alert()ポップアップダイアログ重要なイベントの通知。多用注意
void OnTick()
  {
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

   // ログに記録
   Print("Ask=", ask, " Bid=", bid, " Spread=", spread);

   // チャート上にリアルタイム表示
   Comment("Ask: ", ask, "\n",
           "Bid: ", bid, "\n",
           "Spread: ", spread, " pt");

   // PrintFormat: 書式指定で出力を整える
   PrintFormat("残高: %.2f  証拠金: %.2f  損益: %+.2f",
              AccountInfoDouble(ACCOUNT_BALANCE),
              AccountInfoDouble(ACCOUNT_MARGIN),
              AccountInfoDouble(ACCOUNT_PROFIT));
  }

MetaEditorのデバッガ

  1. MetaEditorでソースコードを開く
  2. 止めたい行の左側をクリック → 赤い丸(ブレークポイント)が表示される
  3. F5でデバッグ開始(ストラテジーテスターが起動する)
  4. ブレークポイントで停止したら「ウォッチ」ウィンドウで変数の値を確認
  5. F10でステップ実行(1行ずつ進む)、F11でステップイン(関数の中に入る)

デバッガはストラテジーテスター上で動作します。ライブチャートでのデバッグはできません。ライブではPrintを使ってください。

ログの読み方

MT5のログは2箇所にあります。

  • 操作履歴タブ(MT5画面下部 → ツールボックス → 操作履歴): EAのPrint出力とシステムメッセージが表示されます。右クリック →「自動スクロール」をONにすると便利です。
  • ログファイル: MT5の「ファイル」→「データフォルダを開く」→ Logs フォルダ内に日付ごとに保存されます。

OnInit()で初期状態をまとめて出力しておくと、後からログを確認する際に便利です。

int OnInit()
  {
   Print("========== EA START ==========");
   Print("EA: ", MQLInfoString(MQL_PROGRAM_NAME));
   Print("Symbol: ", _Symbol, "  Period: ", EnumToString(_Period));
   Print("Account: ", AccountInfoInteger(ACCOUNT_LOGIN),
         "  Server: ", AccountInfoString(ACCOUNT_SERVER));
   Print("Balance: ", AccountInfoDouble(ACCOUNT_BALANCE),
         "  Leverage: 1:", AccountInfoInteger(ACCOUNT_LEVERAGE));
   Print("Trade allowed (terminal): ", TerminalInfoInteger(TERMINAL_TRADE_ALLOWED));
   Print("Trade allowed (EA): ", MQLInfoInteger(MQL_TRADE_ALLOWED));
   Print("==============================");
   return INIT_SUCCEEDED;
  }

あなたのEAをシストレ.COMで販売しませんか? → 出品について

シストレ.COMで実績のあるEAが使い放題!/
無料会員登録はこちら
FX自動売買でEAを探すなら
シストレ.COM
実績あるEAが無料
厳格な審査を乗り越えた実績のあるEAが無料で使えます!
自由な口座選び
有料版を購入し柔軟な口座選びが可能!
フォワードテスト公開
全EAのフォワードテスト結果を公開中!
FX初心者も安心
初心者の方も安心して取引を始められます。
多様なEA選択肢
様々な種別のEAをご用意!自分の手法にあった取引が可能です。
信頼のFX会社と提携
人気のFX会社と提携中!様々なFX会社から選べます。
1分で登録完了!EA探すならシストレ.COM!/
無料会員登録はこちら
【FX自動売買】システムトレード完全ガイド|Forex Guide

この記事が気に入ったら
フォローしてね!

お役立ち情報をシェアする
  • URLをコピーしました!
目次