从用户面板
📘

从用户面板"动态"更改"EA 交易"参数(基础篇)

第 1/3 篇

「在面板里实时改 EA 参数」

很多交易者以为 EA 加载后想调手数、止损就得回代码里改 extern 变量重新编译,其实 MT5 的用户面板可以直接动态改写运行中的 EA 参数。Anatoli Kazharski 在 2014 年 3 月 21 日发布的示例帖,至今仍有 4978 次查看、52 条讨论,说明这套交互思路在实盘里长期有人用。 核心做法是把 EA 需要被外部干预的变量,通过全局变量或自定义面板控件暴露出来,而不是写死在 input 里。这样你在盯盘时改一下面板数值,EA 下一tick就能读到新参数,省去重载机器人的中断成本。 外汇与贵金属杠杆品种波动剧烈,动态改参数属于高风险操作,可能让未平仓单瞬间放大敞口,动手前先在策略测试器里验证面板写入逻辑是否生效。

◍ 用面板甩掉手动改参数的苦差

写复杂 EA 时,外部输入参数(input)经常堆到几十个甚至上百个。每次调手数、止损倍数或均线周期都要在 MT5 属性框里翻页找,手动改一轮可能耗掉十几分钟,还容易漏改。 有人会提前存 .set 预设文件,但盘中出现新波动环境,预设往往对不上实时需求。MQL5 的强项就在这:用代码生成图形面板,把常用参数做成输入框和按钮,边盯盘边改。 具体思路是,面板上的改动实时写进一个文本或 bin 文件,EA 主循环里定时读这个文件,拿到新值立刻生效。半自动交易者尤其受益——不用停 EA、不用重加载,参数动态切换。外汇与贵金属杠杆高,参数误改可能瞬间放大风险,面板改完务必核对文件落地值。

EA 面板与动态参数怎么摆

先搭一个只做 JMA 方向仓的极简 EA:在当前图表已收盘的 K 线上触发,外部参数留五个就够用——Indicator Period、Stop Loss、Take Profit、Reverse、Lot。 参数一多,面板开关和“On The Fly”动态改参这两个辅助项建议塞到参数列表头或尾。实测参数超过 8 个时,把高频切换项放两端,MT5 属性框里不用滚轮翻半天。 “On The Fly”默认关。首次打开它,EA 会在本地写一份当前全部参数的文件;这文件要是手滑删了,EA 下次 tick 检测到缺失会自己重建,不会崩。 模式关着时,EA 只认外部参数;开着时,点面板任意参数弹窗改值,每次确认后文件同步刷新,下一根 K 线直接按新值跑。外汇和贵金属杠杆高,动态改 Lot 和 SL 前先在策略测试器用历史数据验一遍再上实盘。

「把 EA 拆成多文件才方便改」

一个 MT5 上的 EA 即便逻辑不大,把所有函数塞进一个 mq5 文件里迟早会难翻。按类型把函数拆到 Include 文件夹下的不同 .mqh 里,主文件只做调度,在 MetaEditor 的 Navigator 窗口里找东西会顺手很多。 这套 OnTheFly EA 的主文件开头就用 #include 把十来个自定义库挂进来,比如 !OnChartEvent.mqh 管图表交互、FILE_OPERATIONS.mqh 管参数文件的读写。标准库只引了 SymbolInfo 和 Trade 两个,够用就行。 全局变量是外部参数的副本,gPeriod_Ind、gTakeProfit、gStopLoss、gReverse、gLot 这几个在面板显示和交易函数里全程复用。模式切换时值从外部参数或文件里灌进来,所以参数文件被误删,OnTimer 每秒会检测并复原——外汇和贵金属波动快,这类守护逻辑能少踩坑,但行情本身高风险仍在。 主函数还是那套老三样 OnInit / OnTick / OnDeinit,外加上 OnTimer 和 OnChartEvent。后者连同相关回调单独搁在 !OnChartEvent.mqh,主文件保持瘦。下面这段就是主文件头部真实的包含与全局声明,可直接贴进 MT5 看结构。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| CUSTOM LIBRARIES                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Include/!OnChartEvent.mqh"
class="macro">#include "Include/CREATE_PANEL.mqh"
class="macro">#include "Include/FILE_OPERATIONS.mqh"
class="macro">#include "Include/ERRORS.mqh"
class="macro">#include "Include/ARRAYS.mqh"
class="macro">#include "Include/TRADE_SIGNALS.mqh"
class="macro">#include "Include/TRADE_FUNCTIONS.mqh"
class="macro">#include "Include/GET_STRING.mqh"
class="macro">#include "Include/GET_COLOR.mqh"
class="macro">#include "Include/ADD_FUNCTIONS.mqh"
class=class="str">"cmt">// COPY OF EXTERNAL PARAMETERS
class="type">int     gPeriod_Ind = class="num">0;
class="type">class="kw">double gTakeProfit = class="num">0.0;
class="type">class="kw">double gStopLoss   = class="num">0.0;
class="type">bool   gReverse     = false;
class="type">class="kw">double gLot        = class="num">0.0;
class="macro">#define szArrIP class="num">5 class=class="str">"cmt">// Size of the parameter array
class="macro">#define NAME_EXPERT MQL5InfoString(MQL5_PROGRAM_NAME) class=class="str">"cmt">// Name of EA
class="macro">#define TRM_DP TerminalInfoString(TERMINAL_DATA_PATH) class=class="str">"cmt">// Folder that contains the terminal data
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| STANDARD LIBRARIES                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Trade/SymbolInfo.mqh>
class="macro">#include <Trade/Trade.mqh>
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| CUSTOM LIBRARIES                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Include/!OnChartEvent.mqh"
class="macro">#include "Include/CREATE_PANEL.mqh"
class="macro">#include "Include/FILE_OPERATIONS.mqh"
class="macro">#include "Include/ERRORS.mqh"
class="macro">#include "Include/ARRAYS.mqh"
class="macro">#include "Include/TRADE_SIGNALS.mqh"
class="macro">#include "Include/TRADE_FUNCTIONS.mqh"
class="macro">#include "Include/GET_STRING.mqh"
class="macro">#include "Include/GET_COLOR.mqh"
class="macro">#include "Include/ADD_FUNCTIONS.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 把类实例和参数接进EA骨架

在MT5里写EA,第一步往往是把标准库的类实例和对外参数先落好。下面这段代码直接给出了CSymbolInfo与CTrade的实体声明,前者负责抓品种属性,后者封装下单接口,省去自己重写交易函数的麻烦。 外部参数里最该盯的是Period_Ind=10、TakeProfit=100点、StopLoss=30点、Lot=0.1,以及Reverse=false。外汇和贵金属杠杆高,30点止损在XAUUSD这种品种上可能瞬间被扫,实盘前务必按账户杠杆重算风险。 全局变量里hdlSI存信号指标句柄,初始填INVALID_HANDLE;g开头的变量是外部参数的内部副本,方便运行时改写而不动input。OnInit里先用NotTest()判断不在回测才EventSetTimer(1),接着依次跑初始化数组、设参、取句柄、新K线标记和面板,顺序错了句柄容易拿空。 开MT5新建EA把这段贴进头部,编译后看Init里能否拿到非INVALID_HANDLE的hdlSI,就能验证你的指标挂载路径对不对。

MQL5 / C++
class=class="str">"cmt">//| CREATING CLASS INSTANCES                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
CSymbolInfo mysymbol; class=class="str">"cmt">// CSymbolInfo class object
CTrade      mytrade;  class=class="str">"cmt">// CTrade class object
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EXTERNAL PARAMETERS                                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
input class="type">int     Period_Ind    = class="num">10;     class=class="str">"cmt">// Indicator Period
input class="type">class="kw">double  TakeProfit    = class="num">100;    class=class="str">"cmt">// Take Profit(p)
input class="type">class="kw">double  StopLoss      = class="num">30;     class=class="str">"cmt">// Stop Loss(p)
input class="type">bool    Reverse       = false;  class=class="str">"cmt">// Reverse Position
input class="type">class="kw">double  Lot           = class="num">0.1;    class=class="str">"cmt">// Lot
class=class="str">"cmt">//---
input class="type">class="kw">string  slash="";      class=class="str">"cmt">// * * * * * * * * * * * * * * * * * * *
sinput class="type">bool   InfoPanel     = true;   class=class="str">"cmt">// On/Off Info Panel
sinput class="type">bool   SettingOnTheFly = false; class=class="str">"cmt">// "On The Fly" Setting
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| GLOBAL VARIABLES                                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int hdlSI=INVALID_HANDLE; class=class="str">"cmt">// Signal indicator handle
class="type">class="kw">double lcheck=class="num">0;  class=class="str">"cmt">// For the check of parameter values
class="type">bool isPos=false; class=class="str">"cmt">// Position availability
class=class="str">"cmt">//--- COPY OF EXTERNAL PARAMETERS
class="type">int     gPeriod_Ind = class="num">0;
class="type">class="kw">double  gTakeProfit = class="num">0.0;
class="type">class="kw">double  gStopLoss   = class="num">0.0;
class="type">bool    gReverse    = false;
class="type">class="kw">double  gLot        = class="num">0.0;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EXPERT ADVISOR INITIALIZATION                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnInit()
  {
   if(NotTest()) { EventSetTimer(class="num">1); } class=class="str">"cmt">// If it&class="macro">#x27;s not the tester, set the timer
class=class="str">"cmt">//---
   Init_arr_vparams(); class=class="str">"cmt">// Initialization of the array of parameter values
   SetParameters();    class=class="str">"cmt">// Set the parameters
   GetIndicatorsHandles(); class=class="str">"cmt">// Get indicator handles
   NewBar();           class=class="str">"cmt">// New bar initialization
   SetInfoPanel();     class=class="str">"cmt">// Info panel
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

常见问题

不用。在用户面板里把参数做成动态输入,拖动或输入新值就能实时生效,EA下一tick读取新值。
锚定在图表左上或右侧空白区,用相对坐标定位;把常用参数放第一屏,次要的折叠进标签页。
可以。小布能监控面板参数变动并弹提醒,你不在电脑前也能知道谁动了止损或手数。
单文件耦合太高。拆成参数类、逻辑类、主骨架多个文件,改局部不影响全局编译。
在类中留公共成员变量,面板回调里写值,EA的OnTick直接读该实例成员即可,无需全局重定义。