MQL5 简介(第 9 部分):理解和使用 MQL5 中的对象·综合运用
📘

MQL5 简介(第 9 部分):理解和使用 MQL5 中的对象·综合运用

第 3/3 篇

「把持仓的 TP、SL 与开仓价直接画在图上」

这段代码做的是一件很实在的事:把当前图表里某笔持仓的止盈、止损和开仓价,以文字对象形式钉在 K 线旁,省得你每次都要去交易面板核对数字。外汇与贵金属波动快、点值小,肉眼盯价位时容易看错行,直接标在图上是降低误操作概率的办法。 TP 用蓝色、SL 用红色、Entry 用紫红,字号统一设 8,颜色区分能让你在扫图瞬间分辨风险边界。注意 ObjectCreate 的 time 参数传的是 close_zone(平仓时间区),意味着文字锚在平仓那一刻的横坐标,回看历史持仓轨迹时不会漂。 外部输入里 position_index 默认 1(实际索引从 0 起,所以抓的是第二笔持仓),sl_zonez_color 默认粉红、tp_zonez_color 默认春绿、line_zonez_color 默认黄,show_history 默认 "no"。想看历史带单痕迹,把这个字符串改成 "yes" 即可,但 MT5 上过度画对象会拖慢刷新,实盘前先开模拟盘验证渲染开销。

MQL5 / C++
}
      class=class="str">"cmt">// Display the Take Profit(TP) level on the chart
      class="type">class="kw">string tp_display = "TP";
      class="type">class="kw">string t_display = StringFormat("Take Profit: %.5f", take_profit);
      ObjectCreate(chart_id, tp_display, OBJ_TEXT, class="num">0, close_zone, take_profit);
      ObjectSetString(chart_id, tp_display, OBJPROP_TEXT, t_display);
      ObjectSetInteger(chart_id, tp_display, OBJPROP_COLOR, clrBlue); class=class="str">"cmt">// TP text in blue
      ObjectSetInteger(chart_id, tp_display, OBJPROP_FONTSIZE, class="num">8); class=class="str">"cmt">// Set font size for TP
      class=class="str">"cmt">// Display the Stop Loss(SL) level on the chart
      class="type">class="kw">string sl_display = "SL";
      class="type">class="kw">string s_display = StringFormat("Stop Loss: %.5f", stop_loss);
      ObjectCreate(chart_id, sl_display, OBJ_TEXT, class="num">0, close_zone, stop_loss);
      ObjectSetString(chart_id, sl_display, OBJPROP_TEXT, s_display);
      ObjectSetInteger(chart_id, sl_display, OBJPROP_COLOR, clrRed); class=class="str">"cmt">// SL text in red
      ObjectSetInteger(chart_id, sl_display, OBJPROP_FONTSIZE, class="num">8); class=class="str">"cmt">// Set font size for SL
      class=class="str">"cmt">// Display the Entry Price on the chart
      class="type">class="kw">string en_display = "Entry Price";
      class="type">class="kw">string e_display = StringFormat("Entry Point: %.5f", open_price);
      ObjectCreate(chart_id, en_display, OBJ_TEXT, class="num">0, close_zone, open_price);
      ObjectSetString(chart_id, en_display, OBJPROP_TEXT, e_display);
      ObjectSetInteger(chart_id, en_display, OBJPROP_COLOR, clrPaleVioletRed); class=class="str">"cmt">// Entry Price text in pale violet red
      ObjectSetInteger(chart_id, en_display, OBJPROP_FONTSIZE, class="num">8); class=class="str">"cmt">// Set font size for Entry Price
      }
   }
}
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">// Define whether to show past history or not
input class="type">class="kw">string show_history = "no"; class=class="str">"cmt">// Type yes to show past history
class=class="str">"cmt">// Define the start date to show history

用 HistorySelect 拉出图表品种的成交轨迹

想在 MT5 上把某品种的历史成交直接映射到当前图表,第一步是划定时间窗。下面这段代码把起点钉在 1970.08.10、终点放到 2024.08.15,相当于把四十多年内的账户成交都纳入候选池,你可以把 date2 改成昨天收盘时间来跑近期样本。 核心在 OnTick 里的 HistorySelect(date1, date2),它返回布尔值表示指定区间的成交历史是否成功载入。之后用 HistoryDealsTotal() 拿到总数,再按 ticket 逐条翻查 DEAL_ENTRY_IN 与 DEAL_ENTRY_OUT,只保留 ChartSymbol(chart_id) 匹配的那些单子——这样就不会把其他品种的仓位混进来。 对外汇与贵金属这类高杠杆品种,历史成交的滑点和点差会在 deal_close_price 与 deal_open_price 的差值里暴露出来,复盘时重点看 deal_profit 和 deal_sl 的分布,可能比看裸 K 更直观。 别把终端默认品种当过滤条件 ChartSymbol 取的是当前图表 ID 对应的品种,若你手滑切了图表却没改 chart_id,循环会静默跳过所有单子,排查时先打印 chart_id 和 ChartSymbol 返回值。

MQL5 / C++
input class="type">class="kw">datetime date1 = D&class="macro">#x27;class="num">1970.08.class="num">10 class="num">00:class="num">00:class="num">00&class="macro">#x27;; class=class="str">"cmt">// Show history from this date
class=class="str">"cmt">// Define the end date to show history
input class="type">class="kw">datetime date2 = D&class="macro">#x27;class="num">2024.08.class="num">15 class="num">00:class="num">00:class="num">00&class="macro">#x27;; class=class="str">"cmt">// To this date
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">// Check if history display is enabled
   if(show_history == "yes")
     {
      Comment(""); class=class="str">"cmt">// Clear previous comments
      class=class="str">"cmt">// Select deal history within the specified date range
      class="type">bool deal_history = HistorySelect(date1, date2);
      class=class="str">"cmt">// Variables to store deal details
      class="type">class="kw">double deal_close_price = class="num">0.0;
      class="type">class="kw">double deal_open_price = class="num">0.0;
      class="type">class="kw">double deal_sl = class="num">0.0;
      class="type">class="kw">double deal_tp = class="num">0.0;
      class="type">class="kw">double deal_profit = class="num">0.0;
      class="type">class="kw">datetime deal_close_time = class="num">0;
      class="type">class="kw">datetime deal_open_time = class="num">0;
      class=class="str">"cmt">// Check if deal history is available
      if(deal_history)
        {
         class=class="str">"cmt">// Loop through all history deals
         for(class="type">int i = class="num">0; i < HistoryDealsTotal(); i++)
           {
            class="type">class="kw">ulong ticket = HistoryDealGetTicket(i);
            class=class="str">"cmt">// Check for deal entry in
            if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_IN)
              {
               if(HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id))
                 {
                  deal_open_price = HistoryDealGetDouble(ticket, DEAL_PRICE);
                  deal_open_time = (class="type">class="kw">datetime)HistoryDealGetInteger(ticket, DEAL_TIME);
                 }
              }
            class=class="str">"cmt">// Check for deal entry out
            if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
              {
               deal_profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
               deal_close_price = HistoryDealGetDouble(ticket, DEAL_PRICE);
               deal_sl = HistoryDealGetDouble(ticket, DEAL_SL);

◍ 在历史成交上贴盈亏标签

把已平仓交易直接画到 MT5 图表上,比翻历史报表更直观。下面这段逻辑只处理与当前图表品种一致的成交:先取每笔 deal 的止盈价、平仓时间和品种名,匹配上了才往下走。 盈利单用 MediumBlue 写「YOU WON +$xx.xx」,亏损单取绝对值后用 Red 写「YOU LOST -$xx.xx」,字体统一压到 8 号避免挡 K 线。对象名按循环变量 i 拼成「PROFIT i」,重复跑脚本不会撞名。 外汇与贵金属杠杆高,历史盈利不代表未来,贴标只是复盘辅助,别拿它当开仓依据。开 MT5 按 F4 把下面代码塞进脚本,挂到 EURUSD 图表跑一遍,能看到过去成交的盈亏水印。

MQL5 / C++
      deal_tp = HistoryDealGetDouble(ticket, DEAL_TP);
      deal_close_time = (class="type">class="kw">datetime)HistoryDealGetInteger(ticket, DEAL_TIME);
      if(HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id))
        {
          class="type">class="kw">string deal_string;
          class="type">class="kw">string current_deal_profit;
          class="type">class="kw">string object_name;
          class=class="str">"cmt">// Display deal profit/loss
          if(deal_profit > class="num">0)
            {
             deal_string = DoubleToString(deal_profit, class="num">2);
             current_deal_profit = StringFormat("YOU WON +$%s", deal_string);
             object_name = StringFormat("PROFIT %d", i);
             ObjectCreate(chart_id, object_name, OBJ_TEXT, class="num">0, deal_close_time, deal_close_price);
             ObjectSetString(chart_id, object_name, OBJPROP_TEXT, current_deal_profit);
             ObjectSetInteger(chart_id, object_name, OBJPROP_COLOR, clrMediumBlue);
             ObjectSetInteger(chart_id, object_name, OBJPROP_FONTSIZE,class="num">8);
            }
          else
            if(deal_profit < class="num">0)
              {
               class="type">class="kw">double deal_to_positive = MathAbs(deal_profit);
               deal_string = DoubleToString(deal_to_positive, class="num">2);
               object_name = StringFormat("PROFIT %d", i);
               current_deal_profit = StringFormat("YOU LOST -$%s", deal_string);
               ObjectCreate(chart_id, object_name, OBJ_TEXT, class="num">0, deal_close_time, deal_close_price);
               ObjectSetString(chart_id, object_name, OBJPROP_TEXT, current_deal_profit);
               ObjectSetInteger(chart_id, object_name, OBJPROP_COLOR, clrRed);

「把每笔持仓的止损止盈区画进图表」

在 MT5 里逐笔还原历史交易时,用矩形对象把 SL、TP 区间直接铺在 K 线背景上,比只看成交单列表直观得多。下面这段代码在 deal_sl 大于 0 时才创建 SL 矩形,避免无止损单报错;TP 同理。 矩形用 OBJ_RECTANGLE,以开仓时间+开仓价为左上、平仓时间+止损价为右下,OBJPROP_BACK 设 true 保证压在蜡烛后面不挡视线。颜色、线宽、填充都靠 ObjectSetInteger 逐个写,线宽写 1 就够素净。 趋势线部分用 OBJ_TREND 从开仓价连到平仓价,一眼能看出这笔单子持有期间价格的实际路径。外汇和贵金属波动大,这类可视化只帮你复盘概率分布,不构成方向暗示。

MQL5 / C++
ObjectSetInteger(chart_id, object_name, OBJPROP_FONTSIZE, class="num">8);
}
class=class="str">"cmt">// Display deal SL zone
class="type">class="kw">string sl_obj_name = StringFormat("SL ZONE %d", i);
if(deal_sl > class="num">0)
  {
   ObjectCreate(chart_id, sl_obj_name, OBJ_RECTANGLE, class="num">0, deal_open_time, deal_open_price, deal_close_time, deal_sl);
  }
ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_COLOR, sl_zonez_color);
ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_WIDTH, class="num">1);
ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_FILL, sl_zonez_color);
ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_BACK, true);
class=class="str">"cmt">// Display deal TP zone
class="type">class="kw">string tp_obj_name = StringFormat("TP ZONE %d", i);
if(deal_tp > class="num">0)
  {
   ObjectCreate(chart_id, tp_obj_name, OBJ_RECTANGLE, class="num">0, deal_open_time, deal_open_price, deal_close_time, deal_tp);
  }
ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_COLOR, tp_zonez_color);
ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_WIDTH, class="num">1);
ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_FILL, tp_zonez_color);
ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_BACK, true);
class=class="str">"cmt">// Display deal trend line
class="type">class="kw">string line_obj_name = StringFormat("line %d", i);
ObjectCreate(chart_id, line_obj_name, OBJ_TREND, class="num">0, deal_open_time, deal_open_price, deal_close_time, deal_close_price);

用代码给区间边界上色划线

在 MT5 里给自定义区间线做视觉区分,核心靠 ObjectSetInteger 逐个写属性。上面这段把一条名为 line_obj_name 的虚线设成了指定颜色、STYLE_DASH dash 样式、线宽 2,挂在 chart_id 对应的图上。 这种写法适合把支撑阻力带、波动区间的上下沿直接画出来,不用手动在图表上拖。线宽设 2 能在 1080p 屏上明显区分于默认 1 像素线,回看历史 K 线时不至于看漏。 外汇与贵金属杠杆高、滑点随机,任何画线仅作概率参考;开 MT5 把这段塞进你的区间脚本里,改 line_zonez_color 变量就能切换多空色系,立刻能看到图上反应。

MQL5 / C++
ObjectSetInteger(chart_id, line_obj_name, OBJPROP_COLOR, line_zonez_color);
ObjectSetInteger(chart_id, line_obj_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(chart_id, line_obj_name, OBJPROP_WIDTH, class="num">2);

◍ 一点提醒

把止盈止损区画成矩形、用趋势线跟价格、给历史成交贴文本标签,这套对象操作在 MT5 里跑通后,图表的信息密度会明显提升。前面项目文件 MQL5OBJECTS_PROJECT3.mq5 里那套逻辑,直接拖进编辑器就能编译验证。 外汇和贵金属杠杆高、滑点跳空频繁,视觉辅助只帮你读盘,不替你兜底亏损概率。对象画得再清楚,仓位和风控还是得自己盯。 真要落地,先开个模拟账户把矩形坐标和标签刷新频率调一遍,比看十遍说明都管用。

常见问题

用代码读取持仓的 SL、TP、开仓价,在图表上用水平线对象画出来,颜色区分即可,不用手动记数字。
调用历史筛选函数按当前图表品种取出成交记录,逐笔读取价格和时间,用箭头或标签贴到图上就能看清轨迹。
可以,小布盯盘的 AIGC 已内置这类图形诊断,打开对应品种页就能直接看到止损止盈区和历史盈亏标签,不用自己写代码。
按买卖方向用开平仓价差乘手数算盈亏,注意点值和报价精度,标签文字用交易品种后缀避免看串。
多半是对象没绑定具体子窗口或时间坐标,创建时指定好图表 ID 与锚点时间,重绘时先删旧对象再画新的。