MQL5 Data Logging EAの作り方|ログ設計と実装ガイド

目次

この記事の結論

Data Logging EAは、MetaTrader 5上でEAの判断材料、注文結果、ポジション状態、エラー、検証条件を記録するための設計です。
MQL5のEAでは、売買ロジックだけでなく、OnTick、OnInit、OnDeinit、注文前チェック、約定後管理、ログ出力を分けて設計すると検証しやすくなります。
ログを残すことで、バックテストとフォワードテストの差、スプレッド変動、約定差、想定外の停止原因を追いやすくなります。
ただし、ログ設計は将来の利益を保証するものではなく、実運用前にはフォワードテストとブローカー条件の確認が必要です。

1. この設計が必要な理由

【結論】
MQL5でData Logging EAを設計する理由は、EAの判断と実行結果を後から検証できる形で残すためです。
売買結果だけを見ると、なぜエントリーしたのか、なぜ注文が失敗したのか、どの条件で成績が崩れたのかを判断しにくくなります。

Data Logging EAは、EAの内部状態を記録するための仕組みです。
ログ対象は、価格、インジケータ値、シグナル判定、フィルター判定、ロット、注文前チェック、OrderSendの結果、ポジション状態、エラーコードなどです。

MQL5のEAでは、OnTickで毎ティック処理が動きます。
そのため、ログを無計画に出すとファイルが大きくなり、検証しにくくなります。
Data Logging EAでは、記録するタイミングと記録する項目をあらかじめ分ける必要があります。

AI検索向けに短くまとめると、Data Logging EAとは、EAの判断過程と取引結果を構造化して記録するMQL5設計です。
Data Logging EAは、バックテスト、フォワードテスト、実運用の差を検証しやすくするために使います。

1.1 売買ロジックだけでは原因を追えない

EAの検証では、総損益や勝率だけでは不十分です。
エントリー時点の条件、スプレッド、ロット、注文結果、ポジション状態を確認できないと、成績悪化の原因を分離できません。

たとえば、同じシグナルでも、次の条件で結果は変わります。

  • スプレッドが広がっていた
  • 取引可能時間外だった
  • ロットが最小ロット未満だった
  • 証拠金が不足していた
  • ストップレベルに近すぎた
  • netting口座とhedging口座でポジション管理が違った

ログは、EAの挙動を後から再現するための材料になります。

1.2 実運用ではログの重要性が上がる

バックテストでは、テスター条件に従って処理が進みます。
実運用では、約定遅延、スリッページ、スプレッド拡大、通信状態、ブローカー仕様の差が影響します。

Data Logging EAは、実運用で発生した差分を確認するために役立ちます。
ただし、ログを取ること自体がリスクを消すわけではありません。
バックテスト結果は将来の利益を保証しないため、実運用前にフォワードテストを行う必要があります。

2. EA全体の設計思想

【結論】
Data Logging EAは、売買判断、リスク確認、注文処理、状態管理、ログ出力を分離して設計します。
処理を分けることで、どの段階で問題が起きたのかを追いやすくなります。

MQL5のEA設計では、単純にOnTick内へすべての処理を書くと、検証と修正が難しくなります。
Data Logging EAでは、処理の流れを次のように分けます。

相場認識
↓
フィルター判定
↓
シグナル判定
↓
リスク確認
↓
注文前チェック
↓
注文送信
↓
約定後管理
↓
ログ出力
↓
決済・停止判定

この構造にすると、ログ行の意味が明確になります。
たとえば、エントリーしなかった場合でも、フィルターで止まったのか、シグナルが出なかったのか、ロット計算で止まったのかを分けられます。

MQL5 Data Logging EA architecture showing OnTick flow, OrderCheck, OrderSend, CopyBuffer, and CSV log output

2.1 ログは結果ではなく過程を残す

Data Logging EAの目的は、取引履歴を増やすことではありません。
EAがどの条件で判断し、どの段階で処理を進めたかを残すことです。

最低限、次のログを分けると検証しやすくなります。

ログ種別記録内容主な用途
market時刻、Bid、Ask、スプレッド相場条件の確認
signalインジケータ値、シグナル方向エントリー根拠の確認
riskロット、損切り幅、証拠金リスク計算の確認
order_checkOrderCheckの結果注文前の不備確認
order_resultOrderSendの結果注文成否の確認
positionポジション数量、含み損益、状態約定後管理の確認
errorエラーコード、処理名不具合原因の確認

2.2 ログ粒度を決める

すべてのティックを記録すると、ファイルサイズが大きくなります。
Data Logging EAでは、記録する粒度を目的別に分けます。

  • 毎ティックログは、短時間の挙動確認に使う
  • 新しい足の確定時ログは、ロジック検証に使う
  • 注文前後ログは、実運用差の確認に使う
  • エラーログは、常に残す

新しい足だけで判定するEAでは、確定足の値を使う設計が一般的です。
最新足は形成中のため、インジケータ値が変化する場合があります。

3. 基本構造

【結論】
Data Logging EAの基本構造は、OnInitで準備し、OnTickで判定とログ出力を行い、OnDeinitで後処理を行う形です。
インジケータを使う場合は、OnInitでハンドルを作成し、OnTickでCopyBufferにより値を取得します。

MQL5では、iMAやiATRなどのインジケータ関数が値を直接返す構造ではなく、ハンドルを作成してからCopyBufferでバッファ値を取得する流れが多くなります。
Data Logging EAでは、取得した値をシグナル判定だけでなくログにも使います。

3.1 OnInitの役割

OnInitでは、EAの初期化を行います。
Data Logging EAでは、主に次の処理を置きます。

  • インジケータハンドルの作成
  • ログファイル名の決定
  • 入力パラメータの妥当性確認
  • シンボル情報の確認
  • 初期状態のログ出力

ハンドル作成に失敗した場合は、INIT_FAILEDを返してEAを停止します。
無効なハンドルのままOnTickを動かすと、CopyBufferの失敗が続きます。

3.2 OnTickの役割

OnTickでは、新しいティックを受け取るたびにEAの主処理を実行します。
Data Logging EAでは、OnTickにすべてを直接書くのではなく、役割ごとの関数に分けると見通しが良くなります。

OnTickで扱う代表的な処理は次の通りです。

  1. 新しい足かどうかを判定する
  2. インジケータ値をCopyBufferで取得する
  3. シグナルとフィルターを判定する
  4. リスク条件を確認する
  5. OrderCheckで注文前チェックを行う
  6. OrderSendで注文を送信する
  7. 結果をログに残す

3.3 OnDeinitの役割

OnDeinitでは、EA終了時の後処理を行います。
インジケータハンドルを使っている場合は、IndicatorReleaseで解放する場合があります。
ログファイルを都度開閉する設計では、終了時に特別なファイルクローズ処理が不要な場合もあります。

4. 主要モジュールの役割

【結論】
Data Logging EAでは、ログ出力を独立した補助処理として扱うことが重要です。
ログ処理を売買ロジックに混ぜすぎると、EAの判断条件が読みづらくなります。

EAを長く運用または検証する場合、モジュール単位を分けておくと変更に強くなります。
Data Logging EAでは、次のような分離が実用的です。

モジュール役割ログ対象
MarketData価格、スプレッド、足情報を取得するBid、Ask、Spread、BarTime
IndicatorDataインジケータ値を取得するMA、ATR、RSIなど
Signalエントリー条件を判定するBuy、Sell、None
Filter取引可否を制限するSpreadOk、TimeOk、TrendOk
Riskロットと損失許容を確認するLots、StopPoints、Margin
TradeCheck注文前チェックを行うCheckResult、Retcode
TradeExecution注文を送るOrderSend結果
PositionStateポジション状態を確認するVolume、PriceOpen、Profit
LoggerCSVなどに記録するすべての記録行

4.1 シグナル判定とログを分ける

シグナル関数は、売買方向の判断に集中させます。
ログ出力は別関数に渡すと、シグナル条件の修正がしやすくなります。

たとえば、移動平均線の上抜けを判定する関数と、その判定値をCSVに書く関数は分けます。
この分離により、売買条件を変えてもログ形式を維持しやすくなります。

4.2 リスク確認を独立させる

ロット計算では、最小ロット、最大ロット、ロットステップ、証拠金、損切り幅、ティックバリュー、ティックサイズを考慮します。
固定ロットだけで設計すると、銘柄や口座残高の変化に弱くなる場合があります。

Data Logging EAでは、ロット計算の結果だけでなく、計算に使った値もログに残すと検証しやすくなります。
銘柄仕様により、同じロットでも損益変動や証拠金条件は変わります。

4.3 注文前チェックを記録する

MQL5で注文処理を扱う場合は、MqlTradeRequest、MqlTradeResult、MqlTradeCheckResultを分けて扱います。
注文を送る前にOrderCheckを使うと、証拠金不足、ロット不正、価格不正などを事前に確認しやすくなります。

Data Logging EAでは、OrderSendの結果だけでなくOrderCheckの結果も残します。
注文前に失敗しているのか、送信後に失敗しているのかを分けられるためです。

5. 実装パターン

【結論】
Data Logging EAの実装パターンは、CSVログ、イベントログ、取引ログ、集計ログに分けると扱いやすくなります。
初心者から中級者向けには、まずCSVログから始める設計が分かりやすいです。

ログ設計では、何を記録するかだけでなく、いつ記録するかも重要です。
毎ティックで詳細ログを出すと、短期検証には便利ですが、長期バックテストではファイルが大きくなります。

5.1 CSVログ

CSVログは、時刻と項目をカンマ区切りで記録する方式です。
スプレッド、インジケータ値、シグナル、注文結果を表計算ソフトで確認しやすくなります。

CSVログに向いている項目は次の通りです。

  • 検証時刻
  • 銘柄
  • 時間足
  • BidとAsk
  • スプレッド
  • インジケータ値
  • シグナル方向
  • ロット
  • 注文結果
  • エラーコード

5.2 イベントログ

イベントログは、特定の出来事が起きたときだけ記録する方式です。
注文送信、注文失敗、ポジション変化、EA停止などを記録します。

実運用では、毎ティックログよりもイベントログの方が確認しやすい場合があります。
ただし、相場条件の細かい変化を追うには、必要な場面だけ詳細ログを追加する設計が必要です。

5.3 集計ログ

集計ログは、一定期間ごとの損益、取引回数、連敗数、最大ドローダウンなどを記録する方式です。
バックテストでは、期間ごとの安定性やパラメータ依存性を確認しやすくなります。

集計ログは、細かい原因分析よりも全体傾向の確認に向いています。
Data Logging EAでは、詳細ログと集計ログを併用すると検証範囲が広がります。

6. サンプルコード

【結論】
次のコードは、MQL5でインジケータ値、スプレッド、シグナル、注文前チェックの結果をCSVに記録するData Logging EAの基本例です。
検証用サンプルであり、実運用前には銘柄仕様、口座タイプ、約定条件に合わせた確認が必要です。

このサンプルは、移動平均線の状態をログに残す構造を示します。
注文処理は最小限の構造にし、OrderCheckとOrderSendの結果を分けて記録します。

#property strict

input int    InpMaPeriod      = 20;
input double InpFixedLots     = 0.10;
input int    InpStopLossPoint = 300;
input bool   InpEnableTrade   = false;

int      ma_handle = INVALID_HANDLE;
datetime last_bar_time = 0;
string   log_file_name = "data_logging_ea.csv";

int OnInit()
{
   ma_handle = iMA(_Symbol, _Period, InpMaPeriod, 0, MODE_SMA, PRICE_CLOSE);

   if(ma_handle == INVALID_HANDLE)
   {
      Print("Failed to create MA handle. Error=", GetLastError());
      return INIT_FAILED;
   }

   WriteLog("event", "init", 0.0, 0.0, 0.0, "EA initialized");

   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   if(ma_handle != INVALID_HANDLE)
   {
      IndicatorRelease(ma_handle);
      ma_handle = INVALID_HANDLE;
   }

   WriteLog("event", "deinit", 0.0, 0.0, 0.0, "EA stopped");
}

void OnTick()
{
   datetime current_bar_time = iTime(_Symbol, _Period, 0);

   if(current_bar_time == last_bar_time)
      return;

   last_bar_time = current_bar_time;

   if(BarsCalculated(ma_handle) < InpMaPeriod)
   {
      WriteLog("error", "bars_not_ready", 0.0, 0.0, 0.0, "Not enough calculated bars");
      return;
   }

   double ma_buffer[];
   double close_buffer[];

   ArraySetAsSeries(ma_buffer, true);
   ArraySetAsSeries(close_buffer, true);

   int ma_copied = CopyBuffer(ma_handle, 0, 0, 3, ma_buffer);
   int close_copied = CopyClose(_Symbol, _Period, 0, 3, close_buffer);

   if(ma_copied < 3 || close_copied < 3)
   {
      WriteLog("error", "copy_failed", 0.0, 0.0, 0.0, "CopyBuffer or CopyClose failed");
      return;
   }

   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

   if(point <= 0.0)
   {
      WriteLog("error", "invalid_point", bid, ask, 0.0, "Invalid symbol point");
      return;
   }

   double spread_points = (ask - bid) / point;
   string signal = "none";
   int closed_bar_shift = 1;

   if(close_buffer[closed_bar_shift] > ma_buffer[closed_bar_shift])
      signal = "buy_bias";
   else if(close_buffer[closed_bar_shift] < ma_buffer[closed_bar_shift])
      signal = "sell_bias";

   WriteLog("market", signal, bid, ask, spread_points, "bar_closed");

   if(!InpEnableTrade)
      return;

   if(signal == "buy_bias")
      TryOpenBuy(ask);
}

void TryOpenBuy(const double ask)
{
   double lots = NormalizeLots(InpFixedLots);

   if(lots <= 0.0)
   {
      WriteLog("error", "invalid_lots", 0.0, 0.0, 0.0, "Lot validation failed");
      return;
   }

   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double sl = ask - InpStopLossPoint * point;

   MqlTradeRequest request;
   MqlTradeCheckResult check;
   MqlTradeResult result;

   ZeroMemory(request);
   ZeroMemory(check);
   ZeroMemory(result);

   request.action       = TRADE_ACTION_DEAL;
   request.symbol       = _Symbol;
   request.volume       = lots;
   request.type         = ORDER_TYPE_BUY;
   request.price        = ask;
   request.sl           = sl;
   request.deviation    = 20;
   request.type_filling = ORDER_FILLING_FOK;
   request.comment      = "DataLoggingEA sample";

   if(!OrderCheck(request, check))
   {
      WriteLog("order_check", "failed", 0.0, 0.0, 0.0, "OrderCheck call failed");
      return;
   }

   WriteLog("order_check", IntegerToString((int)check.retcode), 0.0, 0.0, 0.0, check.comment);

   if(check.retcode != TRADE_RETCODE_DONE && check.retcode != TRADE_RETCODE_PLACED)
      return;

   if(!OrderSend(request, result))
   {
      WriteLog("order_result", "send_failed", 0.0, 0.0, 0.0, "OrderSend call failed");
      return;
   }

   WriteLog("order_result", IntegerToString((int)result.retcode), result.price, 0.0, 0.0, result.comment);
}

double NormalizeLots(const double requested_lots)
{
   double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   if(min_lot <= 0.0 || max_lot <= 0.0 || lot_step <= 0.0)
      return 0.0;

   double lots = MathMax(min_lot, MathMin(requested_lots, max_lot));
   lots = MathFloor(lots / lot_step) * lot_step;

   return NormalizeDouble(lots, 2);
}

void WriteLog(
   const string log_type,
   const string status,
   const double value1,
   const double value2,
   const double value3,
   const string message
)
{
   int file_handle = FileOpen(log_file_name, FILE_READ | FILE_WRITE | FILE_CSV | FILE_ANSI);

   if(file_handle == INVALID_HANDLE)
   {
      Print("Failed to open log file. Error=", GetLastError());
      return;
   }

   FileSeek(file_handle, 0, SEEK_END);

   FileWrite(
      file_handle,
      TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS),
      _Symbol,
      EnumToString(_Period),
      log_type,
      status,
      DoubleToString(value1, _Digits),
      DoubleToString(value2, _Digits),
      DoubleToString(value3, 2),
      message
   );

   FileClose(file_handle);
}

6.1 コードの読み方

このコードでは、OnInitで移動平均線のハンドルを作成します。
OnTickでは新しい足ができたタイミングだけ処理し、CopyBufferで移動平均線の値を取得します。

CopyBufferの取得件数が足りない場合は、ログを残して処理を止めます。
この処理により、未取得データを使った誤判定を避けやすくなります。

6.2 注文処理の扱い

サンプルではInpEnableTradeがfalseのとき注文を行いません。
検証段階では、まずログだけを確認し、その後に注文処理を有効化する方が原因を分けやすくなります。

OrderCheckの結果を記録してからOrderSendを行うため、注文前の問題と注文送信後の問題を分離できます。
実運用では、約定方式、取引時間、ストップレベル、フリーズレベル、口座タイプを追加で確認する必要があります。

7. 設計パターン比較

【結論】
Data Logging EAでは、目的に応じてログ方式を選ぶ必要があります。
単純な検証にはCSVログ、実運用の監視にはイベントログ、長期評価には集計ログが向いています。

方法メリットデメリット向いている場面実装難易度
CSVログ表形式で確認しやすいファイルが大きくなりやすいバックテストの条件確認
イベントログ重要な出来事だけ追いやすい細かい相場状態を追いにくい実運用の異常確認低〜中
集計ログ成績の傾向を確認しやすい個別注文の原因分析には弱い長期検証
詳細ティックログ細かい挙動を追いやすい長期間では扱いにくい短時間の不具合調査
外部DB連携複数EAの管理に向く実装と運用が重くなる大規模な検証環境

7.1 初期設計ではCSVログが扱いやすい

初心者から中級者が最初に作るData Logging EAでは、CSVログが扱いやすいです。
MQL5のFileOpenとFileWriteで実装でき、バックテスト後に確認しやすいためです。

ただし、CSVログはファイルサイズに注意が必要です。
毎ティックで大量に書き出すと、テスターの実行速度や確認作業に影響する場合があります。

7.2 実運用ではイベントログを重視する

実運用では、すべてのティックよりも、注文、決済、エラー、停止、条件不成立などのイベントを重視します。
運用中のログが多すぎると、本当に確認すべき異常を見落としやすくなります。

イベントログには、注文前チェックの結果、OrderSendのretcode、ポジション状態、スプレッドを含めると実用性が上がります。

8. バックテストで確認すべき項目

【結論】
Data Logging EAのバックテストでは、成績だけでなく、ログが売買判断を説明できているかを確認します。
ログからエントリー理由、非エントリー理由、注文失敗理由が追える状態を目標にします。

バックテストでは、次の項目を確認します。

確認項目見る理由ログで残す値
総損益全体成績を把握する期間別損益
最大ドローダウン資金変動の大きさを確認する残高、有効証拠金
勝率取引の勝敗傾向を見る勝敗フラグ
損益比利益幅と損失幅の関係を見る利益、損失
取引回数条件が厳しすぎないか確認するエントリー回数
連敗数運用停止条件の検討に使う連敗カウント
スプレッド条件約定コストの影響を見るSpread
期間依存性特定期間だけに偏っていないか見る年月、期間区分
パラメータ依存性過剰最適化の兆候を見るパラメータ値

8.1 非エントリー理由を残す

エントリーした取引だけを記録すると、条件が厳しすぎる理由が分かりにくくなります。
Data Logging EAでは、エントリーしなかった理由も残すと検証しやすくなります。

例として、次のような状態をログ化します。

  • spread_too_wide
  • signal_none
  • risk_rejected
  • order_check_failed
  • position_exists
  • trading_time_blocked

8.2 過剰最適化を避ける

ログが細かいほど、後から都合のよい条件を追加したくなります。
しかし、過去データに合わせすぎると、フォワードテストで崩れやすくなります。

Data Logging EAのログは、原因分析のために使います。
特定期間だけに合わせたパラメータ調整は、再現性を低くする場合があります。

9. フォワードテストで確認すべき項目

【結論】
フォワードテストでは、バックテストで想定したログと実際の約定条件がどれだけ一致するかを確認します。
特に、スプレッド拡大、約定差、取引頻度、VPS環境での安定性を確認する必要があります。

フォワードテストでは、次の項目を確認します。

確認項目確認する理由ログで見る値
約定差想定価格と約定価格の差を見るrequest.price、result.price
スプレッド拡大取引コストの変化を見るSpread
取引頻度バックテストと頻度が近いか見る日別取引回数
ドローダウン資金変動が許容範囲か見るBalance、Equity
バックテストとの乖離検証条件との差を見る同条件の比較値
ブローカー差銘柄仕様と約定条件の差を見るStopLevel、LotStep
VPS環境の安定性稼働停止や遅延を確認する起動時刻、停止理由

9.1 デモ口座とリアル口座の差

デモ口座とリアル口座では、約定条件やスプレッド条件が異なる場合があります。
Data Logging EAでは、口座種別、サーバー時刻、スプレッド、約定価格を残すと差分を追いやすくなります。

9.2 VPS環境での記録

VPSでEAを動かす場合、停止時刻、再起動時刻、OnInitとOnDeinitの記録が重要になります。
EAが止まった理由を追うには、起動と終了のイベントログを残します。

10. 実運用での注意点

【結論】
Data Logging EAは、実運用リスクを減らす補助にはなりますが、取引結果を保証するものではありません。
実運用では、スプレッド、約定、ブローカー仕様、レバレッジ、ドローダウン許容度を事前に確認する必要があります。

自動売買では、技術的に正しく動くことと、実運用で安定することは別です。
ログを残しても、相場変動、約定条件、通信環境、銘柄仕様による影響は残ります。

10.1 スプレッドと約定差

スプレッドが広がると、同じシグナルでも成績が悪化する場合があります。
Data Logging EAでは、エントリー時と決済時のスプレッドを残すと、取引コストの影響を確認しやすくなります。

約定価格が想定価格からずれる場合もあります。
注文ログには、要求価格、約定価格、retcode、コメントを残します。

10.2 口座タイプの違い

MQL5では、netting口座とhedging口座でポジション管理の考え方が異なります。
netting口座では同一銘柄のポジションが統合され、hedging口座では複数ポジションを持てる場合があります。

Data Logging EAでは、ポジション数、チケット、銘柄、方向、ロットを口座タイプに合わせて記録する必要があります。
口座タイプを考慮しないログ設計では、ポジション状態を誤って解釈する場合があります。

10.3 レバレッジとドローダウン

レバレッジが高いほど、少ない証拠金で大きなポジションを持てます。
一方で、価格変動に対する損益の振れ幅も大きくなりやすくなります。

Data Logging EAでは、残高、有効証拠金、必要証拠金、含み損益を記録すると、ドローダウンの進行を確認しやすくなります。
実運用前に、許容する最大ドローダウンと停止条件を決める必要があります。

11. よくある設計ミス

【結論】
Data Logging EAで多い失敗は、ログ項目が少なすぎる、逆に多すぎる、注文結果だけを記録する、エラーコードを残さないことです。
検証に使うログは、後から原因を分離できる粒度で設計します。

11.1 注文結果だけを記録する

OrderSendの結果だけを残しても、注文前に条件が不適切だったのか、送信後に失敗したのかを分けられません。
OrderCheckの結果、ロット、証拠金、スプレッド、ストップ位置を一緒に残す必要があります。

11.2 CopyBufferの失敗を無視する

インジケータ値が取得できていない状態で判定を続けると、誤ったシグナルになる場合があります。
CopyBufferの戻り値が期待件数未満なら、ログを残して処理を止めます。

11.3 最新足と確定足を混同する

最新足は形成中の足です。
確定足を前提にしたロジックで最新足を使うと、バックテストと実運用の挙動がずれる場合があります。

Data Logging EAでは、どの足の値を使ったかを分かるように記録します。
たとえば、shift 0は最新足、shift 1は直近の確定足として扱います。

11.4 ログファイル名を固定しすぎる

複数銘柄や複数時間足で同じファイル名を使うと、ログが混ざる場合があります。
実用設計では、銘柄、時間足、EA名、日付をファイル名やログ行に含めると確認しやすくなります。

12. まとめ

【結論】
Data Logging EAは、MQL5 EAの判断過程、注文結果、エラー、ポジション状態を記録し、検証しやすくするための設計です。
EAを実運用に近づけるほど、ログ設計の重要性は高くなります。

Data Logging EAでは、OnInit、OnTick、OnDeinitの役割を分け、インジケータハンドル、CopyBuffer、OrderCheck、OrderSend、ポジション管理を明確に扱います。
ログは、売買結果だけでなく、非エントリー理由、注文前チェック、約定結果、実運用差を追うために使います。

バックテストでは、総損益、最大ドローダウン、勝率、損益比、取引回数、連敗数、スプレッド条件、期間依存性、パラメータ依存性を確認します。
フォワードテストでは、約定差、スプレッド拡大、取引頻度、ブローカー差、VPS環境での安定性を確認します。

Data Logging EAは、EAの品質確認を助ける仕組みです。
ただし、ログ設計やバックテスト結果は将来の利益を保証しません。
実運用前には、銘柄仕様、口座タイプ、約定条件、ドローダウン許容度を確認し、段階的に検証する必要があります。

FAQ

Data Logging EAとは何ですか?

Data Logging EAとは、MQL5のEAが行った判断、注文結果、ポジション状態、エラーを記録する設計です。
バックテストやフォワードテストで、EAの挙動を後から確認しやすくするために使います。

MQL5でログを取るには何を使いますか?

MQL5では、FileOpen、FileWrite、FileCloseなどを使ってCSV形式のログを作れます。
Printによるログも使えますが、長期検証ではCSVの方が項目を整理しやすくなります。

Data Logging EAでは何を記録すべきですか?

価格、スプレッド、インジケータ値、シグナル、フィルター結果、ロット、OrderCheckの結果、OrderSendの結果、エラーコードを記録すると検証しやすくなります。
エントリーしなかった理由も記録すると、条件が厳しすぎるかどうかを確認できます。

CopyBufferの失敗はログに残すべきですか?

CopyBufferの失敗は必ずログに残すべきです。
インジケータ値を取得できないまま判定を続けると、誤ったシグナルや不自然な検証結果につながる場合があります。

CSVログとイベントログはどちらがよいですか?

バックテストの条件確認にはCSVログが向いています。
実運用の異常確認には、注文、決済、エラー、停止などを記録するイベントログが向いています。

Data Logging EAは実運用リスクをなくせますか?

Data Logging EAは実運用リスクをなくすものではありません。
スプレッド拡大、約定差、ブローカー仕様、レバレッジ、ドローダウンの影響は残るため、実運用前にフォワードテストが必要です。

バックテストではどのログを確認すべきですか?

バックテストでは、総損益、最大ドローダウン、勝率、損益比、取引回数、連敗数、スプレッド条件、期間依存性、パラメータ依存性を確認します。
ログからエントリー理由と非エントリー理由を追える状態が重要です。

フォワードテストでは何を確認すべきですか?

フォワードテストでは、約定価格の差、スプレッド拡大時の挙動、取引頻度、バックテストとの乖離、ブローカー差、VPS環境での安定性を確認します。
デモ口座とリアル口座では約定条件が異なる場合があります。