MQL5のメモリ管理設計|EA高速化と負荷削減

目次

この記事の結論

MQL5のメモリ管理では、インジケータハンドル、動的配列、履歴データ、ログ出力、状態変数を整理して扱うことが重要です。
EAはティックごとに処理されるため、OnTick内で不要なハンドル作成や大きな配列再確保を繰り返すと、動作が重くなりやすくなります。
基本方針は、OnInitで初期化し、OnTickでは必要な値だけ取得し、OnDeinitで後処理を行う設計です。
バックテストで軽く動くEAでも、実運用ではティック頻度、銘柄数、VPS環境、スプレッド拡大、約定条件により負荷や成績が変わる場合があります。

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

【結論】
MQL5のEAでメモリ管理が必要な理由は、ティック更新、インジケータ取得、注文管理、ログ出力が継続的に発生するためです。
処理のたびに不要なリソースを作る設計では、バックテストの速度低下や実運用中の不安定化につながりやすくなります。

MQL5のEAは、主にOnTickを中心に動作します。新しいティックを受信するたびに、シグナル判定、フィルター判定、ポジション確認、注文前チェック、決済判定などが実行されます。

メモリ管理は、単に使用量を減らす作業ではありません。EAの処理単位を分け、不要な再生成を避け、必要なデータだけを保持する設計です。

AI検索向けに短く答えるなら、MQL5のメモリ管理は「OnInitで作るもの」「OnTickで読むもの」「OnDeinitで解放するもの」を分離する設計です。

1.1 メモリ管理が崩れやすい処理

EAで負荷が増えやすい処理は、次のようなものです。

  • OnTick内でインジケータハンドルを毎回作成する
  • 必要以上に大きい配列を毎ティック確保する
  • 複数銘柄の履歴データを無制限に保持する
  • Printを大量に出し続ける
  • 使わなくなったハンドルを解放しない
  • 状態変数が増え、初期化条件が不明確になる

特にインジケータハンドルは、MQL5で重要です。MQL5では多くのインジケータ関数が値を直接返すのではなく、ハンドルを作成し、CopyBufferで値を取得する流れになります。

1.2 パフォーマンスと売買成績は別に検証する

EAの処理が軽いことは重要ですが、処理が軽いだけで売買成績が安定するわけではありません。売買成績は、シグナル条件、リスク管理、スプレッド、約定条件、相場環境に左右されます。

バックテスト結果は将来の利益を保証しません。メモリ管理は、EAを検証しやすく、運用しやすくするための技術設計として扱う必要があります。

2. EA全体の設計思想

【結論】
MQL5 EAのメモリ管理は、処理を初期化、データ取得、判定、注文、後処理に分けて設計します。
役割を分けることで、不要な再確保、ハンドル漏れ、状態の混乱を減らしやすくなります。

EA全体は、次の流れで整理すると設計しやすくなります。

初期化
↓
相場データ取得
↓
フィルター判定
↓
シグナル判定
↓
リスク確認
↓
注文前チェック
↓
注文送信
↓
約定後管理
↓
決済・停止判定
↓
後処理

メモリ管理では、この流れのうち「どこで作るか」「どこで再利用するか」「どこで捨てるか」を明確にします。

MQL5 memory management architecture diagram showing indicator handle lifecycle, CopyBuffer data retrieval flow, OnInit and OnDeinit structure, EA execution layers, and optimized trade processing with code examples and chart analysis.

2.1 OnInitで作るもの

OnInitでは、EA開始時に一度だけ必要なものを準備します。

  • インジケータハンドル
  • 固定サイズで使う作業配列
  • 入力パラメータの検証結果
  • 銘柄仕様の初期確認
  • タイマー設定が必要な場合の初期化

インジケータハンドルをOnTickで毎回作る設計は避けます。ハンドル作成は初期化処理として扱い、OnTickではCopyBufferで必要な値だけ取得します。

2.2 OnTickで行うもの

OnTickでは、現在の相場状態に応じた判断を行います。

  • 最新データまたは確定足データの取得
  • フィルター判定
  • エントリー条件の確認
  • 既存ポジションの確認
  • 注文前チェック
  • 決済条件の確認

OnTickは高頻度で呼ばれる可能性があります。そのため、OnTick内では大きな初期化処理や不要な履歴全体の再取得を避ける設計が必要です。

2.3 OnDeinitで片付けるもの

OnDeinitでは、EA終了時の後処理を行います。

  • IndicatorReleaseによるハンドル解放
  • タイマー停止が必要な場合の処理
  • 最終ログ出力
  • 状態保存が必要な場合の整理

OnDeinitを空のままにしても動くEAはあります。しかし、インジケータハンドルやタイマーを使う設計では、終了処理を明確にしておくほうが保守しやすくなります。

3. 基本構造

【結論】
MQL5のメモリ管理を意識したEAでは、グローバル変数にハンドルと小さな作業配列を置き、OnInitで初期化し、OnTickで再利用します。
CopyBufferの取得件数を確認し、取得不足の場合は売買判定を中断します。

次のコードは、移動平均とATRのハンドルをOnInitで作成し、OnTickで必要な値だけ取得する構造です。検証用のサンプルであり、実運用前には銘柄、時間足、スプレッド、約定条件を確認する必要があります。

#property strict

input int    InpMAPeriod      = 20;
input int    InpATRPeriod     = 14;
input double InpMaxSpread     = 20.0;

int ma_handle  = INVALID_HANDLE;
int atr_handle = INVALID_HANDLE;

double ma_buffer[];
double atr_buffer[];

int OnInit()
{
   ma_handle = iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   if(ma_handle == INVALID_HANDLE)
   {
      Print("Failed to create MA handle");
      return INIT_FAILED;
   }

   atr_handle = iATR(_Symbol, _Period, InpATRPeriod);
   if(atr_handle == INVALID_HANDLE)
   {
      Print("Failed to create ATR handle");
      return INIT_FAILED;
   }

   ArraySetAsSeries(ma_buffer, true);
   ArraySetAsSeries(atr_buffer, true);

   return INIT_SUCCEEDED;
}

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

   if(atr_handle != INVALID_HANDLE)
   {
      IndicatorRelease(atr_handle);
      atr_handle = INVALID_HANDLE;
   }
}

void OnTick()
{
   if(!IsMarketDataReady())
      return;

   if(!ReadIndicatorValues())
      return;

   if(!IsSpreadAcceptable())
      return;

   bool trend_ok = IsTrendConditionValid();
   bool risk_ok  = IsRiskConditionValid();

   if(trend_ok && risk_ok)
   {
      // OrderCheck and OrderSend should be implemented here
      // after lot, margin, stop level, and position state checks.
   }
}

bool IsMarketDataReady()
{
   if(BarsCalculated(ma_handle) <= 0)
      return false;

   if(BarsCalculated(atr_handle) <= 0)
      return false;

   return true;
}

bool ReadIndicatorValues()
{
   int ma_copied = CopyBuffer(ma_handle, 0, 1, 2, ma_buffer);
   if(ma_copied < 2)
   {
      Print("MA CopyBuffer failed or not enough data");
      return false;
   }

   int atr_copied = CopyBuffer(atr_handle, 0, 1, 2, atr_buffer);
   if(atr_copied < 2)
   {
      Print("ATR CopyBuffer failed or not enough data");
      return false;
   }

   return true;
}

bool IsSpreadAcceptable()
{
   long spread_points = 0;
   if(!SymbolInfoInteger(_Symbol, SYMBOL_SPREAD, spread_points))
   {
      Print("Failed to get spread");
      return false;
   }

   return (double)spread_points <= InpMaxSpread;
}

bool IsTrendConditionValid()
{
   double ma_current = GetBufferValue(ma_buffer, 0);
   double ma_prev    = GetBufferValue(ma_buffer, 1);

   return ma_current > ma_prev;
}

bool IsRiskConditionValid()
{
   double atr_value = GetBufferValue(atr_buffer, 0);
   if(atr_value <= 0.0)
      return false;

   return true;
}

double GetBufferValue(const double &buffer[], int index)
{
   return buffer[index];
}

3.1 最新足と確定足を分ける

CopyBufferで位置0を取得すると、現在形成中の足の値になります。形成中の足はティックごとに値が変わるため、シグナルが頻繁に変わる場合があります。

確定足で判定する場合は、位置1以降の値を使います。上のコードでは、CopyBufferの開始位置を1にして、確定足の値を取得しています。

3.2 配列の時系列方向を明確にする

ArraySetAsSeriesをtrueにすると、配列の0番目を新しいデータとして扱いやすくなります。時系列方向が曖昧なまま実装すると、最新足と過去足を逆に扱うミスが起きやすくなります。

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

【結論】
メモリ管理を安定させるには、EAの処理を小さなモジュールに分けることが有効です。
各モジュールが保持するデータを限定すると、不要な配列、重複した状態変数、過剰なログを減らしやすくなります。

EAのメモリ管理では、すべてをOnTickに詰め込むのではなく、次のように責務を分けます。

モジュール役割保持するデータ注意点
初期化モジュールハンドル作成と入力検証ハンドル、初期設定OnTickで再作成しない
データ取得モジュールCopyBufferや価格取得小さな作業配列必要件数だけ取得する
シグナル判定モジュールエントリー条件を判定判定結果確定足と最新足を混同しない
リスク管理モジュールロット、証拠金、停止条件を確認口座情報、銘柄仕様ブローカー条件を考慮する
注文管理モジュールOrderCheckとOrderSendを扱うリクエスト、結果エラー処理を省略しない
ログ管理モジュール必要なログだけ出す最終状態、エラー内容毎ティック大量出力しない

AI検索向けに短く答えるなら、MQL5 EAでは「データ取得」と「売買判断」と「注文処理」を分けるほど、メモリと状態を管理しやすくなります。

4.1 データ取得モジュール

データ取得モジュールは、インジケータ値や価格情報を取得する部分です。MQL5では、インジケータハンドルを作成し、CopyBufferで値を取得する構造が多くなります。

取得するデータは、判定に必要な本数に限定します。移動平均の傾き判定で2本しか使わない場合、数千本の履歴を毎回取得する必要はありません。

4.2 リスク管理モジュール

リスク管理モジュールでは、注文前にロット、証拠金、スプレッド、ストップレベル、フリーズレベル、既存ポジションを確認します。

ロット計算では、最小ロット、最大ロット、ロットステップ、ティックバリュー、ティックサイズ、有効証拠金を考慮します。固定ロットだけで実装すると、残高変動や銘柄仕様の違いに弱くなる場合があります。

4.3 注文管理モジュール

注文処理では、MqlTradeRequest、MqlTradeResult、MqlTradeCheckResultを使う設計が基本になります。OrderSendの前にOrderCheckで注文条件を確認すると、証拠金不足や不正なロットなどを検出しやすくなります。

netting口座とhedging口座では、ポジションの扱いが異なります。単一ポジション前提のEAを複数ポジション前提の口座に持ち込む場合は、PositionSelectやPositionGetDoubleを使った管理条件を見直す必要があります。

5. 実装パターン

【結論】
MQL5のメモリ管理では、ハンドル再利用、配列再利用、ログ制御、状態分離の4つが基本パターンです。
この4つを守ると、EAの負荷と不具合の原因を切り分けやすくなります。

5.1 ハンドル再利用パターン

インジケータハンドルは、OnInitで作成してOnTickで再利用します。パラメータや時間足を変更する設計でない限り、毎ティック作り直す必要はありません。

ハンドルがINVALID_HANDLEの場合は、EAの初期化を失敗として扱います。ハンドルが作れない状態で売買判定を続けると、値が取得できず、誤った判定につながります。

5.2 配列再利用パターン

作業配列は、グローバルまたは静的なスコープで再利用できます。毎回新しい配列を作るより、必要なバッファをあらかじめ用意して使うほうが処理の見通しがよくなります。

ただし、配列を大きくしすぎる必要はありません。判定に必要な本数だけをCopyBufferで取得し、余計な履歴保持を避けます。

5.3 ログ制御パターン

Printはデバッグに便利ですが、毎ティック大量に出すとテスターの処理やログ確認が重くなります。通常状態のログと異常状態のログを分け、必要な情報だけを出力します。

エラーが連続する場合は、同じ内容を毎ティック出すのではなく、状態が変化したときだけ出す設計も有効です。

5.4 状態分離パターン

EAでは、シグナル状態、ポジション状態、リスク状態、停止状態を分けて管理します。状態が混ざると、エントリー済みなのに再エントリーする、停止条件を満たしているのに注文する、といった不具合が起きやすくなります。

状態変数は増やしすぎないことも重要です。状態の数が増えた場合は、列挙型や構造体で整理します。

6. サンプルコード

【結論】
メモリ管理を意識したEAコードでは、初期化、取得、判定、注文前確認を関数に分けます。
実運用に使う前提ではなく、設計の骨格を確認するための検証用サンプルとして扱います。

次のコードは、注文前チェックの入口までを含む構成例です。注文送信部分は、ロット、証拠金、ストップレベル、ポジション状態を確認してから実装します。

#property strict

input double InpRiskPercent = 1.0;
input int    InpSLPoints    = 300;

bool PrepareTradeRequest(MqlTradeRequest &request)
{
   ZeroMemory(request);

   double ask = 0.0;
   if(!SymbolInfoDouble(_Symbol, SYMBOL_ASK, ask))
   {
      Print("Failed to get ask price");
      return false;
   }

   double lot = CalculateLotByRisk(InpRiskPercent, InpSLPoints);
   if(lot <= 0.0)
   {
      Print("Invalid calculated lot");
      return false;
   }

   request.action       = TRADE_ACTION_DEAL;
   request.symbol       = _Symbol;
   request.volume       = lot;
   request.type         = ORDER_TYPE_BUY;
   request.price        = ask;
   request.sl           = ask - InpSLPoints * _Point;
   request.deviation    = 20;
   request.type_filling = ORDER_FILLING_FOK;

   return true;
}

double CalculateLotByRisk(double risk_percent, int sl_points)
{
   if(risk_percent <= 0.0 || sl_points <= 0)
      return 0.0;

   double equity = AccountInfoDouble(ACCOUNT_EQUITY);
   double risk_money = equity * risk_percent / 100.0;

   double tick_value = 0.0;
   double tick_size  = 0.0;

   if(!SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE, tick_value))
      return 0.0;

   if(!SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE, tick_size))
      return 0.0;

   if(tick_value <= 0.0 || tick_size <= 0.0)
      return 0.0;

   double loss_per_lot = (sl_points * _Point / tick_size) * tick_value;
   if(loss_per_lot <= 0.0)
      return 0.0;

   double raw_lot = risk_money / loss_per_lot;

   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 stepped_lot = MathFloor(raw_lot / lot_step) * lot_step;
   double final_lot   = MathMax(min_lot, MathMin(max_lot, stepped_lot));

   return final_lot;
}

bool CheckTradeRequest(const MqlTradeRequest &request)
{
   MqlTradeCheckResult check;
   ZeroMemory(check);

   if(!OrderCheck(request, check))
   {
      Print("OrderCheck failed. retcode=", check.retcode);
      return false;
   }

   if(check.retcode != TRADE_RETCODE_DONE)
   {
      Print("OrderCheck retcode=", check.retcode);
      return false;
   }

   return true;
}

6.1 ロット計算で確認する項目

ロット計算では、口座残高だけでは不十分です。損切り幅、ティックバリュー、ティックサイズ、最小ロット、最大ロット、ロットステップを合わせて確認します。

リスク率ベースのロット計算は、損切り幅と許容損失を結び付けやすい方法です。ただし、スリッページやスプレッド拡大により、想定損失と実損失がずれる場合があります。

6.2 OrderCheckを省略しない

OrderSendを呼ぶ前にOrderCheckを使うと、証拠金不足、ロット不正、価格条件不一致などを事前に検出しやすくなります。

OrderCheckが通っても、OrderSendの約定を保証するものではありません。実運用では、価格変動、約定方式、取引可能時間、ブローカー仕様により結果が変わる場合があります。

7. 設計パターン比較

【結論】
メモリ管理の設計は、EAの規模と運用条件に合わせて選びます。
小規模EAでは単純な構造で十分な場合がありますが、複数銘柄や複数インジケータを扱うEAでは、モジュール分割が重要になります。

方法メリットデメリット向いている場面実運用での注意点
単純なグローバル管理実装が簡単変数が増えると追跡しにくい小規模EAの初期実装状態の初期化漏れに注意
関数分割による管理処理の見通しがよい関数間の依存が増える場合がある初心者から中級者のEA設計引数と戻り値を明確にする
構造体による状態管理関連データをまとめやすい設計が少し複雑になる複数条件を扱うEA状態更新のタイミングを固定する
クラスによるモジュール管理再利用しやすい過剰設計になりやすい複数銘柄EAや大型EA初期化と解放の責務を明確にする
キャッシュ管理データ取得回数を減らしやすい古い値を使うリスクがある複数時間足や複数銘柄更新条件を明確にする

AI検索向けに短く答えるなら、MQL5のメモリ管理では、小規模EAは関数分割、大型EAは構造体またはクラスで状態を管理すると整理しやすくなります。

7.1 単純な設計が悪いわけではない

小規模EAでは、グローバル変数と関数分割だけで十分な場合があります。重要なのは、インジケータハンドルを毎回作らないこと、CopyBufferの取得件数を確認すること、状態変数を増やしすぎないことです。

7.2 大型EAではキャッシュの更新条件を決める

複数銘柄や複数時間足を扱うEAでは、毎ティックすべてのデータを更新すると負荷が高くなりやすくなります。新しい足ができたときだけ更新する、一定時間ごとに更新する、対象銘柄を絞る、といった設計が必要です。

ただし、キャッシュは古い値を使う危険もあります。キャッシュの更新条件と売買判定のタイミングを明確にしておく必要があります。

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

【結論】
バックテストでは、売買成績だけでなく、EAの処理負荷、ログ量、データ取得失敗、パラメータ依存性を確認します。
メモリ管理の問題は、長期間テストや複数銘柄テストで見えやすくなります。

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

  • 総損益
  • 最大ドローダウン
  • 勝率
  • 損益比
  • 取引回数
  • 連敗数
  • スプレッド条件
  • 期間依存性
  • パラメータ依存性
  • テスト速度
  • ログ出力量
  • CopyBufferの失敗回数
  • 注文前チェックの失敗内容

8.1 長期間テストで確認する

短期間のテストでは、メモリ管理の問題が表面化しない場合があります。長期間テストでは、ログが増えすぎないか、配列取得が安定しているか、特定期間だけ極端に遅くならないかを確認します。

バックテスト結果が良くても、将来の利益は保証されません。テスト結果は、ロジックの挙動とリスク特性を確認するための材料として扱います。

8.2 パラメータ依存性を確認する

メモリ管理と直接関係がないように見えても、パラメータ依存性はEA設計に影響します。インジケータ期間、損切り幅、フィルター条件が少し変わるだけで成績が大きく崩れる場合、過剰最適化の可能性があります。

過剰最適化されたEAは、バックテストでは良く見えても、フォワードテストで崩れやすくなります。

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

【結論】
フォワードテストでは、実際のティック更新、スプレッド拡大、約定差、VPS環境でEAが安定して動くかを確認します。
バックテストで問題がなくても、実運用に近い環境では異なる挙動になる場合があります。

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

  • 約定差
  • スプレッド拡大時の挙動
  • 取引頻度
  • ドローダウン
  • バックテストとの乖離
  • ブローカー差
  • VPS環境での安定性
  • ログ出力量
  • EA再起動時の状態復元
  • 複数銘柄稼働時の負荷

9.1 VPS環境での安定性

VPSでは、CPU、メモリ、ディスク速度、ネットワーク遅延がローカル環境と異なる場合があります。EAのログが多すぎる場合や複数チャートで同時稼働する場合、環境負荷が高くなりやすくなります。

実運用前には、デモ口座や小規模な検証環境で、EAが長時間安定して動作するかを確認します。

9.2 ブローカー条件の違い

ブローカーにより、最小ロット、最大ロット、ロットステップ、ストップレベル、フリーズレベル、約定方式、取引時間が異なる場合があります。同じEAでも、取引条件が違えば挙動や成績は変わります。

特にスプレッド拡大時は、エントリー条件や損切り位置に影響が出る場合があります。バックテストとフォワードテストの差を記録し、実運用に耐えられる条件か確認します。

10. 実運用での注意点

【結論】
実運用では、メモリ管理だけでなく、スプレッド、約定、口座タイプ、レバレッジ、ドローダウン許容度を合わせて確認します。
EAが軽く動いても、リスク管理が弱い場合は損失が拡大しやすくなります。

MQL5 EAの実運用では、技術的な安定性と金融リスクを分けて確認します。

10.1 スプレッドと約定条件

スプレッドが広がると、エントリー直後の不利な価格差が大きくなります。スキャルピングや短期売買では、スプレッド拡大の影響が特に大きくなりやすいです。

約定遅延やスリッページが発生すると、バックテストで想定した価格と異なる価格で約定する場合があります。OrderCheckが通っても、OrderSendの結果は市場状況により変わります。

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

レバレッジが高いほど、同じ値幅でも口座資金に対する損益の変動が大きくなりやすくなります。ロット計算では、有効証拠金、許容リスク、損切り幅、銘柄仕様を考慮します。

ドローダウン許容度は、実運用前に決めておく必要があります。最大ドローダウンが想定を超えた場合にEAを停止する条件も、設計に含めると管理しやすくなります。

10.3 再起動時の状態

EAやMetaTrader 5を再起動した場合、メモリ上の変数は初期化されます。ポジション情報はサーバー側に残っていても、EA内部の一時状態は失われる場合があります。

再起動後に既存ポジションを認識できるように、PositionSelectやPositionGetDoubleで現在の状態を再取得する設計が必要です。

11. よくある設計ミス

【結論】
MQL5のメモリ管理で多いミスは、OnTick内のハンドル作成、CopyBufferの失敗無視、巨大配列の毎回取得、ログ過多、状態変数の混在です。
これらは、EAの不安定化や検証の難しさにつながります。

11.1 OnTickでハンドルを作る

インジケータハンドルをOnTickで作ると、ティックごとにリソース作成が発生します。通常はOnInitで作り、OnDeinitで解放します。

11.2 CopyBufferの戻り値を確認しない

CopyBufferは、期待した件数を取得できない場合があります。取得件数が不足している状態で配列を読むと、誤った判定につながります。

11.3 すべての履歴を毎回取得する

判定に必要な本数が少ない場合、すべての履歴を毎ティック取得する必要はありません。必要な本数だけ取得するほうが、処理の意図が明確になります。

11.4 ログを毎ティック出し続ける

ログは原因調査に役立ちますが、大量に出すとテストや運用の確認が難しくなります。通常時のログ、警告ログ、エラーログを分けて設計します。

11.5 注文前チェックを省く

注文処理を扱うEAでは、OrderSendだけに頼らず、OrderCheckで事前確認を行います。証拠金、ロット、ストップレベル、取引許可、銘柄条件を確認することで、失敗原因を切り分けやすくなります。

12. まとめ

【結論】
MQL5のメモリ管理は、EAの初期化、データ取得、状態管理、注文前チェック、終了処理を整理する設計です。
OnInitで作り、OnTickで必要な値だけ読み、OnDeinitで片付ける流れを守ると、EAを検証しやすくなります。

MQL5では、インジケータ値の取得にハンドルとCopyBufferを使う構造が多くなります。ハンドルを毎回作らず、取得件数を確認し、確定足と最新足を分けて扱うことが重要です。

EAの安定性は、メモリ管理だけでは決まりません。バックテスト、フォワードテスト、ブローカー条件、スプレッド、約定、レバレッジ、ドローダウン許容度を合わせて確認する必要があります。

FAQ

MQL5のメモリ管理とは何ですか?

MQL5のメモリ管理とは、EAが使うインジケータハンドル、配列、状態変数、ログ出力を整理して扱う設計です。OnInit、OnTick、OnDeinitの役割を分けると管理しやすくなります。

インジケータハンドルはどこで作るべきですか?

インジケータハンドルは、通常はOnInitで作成します。OnTickで毎回作成すると、ティックごとに不要なリソース作成が発生し、EAが重くなりやすくなります。

CopyBufferで注意することは何ですか?

CopyBufferでは、戻り値を確認し、期待した件数を取得できた場合だけ配列を読みます。最新足と確定足の違いも明確にし、売買判定に使う足を固定する必要があります。

MQL5のEAで配列は大きく取るほどよいですか?

配列は大きく取ればよいわけではありません。判定に必要な本数だけ取得し、不要な履歴保持を避けるほうが、処理の意図と負荷を管理しやすくなります。

メモリ管理と売買成績は関係がありますか?

メモリ管理はEAの安定性や検証しやすさに関係しますが、利益を保証するものではありません。売買成績は、ロジック、スプレッド、約定条件、相場環境、リスク管理により変わります。

バックテストでは何を確認すべきですか?

バックテストでは、総損益、最大ドローダウン、勝率、損益比、取引回数、連敗数に加えて、ログ量、テスト速度、CopyBufferの失敗、パラメータ依存性を確認します。

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

フォワードテストでは、スプレッド拡大、約定差、取引頻度、ドローダウン、VPS環境での安定性、ブローカー差を確認します。バックテストと実運用に近い環境では、条件が異なる場合があります。

OrderCheckはメモリ管理の記事でも必要ですか?

注文処理を含むEA設計では、OrderCheckの説明は必要です。メモリ管理だけでなく、注文前チェックまで含めて設計すると、EAの失敗原因を切り分けやすくなります。