MQL5 Cookbook: 获取仓位属性(基础篇)
◍ 在 MT5 里读出持仓的真实属性
做价格行为分析时,很多人只盯着图表上的 K 线,却忽略了终端里已经算好的仓位元数据。MT5 的 MQL5 通过 PositionGet 系列函数,可以直接取到当前选中账户的持仓属性,不用自己从成交记录里反推。 关键入口是 PositionSelect():先用它按 ticket 或 symbol 锁定一条持仓,失败返回 false,之后才能安全地调用 PositionGetInteger()、PositionGetDouble()、PositionGetString()。比如持仓量、开仓价、止损止盈、注释字段,分别对应不同的标识符常量。 下面这段演示了如何选出 EURUSD 的持仓并打印手数与开仓价。注意 PositionSelect(_Symbol) 只选当前图表品种的第一条持仓,若同一品种有多条独立持仓需循环遍历 ticket。外汇与贵金属杠杆高,持仓属性随时受点差和强制平仓影响,读数仅反映查询瞬间的账户状态。
if(PositionSelect(_Symbol)) { class="type">class="kw">double volume = PositionGetDouble(POSITION_VOLUME); class="type">class="kw">double open_price = PositionGetDouble(POSITION_PRICE_OPEN); Print("Volume: ", volume, " Open: ", open_price); }
用脚本把持仓属性一次性翻出来
上篇讲了三种打印模式快速输出信息,这一节把目标换成持仓属性:写个脚本,把当前账户里所有持仓的关键字段直接弹窗列给你看。 脚本要留一个外部输入项,让用户二选一:只抓当前图表品种的那一笔持仓,还是按交易品种逐个把全部持仓扫一遍。弹窗比终端日志更适合临场核对,尤其是你同时盯几个品种时,不用去‘交易’标签里手动翻。 外汇和贵金属保证金交易杠杆高、滑点不可控,脚本只做属性读取不替你下单,但账户若开了自动交易,任何脚本运行都先把EA总开关确认好再跑。
「把仓位属性读出来:MT5脚本骨架」
做这类小工具,开头先声明脚本属性,再用 #define 把程序名绑到 SCRIPT_NAME 上,后续弹窗和日志都能直接复用。模式用枚举区分:CURRENT_SYMBOL=0 只看当前品种,ALL_SYMBOLS=1 扫全部品种;input 里只暴露一个 mode 参数,下拉文字就是枚举注释,写代码时变量名短、窗口里名字直观。 全局变量必须写在函数外,pos_magic、pos_symbol、pos_volume 这类字段放最前面,PrintPositionProperties() 在任何分支都能直接填。主函数只调这一用户函数,逻辑全收在里面,避免 OnStart 越写越肿。 当前品种分支先用 PositionSelect(_Symbol) 探持仓:返回真值才有后续,否则弹「无持仓」提醒。把属性抓取抽成 GetPositionProperties(),类型转换交给 PositionTypeToString(),同样的逻辑在「所有品种」模式还要跑一遍,抽函数能少复制几十行。 验证路径很直接:MT5 里按 F9 开订单窗口,下个 AUDUSD 或 EURUSD 的真实仓位(外汇/贵金属杠杆高,先用模拟盘跑)。把脚本拖进图表,mode 选「当前交易品种」确定后,对话框会列出成交量、库存费、SL/TP 等 11 个字段;切到「所有交易品种」就能一次看跨品种仓位。下面是从原文扒出的声明段,逐行都是后续函数的地基。
class="macro">#class="kw">property copyright "Copyright class="num">2012, http:class=class="str">"cmt">//tol64.blogspot.com" class="macro">#class="kw">property link "http:class=class="str">"cmt">//tol64.blogspot.com" class="macro">#class="kw">property description "email: hello.tol64@gmail.com" class="macro">#class="kw">property version "class="num">1.0" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//--- class="macro">#define SCRIPT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) class=class="str">"cmt">// 脚本名称 class=class="str">"cmt">//--- class=class="str">"cmt">// 模式枚举 enum ENUM_SYMBOLS_MODE { CURRENT_SYMBOL =class="num">0, class=class="str">"cmt">// 当前交易品种 ALL_SYMBOLS =class="num">1 class=class="str">"cmt">// 所有交易品种 }; class=class="str">"cmt">//--- class=class="str">"cmt">// 输入参数 input ENUM_SYMBOLS_MODE mode=CURRENT_SYMBOL; class=class="str">"cmt">// 模式 class=class="str">"cmt">// 全局变量 class="type">long pos_magic=class="num">0; class=class="str">"cmt">// 幻数 class="type">class="kw">string pos_symbol=""; 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">// 仓位获利价位
◍ 把持仓属性弹窗打印出来
想在 MT5 里一眼看清单前品种持仓的全部细节,可以写个脚本把 PositionSelect 选中的仓位属性用 MessageBox 弹出来。下面这段骨架已经把建仓时间、编号、类型三个变量先置空,等真正选中持仓再填值。 datetime pos_time=NULL; // 仓位建仓时间 long pos_id=0; // 仓位编号 ENUM_POSITION_TYPE pos_type=NULL; // 仓位类型 主逻辑放在 OnStart 里只调一个 PrintPositionProperties,结构很轻,适合直接拖进策略测试器跑。 void OnStart() { PrintPositionProperties(); } PrintPositionProperties 内部用 mode 变量切换:CURRENT_SYMBOL 只看当前图品种,ALL_SYMBOLS 扫全部品种。若 PositionSelect(_Symbol) 返回真,就调 GetPositionProperties 抓属性,随后用 MessageBox 把交易品种、注释、幻数、建仓价、当前价、SL、TP、类型、交易量、手续费拼成字符串弹出。 外汇与贵金属杠杆高,弹窗里的止损、手续费数字仅反映当时持仓状态,不代表任何未来走向,实际滑点可能让弹出值与成交价偏差数个点数。
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=NULL; class=class="str">"cmt">// 仓位类型 class=class="str">"cmt">//--- class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 主函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { PrintPositionProperties(); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 打开对话框并显示交易品种数据 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void PrintPositionProperties() { class="type">int err=class="num">0; class=class="str">"cmt">// 处理错误的变量 class=class="str">"cmt">//--- class=class="str">"cmt">// 如果您只需要获取当前交易品种的仓位属性 if(mode==CURRENT_SYMBOL) { } class=class="str">"cmt">//--- class=class="str">"cmt">// 如果您需要获取全部交易品种的仓位属性 if(mode==ALL_SYMBOLS) { } } class=class="str">"cmt">//--- class=class="str">"cmt">// 如果已有持仓,那么... if(PositionSelect(_Symbol)) { class=class="str">"cmt">// ...获取它的属性 GetPositionProperties(); class=class="str">"cmt">//--- class=class="str">"cmt">// 打开对话框显示我们获得的全部数据 MessageBox("交易品种 : "+pos_symbol+"\n"+ "注释 : "+pos_comment+"\n"+ "幻数 : "+IntegerToString(pos_magic)+"\n"+ "建仓价位 : "+DoubleToString(pos_price,_Digits)+"\n"+ "当前价位 : "+DoubleToString(pos_cprice,_Digits)+"\n"+ "止损价位 : "+DoubleToString(pos_sl,_Digits)+"\n"+ "获利价位 : "+DoubleToString(pos_tp,_Digits)+"\n"+ "类型 : "+PositionTypeToString(pos_type)+"\n"+ "交易量 : "+DoubleToString(pos_volume,class="num">2)+"\n"+ "手续费 : "+DoubleToString(pos_commission,class="num">2)+"\n"+