MQL5マルチロジックEA実務ノート|複数戦略・Magic Number・状態管理の考え方

EAファンクラブ

MQL5でEAを拡張していくと、1つのEA内に複数の戦略や複数のロジックを入れたくなることがあります。

たとえば、順張りロジック、逆張りロジック、レンジ用ロジック、時間足違いのロジック、BUY専用・SELL専用ロジック、検証中の追加ロジックなどです。

複数ロジックEAは便利ですが、設計を間違えると危険です。どのロジックのポジションか分からなくなる、別ロジックのポジションを決済してしまう、ロジック別の成績が追えない、検証中のロジックが実売買へつながる、という問題が起きやすくなります。

マルチロジックEAで重要なのは、ロジックごとの状態、マジックナンバー、Position Snapshot、Close Scope、risk、executionを分けることです。

この記事では、MQL5で複数戦略EAを作る時の設計判断を、開発実務ノートとして整理します。完成EAソース全文、外部シート制御ロジック、認証ロジック、endpoint、token、URL実値、実運用set値、中核Entry条件は公開しません。

本記事は、投資判断や売買指示ではなく、MQL5のマルチロジックEAを設計・検証・サポートしやすくするための技術記事です。

この記事で扱う実務課題

項目この記事で扱う内容扱わない内容
目的複数戦略EAでロジック別の状態・注文・決済を分ける設計利益を狙う売買ロジック、具体的なEntry条件
主な対象LogicSlot、マジックナンバー、Position Snapshot、Close Scope、audit only完成EAソース全文、実運用コード全文
設計観点誤発注防止、誤決済防止、ロジック別検証、販売後サポート認証ロジック、外部制御、実運用set値
コード例一般化したLogicSlot、Position Snapshot、Close Scope、audit log例実Entry条件、実Trail条件、実Nanpin条件
読者MQL5開発者、複数ロジックEAを依頼したい人、検証担当者売買判断や推奨設定を知りたい人

なぜマルチロジックEAでは状態管理が重要なのか

1つのEAに複数ロジックを入れる場合、単に条件式を増やすだけでは不十分です。

それぞれのロジックが、どのマジックナンバーを使い、どのポジションを管理し、どの決済scopeを持ち、どのrisk条件で止まるのかを分ける必要があります。

問題起きる原因分けるべき責務
別ロジックのポジションを決済するClose Scopeが広すぎるexit / close scope
ポジション集計が混ざるマジックナンバーやlogic_idで集計していないPosition Snapshot
検証中ロジックが実売買するaudit onlyとtrade routeを分けていないruntime state / execution
ロジック別成績が分からない注文・決済・ログにlogic_idがないlog / order identification
risk停止の範囲が曖昧全体riskとロジック別riskを混同しているrisk
既存ロジックに追加ロジックが影響する状態変数や発注経路を共有しすぎているLogicSlot / route separation

マルチロジックEAでは、「EA全体の状態」と「ロジックごとの状態」を分けて管理することが重要です。

LogicSlotとは何か

LogicSlotとは、1つのロジックを管理するための単位です。

1つのEAに複数ロジックを入れる場合、それぞれをLogicSlotとして扱うと、設定、状態、マジックナンバー、ポジション集計、実行可否を整理しやすくなります。

項目役割
logic_idロジックを識別する番号
logic_nameログや表示で使うロジック名
magic注文・ポジション識別用のマジックナンバー
enabledロジック自体を有効にするか
trade_route_enabled実売買へ接続するか
runtime_reason現在の状態理由
risk_stateロジック別risk状態
position_snapshotロジック別ポジション集計

LogicSlotを持たないまま条件式を増やすと、どのロジックがどのポジションを持っているのか、どのロジックが停止中なのかを追いにくくなります。

マジックナンバーをロジック別に分ける理由

マジックナンバーは、EAの注文やポジションを識別するための重要な情報です。

複数ロジックEAでは、原則としてロジックごとにマジックナンバーを分けます。同じマジックナンバーを複数ロジックで使うと、ポジション集計や決済対象が混ざります。

分けない場合の問題内容
誤決済Logic2がLogic1のポジションを閉じる可能性がある
集計混在ロジック別の保有数や損益が分からない
検証不能どのロジックの成績か分からない
risk混在ロジック別上限と全体上限が混ざる
ログ追跡困難注文・決済の原因ロジックを追えない

ただし、マジックナンバーを分けるだけでは不十分です。ログ、Position Snapshot、Close Scope、OrderSend request、決済処理も同じ識別情報で揃える必要があります。

Position Snapshotをロジック別に持つ

Position Snapshotとは、現在のポジション状態を集計した情報です。

マルチロジックEAでは、EA全体のポジション数だけでなく、ロジック別のPosition Snapshotを持つことが重要です。

Snapshot項目確認する理由
position_count対象ロジックの保有数を確認するため
buy_count / sell_count方向別の保有状態を確認するため
total_volumeロジック別の合計ロットを確認するため
floating_profitロジック別の含み損益を確認するため
has_position新規Entryや決済管理の前提に使うため
magicどのマジックナンバーで集計したか確認するため
logic_idどのロジックの状態か確認するため

全体ポジションだけを見ていると、Logic1は保有中だがLogic2はノーポジション、という状態を区別できません。

Close Scopeを狭くする

Close Scopeとは、決済対象の範囲です。

複数ロジックEAでは、決済処理が他ロジックのポジションを巻き込まないように、Close Scopeを明確にする必要があります。

確認項目理由
symbol一致別銘柄のポジションを閉じないため
magic一致別ロジックのポジションを閉じないため
logic_id一致管理対象ロジックを明確にするため
side一致BUY / SELLの対象を間違えないため
ticket確認対象ポジションを明確にするため
close reasonなぜ閉じるのかをログで追うため

特に、symbolだけで決済対象を選ぶ設計は危険です。複数ロジック、複数EA、手動ポジションが混在する環境では、magic、logic_id、scopeを確認する必要があります。

audit onlyとtrade routeを分ける

新しいロジックを追加する時は、いきなり実売買へ接続しない方が安全です。

まずはaudit onlyとして、シグナル候補、GATE、risk、Position Snapshot、ログだけを確認し、その後にtrade routeを有効化します。

段階状態確認内容
definedLogicSlotだけ定義logic_id、name、magicが重複していないか
snapshot onlyポジション集計だけ行う対象ポジションを正しく集計できるか
audit only判定結果をログに出す候補、block理由、risk状態が追えるか
pre-route gate実行前条件まで確認するspread、duplicate、position gateが通るか
trade route enable実売買へ接続するOrderSend、retcode、position反映を確認する

この段階を分けておくと、既存ロジックを壊さずに新ロジックを検証しやすくなります。

ロジック別riskとEA全体riskを分ける

マルチロジックEAでは、risk管理も2層に分ける必要があります。

1つはロジック別riskです。もう1つはEA全体riskです。

risk分類確認すること
ロジック別risk対象ロジックだけの上限を確認するLogic1最大1ポジション、Logic2最大2ポジション
EA全体riskEA全体としての上限を確認する全体最大ロット、全体最大ポジション数
方向別riskBUY / SELL別の偏りを確認するBUY最大数、SELL最大数
口座・日次risk口座全体や日次停止を確認する日次損失停止、連続損失停止

ロジック別riskで許可されていても、EA全体riskで止める場合があります。この場合は、NO_SIGNALではなく、RISK_BLOCKとしてログに残します。

実コード例1:LogicSlotを定義する

以下は、設計判断を理解するために一般化した学習用コード例です。完成EAのソース全文ではありません。

// 学習用に一般化したLogicSlot例です。
// 実運用EAの完成ソースではありません。

struct LogicSlot
{
   int id;
   string name;
   long magic;
   bool enabled;
   bool tradeRouteEnabled;
   string runtimeReason;
};

#define LOGIC_COUNT 3

LogicSlot g_logicSlots[LOGIC_COUNT];

void InitLogicSlots()
{
   g_logicSlots[0].id = 1;
   g_logicSlots[0].name = "Logic1";
   g_logicSlots[0].magic = 910001;
   g_logicSlots[0].enabled = true;
   g_logicSlots[0].tradeRouteEnabled = true;
   g_logicSlots[0].runtimeReason = "OK";

   g_logicSlots[1].id = 2;
   g_logicSlots[1].name = "Logic2";
   g_logicSlots[1].magic = 910002;
   g_logicSlots[1].enabled = true;
   g_logicSlots[1].tradeRouteEnabled = false;
   g_logicSlots[1].runtimeReason = "AUDIT_ONLY";

   g_logicSlots[2].id = 3;
   g_logicSlots[2].name = "Logic3";
   g_logicSlots[2].magic = 910003;
   g_logicSlots[2].enabled = false;
   g_logicSlots[2].tradeRouteEnabled = false;
   g_logicSlots[2].runtimeReason = "DISABLED";
}

この例では、enabledとtradeRouteEnabledを分けています。enabledはロジックを確認対象にするかどうか、tradeRouteEnabledは実売買へ接続するかどうかです。

実コード例2:マジックナンバー重複を確認する

以下は、設計判断を理解するために一般化した学習用コード例です。完成EAのソース全文ではありません。

// 学習用に一般化したマジックナンバー重複チェック例です。
// 実運用EAの完成ソースではありません。

bool ValidateLogicMagicNumbers()
{
   for(int i = 0; i < LOGIC_COUNT; i++)
   {
      if(g_logicSlots[i].magic <= 0)
      {
         Print("DIAG/LOGIC: event=VALIDATION_FAIL",
               " logic=", g_logicSlots[i].name,
               " reason=INVALID_MAGIC");
         return false;
      }

      for(int j = i + 1; j < LOGIC_COUNT; j++)
      {
         if(g_logicSlots[i].magic == g_logicSlots[j].magic)
         {
            Print("DIAG/LOGIC: event=VALIDATION_FAIL",
                  " reason=DUPLICATE_MAGIC",
                  " logic_a=", g_logicSlots[i].name,
                  " logic_b=", g_logicSlots[j].name);
            return false;
         }
      }
   }

   Print("DIAG/LOGIC: event=VALIDATION_OK",
         " reason=UNIQUE_MAGIC");

   return true;
}

マジックナンバーの重複は、複数ロジックEAで特に避けたい事故です。起動時に検出し、重複があれば安全側で止める設計が必要です。

実コード例3:ロジック別Position Snapshotを作る

以下は、設計判断を理解するために一般化した学習用コード例です。完成EAのソース全文ではありません。

// 学習用に一般化したPosition Snapshot例です。
// 実運用EAの完成ソースではありません。

struct PositionSnapshot
{
   int count;
   int buyCount;
   int sellCount;
   double totalVolume;
   double floatingProfit;
   bool hasPosition;
};

PositionSnapshot BuildPositionSnapshotForMagic(long magic)
{
   PositionSnapshot snap;
   snap.count = 0;
   snap.buyCount = 0;
   snap.sellCount = 0;
   snap.totalVolume = 0.0;
   snap.floatingProfit = 0.0;
   snap.hasPosition = false;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);

      if(ticket == 0)
         continue;

      if(!PositionSelectByTicket(ticket))
         continue;

      if(PositionGetString(POSITION_SYMBOL) != _Symbol)
         continue;

      if((long)PositionGetInteger(POSITION_MAGIC) != magic)
         continue;

      long type = PositionGetInteger(POSITION_TYPE);
      double volume = PositionGetDouble(POSITION_VOLUME);
      double profit = PositionGetDouble(POSITION_PROFIT);

      snap.count++;
      snap.totalVolume += volume;
      snap.floatingProfit += profit;

      if(type == POSITION_TYPE_BUY)
         snap.buyCount++;

      if(type == POSITION_TYPE_SELL)
         snap.sellCount++;
   }

   snap.hasPosition = (snap.count > 0);
   return snap;
}

この例では、symbolとマジックナンバーで対象ポジションを絞り込んでいます。ロジック別にSnapshotを作ることで、他ロジックのポジションを誤って管理しにくくなります。

実コード例4:audit onlyでロジック状態を確認する

以下は、設計判断を理解するために一般化した学習用コード例です。完成EAのソース全文ではありません。

// 学習用に一般化したLogicSlot監査例です。
// 実運用EAの完成ソースではありません。

void PrintLogicAudit(LogicSlot slot,
                     PositionSnapshot snap,
                     string eventName,
                     string reason)
{
   Print("DIAG/LOGIC_AUDIT: logic=", slot.name,
         " magic=", slot.magic,
         " event=", eventName,
         " reason=", reason,
         " pos_count=", snap.count,
         " buy=", snap.buyCount,
         " sell=", snap.sellCount,
         " trade_route=", slot.tradeRouteEnabled);
}

void RunLogicSlotAudit()
{
   for(int i = 0; i < LOGIC_COUNT; i++)
   {
      LogicSlot slot = g_logicSlots[i];
      PositionSnapshot snap = BuildPositionSnapshotForMagic(slot.magic);

      if(!slot.enabled)
      {
         PrintLogicAudit(slot, snap, "SKIP", "LOGIC_DISABLED");
         continue;
      }

      if(!slot.tradeRouteEnabled)
      {
         PrintLogicAudit(slot, snap, "AUDIT_ONLY", slot.runtimeReason);
         continue;
      }

      PrintLogicAudit(slot, snap, "READY", "TRADE_ROUTE_ENABLED");

      // 実際のEAでは、この後にsignal / gate / risk / executionへ分けて渡します。
      // この記事では中核Entry条件や実発注処理は扱いません。
   }
}

audit onlyを使うと、新ロジックを実売買へ接続する前に、対象ポジション、候補、停止理由をログで確認できます。

ログで確認するポイント

マルチロジックEAでは、ログにlogic_idやマジックナンバーがないと、原因を追いにくくなります。

ログ区分確認できること
LOGIC_INITロジック定義が正しく初期化されたかlogic_id、name、magic、enabled
LOGIC_AUDITロジックごとの状態AUDIT_ONLY、TRADE_ROUTE_ENABLED
POSITION_SNAPSHOTロジック別保有状態count、buy、sell、volume、profit
GATEロジック別に実行前条件を通過したかGATE_PASS、SPREAD_BLOCK、DUPLICATE_BLOCK
RISKロジック別riskや全体riskで止まったかLOGIC_RISK_BLOCK、GLOBAL_RISK_BLOCK
ORDERどのロジックが注文したかlogic_id、magic、retcode
CLOSE_SCOPE決済対象が正しいかsymbol、magic、ticket、reason

ログには、sideだけでなく、logic_id、magic、route、reasonを含めると確認しやすくなります。

よくある失敗例

失敗1:複数ロジックで同じマジックナンバーを使う

同じマジックナンバーを使うと、ポジション集計、決済対象、risk管理、成績確認が混ざります。ロジックごとに一意のマジックナンバーを割り当てることが基本です。

失敗2:全体ポジションだけを見ている

EA全体の保有数だけを見ると、どのロジックがポジションを持っているのか分かりません。ロジック別Position Snapshotが必要です。

失敗3:Close Scopeが広すぎる

symbolだけで決済対象を選ぶと、他ロジックや他EAのポジションを巻き込む可能性があります。symbol、magic、logic_id、ticketを確認します。

失敗4:検証中ロジックをいきなり実売買へつなぐ

新ロジックは、defined、snapshot only、audit only、pre-route gate、trade route enableの段階を分けて確認する方が安全です。

失敗5:ロジック別riskと全体riskを混同する

ロジック別には許可されていても、EA全体riskで止める場合があります。LOGIC_RISK_BLOCKとGLOBAL_RISK_BLOCKを分けます。

失敗6:ログにlogic_idがない

複数ロジックEAでlogic_idやmagicがログにないと、どのロジックが何を判断したのか分かりません。

失敗7:追加ロジックが既存ロジックの状態変数を使い回す

状態変数の使い回しは、意図しない停止、誤発注、誤決済の原因になります。LogicSlotごとに状態を分けます。

導入前・開発依頼前に整理する情報

マルチロジックEAを開発・改修する場合、次の情報を整理しておくと仕様確認がスムーズになります。

  • ロジック数
  • 各ロジックの役割
  • 各ロジックのマジックナンバー
  • 各ロジックのBUY / SELL対象
  • 同時稼働するか、排他制御するか
  • ロジック別risk
  • EA全体risk
  • ロジック別Position Snapshotの項目
  • Close Scopeの範囲
  • 新ロジックをaudit onlyから始めるか
  • 実売買へ接続する条件
  • ログに出すlogic_id、magic、route、reason
  • 既存ロジックへ影響させないための検証手順

マルチロジックEAは、条件を増やすだけではなく、識別、状態、risk、決済、ログを分けて設計する必要があります。

関連する技術講座・確認ページ

ページ確認できること
技術講座ハブMQL5やMT5開発に関する講座一覧
MQL5 EA設計パターン完全ガイドEA設計全体の基本構造
MQL5注文・ポジション・履歴管理完全ガイド注文、ポジション、履歴管理の基本
MQL5デバッグ・ログファースト開発完全ガイドログ確認、デバッグ、原因調査の基本
MQL5ロット・証拠金・銘柄仕様完全ガイドロット、証拠金、銘柄仕様の確認
MT5開発依頼前に用意する資料まとめ仕様書、setファイル、ログ、スクリーンショットの整理
不具合報告・調査依頼について不具合相談前に送る情報
免責事項・リスク説明投資判断、損益、利用上の注意に関する確認

FAQ

マルチロジックEAとは何ですか?

1つのEA内で複数の戦略やロジックを扱うEAです。順張り、逆張り、レンジ、時間足違い、BUY専用、SELL専用などを同じEA内で扱う場合があります。

ロジックごとにマジックナンバーを分ける必要がありますか?

基本的には分けるべきです。同じマジックナンバーを使うと、ポジション集計や決済対象が混ざり、誤決済や検証不能につながる可能性があります。

enabledとtradeRouteEnabledは何が違いますか?

enabledはロジックを確認対象にするかどうか、tradeRouteEnabledは実売買へ接続するかどうかです。enabled=trueでもtradeRouteEnabled=falseなら、audit onlyとしてログ確認だけ行えます。

Position Snapshotはなぜ必要ですか?

ロジックごとの保有数、方向、ロット、損益を分けて確認するためです。全体集計だけでは、どのロジックのポジションか切り分けにくくなります。

Close Scopeとは何ですか?

決済対象の範囲です。マルチロジックEAでは、symbolだけでなく、magic、logic_id、ticketなどで対象を限定し、他ロジックのポジションを巻き込まないようにします。

新しいロジックはすぐ実売買へ接続してよいですか?

避けた方が安全です。まずはLogicSlot定義、Snapshot確認、audit only、pre-route gateの順に進め、ログ確認後にtrade routeを有効化する流れが安全です。

全体riskとロジック別riskはどちらを優先しますか?

仕様によりますが、実務上はロジック別riskとEA全体riskを両方確認します。ロジック別には許可されていても、EA全体riskで止める場合があります。

実装コードがなくてもマルチロジックEAの相談はできますか?

可能です。ロジック数、役割、マジックナンバー、同時稼働方針、risk、Close Scope、ログ項目が整理されていれば、相談を進めやすくなります。

関連する開発実務ノート

マルチロジックEAでは、ロジック別の状態管理だけでなく、EA全体の責務分離、ログ設計、バックテスト条件、商品化前チェックも重要です。

まとめ

MQL5でマルチロジックEAを作る場合、単に条件式を増やすだけでは不十分です。

特に、次の4点を分けると、誤発注、誤決済、検証不能、既存ロジックへの影響を防ぎやすくなります。

  • LogicSlot:ロジックごとの設定・状態・実行可否を管理する
  • マジックナンバー:注文とポジションをロジック単位で識別する
  • Position Snapshot:ロジック別の保有数・方向・損益を固定して確認する
  • Close Scope:決済対象をsymbol、magic、logic_id、ticketで限定する

また、新しいロジックは、いきなり実売買へ接続せず、defined、snapshot only、audit only、pre-route gate、trade route enableのように段階を分けて確認する方が安全です。

完成EAの中核ロジックを公開しなくても、マルチロジックEAの状態管理、マジックナンバー、Snapshot、Close Scope、risk分離を理解しておくことで、開発依頼、既存EA改修、検証、不具合調査、販売後サポートの品質を上げやすくなります。

ABOUT ME
記事URLをコピーしました