从用户面板"动态"更改"EA 交易"参数(基础篇)
「在面板里实时改 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 看结构。
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,就能验证你的指标挂载路径对不对。
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">//+------------------------------------------------------------------+