MQL5パネルUI・チャートObject表示を実コードで解説|表示系と判定系を分ける理由

EAファンクラブ

MQL5でパネルEAや裁量補助EAを作る場合、チャート上にラベル、ボタン、ステータス枠、ラインなどを表示することがあります。

しかし、パネルUIやチャートObjectは、見た目を作るだけではありません。表示系と判定系を混同すると、ボタン表示が変わっただけで売買挙動が変わる、古いObjectを判定に使ってしまう、時間足変更後に表示が崩れる、EA削除時にObjectが残る、といった問題につながります。

この記事では、MQL5のパネルUI・チャートObject表示を、学習用に一般化したコード断片で解説します。完成EAソース全文、外部シート制御、認証、endpoint、token、URL、実運用set値、中核エントリー条件は公開しません。

扱うのは、OBJ_LABEL、OBJ_BUTTON、OnChartEvent、UI状態管理、表示系と判定系の責務分離、表示更新ログ、Object名のprefix設計です。

この記事で扱う範囲

項目この記事で扱う内容扱わない内容
目的パネルUIとチャートObjectを安全に扱う設計利益を狙う売買ロジック、具体的なエントリー条件
主な機能OBJ_LABEL、OBJ_BUTTON、OnChartEvent、表示更新helper完成EAソース全文、実運用コード全文
設計対象表示系と判定系の分離、UIイベント、Object命名、表示更新外部制御、認証、実運用set値
コード例学習用に簡略化した短いコード断片中核エントリー条件、独自優位性のある判定式
確認対象UI_RENDER、BUTTON_CLICK、UI_REQUEST、OBJECT_UPDATEログ推奨ロット、推奨銘柄、売買判断

パネルUIで起きやすい問題

MQL5のパネルUIでは、見た目の問題だけでなく、EAの安全性に関わる問題が起きることがあります。

現象原因になりやすい設計改善方針
ボタンが残るObject lifecycleが整理されていない自EA所有のUI Objectだけを対象に管理する
クリック後に誤発注するOnChartEventから直接発注しているUI requestとexecutionを分ける
表示と内部状態がずれる画面表示を判定の真実として使っているruntime stateを真実にし、UIは表示補助にする
毎tickで表示がちらつくObjectを毎回削除・再作成している既存Objectを差分更新する
他EAや手動Objectを消すprefixなしでObjectDeleteしているowner prefixとobject kindで対象を限定する
時間足変更後に崩れる初期化・再描画・残存監査が不足しているOnInitで再構築し、必要に応じてstartup auditする

パネルUIは利用者にとって重要ですが、EAの売買判定そのものではありません。表示は表示、判定はruntime state、実行はexecutionとして分けることが重要です。

表示系と判定系を分ける理由

パネルEAでは、画面に表示されている文字やボタン状態を、そのまま売買判定の根拠にしてはいけません。

たとえば、ボタンに「READY」と表示されているから発注可能、ラベルに「BUY」と表示されているから買い判定、ラインがあるからTrail中、といった設計は危険です。

責務役割保持する情報
runtime stateEA内部の真の状態ready、mode、position state、request state
signal判定候補を作るsignal side、score、reason
execution発注・決済を行うorder request、retcode、ticket
UI状態を表示し、操作要求を受けるlabel text、button state、panel color
log状態変化と理由を記録するevent、reason、detail

UIはあくまでruntime stateを表示するための層です。UIに表示されている文字を読み返して判定に使うのではなく、内部状態をもとに表示を更新します。

Object名のprefix設計

チャート上のObjectを安全に管理するには、Object名にprefixを付けて、自EAが作成したものだけを識別できるようにします。

Object名には、少なくとも次の情報を含めると管理しやすくなります。

  • EAまたはシリーズ識別用のprefix
  • UIかラインかラベルかのkind
  • 用途名
  • 必要に応じてsideやlogic id

たとえば、学習用には次のような命名が考えられます。

EAFC_UI_StatusLabel
EAFC_UI_BuyButton
EAFC_UI_SellButton
EAFC_UI_ModeLabel
EAFC_LINE_Avg_Buy
EAFC_LINE_Trail_Sell

prefixがないと、他EAや手動Objectを誤って削除・更新する危険があります。Object操作では、必ず自EA所有かどうかを確認する方針が重要です。

OBJ_LABELとOBJ_BUTTONの違い

パネルUIでよく使うObjectには、OBJ_LABELとOBJ_BUTTONがあります。

Object種別用途注意点
OBJ_LABEL状態、説明、数値、警告などの表示表示専用。判定の真実として使わない
OBJ_BUTTONクリック操作、モード切替、確認操作クリックで直接発注せず、request化する
OBJ_RECTANGLE_LABEL背景枠、パネル枠重ね順、座標、サイズを整理する
OBJ_HLINE価格ライン、目安ライン表示専用かロジック参照対象かを分ける
OBJ_TEXT価格位置に紐づく文字表示チャートスケールや表示位置の影響を受ける

OBJ_BUTTONを使う場合でも、OnChartEvent内で直接注文を送信するのではなく、「ユーザーがクリックした」というrequestを作り、execution側で安全確認を行ってから実行します。

OnChartEventで直接発注しない理由

OnChartEventは、チャート上のクリックやキー操作などのイベントを受け取る関数です。

ボタン操作を扱えるため便利ですが、OnChartEventから直接OrderSendや決済処理へ進む設計は避けた方が安全です。

理由は次の通りです。

  • クリックイベントと実行条件確認が混ざる
  • 誤クリック時のガードが弱くなりやすい
  • ログ上、UI操作と発注実行の境界が分かりにくい
  • AutoTrading、spread、ポジション状態、重複制御を飛ばす危険がある
  • 後からconfirmやREADY制御を追加しにくい

安全な設計では、OnChartEventは「UI requestを作る場所」として扱い、実際のexecutionは別の関数で行います。

実コード断片1:UI Object名を作る

以下は、実際のEAで使う考え方を学習用に簡略化したコード例です。完成EAのソース全文ではなく、Object命名の構造を理解するための抜粋です。

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

string UiPrefix()
{
   return "EAFC_UI_";
}

string UiObjectName(string partName)
{
   return UiPrefix() + partName;
}

bool IsOwnUiObject(string name)
{
   return (StringFind(name, UiPrefix()) == 0);
}

string BuildSidePartName(string baseName, string side)
{
   return baseName + "_" + side;
}

実際のEAでは、認証、外部制御、口座条件、エラー処理、ログ出力などを分けて設計します。この記事では、公開できる範囲の構造だけを取り上げています。

このコードの役割

処理役割
UiPrefix自EAのUI Objectであることを示すprefixを返す
UiObjectNameUI部品名を統一形式で作る
IsOwnUiObject他EAや手動Objectと区別する
BuildSidePartNameBUY / SELLなど方向付き部品名を作る

Object名の作り方をhelperにまとめると、ボタンやラベルが増えても命名ルールを揃えやすくなります。

実コード断片2:ラベルを作成・更新する

以下は、OBJ_LABELを作成し、すでに存在する場合はテキストだけ更新する学習用コード例です。

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

bool EnsureLabel(string name, int x, int y)
{
   if(ObjectFind(0, name) >= 0)
      return true;

   ResetLastError();

   if(!ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0))
   {
      Print("DIAG/UI: event=CREATE_FAIL",
            " kind=LABEL",
            " name=", name,
            " error=", GetLastError());
      return false;
   }

   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);

   Print("DIAG/UI: event=CREATE_OK",
         " kind=LABEL",
         " name=", name);

   return true;
}

void SetLabelText(string name, string text)
{
   if(ObjectFind(0, name) < 0)
      return;

   ObjectSetString(0, name, OBJPROP_TEXT, text);
}

この例では、ラベルがなければ作成し、存在する場合は再作成しません。毎tickで削除と作成を繰り返すのではなく、既存Objectを差分更新する方針です。

このコードの役割

処理役割
EnsureLabelラベルが存在しなければ作成する
ObjectFind既存Objectの有無を確認する
ObjectCreateOBJ_LABELを作成する
ObjectSetInteger座標、角、フォントサイズなどを設定する
SetLabelText既存ラベルの文字だけ更新する

表示更新は、売買判定ではなくUI層の責務です。ラベルに表示した文字を後から読み取って判定する構造は避けます。

実コード断片3:ボタンを作成する

以下は、OBJ_BUTTONを作成する学習用コード例です。ボタン作成と、クリック後の実行処理は分けて考えます。

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

bool EnsureButton(string name, string text, int x, int y, int width, int height)
{
   if(ObjectFind(0, name) >= 0)
      return true;

   ResetLastError();

   if(!ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0))
   {
      Print("DIAG/UI: event=CREATE_FAIL",
            " kind=BUTTON",
            " name=", name,
            " error=", GetLastError());
      return false;
   }

   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
   ObjectSetString(0, name, OBJPROP_TEXT, text);

   Print("DIAG/UI: event=CREATE_OK",
         " kind=BUTTON",
         " name=", name);

   return true;
}

このコードは、ボタンを表示するだけの例です。クリックされた時に何をするかは、OnChartEvent側で受け取り、requestとしてruntimeへ渡します。

このコードの役割

処理役割
EnsureButtonボタンが存在しなければ作成する
OBJ_BUTTONチャート上のクリック可能なObjectを作る
OBJPROP_XSIZE / YSIZEボタンサイズを設定する
OBJPROP_TEXTボタンに表示する文字を設定する
CREATE_OKボタン作成が成功したことをログへ残す

ボタン表示が成功していることと、発注可能であることは別です。UI表示とexecution条件は必ず分けます。

実コード断片4:UI requestを作る

以下は、ボタンクリックを直接実行せず、UI requestとして内部状態へ渡す学習用コード例です。

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

enum UiRequestType
{
   UI_REQUEST_NONE = 0,
   UI_REQUEST_BUY,
   UI_REQUEST_SELL,
   UI_REQUEST_CANCEL
};

struct UiRequest
{
   UiRequestType type;
   datetime requestedAt;
   string reason;
};

UiRequest g_uiRequest;

void ClearUiRequest()
{
   g_uiRequest.type = UI_REQUEST_NONE;
   g_uiRequest.requestedAt = 0;
   g_uiRequest.reason = "NONE";
}

void SetUiRequest(UiRequestType type, string reason)
{
   g_uiRequest.type = type;
   g_uiRequest.requestedAt = TimeCurrent();
   g_uiRequest.reason = reason;

   Print("DIAG/UI_REQUEST: event=SET",
         " type=", (int)type,
         " reason=", reason);
}

UI requestを作ることで、クリック操作と実際のexecutionを分離できます。

このコードの役割

処理役割
UiRequestTypeUIから来た操作要求の種類を定義する
UiRequest操作要求の種類、時刻、理由を保持する
ClearUiRequest処理済みまたは無効なrequestをクリアする
SetUiRequestクリックされた操作をrequestとして記録する
UI_REQUESTログUI操作が発生したことをExpertsログで追えるようにする

この時点では、まだ発注や決済を行いません。発注や決済を行う前に、AutoTrading、spread、保有状態、重複制御、risk条件などの確認が必要です。

実コード断片5:OnChartEventでクリックを受ける

以下は、OnChartEventでボタンクリックを受け取り、UI requestを作る学習用コード例です。

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

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   if(id != CHARTEVENT_OBJECT_CLICK)
      return;

   if(!IsOwnUiObject(sparam))
      return;

   Print("DIAG/UI: event=BUTTON_CLICK",
         " object=", sparam);

   if(sparam == UiObjectName("BuyButton"))
   {
      SetUiRequest(UI_REQUEST_BUY, "BUY_BUTTON_CLICK");
      return;
   }

   if(sparam == UiObjectName("SellButton"))
   {
      SetUiRequest(UI_REQUEST_SELL, "SELL_BUTTON_CLICK");
      return;
   }

   if(sparam == UiObjectName("CancelButton"))
   {
      SetUiRequest(UI_REQUEST_CANCEL, "CANCEL_BUTTON_CLICK");
      return;
   }

   Print("DIAG/UI: event=CLICK_IGNORED",
         " reason=UNKNOWN_OBJECT",
         " object=", sparam);
}

この例では、クリックされたObjectが自EAのUI Objectかを確認し、対象ボタンに応じてrequestを作っています。

このコードの役割

処理役割
CHARTEVENT_OBJECT_CLICKObjectクリックイベントだけを対象にする
IsOwnUiObject自EAのUI Object以外を無視する
BUTTON_CLICKクリックされたObject名をログへ残す
SetUiRequestクリック操作を内部requestへ変換する
CLICK_IGNORED未知のObjectクリックを無視したことを記録する

OnChartEventはUIイベントを受ける場所であり、executionを直接行う場所ではありません。

実コード断片6:UI requestを安全に処理する

以下は、UI requestを確認し、実行前ガードへ渡す考え方を示す学習用コード例です。実際の発注処理や中核エントリー条件は含めていません。

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

bool CanProcessUiRequest()
{
   // 実際はAutoTrading、spread、position、risk、duplicate gateなどを確認します。
   return true;
}

void ProcessUiRequest()
{
   if(g_uiRequest.type == UI_REQUEST_NONE)
      return;

   Print("DIAG/UI_REQUEST: event=PROCESS_START",
         " type=", (int)g_uiRequest.type,
         " reason=", g_uiRequest.reason);

   if(!CanProcessUiRequest())
   {
      Print("DIAG/UI_REQUEST: event=BLOCK",
            " reason=PRECHECK_FAIL");
      ClearUiRequest();
      return;
   }

   if(g_uiRequest.type == UI_REQUEST_BUY)
   {
      Print("DIAG/UI_REQUEST: event=ROUTE",
            " target=BUY_EXECUTION_CHECK");
   }
   else if(g_uiRequest.type == UI_REQUEST_SELL)
   {
      Print("DIAG/UI_REQUEST: event=ROUTE",
            " target=SELL_EXECUTION_CHECK");
   }
   else if(g_uiRequest.type == UI_REQUEST_CANCEL)
   {
      Print("DIAG/UI_REQUEST: event=ROUTE",
            " target=CANCEL_REQUEST");
   }

   ClearUiRequest();
}

この例では、UI requestを受けても、すぐに発注へ進まず、まず実行前確認へ渡しています。

このコードの役割

処理役割
CanProcessUiRequest実行前に必要な安全確認を行う入口
PROCESS_STARTUI request処理の開始をログへ残す
BLOCK安全条件を満たさず処理を止めたことを示す
ROUTE次にどの実行確認へ進むかを示す
ClearUiRequest処理済みrequestを残さない

このように、UI操作とexecutionを分けることで、ボタンクリックから直接発注へ進む事故を防ぎやすくなります。

実コード断片7:パネル表示をruntime stateから更新する

以下は、runtime stateをもとにパネル表示を更新する学習用コード例です。

// 学習用に一般化したパネル表示更新例です。
// 実運用EAの完成ソースではありません。

struct PanelState
{
   bool runtimeReady;
   string modeText;
   string statusText;
   string lastReason;
};

PanelState BuildPanelState()
{
   PanelState state;
   state.runtimeReady = true;
   state.modeText = "MONITOR";
   state.statusText = "READY";
   state.lastReason = "OK";

   return state;
}

void RenderPanel(const PanelState &state)
{
   string statusName = UiObjectName("StatusLabel");
   string modeName   = UiObjectName("ModeLabel");

   EnsureLabel(statusName, 20, 20);
   EnsureLabel(modeName, 20, 40);

   SetLabelText(statusName, "Status: " + state.statusText);
   SetLabelText(modeName, "Mode: " + state.modeText);

   Print("DIAG/UI_RENDER: event=UPDATE",
         " status=", state.statusText,
         " reason=", state.lastReason);
}

この例では、UI表示をPanelStateから更新しています。画面上のラベルを読み返してEAの状態を決めるのではなく、runtime stateから表示を作ります。

このコードの役割

処理役割
PanelState表示に必要な状態だけをまとめる
BuildPanelStateruntime stateから表示用stateを作る
RenderPanel表示用stateをラベルへ反映する
UI_RENDER表示更新が行われたことをログへ残す

UIはruntime stateの結果を表示する層です。UIそのものを判定の真実として扱わないことが重要です。

表示更新を毎tickで重くしない

パネルUIは、毎tickで更新しすぎると重くなります。

特に、次の処理は避けた方が安全です。

  • 毎tickで全Objectを削除して再作成する
  • 毎tickで全ラベルの座標やサイズを再設定する
  • 毎tickで大量のUI_RENDERログを出す
  • 変化していない文字列を何度も更新する
  • 表示更新失敗でEA本体を止める

表示更新は、初期化時、状態変化時、または一定間隔で行うと安定しやすくなります。

表示系の失敗は売買系へ波及させない

パネルUIの表示失敗は、可能な限り売買系へ直接波及させない設計にします。

状態推奨する扱い
ラベル作成に失敗ログに残し、表示だけbest-effortで継続
ボタン作成に失敗手動操作系を無効化し、ログに残す
表示更新が遅延runtime stateを優先し、表示は次回更新で補正
クリック対象が未知無視してログに残す
UI requestが古い有効期限切れとして破棄する

表示系は利用者の確認に必要ですが、表示Objectの状態をそのまま発注や決済の根拠にしないことが重要です。

OnDeinitでのUI cleanup

UI Objectは、平均価格ラインやTrailラインなどの取引補助ラインとは異なり、自EA所有が明確なステータス表示として整理しやすい場合があります。

ただし、OnDeinitで広範囲のObjectを消すのではなく、prefixが一致する軽量なUI Objectだけを対象にします。

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

void DeleteOwnUiObjects()
{
   for(int i = ObjectsTotal(0) - 1; i >= 0; i--)
   {
      string name = ObjectName(0, i);

      if(!IsOwnUiObject(name))
         continue;

      ObjectDelete(0, name);

      Print("DIAG/UI: event=DELETE",
            " name=", name);
   }
}

void OnDeinit(const int reason)
{
   Comment("");

   EventKillTimer();

   DeleteOwnUiObjects();

   Print("DIAG/DEINIT: event=UI_CLEANUP_DONE",
         " reason=", reason);
}

この例は、自EA所有が明確なUI Objectだけを対象にしています。実ロジックに関係する価格ラインや残存監査対象のObjectを、同じcleanupでまとめて消す設計は避けます。

よくある失敗例

失敗1:OnChartEventから直接発注する

ボタンクリックから直接発注へ進むと、precheck、duplicate gate、risk、position stateの確認を飛ばしやすくなります。UI requestを作り、execution側で安全確認してから処理します。

失敗2:表示ラベルの文字を判定に使う

ラベルは表示結果であり、判定の真実ではありません。EA内部のruntime stateを真実として扱い、ラベルはそこから作ります。

失敗3:毎tickでObjectを作り直す

毎tickでObjectDeleteとObjectCreateを繰り返すと、ちらつき、重さ、Object残存の原因になります。既存Objectを差分更新します。

失敗4:prefixなしでObjectを削除する

prefixなしでObjectDeleteすると、手動ラインや他EAのObjectまで巻き込む可能性があります。自EA所有のUI Objectだけを対象にします。

失敗5:UI表示失敗でEA本体を止める

表示系の失敗は、売買系と分けて扱う必要があります。表示はbest-effort、判定やexecutionはruntime stateで管理します。

ログで確認するポイント

パネルUI・チャートObject表示の問題を確認する時は、Expertsログで次の情報を見ます。

ログ見るポイント
CREATE_OKラベルやボタンが作成できているか
CREATE_FAILObjectCreate失敗時のerrorが確認できるか
BUTTON_CLICKクリックされたObject名が確認できるか
UI_REQUEST SETクリックがrequestへ変換されているか
UI_REQUEST BLOCK安全条件で止まった理由が分かるか
UI_RENDER UPDATEruntime stateから表示更新されているか
UI_CLEANUP_DONEEA終了時のUI cleanupが確認できるか

ログ確認の基本は、次のページも参考にしてください。

MT5のログ確認方法|Experts・Journalの見方

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

パネルEAや裁量補助EAの開発を依頼する場合、次の情報を整理しておくと仕様のすれ違いを減らせます。

  • 表示したい項目
  • ボタン操作の種類
  • クリック後に即実行するのか、確認段階を挟むのか
  • BUY / SELL / CANCEL / RESETなどの操作範囲
  • 表示系と判定系を分けるか
  • UI requestの有効期限
  • Object名のprefix
  • OnDeinitで削除するUI Objectの範囲
  • 残すラインと消すパネル部品の違い
  • UI操作ログの粒度

仕様書、setファイル、ログ、スクリーンショットを整理する場合は、次のページも確認してください。

MT5開発依頼前に用意する資料まとめ|仕様書・setファイル・ログ・スクリーンショット

公開しない情報

この記事では、MQL5のパネルUI・チャートObject表示を学ぶために、公開可能な範囲だけを一般化して解説しています。以下は公開しません。

  • 完成EAソース全文
  • 外部シート参照による動作制御ロジック
  • 外部シートCSV取得、解析、時間枠、方向制御ロジック
  • 認証、口座許可判定、購入者管理ロジック
  • endpoint、token、URL、Google Sheet ID、Webhook URL、GAS URL
  • APIキー、認証トークン、口座番号、サーバー名
  • 実運用set値
  • 中核エントリー条件
  • 中核Trail / Nanpin判定
  • 独自優位性のある売買判定式
  • 利益保証、勝率保証、推奨ロット、推奨銘柄、推奨エントリー

本記事は、投資判断や売買指示ではなく、MQL5開発におけるパネルUI、チャートObject、OnChartEvent、表示系と判定系の分離を理解するための技術解説です。

FAQ

パネルUIの表示内容を売買判定に使ってよいですか?

避けた方が安全です。表示内容はruntime stateを表示した結果であり、判定の真実ではありません。売買判定は内部状態やsnapshotをもとに行い、UIは表示補助として扱います。

OnChartEventから直接発注してよいですか?

避けるべきです。OnChartEventではクリックを受け取り、UI requestを作るまでに留めます。実際の発注や決済は、precheck、risk、duplicate gateなどを通したexecution側で行います。

OBJ_LABELとOBJ_BUTTONは何が違いますか?

OBJ_LABELは表示用、OBJ_BUTTONはクリック操作用です。どちらもチャートObjectですが、役割が違います。表示Objectを判定の真実として使わないことが重要です。

毎tickでパネルを更新してもよいですか?

状態表示の内容によります。毎tickでObjectを削除・再作成するのは避けるべきです。既存Objectの文字だけ更新する、状態変化時に更新する、一定間隔で更新するなどの方法が安全です。

EA削除時にUI Objectは消してよいですか?

自EA所有が明確な軽量UI Objectであれば、OnDeinitで整理しやすい対象です。ただし、価格ラインや残存監査対象のObjectを広範囲にまとめて消す設計は避けるべきです。

Object名にprefixは必要ですか?

必要です。prefixがないと、他EAや手動Objectと区別できず、誤削除や誤更新の原因になります。自EA所有のObjectだけを扱える命名ルールが重要です。

このコードは完成EAとして使えますか?

いいえ。この記事のコード例は、パネルUI・チャートObject表示の考え方を理解するために簡略化した学習用コードです。完成EAとしてそのまま使うことは想定していません。

実際のEAソース全文は公開されていますか?

公開していません。完成EAソース全文、外部シート制御、認証、endpoint、token、URL、実運用set値、中核エントリー条件は公開対象外です。

関連ページ

ページ確認できること
MQL5 EAのObject lifecycleを実コードで解説Object残存、OnDeinit cleanup、startup auditの考え方
MQL5ログファースト設計を実コードで解説UI操作やObject更新をreason付きでログ確認する考え方
MQL5 EAの基本イベント構造を実コードで解説OnInit / OnTick / OnDeinitの責務分離
MQL5 CopyBufferとインジケーターハンドル管理を実コードで解説表示系とは別に、インジケーター値取得を管理する考え方
MT5のログ確認方法|Experts・Journalの見方ExpertsログとJournalログの基本確認
MT5開発依頼前に用意する資料まとめ|仕様書・setファイル・ログ・スクリーンショット開発相談前に整理する資料
不具合報告・調査依頼について不具合相談前に送る情報
免責事項投資判断、損益、利用上の注意に関する確認
投資助言を行わない方針売買助言ではなく技術支援として扱う方針

まとめ

MQL5でパネルUIやチャートObjectを扱う場合、見た目を作ることよりも、表示系と判定系を分けることが重要です。

特に、次の4点を分けておくと、誤操作・表示崩れ・Object残存・判定混線を防ぎやすくなります。

  • UI Object:OBJ_LABELやOBJ_BUTTONで状態表示・操作受付を行う
  • runtime state:EA内部の真の状態を保持する
  • UI request:クリック操作を直接実行せず、操作要求として扱う
  • execution:precheck、risk、duplicate gateを通して実行する

OnChartEventは、クリックイベントを受ける入口です。そこから直接発注や決済へ進むのではなく、UI requestを作り、別のexecution層で安全確認してから処理する構成が安全です。

完成EAの中核ロジックを公開しなくても、パネルUI、Object命名、OnChartEvent、UI request、runtime stateの分離を理解しておくことで、パネルEAや裁量補助EAの設計・検証・不具合調査がしやすくなります。

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