可视化交易图表(第二部分):数据图形化展示·综合运用
📘

可视化交易图表(第二部分):数据图形化展示·综合运用

第 3/3 篇

◍ 把历史仓位画进图表的关键方法

想在 MT5 图表上把某笔历史交易的开平、止损、止盈一次性标出来,核心就是重写两个绘制方法。paintDeal() 专门负责画价位标签和连线,paintPanel() 负责把整块交易信息面板叠上去。 paintDeal() 的入参已经把画图要用的数据全带了进来:handlE 是图表句柄,tickeT 是交易编号,stop_losS / take_profiT 分别是止损止盈价(没有就传 0),opeN / closE 是开收盘价,timE / time_closE 是开平时间。用交易编号拼唯一对象名,能避免重复创建导致旧标签被覆盖。 止损标签用 OBJ_ARROW_LEFT_PRICE 类型,名字前缀 name_sl_ 加编号,颜色 clrRed,止盈用 name_tp_ 前缀、clrLawnGreen。开仓价用 name_open_ 前缀、clrWhiteSmoke 弱化显示。开平之间连一段趋势线要改用 OBJ_TREND,并把两个端点的价格与时间都传进去;平仓标签用 OBJ_ARROW_RIGHT_PRICE 放右侧,打印截图时更顺眼。每画完一个模块都该调一次 ChartRedraw() 强制刷新。 面板部分靠 LabelCreate() 与 RectLabelCreate() 两个辅助方法撑起来。前者建 OBJ_LABEL 文本,后者建 OBJ_RECTANGLE_LABEL 当背景框。LabelCreate() 里用 ObjectCreate() 建对象,失败就 ResetLastError() 后写日志并 return;成功再用 ObjectSetInteger / String / Double 设坐标、字体、颜色、隐藏属性。行高写死 20、列坐标存进 x_column[] / y_column[],标题和数值分两个 string 数组静态初始化,顺序固定,找起来比动态隐藏空字段更直观。 下面这段是 paintDeal() 头部拼名字和建止损标签的原文片段,逐行看:handlE 进图表、tickeT 拼唯一名、ObjectCreate 用左价箭头把止损画在 timE 时刻的 stop_losS 价位。 外汇与贵金属图表对象绘制涉及真实账户历史,回测或实盘导出均属高风险操作,图形仅作复盘辅助,不代表任何方向判断。

MQL5 / C++
class="type">void paintDeal(class="type">long handlE,
                  class="type">ulong tickeT,
                  class="type">class="kw">double stop_losS,
                  class="type">class="kw">double take_profiT,
                  class="type">class="kw">double opeN,
                  class="type">class="kw">double closE,
                  class="type">class="kw">datetime timE,
                  class="type">class="kw">datetime time_closE)
  class="type">class="kw">string name_sl = "name_sl_"+IntegerToString(tickeT);                    class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_sl,OBJ_ARROW_LEFT_PRICE,class="num">0,timE,stop_losS);      class=class="str">"cmt">// create the left label object
class=class="str">"cmt">//--- draw stop loss

把挂单的三条线画进图表

想在 MT5 图表上直观看到每笔交易的入场、止损、止盈与持仓过程,用左侧价格箭头加趋势线就能做到。下面这段逻辑给对象名拼上 tick 时间戳,保证同图表多次绘制不重名。 止损用红色左箭头标注在 stop_losS 价位,止盈用草绿色标在 take_profiT,入场用白烟色标在 opeN。三者都设 OBJ_ALL_PERIODS,切周期也持续可见。 持仓过程用 OBJ_TREND 从开仓时间价位连到平仓时间价位,一眼能看出这笔单子扛了多远。外汇与贵金属波动剧烈,这类标注只做复盘参考,不代表后续方向。 复制下面代码到 EA 的成交处理块,把 timE、opeN、closE 等变量接上你的实际值,编译后跑一根 EURUSD 分钟线就能看到三条线落图。

MQL5 / C++
  class="type">class="kw">string name_sl = "name_sl_"+IntegerToString(tickeT);                                                                          class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_sl,OBJ_ARROW_LEFT_PRICE,class="num">0,timE,stop_losS);                                                              class=class="str">"cmt">// create the left label object
  ObjectSetInteger(handlE,name_sl,OBJPROP_COLOR,clrRed);                                                                           class=class="str">"cmt">// add class="type">color
  ObjectSetInteger(handlE,name_sl,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);                                                             class=class="str">"cmt">// set visibility
  ChartRedraw(handlE);                                                                                                            class=class="str">"cmt">// redraw
class=class="str">"cmt">//--- draw take profit
  class="type">class="kw">string name_tp = "name_tp_"+IntegerToString(tickeT);                                                                            class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_tp,OBJ_ARROW_LEFT_PRICE,class="num">0,timE,take_profiT);                                                            class=class="str">"cmt">// create the left label object
  ObjectSetInteger(handlE,name_tp,OBJPROP_COLOR,clrLawnGreen);                                                                     class=class="str">"cmt">// add class="type">color
  ObjectSetInteger(handlE,name_tp,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);                                                             class=class="str">"cmt">// set visibility
  ChartRedraw(handlE);                                                                                                            class=class="str">"cmt">// redraw
class=class="str">"cmt">//--- draw entry price
  class="type">class="kw">string name_open = "name_open_"+IntegerToString(tickeT);                                                                         class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_open,OBJ_ARROW_LEFT_PRICE,class="num">0,timE,opeN);                                                                 class=class="str">"cmt">// create the left label object
  ObjectSetInteger(handlE,name_open,OBJPROP_COLOR,clrWhiteSmoke);                                                                  class=class="str">"cmt">// add class="type">color
  ObjectSetInteger(handlE,name_open,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);                                                           class=class="str">"cmt">// set visibility
  ChartRedraw(handlE);                                                                                                            class=class="str">"cmt">// redraw
class=class="str">"cmt">//--- deal line
  class="type">class="kw">string name_deal = "name_deal_"+IntegerToString(tickeT);                                                                         class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_deal,OBJ_TREND,class="num">0,timE,opeN,time_closE,closE);                                                           class=class="str">"cmt">// create the left label object
  ObjectSetInteger(handlE,name_deal,OBJPROP_COLOR,clrWhiteSmoke);                                                                  class=class="str">"cmt">// add class="type">color
  ObjectSetInteger(handlE,name_deal,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);                                                           class=class="str">"cmt">// set visibility

「用箭头和标签把平仓价钉在图上」

在 MT5 里画平仓价,别只靠 Print 输出到日志,肉眼盯盘根本来不及看。用 OBJ_ARROW_RIGHT_PRICE 在收盘价对应的时间轴上挂一个右向价格箭头,比在 EA 面板里翻记录直观得多。 下面这段先建箭头对象:用 IntegerToString(tickeT) 拼出唯一对象名避免重名冲突,再把时间和收盘价传进 ObjectCreate。颜色设成 clrWhiteSmoke、可见周期设 OBJ_ALL_PERIODS,最后 ChartRedraw 强制重绘,否则图表不会立刻刷新。 ChartRedraw(handlE); // redraw //--- draw exit price string name_close = "name_close"+IntegerToString(tickeT); // assign the name ObjectCreate(handlE,name_close,OBJ_ARROW_RIGHT_PRICE,0,time_closE,closE); // create the left label object ObjectSetInteger(handlE,name_close,OBJPROP_COLOR,clrWhiteSmoke); // add color ObjectSetInteger(handlE,name_close,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS); // set visibility ChartRedraw(handlE); // redraw 如果想在图角再补一行文字标签(比如「平仓 XX 点」),可以封装一个 LabelCreate 函数。它的参数表里默认 font_size=10、clr=clrRed、corner=CORNER_LEFT_UPPER,意味着标签默认红字、Arial、钉在左上角——你复制去用时若想低调一点,把 clr 改成 clrSilver 就行。外汇和贵金属波动快、滑点随机,这类图形标记仅辅助复盘,不预示后续方向。 bool LabelCreate(const long chart_ID=0, // chart ID const string name="Label", // label name const int sub_window=0, // subwindow number const long x=0, // X coordinate const long y=0, // Y coordinate const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // chart corner for anchoring const string text="Label", // text const string font="Arial", // font const int font_size=10, // font size const color clr=clrRed) // color

MQL5 / C++
ChartRedraw(handlE);                                                                       class=class="str">"cmt">// redraw
class=class="str">"cmt">//--- draw exit price
  class="type">class="kw">string name_close = "name_close"+IntegerToString(tickeT);                               class=class="str">"cmt">// assign the name
  ObjectCreate(handlE,name_close,OBJ_ARROW_RIGHT_PRICE,class="num">0,time_closE,closE);               class=class="str">"cmt">// create the left label object
  ObjectSetInteger(handlE,name_close,OBJPROP_COLOR,clrWhiteSmoke);                         class=class="str">"cmt">// add class="type">color
  ObjectSetInteger(handlE,name_close,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);                 class=class="str">"cmt">// set visibility
  ChartRedraw(handlE);                                                                     class=class="str">"cmt">// redraw
class="type">bool LabelCreate(const class="type">long      chart_ID=class="num">0,             class=class="str">"cmt">// chart ID
                 const class="type">class="kw">string    name="Label",           class=class="str">"cmt">// label name
                 const class="type">int       sub_window=class="num">0,           class=class="str">"cmt">// subwindow number
                 const class="type">long      x=class="num">0,                    class=class="str">"cmt">// X coordinate
                 const class="type">long      y=class="num">0,                    class=class="str">"cmt">// Y coordinate
                 const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, class=class="str">"cmt">// chart corner for anchoring
                 const class="type">class="kw">string    text="Label",           class=class="str">"cmt">// text
                 const class="type">class="kw">string    font="Arial",           class=class="str">"cmt">// font
                 const class="type">int       font_size=class="num">10,           class=class="str">"cmt">// font size
                 const class="type">color     clr=clrRed)             class=class="str">"cmt">// class="type">color

◍ 用 OBJ_LABEL 在图表角落钉死文字标签

想在 MT5 图表上不随价格滚动地标注信号,比如「波动率突破」或「小布预警」,OBJ_LABEL 是最轻量的办法。它靠像素坐标(XDISTANCE/YDISTANCE)和图表角落(CORNER)定位,而非时间/价格轴,所以在外汇和贵金属这种高波动品种上,不会被 K 线挤出视野。 下面这段函数签名定义了标签的默认参数:角度 0 度、锚点左上、不进背景层、禁止鼠标选中、隐藏于对象列表、鼠标点击优先级 0。这些默认值适合做只读提示,若要交互再改 selection 和 z_order。 [CODE]const double angle=0.0, // text angle const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type const bool back=false, // in the background const bool selection=false, // select to move const bool hidden=true, // hidden in the list of objects const long z_order=0) // priority for clicking with a mouse[/CODE] 创建流程是先 ResetLastError 清错误码,再 ObjectCreate 建标签;失败就打印函数名和 GetLastError 并返回 false。实测若 chart_ID 填 0 表示当前图表,sub_window 填 0 为主窗口,坐标 (0,0) 配合 CORNER 才能落对位置。 [CODE]//--- reset the error value ResetLastError(); //--- create a text label if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) { Print(__FUNCTION__, ": failed to create the text label! Error code = ",GetLastError()); return(false); }[/CODE] 建完之后用 ObjectSetInteger / ObjectSetString / ObjectSetDouble 逐项写属性:X/Y 距离、角落、文本内容、字体、字号、角度、锚点、颜色、背景层、鼠标拖动。外汇贵金属交易高风险,这类标签只作辅助参考,信号真伪仍需结合价格行为确认。

MQL5 / C++
const class="type">class="kw">double angle=class="num">0.0, class=class="str">"cmt">// text angle
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, class=class="str">"cmt">// anchor type
const class="type">bool back=false, class=class="str">"cmt">// in the background
const class="type">bool selection=false, class=class="str">"cmt">// select to move
const class="type">bool hidden=true, class=class="str">"cmt">// hidden in the list of objects
const class="type">long z_order=class="num">0) class=class="str">"cmt">// priority for clicking with a mouse
class=class="str">"cmt">//--- reset the error value
 ResetLastError();
class=class="str">"cmt">//--- create a text label
 if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,class="num">0,class="num">0))
  {
   Print(__FUNCTION__,
        ": failed to create the text label! Error code = ",GetLastError());
   class="kw">return(false);
  }
class=class="str">"cmt">//--- reset the error value
 ResetLastError();
class=class="str">"cmt">//--- create a text label
 if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,class="num">0,class="num">0))
  {
   Print(__FUNCTION__,
        ": failed to create the text label! Error code = ",GetLastError());
   class="kw">return(false);
  }
class=class="str">"cmt">//--- set label coordinates
 ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
 ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
class=class="str">"cmt">//--- set the chart&class="macro">#x27;s corner, relative to which point coordinates are defined
 ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
class=class="str">"cmt">//--- set the text
 ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
class=class="str">"cmt">//--- set the text font
 ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
class=class="str">"cmt">//--- set font size
 ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
class=class="str">"cmt">//--- set the text angle
 ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
class=class="str">"cmt">//--- set anchor type
 ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
class=class="str">"cmt">//--- set the class="type">color
 ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
class=class="str">"cmt">//--- display in the foreground(false) or background(true)
 ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
class=class="str">"cmt">//--- enable(true) or disable(false) the mode of moving the label by mouse

矩形标签对象的选中与层级属性设置

在 MT5 自定义图形对象时,RectLabel 这类矩形标签的交互属性靠 ObjectSetInteger 逐个写入。下面这段把可选中、选中态、隐藏于对象列表、鼠标点击层级一次性设完,返回 true 表示执行通过。 ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); // 设定对象是否允许被鼠标点选 ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); // 设定对象当前是否处于被选中状态 //--- hide (true) or display (false) graphical object name in the object list ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); // 隐藏(true)或显示(false)对象在导航列表里的名字 //--- set the priority for receiving the event of a mouse click on the chart ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); // 设定接收图表鼠标点击事件优先级 //--- successful execution return(true); 紧接着的 RectLabelCreate 函数给出了默认参数实例:左上角锚定(CORNER_LEFT_UPPER),X/Y 坐标均为 19,宽 150、高 20,背景色 C'236,233,216',下沉边框(BORDER_SUNKEN),红边实线。把这些直接贴进 EA 的 include 段,开 MT5 挂 EURUSD 图表就可能看到左上角浮出一块 150×20 的标签。 外汇与贵金属图表叠加自绘标签存在重绘覆盖风险,参数 z_order 设错可能导致点击事件被底层对象吞掉,实盘前务必在策略测试器里验证。

MQL5 / C++
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
class=class="str">"cmt">//--- hide(true) or display(false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
class=class="str">"cmt">//--- set the priority for receiving the event of a mouse click on the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
class=class="str">"cmt">//--- successful execution
class="kw">return(true);
class="type">bool RectLabelCreate(const class="type">long chart_ID=class="num">0, class=class="str">"cmt">// chart ID
                    const class="type">class="kw">string name="RectLabel", class=class="str">"cmt">// label name
                    const class="type">int sub_window=class="num">0, class=class="str">"cmt">// subwindow number
                    const class="type">int x=class="num">19, class=class="str">"cmt">// X coordinate
                    const class="type">int y=class="num">19, class=class="str">"cmt">// Y coordinate
                    const class="type">int width=class="num">150, class=class="str">"cmt">// width
                    const class="type">int height=class="num">20, class=class="str">"cmt">// height
                    const class="type">color back_clr=C&class="macro">#x27;class="num">236,class="num">233,class="num">216&class="macro">#x27;, class=class="str">"cmt">// background class="type">color
                    const ENUM_BORDER_TYPE border=BORDER_SUNKEN, class=class="str">"cmt">// border type
                    const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, class=class="str">"cmt">// chart corner for anchoring
                    const class="type">color clr=clrRed, class=class="str">"cmt">// flat border class="type">color (Flat)
                    const ENUM_LINE_STYLE style=STYLE_SOLID class=class="str">"cmt">// flat border style

「矩形标签对象的参数与创建流程」

在 MT5 自定义面板里画一块矩形标签,核心是用 OBJ_RECTANGLE_LABEL 把坐标、尺寸、边框和锚点一次性设好。下面这段函数声明给出了默认参数:线宽固定为 1,背景层 back=true,不允许鼠标选中移动(selection=false),对象隐藏在终端列表里(hidden=true),鼠标点击优先级 z_order=0。 创建前先调 ResetLastError() 清掉上一次错误码,再用 ObjectCreate 以图表 ID、对象名、子窗口编号和起点的 0,0 生成对象。若返回为真,就进入属性设置:XDISTANCE/YDISTANCE 管屏幕像素坐标,XSIZE/YSIZE 定宽高,BGCOLOR 填背景色,BORDER_TYPE 选边框形态,CORNER 决定以哪个图表角为基准,COLOR 在 Flat 模式下就是边框色。 把这些整数属性逐个用 ObjectSetInteger 写进对象,就能在图上得到一个不可选中、藏进后台的纯展示区块。外汇与贵金属图表叠加此类 UI 元素时波动跳价频繁,建议先在模拟盘验证锚点偏移量,避免框体随重绘错位。

MQL5 / C++
const class="type">int      line_width=class="num">1,      class=class="str">"cmt">// flat border width
const class="type">bool      back=true,           class=class="str">"cmt">// &class="macro">#x27;true&class="macro">#x27; in the background
const class="type">bool      selection=false,     class=class="str">"cmt">// select to move
const class="type">bool      hidden=true,         class=class="str">"cmt">// hidden in the list of objects
const class="type">long      z_order=class="num">0)           class=class="str">"cmt">// priority for clicking with a mouse
class=class="str">"cmt">//--- reset the error value
  ResetLastError();                  class=class="str">"cmt">// reset error
class=class="str">"cmt">//--- create a rectangle label
  if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,class="num">0,class="num">0))  class=class="str">"cmt">// create object
    {
    class=class="str">"cmt">//--- set label coordinates
    ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);              class=class="str">"cmt">// assign x coordinate
    ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);              class=class="str">"cmt">// assign y coordinate
    class=class="str">"cmt">//--- set label size
    ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);              class=class="str">"cmt">// width
    ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);             class=class="str">"cmt">// height
    class=class="str">"cmt">//--- set the background class="type">color
    ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);         class=class="str">"cmt">// background class="type">color
    class=class="str">"cmt">//--- set border type
    ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border);       class=class="str">"cmt">// border type
    class=class="str">"cmt">//--- set the chart corner, relative to which point coordinates are defined
    ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);            class=class="str">"cmt">// anchor corner
    class=class="str">"cmt">//--- set flat border class="type">color (in Flat mode)
    ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);                class=class="str">"cmt">// frame
    class=class="str">"cmt">//--- set flat border line style

◍ 画线对象的属性落点与面板渲染入口

在 MT5 里用 ObjectSetInteger 给图形对象赋属性时,OBJPROP_BACK 设 true 会把对象塞进背景层,设 false 则浮在前端;默认行为就是背景绘制,做交易线框若想不被 K 线盖住,必须显式传 false。 OBJPROP_SELECTABLE 与 OBJPROP_SELECTED 成对出现,前者决定鼠标能否点中,后者决定初始是否处于选中态,做可拖拽止损线时这两个参数直接决定交互手感。 OBJPROP_HIDDEN 控制对象是否出现在终端的「对象列表」里,脚本批量画的辅助线建议藏掉,避免列表被刷屏;OBJPROP_ZORDER 则管鼠标点击事件优先级,默认不抢事件,叠多层标注时才需要调。 下面这段 paintPanel 函数签名把每笔成交的开平时间、止盈止损、魔术码、手续费、库存费全列成参数,说明面板渲染是按「单笔交易」粒度喂数据,而不是读账户总览——接历史回测时直接按 tick 记录逐条调用即可。

MQL5 / C++
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); class=class="str">"cmt">// style
class=class="str">"cmt">//--- set flat border width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width); class=class="str">"cmt">// width
class=class="str">"cmt">//--- display in the foreground(false) or background(true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); class=class="str">"cmt">// class="kw">default is background
class=class="str">"cmt">//--- enable(true) or disable(false) the mode of moving the label by mouse
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); class=class="str">"cmt">// is it possible to select
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); class=class="str">"cmt">//
class=class="str">"cmt">//--- hide(true) or display(false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); class=class="str">"cmt">// is it visible in the list
class=class="str">"cmt">//--- set the priority for receiving the event of a mouse click on the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); class=class="str">"cmt">// no events
class=class="str">"cmt">//--- successful execution
}
class="kw">return(true);
class="type">void paintPanel(class="type">long handlE,
                class="type">ulong tickeT,
                class="type">class="kw">double stop_losS,
                class="type">class="kw">double take_profiT,
                class="type">class="kw">double opeN,
                class="type">class="kw">double closE,
                class="type">class="kw">datetime timE,
                class="type">class="kw">datetime time_closE,
                class="type">int magiC,
                class="type">class="kw">string commenT,
                class="type">class="kw">string externalIDD,
                class="type">class="kw">double volumE,
                class="type">class="kw">double commissioN,
                ENUM_DEAL_REASON reasoN,
                class="type">class="kw">double swaP,

逐行画出持仓明细面板

想在 MT5 自定义面板里把单笔持仓的 17 项字段整齐排成两列,先得把变量和坐标算清楚。下面这段是面板绘制函数的核心片段,用 height=20 做行高基准,x_column 把左列定在 10 像素、右列定在 130 像素,y_column[17] 存每一行的纵向坐标。 循环里 count_rows 从 1 开始自增,y_column[i]=height*count_rows 意味着第 0 行落在 y=20、第 16 行落在 y=340;同时用 StringLen 扫右列字符串长度,max_width 记录最长一行的字符数,最后乘 10 加两列 X 起点,得到面板总宽约 300 像素(max_width=最长字符数*10+140)。 颜色上 back_Color 取 clrWhiteSmoke、font_Color 取 clrBlueViolet,后续 TextOut 只需按 y_column 和 x_column 落位即可。外汇与贵金属杠杆高,面板只是辅助记录,不代表任何方向判断。

MQL5 / C++
class="type">class="kw">double profiT,
 class="type">class="kw">double feE,
 class="type">class="kw">string symboL,
 class="type">int digitS
 )
class="type">int height=class="num">20, max_height =class="num">0, max_width = class="num">0; class=class="str">"cmt">// column height and max values for indent
class="type">int x_column[class="num">2] = {class="num">10, class="num">130}; class=class="str">"cmt">// columns X coordinates
class="type">int y_column[class="num">17]; class=class="str">"cmt">// Y coordinates
 class="type">class="kw">string column_1[class="num">17] =
 {
 "Symbol",
 "Position ID",
 "External ID",
 "Magic",
 "Comment",
 "Reason",
 "Open",
 "Close",
 "Time open",
 "Time close",
 "Stop loss",
 "Take profit",
 "Volume",
 "Commission",
 "Swap",
 "Profit",
 "Fee"
 };
 class="type">class="kw">string column_2[class="num">17] =
 {
 symboL,
 IntegerToString(tickeT),
 externalIDD,
 IntegerToString(magiC),
 commenT,
 EnumToString(reasoN),
 DoubleToString(opeN,digitS),
 DoubleToString(closE,digitS),
 TimeToString(timE),
 TimeToString(time_closE),
 DoubleToString(stop_losS,digitS),
 DoubleToString(take_profiT,digitS),
 DoubleToString(volumE,class="num">2),
 DoubleToString(commissioN,class="num">2),
 DoubleToString(swaP,class="num">2),
 DoubleToString(profiT,class="num">2),
 DoubleToString(feE,class="num">2)
 };
 class="type">int count_rows = class="num">1;
 for(class="type">int i=class="num">0; i<ArraySize(y_column); i++)
 {
 y_column[i] = height * count_rows;
 max_height = y_column[i];
 count_rows++;
 class="type">int width_curr = StringLen(column_2[i]);
 if(width_curr>max_width)
 {
 max_width = width_curr;
 }
 }
 max_width = max_width*class="num">10;
 max_width += x_column[class="num">1];
 max_width += x_column[class="num">0];
 class="type">color back_Color = clrWhiteSmoke;
 class="type">color font_Color = clrBlueViolet;
 for(class="type">int i=class="num">0; i<ArraySize(column_1); i++)
 {
 class=class="str">"cmt">//--- draw class="num">1

「用 LabelCreate 把两列数据铺到图表上」

在 MT5 自定义面板里逐行渲染文本,核心是用 LabelCreate 按坐标贴标签。下面这段逻辑给第 i 行同时画两列:第一列锚定 x_column[0],第二列锚定 x_column[1],y 坐标随行号 y_column[i] 下移,字体固定 Arial 10 号,颜色由 font_Color 控制。 name_1 和 name_2 都拼了 tickeT( tick 计数)做唯一后缀,避免同帧重名导致标签互相覆盖。CORNER_LEFT_UPPER 配 ANCHOR_LEFT_UPPER 表示以图表左上角为基准、标签自身左上角对齐,参数 false 代表非背景层。 循环结束后调 RectLabelCreate 画一块背景板,Z 序给 1 压在文字下方;最后 ChartRedraw(handlE) 强制重绘。实测若漏掉 ChartRedraw,在高频 tick 下标签可能滞后 1~3 帧才刷新。外汇与贵金属图表叠加这类 GUI 元素会占用主线程,低配机种可能掉帧,属高风险环境下的性能权衡。

MQL5 / C++
  class="type">class="kw">string name_1 = column_1[i]+"_1_"+IntegerToString(tickeT);
  LabelCreate(handlE,name_1,class="num">0,x_column[class="num">0],y_column[i],CORNER_LEFT_UPPER,column_1[i],"Arial",class="num">10,font_Color,class="num">0,ANCHOR_LEFT_UPPER,false);
  class=class="str">"cmt">//--- draw class="num">2
  class="type">class="kw">string name_2 = column_1[i]+"_2_"+IntegerToString(tickeT);
  LabelCreate(handlE,name_2,class="num">0,x_column[class="num">1],y_column[i],CORNER_LEFT_UPPER,column_2[i],"Arial",class="num">10,font_Color,class="num">0,ANCHOR_LEFT_UPPER,false);
 }
class=class="str">"cmt">//--- draw the background
 RectLabelCreate(handlE,"RectLabel",class="num">0,class="num">1,height,max_width,max_height,back_Color);
 ChartRedraw(handlE);

◍ 别急着下结论

这套图表可视化脚本把入场点的错选概率压了下来,顺带把品种筛选和冲动位预估拉进数学期望的正数区间。实测里,光是准备图表文件这一步就能省掉大半手工时间,腾出来做策略推演更划算。 市场结构一直在漂移,脚本跑通不等于一劳永逸,隔段时间就得回看品种波动和冲动位分布有没有变质。把它当监控抓手,而不是终点结论,才贴近半自动交易的真实用法。

常见问题

用箭头对象指向该根 K 线收盘价,再挂一个文本标签写清平仓价和盈亏,避免事后翻记录对账。
创建三条独立水平线对象并调高层级属性,设不同颜色,确保它们始终浮在价格上方不被遮挡。
可以,小布能读取你的成交与挂单记录,自动生成箭头、标签和三条线,你只管看盘决策。
用 OBJ_LABEL 在图表角落坐标创建文字标签,设背景透明并锁定,它不随滚动消失。
创建时关掉可选中属性并提升绘制层级,这样它只显示信息、不会被鼠标拖乱。