从用户面板
🎛️

从用户面板"动态"更改"EA 交易"参数·综合运用

(3/3)· 当 EA 外部参数堆到几十个,手动改设置比盯盘还累,这篇给完整落地方案

案例拆解新手友好 第 3/3 篇
参数一多,每次调手数或止损都要回设置页翻半天,交易节奏直接断。其实只要在 EA 里挂个用户面板,点一下就能改、还能落盘持久化。这套做法不挑品种,外汇贵金属高波动时段尤其省事。

面板编辑框里的输入校验与回写

在 MT5 自定义指标面板里,用户改了编辑框内容并不会自动生效,必须靠 CHARTEVENT_OBJECT_ENDEDIT(id==3)事件捕获。上面这段代码先拿 sparam 里的对象名,只处理名为 "editValIP" 的编辑框,其余控件忽略。 当 number==0 即修改「指标周期」时,代码做了硬约束:如果输入是 "0"、空串、或 SD() 解析出的数值 ≤0,就强制把 currVal 改写成 "1"。这能避免把周期设成非法值导致指标句柄失效。 校验通过后,用 ObjectSetString 把值写回面板上的 "enumMB0" 文本对象,完成界面与内部变量的同步。外汇与贵金属波动剧烈,这类输入防护能降低 EA 在极端行情下因参数异常崩掉的概率,建议直接复制这段逻辑到自己的面板回调里验证。

MQL5 / C++
class="type">bool ChartEvent_ObjectEndEdit(class="type">int id,class="type">long lparam,class="type">class="kw">double dparam,class="type">class="kw">string sparam)
  {
   if(id==CHARTEVENT_OBJECT_ENDEDIT) class=class="str">"cmt">// id==class="num">3
    {
     class="type">class="kw">string editObject=sparam; class=class="str">"cmt">// Name of the edited object
     class=class="str">"cmt">//---
     class=class="str">"cmt">// If the value has been entered in the input box in the dialog window
     if(editObject=="editValIP")
      {
       class=class="str">"cmt">// Get the entered value
       currVal=ObjectGetString(class="num">0,"editValIP",OBJPROP_TEXT);
       class=class="str">"cmt">//---
       class=class="str">"cmt">// (class="num">0) Period Indicator
       if(number==class="num">0)
        {
         class=class="str">"cmt">// Correct the value if it is wrong
         if(currVal=="class="num">0" || currVal=="" || SD(currVal)<=class="num">0) { currVal="class="num">1"; }
         class=class="str">"cmt">//---
         class=class="str">"cmt">// Set the entered value
         ObjectSetString(class="num">0,"enumMB0",OBJPROP_TEXT,currVal);
        }
     class=class="str">"cmt">//---
     class=class="str">"cmt">// (class="num">4) Lot

◍ 输入框校验与面板回写逻辑

这段处理的是 MT5 面板里手填参数后的兜底:当编号 number 为 4(对应成交量类字段)时,若当前字符串 currVal 是 "0"、空串,或经 SD() 转double后小于等于 0,就把它重置为 SS.vol_min 保留两位小数的值,避免零手数发单。 编号 1 和 2 分别对应止盈、止损点数,逻辑更硬:只要填了非法值(0、空、或转数值≤0),直接回退成 "1" 点,保证风控字段不可能静默失效。 回写用 ObjectSetString 打到 enumMB0 / enumMB1 文本对象,最后删掉临时编辑框 editValIP 并 ChartRedraw(),界面即时刷新。外汇与贵金属波动剧烈,这类输入校验缺失可能在跳空时放大滑点风险,建议直接把这段拷进自己的 EA 面板事件分支里跑一遍。

MQL5 / C++
if(number==class="num">4)
  {
  class=class="str">"cmt">// Correct the value if it is wrong
  if(currVal=="class="num">0" || currVal=="" || SD(currVal)<=class="num">0) { currVal=DS(SS.vol_min,class="num">2); }
  class=class="str">"cmt">//---
  class=class="str">"cmt">// Set the entered value
  ObjectSetString(class="num">0,"enumMB0",OBJPROP_TEXT,DS2(SD(currVal)));
  }
class=class="str">"cmt">//---
class=class="str">"cmt">// (class="num">1) Take Profit(p)
class=class="str">"cmt">// (class="num">2) Stop Loss(p)
if(number==class="num">1 || number==class="num">2)
  {
  class=class="str">"cmt">// Correct the value if it is wrong
  if(currVal=="class="num">0" || currVal=="" || SD(currVal)<=class="num">0) { currVal="class="num">1"; }
  class=class="str">"cmt">//---
  class=class="str">"cmt">// Set the entered value
  ObjectSetString(class="num">0,"enumMB1",OBJPROP_TEXT,currVal);
  }
class=class="str">"cmt">//---     
DelObjbyName("editValIP"); ChartRedraw();
   }
   }
class=class="str">"cmt">//---
  class="kw">return(false);
}

「别急着下结论」

随附的压缩包(约 26.38 KB)里放了可跑的面板样例,想深究直接拖进 MT5 的 MQL5 目录解压验证。原文作者故意漏了两类边界检查:对话框弹出后若手动改图表宽高,面板不会自动回中;列表切换选项时,标记选中行的对象会错位——这两处留给你当练手。 下面这段是评论区一位用户踩过的坑:用变量 tf / tf1 传给 iCustom 想「即时」切周期却失效,写死 PERIOD_M5、PERIOD_M15 反而正常。 ENUM_TIMEFRAMES tf0,tf,tf1; void OnInit() { ................. tf0 = PERIOD_CURRENT; switch (PERIOD_CURRENT) { case PERIOD_M1: tf =PERIOD_M5;tf1 =PERIOD_M15; break; case PERIOD_M5: tf =PERIOD_M15; tf1 =PERIOD_H1;break; case PERIOD_M15: tf =PERIOD_H1;tf1 =PERIOD_H4;break; case PERIOD_M30: tf =PERIOD_H2;tf1 =PERIOD_H8; break; case PERIOD_H1: tf =PERIOD_H4; tf1 =PERIOD_H12;break; case PERIOD_H4: tf =PERIOD_H12; tf1 =PERIOD_D1; break; case PERIOD_D1: tf =PERIOD_D1; tf1 =PERIOD_W1; break; } //--- 获取 MA 的手柄 Ext1Handle=iCustom(NULL,PERIOD_CURRENT,"xxxx",SlowEMA1);//工作正常 Ext2Handle=iCustom(NULL,PERIOD_M5,"xxxx",SlowEMA1);//工作正常 Ext3Handle=iCustom(NULL,PERIOD_M15,"xxxx",SlowEMA1);//工作正常 //下面的工作出错! // Ext1Handle=iCustom(NULL,PERIOD_CURRENT, "xxxx",SlowEMA1); // Ext2Handle=iCustom(NULL,tf, "xxxx",SlowEMA1); // Ext3Handle=iCustom(NULL,tf1, "xxxx",SlowEMA1); 逐行看:tf0/tf/tf1 声明周期枚举变量;OnInit 里先把 tf0 设为当前周期,再用 switch 按当前周期给 tf、tf1 派生出更高层级周期。Ext1~3 用写死周期调用 iCustom 能拿到句柄,但换成变量 tf、tf1 的注释行却报错——说明 OnInit 阶段变量周期未必被终端接受,可能要在别处刷新句柄。 外汇和贵金属波动剧烈、杠杆风险高,这类 GUI 练习只帮你熟悉 MQL5 机制,别直接当实盘信号。把上面代码贴进 MT5 试一次,比看十遍文字更有用。

MQL5 / C++
ENUM_TIMEFRAMES tf0,tf,tf1;
class="type">void OnInit()
  {
.................
tf0 = PERIOD_CURRENT;
  class="kw">switch (PERIOD_CURRENT)
  {
    case PERIOD_M1:   tf =PERIOD_M5;tf1 =PERIOD_M15; break;
     case PERIOD_M5:   tf =PERIOD_M15; tf1 =PERIOD_H1;break;
     case PERIOD_M15:   tf =PERIOD_H1;tf1 =PERIOD_H4;break;
     case PERIOD_M30:   tf =PERIOD_H2;tf1 =PERIOD_H8;  break;
     case PERIOD_H1:   tf =PERIOD_H4; tf1 =PERIOD_H12;break;
     case PERIOD_H4:   tf =PERIOD_H12;  tf1 =PERIOD_D1; break;
     case PERIOD_D1:   tf =PERIOD_D1;  tf1 =PERIOD_W1;  break;
  }
class=class="str">"cmt">//--- 获取 MA 的手柄
  Ext1Handle=iCustom(NULL,PERIOD_CURRENT,"xxxx",SlowEMA1);class=class="str">"cmt">//工作正常
  Ext2Handle=iCustom(NULL,PERIOD_M5,"xxxx",SlowEMA1);class=class="str">"cmt">//工作正常
  Ext3Handle=iCustom(NULL,PERIOD_M15,"xxxx",SlowEMA1);class=class="str">"cmt">//工作正常
class=class="str">"cmt">//下面的工作出错! 
class=class="str">"cmt">// Ext1Handle=iCustom(NULL,PERIOD_CURRENT, "xxxx",SlowEMA1);
class=class="str">"cmt">// Ext2Handle=iCustom(NULL,tf, "xxxx",SlowEMA1); 
class=class="str">"cmt">// Ext3Handle=iCustom(NULL,tf1, "xxxx",SlowEMA1);
让小布替你跑这套
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到参数异动与面板状态,你把重复劳动交给小布,专注决策。

常见问题

文件在每次改参时即时更新,异常退出仅可能丢失最后一次未落盘的改动,重启用面板调一次即可,概率上影响不大。
可以,示例逻辑基于当前品种和图表周期,换贵金属只需注意点差和止损倍数,外汇贵金属均属高风险。
小布盯盘目前内置参数诊断与异动提示,EA 生成需自行按本篇结构写,但可把面板状态同步给小布看盘口。
可能文件未被清理或模式切换逻辑有残留,检查开关参数位置与文件删除检测,倾向把开关放参数列表首尾。