创建一个人工交易助手(基础篇)
给手动外汇交易者搭个 MT5 面板
手动做外汇差价合约,最烦的是反复开图表、点按钮、盯多个品种。Dmitriy Gizlyk 在 2016 年 7 月 25 日发布过一个完整交易面板实例,原始帖累计 14407 次浏览、94 条讨论,说明这类工具在 MT5 社区有真实需求。 这篇实例的定位很直接:不写 EA 替你自动跑,而是从零搭一个带完整功能的交易面板,帮人工交易者少点几次鼠标、把下单和风控集中到一个界面里。外汇与贵金属杠杆高、滑点跳空频繁,面板只是提高效率,不替你判断方向,亏损风险仍在交易者自己身上。 如果你手头是 MT5 终端,可以照着这类面板思路自己写一个,先解决「一键平仓 / 部分平仓 / 快速改止损」这几个高频动作,比装一堆指标实用。
「交易面板该长什么样」
动手写面板前,先把终态想清楚:你究竟要让它在 MT5 里替你干哪些活。我的版本至少塞进这几块:买/卖按钮、按品种或账户或方向(多/空)一键清仓的按钮。 外汇与贵金属杠杆高,错单清不掉比少赚更伤,所以清仓逻辑必须能按维度切,而不是只会全平。 止损止盈要支持两种模式:手填点数后存款币种与其它参数联动改写;或给定风险参数(存款额或余额百分比)自动算量并画在图上。图表上拖线改 SL/TP,面板数值要实时回显。 输入项得落盘——重启 MT5 后不重填。否则每次开盘前复算一遍,实战里就是纯损耗。
◍ 把面板当成工具而不是装饰
设计交易面板的第一页就该想清楚:它最终要落在 MT5 独立的子窗口里,所有控件和指标都塞进这个固定区域,而不是散在图表上。 可行性优先于好看。面板必须包含下单、撤单、看账户这些核心信息,文字和按钮密度以一眼能扫完为上限,多余的装饰元件只会拖慢点击决策。 我自己的版本就是把必需软件全收进一个页面里绘制,不堆视觉元素——它本质是交易者的操作台,不是屏幕壁纸。外汇和贵金属波动快,面板响应慢半秒都可能错过价位,这类品种高风险,界面冗余等于主动加杠杆。
用 CAppDialog 派生出面板骨架
想在 MT5 里快速搭一个可交互的交易面板,不必从零写窗口管理逻辑。MQL5 标准库里的 CAppDialog 已经封装了对话框基类,直接继承它就能省掉大量底层代码。 我们建一个 CTradePanel 类,public 继承 CAppDialog,只留构造和析构的空实现。再在全局声明一个 TradePanel 实例,EA 加载时就有了可操作的窗口对象。 OnInit 里调用 TradePanel.Create(),传入 ChartID()、名称 "Trade Panel",以及左上角坐标 (20,20) 和尺寸 320×420 像素。若创建失败返回 INIT_FAILED,成功则 Run() 启动消息循环,返回 INIT_SUCCEEDED。 别把正态当圣经:坐标和尺寸是写死的 20/20/320/420,实盘前最好按自己显示器分辨率调,否则面板可能挡住 K 线。外汇与贵金属杠杆高,任何 EA 面板都只辅助下单,不替你判断方向。
class="macro">#include <Controls\Dialog.mqh> class CTradePanel : class="kw">public CAppDialog { class="kw">public: CTradePanel(class="type">void){}; ~CTradePanel(class="type">void){}; }; CTradePanel TradePanel; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA 初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- class=class="str">"cmt">// 创建交易面板 if(!TradePanel.Create(ChartID(),"Trade Panel",class="num">0,class="num">20,class="num">20,class="num">320,class="num">420)) { class="kw">return (INIT_FAILED); } class=class="str">"cmt">// 运行交易面板 TradePanel.Run(); class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); }
「面板控件对象的声明与私有布局」
在 MT5 里搭交易面板,第一步是把界面上每一个可见元件都映射成一个类对象。标准库已经给了 CLabel、CEdit、CButton、CBmpButton 这些现成控件类,直接拿来声明就行,不用自己重写底层绘图。 注意 Edit.mqh 和 BmpButton.mqh 不用手动 include,它们会在 Dialog.mqh 内部被间接引入,多写反而容易重复定义报错。 变量声明要放在 CTradePanel 类的 private 段,外部只允许调用 public 里的 Creat() 来管理全部元件。下面这段就是声明区的骨架,ASK/BID 挂买卖价,Balance_label 与 Balance_value 分开存标签和数值,一共列了 19 个 CLabel 成员覆盖价格、余额、净值、风险、手数等面板字段。 打开 MT5 的 MetaEditor,新建一个继承 CAppDialog 的 CTradePanel 类,把这段贴进 private 区,编译若提示找不到 CLabel 再检查 Dialog.mqh 路径是否包含在编译头里。
class="macro">#include <Controls\Dialog.mqh> class="macro">#include <Controls\Label.mqh> class="macro">#include <Controls\Button.mqh> class CTradePanel : class="kw">public CAppDialog { class="kw">private: CLabel ASK, BID; class=class="str">"cmt">// 显示买入和卖出价格 CLabel Balance_label; class=class="str">"cmt">// 显示 "账户余额" 标签 CLabel Balance_value; class=class="str">"cmt">// 显示账户余额 CLabel Equity_label; class=class="str">"cmt">// 显示 "账户净值" 标签 CLabel Equity_value; class=class="str">"cmt">// 显示账户净值 CLabel PIPs; class=class="str">"cmt">// 显示 "点数" 标签 CLabel Currency; class=class="str">"cmt">// 显示账户币别 CLabel ShowLevels; class=class="str">"cmt">// 显示"显示"标签 CLabel StopLoss; class=class="str">"cmt">// 显示 "止损" 标签 CLabel TakeProfit; class=class="str">"cmt">// 显示"获利"标签 CLabel Risk; class=class="str">"cmt">// 显示"风险"标签 CLabel Equity; class=class="str">"cmt">// 显示 "净值百分比"标签 CLabel Currency2; class=class="str">"cmt">// 显示账户币别 CLabel Orders; class=class="str">"cmt">// 显示 "开启的订单" 标签 CLabel Buy_Lots_label; class=class="str">"cmt">// 显示"买入手数"标签 CLabel Buy_Lots_value; class=class="str">"cmt">// 显示买入手数值 CLabel Sell_Lots_label; class=class="str">"cmt">// 显示 "卖出手数" 标签 CLabel Sell_Lots_value; class=class="str">"cmt">// 显示卖出手数数值 CLabel Buy_profit_label; class=class="str">"cmt">// 显示 "买入利润" 标签
◍ 面板控件声明与生命周期钩子
上面这段声明集中列出了自定义交易面板用到的所有界面对象,从标签、编辑框到位图按钮一应俱全。CLabel 负责展示买卖盈亏数值,CEdit 承接手数、止损止盈点数与金额、风险百分比等可输入或回显字段,CBmpButton 则用于切换止损/止盈的计量方式(点数或资金)以及增减手数,CButton 直接挂上 BUY/SELL 与各类平仓按钮。 从变量命名能看出面板的逻辑:StopLoss_pips_b 与 StopLoss_money_b 成对出现,意味着止损既能按点数算也能按固定资金算,TakeProfit 与 Risk 同理。这种双模切换在 MT5 实盘里很实用,尤其贵金属跳点大时,用金额约束风险比死盯点数更直观。 类里只留了空构造与析构:CTradePanel(void){} 和 ~CTradePanel(void){},说明资源由控件自身管理,真正的创建逻辑在注释 //--- 创建函数 之后补。你开 MT5 新建面板类时,照这个声明清单抄一遍,编译就能看到控件骨架。
CLabel Buy_profit_value; class=class="str">"cmt">// 显示买入利润数值 CLabel Sell_profit_label; class=class="str">"cmt">// 显示 "卖出利润" 数值 CLabel Sell_profit_value; class=class="str">"cmt">// 显示卖出利润数值 CEdit Lots; class=class="str">"cmt">// 显示下一个订单的交易量 CEdit StopLoss_pips; class=class="str">"cmt">// 显示止损点数 CEdit StopLoss_money; class=class="str">"cmt">// 显示止损资金数 CEdit TakeProfit_pips; class=class="str">"cmt">// 显示获利点数 CEdit TakeProfit_money; class=class="str">"cmt">// 显示获利资金数 CEdit Risk_percent; class=class="str">"cmt">// 显示风险占净值百分比 CEdit Risk_money; class=class="str">"cmt">// 显示风险资金数 CBmpButton StopLoss_line; class=class="str">"cmt">// 选中以显示止损线 CBmpButton TakeProfit_line; class=class="str">"cmt">// 选中以显示获利线 CBmpButton StopLoss_pips_b; class=class="str">"cmt">// 选择以点数止损 CBmpButton StopLoss_money_b; class=class="str">"cmt">// 选择以资金数止损 CBmpButton TakeProfit_pips_b; class=class="str">"cmt">// 选择以点数获利 CBmpButton TakeProfit_money_b; class=class="str">"cmt">// 选择以资金数获利 CBmpButton Risk_percent_b; class=class="str">"cmt">// 选择以净值百分比为风险参数 CBmpButton Risk_money_b; class=class="str">"cmt">// 选择以账户资金数为风险参数 CBmpButton Increase,Decrease; class=class="str">"cmt">// 增加和减小按钮 CButton SELL,BUY; class=class="str">"cmt">// 卖出和买入按钮 CButton CloseSell,CloseBuy,CloseAll; class=class="str">"cmt">// 关闭按钮 class="kw">public: CTradePanel(class="type">void){}; ~CTradePanel(class="type">void){}; class=class="str">"cmt">//--- 创建函数