MQL5 简介(第 9 部分):理解和使用 MQL5 中的对象·进阶篇
◍ 抓当前图表那张持仓的单子
想在 MT5 里只盯当前图表品种的第一张持仓,核心是先拿 ChartID() 锁定图表,再用 PositionGetString(POSITION_SYMBOL) 跟 ChartSymbol(chart_id) 做比对,避免把别的品种持仓误读进来。 下面这段逻辑用 position_index 输入参数(默认 0,索引从 0 起算)指定取第几张单,循环里用 PositionGetTicket(i) 拿每张单的 ticket,再判断 ticket 是否等于 PositionGetTicket(position_index) 且品种对得上。 匹配成功后,用 PositionGetDouble 取开仓价、SL、TP,用 PositionGetInteger(POSITION_TIME) 强转 int 拿开仓时间,最后 Print 出来。你在策略测试器里跑 EA,终端面板的 Experts 标签会按 index 0 打出类似『Open Price index 0: 1.08562 / SL index 0: 1.08310』的四行记录,可直接核对抓取是否准确。 外汇与贵金属杠杆高,持仓抓取仅作监控用途,任何据此调整仓位的动作都伴随本金回撤可能。
class="type">class="kw">double open_price; class=class="str">"cmt">// Variable to store the entry price of the position class="type">class="kw">double stop_loss; class=class="str">"cmt">// Variable to store the Stop Loss level of the position class="type">class="kw">double take_profit; class=class="str">"cmt">// Variable to store the Take Profit level of the position class="type">class="kw">datetime position_open_time; class=class="str">"cmt">// Variable to store the open time of the position class=class="str">"cmt">// Define the position index for the first position input class="type">int position_index = class="num">0; class=class="str">"cmt">// POSITION INDEX(Index starts from class="num">0) class=class="str">"cmt">// Get the ID of the current chart class="type">long chart_id = ChartID(); class="type">void OnTick() { for(class="type">int i = class="num">0; i < PositionsTotal(); i++) { class="type">class="kw">ulong ticket = PositionGetTicket(i); if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { open_price = PositionGetDouble(POSITION_PRICE_OPEN); stop_loss = PositionGetDouble(POSITION_SL); take_profit = PositionGetDouble(POSITION_TP); position_open_time = (class="type">int)PositionGetInteger(POSITION_TIME); Print("Open Price index ",i,": ",open_price); Print("SL index ",i,": ",stop_loss); Print("TP index ",i,": ",take_profit); Print("Open time index ",i,": ",position_open_time); } } }
「抓持仓要素并画风险收益带」
在 MT5 的 EA 里想可视化某笔持仓的止损盈利区,第一步是把仓位的关键字段抓出来。下面这段代码定义了开仓价、SL、TP、开仓时间四个变量,并用 input 把 position_index 默认设为 1(注意索引从 0 起算,所以实际抓的是第二笔持仓),同时用 ChartID() 锁定当前图表、用 "23:59" 字符串预留一个平仓 zone 时间点。 循环里用 PositionsTotal() 遍历所有持仓,通过 PositionGetTicket(position_index) 比对票据号,再叠加 ChartSymbol(chart_id) 确认品种一致才取值。open_price、stop_loss、take_profit 分别来自 POSITION_PRICE_OPEN / POSITION_SL / POSITION_TP,position_open_time 则把 POSITION_TIME 强转 int。 每抓一笔就用 Print 把四个值打到日志,你直接在 MT5 终端的 Experts 标签里就能看到类似 "Open Price index 1: 1.08432" 的输出,据此判断 EA 有没有认错仓位。外汇与贵金属杠杆高,SL/TP 区域仅作概率参考,实盘须自担风险。 别把索引当摆设 position_index 设成 1 却只有 0 号持仓时,PositionGetTicket(1) 会返回 0,整个 if 不进,画面上一根 zone 都不会画。开 EA 前先确认持仓数 ≥ 2,或改成 0 测第一笔。
class="type">class="kw">double open_price; class=class="str">"cmt">// Variable to store the entry price of the position class="type">class="kw">double stop_loss; class=class="str">"cmt">// Variable to store the Stop Loss level of the position class="type">class="kw">double take_profit; class=class="str">"cmt">// Variable to store the Take Profit level of the position class="type">class="kw">datetime position_open_time; class=class="str">"cmt">// Variable to store the open time of the position class=class="str">"cmt">// Define the position index for the first position input class="type">int position_index = class="num">1; class=class="str">"cmt">// POSITION INDEX(Index starts from class="num">0) class=class="str">"cmt">// Get the ID of the current chart class="type">long chart_id = ChartID(); class=class="str">"cmt">// Store the ID of the current chart class="type">class="kw">string time = "class="num">23:class="num">59"; class=class="str">"cmt">// Define a specific time as a class="type">class="kw">string class=class="str">"cmt">// Define the class="type">color for the losing zone input class="type">color sl_zonez_color = clrPink; class=class="str">"cmt">// Choose a class="type">color for Losing Zone class=class="str">"cmt">// Define the class="type">color for the winning zone input class="type">color tp_zonez_color = clrSpringGreen; class=class="str">"cmt">// Choose a class="type">color for Winning Zone class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">// Convert the class="type">class="kw">string time to class="type">class="kw">datetime class="type">class="kw">datetime close_zone = StringToTime(time); class=class="str">"cmt">// Loop through all open positions for(class="type">int i = class="num">0; i < PositionsTotal(); i++) { class=class="str">"cmt">// Get the ticket number of the position at index &class="macro">#x27;i&class="macro">#x27; class="type">class="kw">ulong ticket = PositionGetTicket(i); class=class="str">"cmt">// Check if the position matches the specified index and symbol of the current chart if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { class=class="str">"cmt">// Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); class=class="str">"cmt">// Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); class=class="str">"cmt">// Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP); class=class="str">"cmt">// Retrieve and store the open time of the position position_open_time = (class="type">int)PositionGetInteger(POSITION_TIME); class=class="str">"cmt">// Print the retrieved values for debugging or verification Print("Open Price index ",i,": ",open_price); Print("SL index ",i,": ",stop_loss); Print("TP index ",i,": ",take_profit); Print("Open time index ",i,": ",position_open_time); class=class="str">"cmt">// Create a rectangle to represent the Stop Loss(SL) zone on the chart
用矩形和趋势线把持仓区间画出来
在 MT5 里给已开仓位标视觉区间,最直接的方法是 OBJ_RECTANGLE 矩形加 OBJ_TREND 趋势线。下面这段代码在仓位有 SL/TP 时分别画「SL Zone」「TP zone」两块矩形,无对应止损止盈则跳过该矩形创建。 矩形属性里 OBJPROP_BACK 设成 true 很关键,否则色块会盖住 K 线导致无法看价格行为。OBJPROP_FILL 接受的是颜色值而非布尔,填 sl_zonez_color 即可让区块半透明着色,边框宽度 1 够用不抢视线。 趋势线从 position_open_time 的 open_price 拉到 TimeCurrent() 的实时 ask,等于把建仓点到现在的市价连成一条通道。外汇和贵金属杠杆高,这种可视化仅辅助读盘,不代表任何方向确定性,价格可能随时反向击穿区块。 复制时确认 chart_id 已正确获取(通常用 0 指代当前图表),close_zone 需是时间类型变量,否则矩形右边界会渲染异常。
ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, stop_loss); class=class="str">"cmt">// Create a rectangle to represent the Take Profit(TP) zone on the chart ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, take_profit); class=class="str">"cmt">// Set properties for the SL zone rectangle ObjectSetInteger(chart_id, "SL Zone", OBJPROP_COLOR, sl_zonez_color); class=class="str">"cmt">// Set class="type">color to the selected SL zone class="type">color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_STYLE, STYLE_SOLID); class=class="str">"cmt">// Set style to solid ObjectSetInteger(chart_id, "SL Zone", OBJPROP_WIDTH, class="num">1); class=class="str">"cmt">// Set the width of the rectangle border ObjectSetInteger(chart_id, "SL Zone", OBJPROP_FILL, sl_zonez_color); class=class="str">"cmt">// Fill the rectangle with the selected SL zone class="type">color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_BACK, true); class=class="str">"cmt">// Set the rectangle to appear behind the chart objects class=class="str">"cmt">// Set properties for the TP zone rectangle ObjectSetInteger(chart_id, "TP zone", OBJPROP_COLOR, tp_zonez_color); class=class="str">"cmt">// Set class="type">color to the selected TP zone class="type">color ObjectSetInteger(chart_id, "TP zone", OBJPROP_STYLE, STYLE_SOLID); class=class="str">"cmt">// Set style to solid ObjectSetInteger(chart_id, "TP zone", OBJPROP_WIDTH, class="num">1); class=class="str">"cmt">// Set the width of the rectangle border ObjectSetInteger(chart_id, "TP zone", OBJPROP_FILL, tp_zonez_color); class=class="str">"cmt">// Fill the rectangle with the selected TP zone class="type">color ObjectSetInteger(chart_id, "TP zone", OBJPROP_BACK, true); class=class="str">"cmt">// Set the rectangle to appear behind the chart objects } } } if(stop_loss > class="num">0) { class=class="str">"cmt">// Create a rectangle to represent the Stop Loss(SL) zone on the chart ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, stop_loss); } if(take_profit > class="num">0) { class=class="str">"cmt">// Create a rectangle to represent the Take Profit(TP) zone on the chart ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, take_profit); } class=class="str">"cmt">// Get the current ask price class="type">class="kw">double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); class=class="str">"cmt">// Create a trend line object on the chart from the position&class="macro">#x27;s open time and price to the current time and ask price ObjectCreate(chart_id, "Trend Line", OBJ_TREND, class="num">0, position_open_time, open_price, TimeCurrent(), ask); class=class="str">"cmt">// Set the class="type">color of the trend line
◍ 用代码把持仓区间画成可视区块
在 MT5 图表上把持仓的盈亏区间直接画出来,比盯着终端数字更直观。下面这段逻辑先给一条名为 Trend Line 的趋势线设了黄色、虚线、2 像素宽,再声明了开仓价、止损、止盈和时间等变量,方便后续定位。 position_index 输入项默认填 1,但注释里写明索引从 0 起算,也就是说默认抓的是账户里第二笔持仓;若你想盯第一笔,得改成 0。sl_zonez_color 用 clrPink 标亏损区,tp_zonez_color 用 clrSpringGreen 标盈利区,line_zonez_color 用 clrYellow 画线,都在 input 里可调。 OnTick 里先取当前卖价 ask,再把字符串 "23:59" 转成 datetime 作为区间截止时间。随后用 for 循环扫 PositionsTotal() 笔持仓,靠 PositionGetTicket(position_index) 匹配指定索引,且要求 POSITION_SYMBOL 等于当前图表品种才继续取数。 外汇与贵金属杠杆高,这类可视化脚本只做辅助参考,信号本身不预示走向,实际成交受滑点与点差影响可能偏离画线区间。
ObjectSetInteger(chart_id, "Trend Line", OBJPROP_COLOR, clrYellow); class=class="str">"cmt">// Set the style of the trend line to dashed ObjectSetInteger(chart_id, "Trend Line", OBJPROP_STYLE, STYLE_DASH); class=class="str">"cmt">// Set the width of the trend line ObjectSetInteger(chart_id, "Trend Line", OBJPROP_WIDTH, class="num">2); class=class="str">"cmt">// Variables to store position details class="type">class="kw">double open_price; class=class="str">"cmt">// Variable to store the entry price of the position class="type">class="kw">double stop_loss; class=class="str">"cmt">// Variable to store the Stop Loss level of the position class="type">class="kw">double take_profit; class=class="str">"cmt">// Variable to store the Take Profit level of the position class="type">class="kw">datetime position_open_time; class=class="str">"cmt">// Variable to store the open time of the position class=class="str">"cmt">// Define the position index for the first position input class="type">int position_index = class="num">1; class=class="str">"cmt">// POSITION INDEX(Index starts from class="num">0) class=class="str">"cmt">// Get the ID of the current chart class="type">long chart_id = ChartID(); class=class="str">"cmt">// Store the ID of the current chart class="type">class="kw">string time = "class="num">23:class="num">59"; class=class="str">"cmt">// Define a specific time as a class="type">class="kw">string class=class="str">"cmt">// Define the class="type">color for the losing zone input class="type">color sl_zonez_color = clrPink; class=class="str">"cmt">// Choose a class="type">color for Losing Zone class=class="str">"cmt">// Define the class="type">color for the winning zone input class="type">color tp_zonez_color = clrSpringGreen; class=class="str">"cmt">// Choose a class="type">color for Winning Zone class=class="str">"cmt">// Define the class="type">color for the trend line input class="type">color line_zonez_color = clrYellow; class=class="str">"cmt">// Choose a class="type">color for the line class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">// Get the current ask price class="type">class="kw">double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); class=class="str">"cmt">// Convert the class="type">class="kw">string time to class="type">class="kw">datetime class="type">class="kw">datetime close_zone = StringToTime(time); class=class="str">"cmt">// Loop through all open positions for(class="type">int i = class="num">0; i < PositionsTotal(); i++) { class=class="str">"cmt">// Get the ticket number of the position at index &class="macro">#x27;i&class="macro">#x27; class="type">class="kw">ulong ticket = PositionGetTicket(i); class=class="str">"cmt">// Check if the position matches the specified index and symbol of the current chart if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { class=class="str">"cmt">// Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); class=class="str">"cmt">// Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); class=class="str">"cmt">// Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP);
「把止损止盈画成图表上的实体区」
持仓一开出来,先把开仓时间抓到手:用 PositionGetInteger(POSITION_TIME) 强转成 int 存进 position_open_time,后面画对象全靠这个锚点。 如果 stop_loss 大于 0,就调 ObjectCreate 画一个名为 "SL Zone" 的 OBJ_RECTANGLE,时间轴从 position_open_time 拉到 close_zone,价格轴从 open_price 到 stop_loss;take_profit 同理画 "TP zone",边界到 take_profit。这两块矩形就是肉眼可见的止损 / 止盈触发带。 外观全靠 ObjectSetInteger 堆出来:颜色用 sl_zonez_color / tp_zonez_color,线型 STYLE_SOLID,边框宽度 1,OBJPROP_FILL 填同色,OBJPROP_BACK 设 true 让矩形沉到 K 线后面不挡视野。外汇与贵金属杠杆高,SL/TP 区只作空间参考,实际滑点可能让成交偏离该带。 最后一条 OBJ_TREND 从开仓点连到 TimeCurrent() 与 ask 价,命名 "Trend Line",把持仓成本到现价的斜率直接晒在图上,方便你一眼判断浮盈浮亏的倾斜方向。
position_open_time = (class="type">int)PositionGetInteger(POSITION_TIME); if(stop_loss > class="num">0) { ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, stop_loss); } if(take_profit > class="num">0) { ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, class="num">0, position_open_time, open_price, close_zone, take_profit); } ObjectSetInteger(chart_id, "SL Zone", OBJPROP_COLOR, sl_zonez_color); ObjectSetInteger(chart_id, "SL Zone", OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(chart_id, "SL Zone", OBJPROP_WIDTH, class="num">1); ObjectSetInteger(chart_id, "SL Zone", OBJPROP_FILL, sl_zonez_color); ObjectSetInteger(chart_id, "SL Zone", OBJPROP_BACK, true); ObjectSetInteger(chart_id, "TP zone", OBJPROP_COLOR, tp_zonez_color); ObjectSetInteger(chart_id, "TP zone", OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(chart_id, "TP zone", OBJPROP_WIDTH, class="num">1); ObjectSetInteger(chart_id, "TP zone", OBJPROP_FILL, tp_zonez_color); ObjectSetInteger(chart_id, "TP zone", OBJPROP_BACK, true); ObjectCreate(chart_id, "Trend Line", OBJ_TREND, class="num">0, position_open_time, open_price, TimeCurrent(), ask);
把持仓盈亏钉在趋势线上
给图表上的趋势线做完外观设定后,下一步是把当前持仓的浮动盈亏直接标在图里,省得切仓位窗口看数字。下面这段逻辑先取 POSITION_PROFIT,再按正负拼成带符号的字符串,最后用 OBJ_TEXT 画到 ask 价位置。 盈利为正或零时,DoubleToString 保留 2 位小数,StringFormat 套上 +$ 前缀;亏损则先用 MathAbs 转正数再格式化,前缀换成 -$。颜色上,正利润用 clrMediumBlue、负利润用 clrRed,一眼能分出方向。 外汇和贵金属杠杆高,浮盈浮亏随时翻转,这种图上标注只作实时参考,不代表平仓结果。开 MT5 把这段接进 EA 的 OnTick,就能在盯盘时直接看到线旁的金额。
ObjectSetInteger(chart_id, "Trend Line", OBJPROP_COLOR, line_zonez_color); ObjectSetInteger(chart_id, "Trend Line", OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(chart_id, "Trend Line", OBJPROP_WIDTH, class="num">2); class=class="str">"cmt">// Calculate the profit of the current position class="type">class="kw">double profit = PositionGetDouble(POSITION_PROFIT); class=class="str">"cmt">// Variables to store the formatted profit text class="type">class="kw">string curent_profits; class="type">class="kw">string profit_to_string; class=class="str">"cmt">// Check if the profit is positive or zero if(profit >= class="num">0) { class=class="str">"cmt">// Convert the profit to a class="type">class="kw">string with class="num">2 decimal places profit_to_string = DoubleToString(profit, class="num">2); class=class="str">"cmt">// Format the profit as a positive amount with a &class="macro">#x27;+&class="macro">#x27; sign curent_profits = StringFormat("+$%s", profit_to_string); } class=class="str">"cmt">// Check if the profit is negative else if(profit < class="num">0) { class=class="str">"cmt">// Convert the negative profit to a positive number class="type">class="kw">double profit_to_positive = MathAbs(profit); class=class="str">"cmt">// Convert the positive profit to a class="type">class="kw">string with class="num">2 decimal places profit_to_string = DoubleToString(profit_to_positive, class="num">2); class=class="str">"cmt">// Format the profit as a negative amount with a &class="macro">#x27;-&class="macro">#x27; sign curent_profits = StringFormat("-$%s", profit_to_string); } class=class="str">"cmt">// Create a text label on the chart to display the current profit class="type">class="kw">string text_object_name = "Profit"; ObjectCreate(chart_id, text_object_name, OBJ_TEXT, class="num">0, TimeCurrent(), ask); ObjectSetString(chart_id, text_object_name, OBJPROP_TEXT, curent_profits); class=class="str">"cmt">// Set the class="type">color of the profit text based on whether the profit is positive or negative if(profit > class="num">0) { ObjectSetInteger(chart_id, text_object_name, OBJPROP_COLOR, clrMediumBlue); class=class="str">"cmt">// Positive profit in blue } else if(profit < class="num">0) { ObjectSetInteger(chart_id, text_object_name, OBJPROP_COLOR, clrRed); class=class="str">"cmt">// Negative profit in red }