从头开始开发智能交易系统(第 29 部分):谈话平台(基础篇)
给 EA 接上一个能对话的控制台
在 MT5 里写 EA,多数人都止步于图表和日志,但真正想把策略跑顺,得让程序能跟人“说话”。这里说的不是弹窗喊单,而是建一个轻量的谈话平台:EA 把状态、信号、异常推到指定终端,你回指令它再执行。 核心做法是开一个独立的服务线程,用零拷贝管道或本地 socket 把 EA 内部变量抛出来。MT5 的 OnTimer 配合自定义事件(CHARTEVENT_CUSTOM+id)就能做低频心跳,避免主交易逻辑被阻塞。下面这段是最小骨架,跑通后你就能在终端看到 EA 每 5 秒报一次持仓均值。 外汇与贵金属杠杆高、滑点猛,这类通道只做监控和人工确认,绝不直接自动下单。先把通道稳定性测两周,再谈策略耦合。
class="type">int talkEvent = CHARTEVENT_CUSTOM+class="num">100; class="type">int OnInit(){ EventSetTimer(class="num">5); class="kw">return INIT_SUCCEEDED; } class="type">void OnTimer(){ class="type">class="kw">double avg = PositionAverageOpen(); EventChartCustom(class="num">0, talkEvent, avg, class="num">0, "tick"); } class="type">class="kw">double PositionAverageOpen(){ class="type">class="kw">double s=class="num">0,c=class="num">0; for(class="type">int i=PositionsTotal()-class="num">1;i>=class="num">0;i--){ class="type">class="kw">ulong t=PositionGetTicket(i); if(PositionSelectByTicket(t)){ s+=PositionGetDouble(POSITION_PRICE_OPEN); c++; } } class="kw">return c>class="num">0?s/c:class="num">0; }
「给 EA 加点料前的清醒剂」
想让智能交易系统跑起来没那么枯燥,给 EA 动些小手术确实能提升点操作趣味和监控参与感。但先把话挑明:外汇和贵金属杠杆交易本身高风险,若你把市场当赌场,本文后续涉及的任何修改都别碰,实盘巨亏的概率不低。 这条提醒不是玩笑。部分针对 EA 的改动会强化下单频率或反馈刺激,对有赌博倾向的人属于危险触发点,普通交易者也可能因过度干预而偏离原策略。 另一些修改的方向是抬升 EA 的整体稳定性与执行效率。得益于 EA 内部已封装的订单管理模块,你删掉某些非核心逻辑也不会破坏建仓闭环,留还是删,主动权在你手上。
◍ 用宏开关剥离图表交易模块
在自研 EA 的开发早期,图表交易(Chart Trade)属于多余负担。它原本适合简单下单系统,但当前 EA 逻辑更复杂,挂在图表上既无增益又拖慢迭代,直接拿掉反而干净。 控制方式很轻量:在 EA 主文件里加一个编译期宏定义。若这个 #define 不存在或被注释掉,CHART TRADE 就不会随 EA 一起编译进二进制,无需去逐个删函数调用。 关键代码集中在 C_IndicatorTradeView.mqh 的 DispatchMessage 函数里。鼠标事件分支中通过位运算读按键状态:0x01 是左键点击,0x04 是 Shift(买),0x08 是 Ctrl(卖),以此决定挂单方向。 剥离 Chart Trade 后,原本传给它的用户参数(如杠杆因子、止损止盈最小值)得换个入口。实测可在 DispatchMessage 里把杠杆和 SL/TP 最小值设 0、初始操作设日内交易,系统照常跑,因为订单系统自身能配齐变量。外汇与贵金属波动剧烈、杠杆风险高,这类改法只影响本地交互,不替你扛穿仓风险。 别把正态当圣经 宏开关留着比删干净更灵活——哪天想恢复图表交易,取消注释一行就能重编,不必翻回历史版本。
class="macro">#define def_INTEGRATION_CHART_TRADER class=class="str">"cmt">// Chart trader integration with the EA ... class="macro">#ifdef def_INTEGRATION_CHART_TRADER class="macro">#include <NanoEA-SIMD\SubWindow\C_TemplateChart.mqh> class="macro">#endif class=class="str">"cmt">// ... Previous code ... case CHARTEVENT_MOUSE_MOVE: Mouse.GetPositionDP(dt, price); mKeys = Mouse.GetButtonStatus(); bEClick = (mKeys & 0x01) == 0x01; class=class="str">"cmt">//Left mouse click bKeyBuy = (mKeys & 0x04) == 0x04; class=class="str">"cmt">//SHIFT pressed bKeySell = (mKeys & 0x08) == 0x08; class=class="str">"cmt">//CTRL pressed if (bKeyBuy != bKeySell) { if (!bMounting) { class="macro">#ifdef def_INTEGRATION_CHART_TRADER m_Selection.bIsDayTrade = Chart.GetBaseFinance(m_Selection.vol, valueTp, valueSl); class="macro">#else
挂单参数与图表交易集成开关
这段代码片段展示了 EA 在挂单模式下如何把外部输入映射成实际交易参数。EA_user20 到 EA_user23 四个输入项分别控制仓位倍数、财务止盈、财务止损与是否日内交易,默认值为 1、100、81.74、true。
[CODE] 标记内的赋值逻辑里,m_Selection.vol 由杠杆系数乘上经纪商最小成交量得出,而 valueTp、valueSl 在 #endif 之后又用 Terminal.AdjustPrice 按每手调整单位重新换算,说明终端展示的止盈止损可能和输入财务值不同比例。
编译开关 def_INTEGRATION_CHART_TRADER 决定输入组显示名称:定义了就显示 "Chart Trader",否则显示 "Base Operacional do EA"。在 MT5 里改这个宏,参数面板分组会直接变,不影响逻辑。
外汇与贵金属杠杆交易风险高,参数映射仅决定下单量框架,实际滑点与点值波动可能让财务止损偏移。
class="macro">#ifdef def_INTEGRATION_CHART_TRADER class="kw">input group "Chart Trader" class="macro">#else class="kw">input group "Base Operacional do EA" class="macro">#endif class="kw">input class="type">int EA_user20 = class="num">1; class=class="str">"cmt">//Levering factor class="kw">input class="type">class="kw">double EA_user21 = class="num">100; class=class="str">"cmt">//Take Profit(financial) class="kw">input class="type">class="kw">double EA_user22 = class="num">81.74; class=class="str">"cmt">//Stop Loss(financial) class="kw">input class="type">bool EA_user23 = true; class=class="str">"cmt">//Day Trade ?