自定义信息面板上的仓位属性:用EA把持仓数据钉在图表上(基础篇)
(1/3)·手工跑脚本看仓位太折腾?这篇基础篇教你用MQL5画一个随单刷新的面板
很多交易者还在靠反复跑脚本确认当前品种持仓,切周期或换品种就失效。把仓位属性做成常驻面板,才是MetaTrader 5里省手的正确起点。本文是三篇系列的第一部分,先把图形对象与EA生命周期讲透。
◍ 在MT5面板上读出持仓的真实属性
很多交易者盯盘时只靠图表和终端窗口,却没意识到 MT5 允许你在自定义信息面板上直接列出当前仓位的逐项属性。把持仓的票种、方向、手数、开仓价、当前价、浮动盈亏拉到一块看,比反复切窗口更省反应时间。
下面这段 MQL5 代码演示了如何遍历交易账户的所有持仓,并把关键字段打印到专家日志。注意它用的是 PositionGetInteger / PositionGetDouble / PositionGetString 三类函数,分别对应整数、双精度与字符串类型的仓位属性。
外汇与贵金属杠杆高、滑点突发行情多,面板读数只反映瞬时状态,不能当作方向结论;用它做盘口核对,不替你做进场决策。
class="type">void OnStart() { class="type">int total=PositionsTotal(); for(class="type">int i=class="num">0;i<total;i++) { class="type">ulong ticket=PositionGetTicket(i); class="type">class="kw">string symbol=PositionGetString(POSITION_SYMBOL); class="type">long type=PositionGetInteger(POSITION_TYPE); class="type">class="kw">double volume=PositionGetDouble(POSITION_VOLUME); class="type">class="kw">double open=PositionGetDouble(POSITION_PRICE_OPEN); class="type">class="kw">double current=PositionGetDouble(POSITION_PRICE_CURRENT); class="type">class="kw">double profit=PositionGetDouble(POSITION_PROFIT); Print("Ticket:",ticket," Symbol:",symbol," Type:",type," Volume:",volume," Open:",open," Current:",current," Profit:",profit); } }
「用EA把仓位属性钉在面板上」
这套思路是写一个轻量EA,专门盯当前交易品种的持仓,把仓位属性直接画成自定义信息面板。 相比之前那篇靠脚本手动跑、每次要看属性都得重新执行一次,EA挂在图表上之后,只要有订单变动就自动刷新,不用再人工触发。 面板用图形对象搭,开MT5新建EA把仓位读取逻辑接进OnTradeTransaction,就能替代反复手点脚本的动作。外汇和贵金属杠杆高,面板只做信息呈现,不构成任何方向建议。
用EA在MT5图表上画出持仓信息面板
想在MT5图表上挂一个实时显示持仓属性的面板,第一步不是写逻辑,而是先在图表里手动画布局。用长方形标签或文本对象摆出背景、抬头、字段名和值的位置,右键属性里调坐标和尺寸,写完代码后这些布局对象得手动删掉——EA看不见它们,也不会自动清理。 MQL5向导里选Expert Advisor(template)直接出骨架,和脚本最大的区别是多了OnInit()、OnDeinit()、OnTick()三个主函数。OnInit在加载、改参数、换品种周期时触发;OnDeinit在移除或切换账户时走,可用GetDeinitReasonText()把去初始化编号转成文字;OnTick每次当前图表品种有新报价就调用。 全局先定常量INFOPANEL_SIZE=14,再声明两个各14元素的字符串数组存对象名。MQL5程序建的对象默认隐藏,在物件列表(Ctrl+B)点“所有”才能看到,这正好用来区分人工和代码生成的对象。 建对象别反复调ObjectCreate(),自己包一层CreateEdit()和CreateLabel(),一行就能生成一个文本或文本标签对象。删除时写DeleteObjectByName(),里面用ObjectFind()搜、ObjectDelete()删,并用ErrorDescription()把错误码翻成中文方便排错。 GetPositionProperties()里用全局变量pos_open记是否有仓,有仓读属性,无仓调ZeroPositionProperties()把所有值清零。SetInfoPanel()负责把属性刷到面板上,纵坐标可以硬写也可以用循环少写几行;最后必须调ChartRedraw()否则屏幕不更新。GetPropertyValue()按对象编号返回字符串,无仓时统一返回横线“-”。 把上述方法塞进OnInit、OnTick和OnDeinit即可。实测挂到无仓图表,面板全显“-”;有仓或开仓后横线被真实属性替换。平仓后数值要等下一笔报价才刷,立即更新的办法留到下一篇。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| PositionPropertiesPanel.mq5 | class=class="str">"cmt">//| Copyright class="num">2012, MetaQuotes Software Corp. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2012, MetaQuotes Software Corp." class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.00" 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">//--- class="kw">return(class="num">0); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA去初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnDeinit(const class="type">int reason)
◍ 持仓面板的状态容器怎么搭
想在 MT5 的 EA 里实时盯住当前持仓的十几项属性,第一步是把状态塞进一组全局变量。下面这段代码把持仓有无、品种、幻数、库存费、手续费、开仓价、当前价、浮盈、手数、SL/TP、开仓时间、仓位编号和类型一次性声明,后面 OnTick 里直接读写就行。 信息面板对象数组大小定为 14,但 positionPropertyNames 里实际列了 16 个字符串名字——多出来的 name_pos_symbol 和 name_pos_type 在面板渲染时要自己补逻辑,别照着 INFOPANEL_SIZE 硬循环,否则会漏掉两项。 全局变量里 pos_open 用 bool 做标志位,pos_type 给的是 WRONG_VALUE 这种枚举初值,比直接写 0 更不容易在没持仓时误判方向。外汇和贵金属持仓受点差与库存费影响明显,这类面板数据只作辅助参考,实际下单前仍要在 MT5 里核对高风险品种的真实成本。
{
class=class="str">"cmt">//---
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EA订单函数 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
{
class=class="str">"cmt">//---
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//---
class="macro">#define INFOPANEL_SIZE class="num">14 class=class="str">"cmt">// 信息面板对象数组的大小
class="macro">#define EXPERT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) class=class="str">"cmt">// EA交易的名称
class=class="str">"cmt">//---
class=class="str">"cmt">//--- 全局变量
class="type">bool pos_open=false; class=class="str">"cmt">// 有/无持仓的标志
class="type">class="kw">string pos_symbol=""; class=class="str">"cmt">// 交易品种
class="type">long pos_magic=class="num">0; class=class="str">"cmt">// 幻数
class="type">class="kw">string pos_comment=""; class=class="str">"cmt">// 注释
class="type">class="kw">double pos_swap=class="num">0.0; class=class="str">"cmt">// 库存费
class="type">class="kw">double pos_commission=class="num">0.0; class=class="str">"cmt">// 手续费
class="type">class="kw">double pos_price=class="num">0.0; class=class="str">"cmt">// 建仓价位
class="type">class="kw">double pos_cprice=class="num">0.0; class=class="str">"cmt">// 持仓的当前价位
class="type">class="kw">double pos_profit=class="num">0.0; class=class="str">"cmt">// 仓位的利润/亏损
class="type">class="kw">double pos_volume=class="num">0.0; class=class="str">"cmt">// 仓位交易量
class="type">class="kw">double pos_sl=class="num">0.0; class=class="str">"cmt">// 仓位的止损价格
class="type">class="kw">double pos_tp=class="num">0.0; class=class="str">"cmt">// 仓位的获利价格
class="type">class="kw">datetime pos_time=NULL; class=class="str">"cmt">// 建仓时间
class="type">long pos_id=class="num">0; class=class="str">"cmt">// 仓位编号
class="type">ENUM_POSITION_TYPE pos_type=WRONG_VALUE; class=class="str">"cmt">// 仓位类型
class=class="str">"cmt">// 显示仓位属性名称对象的名字的数组
class="type">class="kw">string positionPropertyNames[INFOPANEL_SIZE]=
{
"name_pos_symbol",
"name_pos_magic",
"name_pos_comment",
"name_pos_swap",
"name_pos_commission",
"name_pos_price",
"name_pos_cprice",
"name_pos_profit",
"name_pos_volume",
"name_pos_sl",
"name_pos_tp",
"name_pos_time",
"name_pos_id",
"name_pos_type"
};「仓位面板字段与文本对象创建」
想在 MT5 图表上做一个常驻的仓位信息面板,第一步是把要展示的字段名先排进数组。下面这段把 15 个仓位属性对象的名字塞进了 positionPropertyValues,数组长度由 INFOPANEL_SIZE 控制,实际跑起来就是 15 个文本控件一一对应。 这些名字覆盖了品种、魔术码、注释、库存费、佣金、开仓价、当前价、浮动盈亏、手数、止损、止盈、时间、订单号、持仓方向等。改面板布局时,直接增删数组元素就能调整显示项,不用动绘制逻辑。 真正把文字画到图上靠 CreateEdit。它接收图表 ID、子窗口号、对象名、文本内容、锚定拐角、字体参数、尺寸坐标和背景色等 15 个参数,最后有个 read_only 开关决定用户能不能改。外汇和贵金属杠杆高,面板只是辅助围观风险,别把它当风控替身。 调用前建议先在脚本里打印 INFOPANEL_SIZE 的值确认边界,避免数组越界把对象名写飞。开盘后挂个 EA 跑一遍,就能在图表角上看到实时刷新的仓位标签。
class="type">class="kw">string positionPropertyValues[INFOPANEL_SIZE]= { "value_pos_symbol", "value_pos_magic", "value_pos_comment", "value_pos_swap", "value_pos_commission", "value_pos_price", "value_pos_cprice", "value_pos_profit", "value_pos_volume", "value_pos_sl", "value_pos_tp", "value_pos_time", "value_pos_id", "value_pos_type" }; class="type">void CreateEdit(class="type">long chart_id, class=class="str">"cmt">// 图表编号 class="type">int sub_window, class=class="str">"cmt">// (子)窗口编号 class="type">class="kw">string name, class=class="str">"cmt">// 对象名称 class="type">class="kw">string text, class=class="str">"cmt">// 显示的文本 ENUM_BASE_CORNER corner, class=class="str">"cmt">// 图表拐角 class="type">class="kw">string font_name, class=class="str">"cmt">// 字体名称 class="type">int font_size, class=class="str">"cmt">// 字体大小 class="type">color font_color, class=class="str">"cmt">// 字体颜色 class="type">int x_size, class=class="str">"cmt">// 宽度 class="type">int y_size, class=class="str">"cmt">// 高度 class="type">int x_distance, class=class="str">"cmt">// 横坐标 class="type">int y_distance, class=class="str">"cmt">// 纵坐标 class="type">long z_order, class=class="str">"cmt">// 深度顺序 class="type">color background_color,class=class="str">"cmt">// 背景颜色 class="type">bool read_only) class=class="str">"cmt">// 只读标志 {
在图表上落地一个可显示文本的输入框
想在 MT5 图表上叠一个自定义文本块(比如给小布盯盘面板写提示语),核心是先 ObjectCreate 出 OBJ_EDIT 对象,再用 ObjectSetInteger / ObjectSetString 逐个填属性。下面这段是可直接拷进 EA 或脚本的骨架。 创建成功后第一件事是写内容:ObjectSetString 的 OBJPROP_TEXT 决定显示文字,OBJPROP_FONT 和 OBJPROP_FONTSIZE 控制字体与字号,OBJPROP_COLOR 与 OBJPROP_BGCOLOR 分别管字色和底色。 位置由 OBJPROP_CORNER 选锚定拐角,再用 OBJPROP_XDISTANCE / OBJPROP_YDISTANCE 以像素偏移;OBJPROP_XSIZE / OBJPROP_YSIZE 定宽高,OBJPROP_ZORDER 调图层深度,避免被蜡烛盖住。 把 OBJPROP_SELECTABLE 设 false、OBJPROP_READONLY 按需要设 true,可防误点;OBJPROP_TOOLTIP 传 "\n" 即关掉悬浮提示。外汇与贵金属波动剧烈、杠杆高风险大,这类界面对象只做信息呈现,不参与下单决策。
if(ObjectCreate(chart_id,name,OBJ_EDIT,sub_window,class="num">0,class="num">0)) { class=class="str">"cmt">// ...设置其属性 ObjectSetString(chart_id,name,OBJPROP_TEXT,text); class=class="str">"cmt">// 显示的文本 ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner); class=class="str">"cmt">// 设置图表拐角 ObjectSetString(chart_id,name,OBJPROP_FONT,font_name); class=class="str">"cmt">// 设置字体名称 ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size); class=class="str">"cmt">// 设置字体大小 ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color); class=class="str">"cmt">// 字体颜色 ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,background_color); class=class="str">"cmt">// 背景颜色 ObjectSetInteger(chart_id,name,OBJPROP_XSIZE,x_size); class=class="str">"cmt">// 宽度 ObjectSetInteger(chart_id,name,OBJPROP_YSIZE,y_size); class=class="str">"cmt">// 高度 ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance); class=class="str">"cmt">// 设置横坐标 ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance); class=class="str">"cmt">// 设置纵坐标 ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false); class=class="str">"cmt">// 如果设为FALSE则不能选择 ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order); class=class="str">"cmt">// 对象深度顺序 ObjectSetInteger(chart_id,name,OBJPROP_READONLY,read_only); class=class="str">"cmt">// 只读 ObjectSetInteger(chart_id,name,OBJPROP_ALIGN,ALIGN_LEFT); class=class="str">"cmt">// 左对齐 ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n"); class=class="str">"cmt">// 如果设为"\n"说明没有Tooltip提示 } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 创建文本标签 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void CreateLabel(class="type">long chart_id, class=class="str">"cmt">// 图表编号 class="type">int sub_window, class=class="str">"cmt">// (子)窗口编号 class="type">class="kw">string name, class=class="str">"cmt">// 对象名称 class="type">class="kw">string text, class=class="str">"cmt">// 显示的文本 ENUM_ANCHOR_POINT anchor, class=class="str">"cmt">// 锚点