可视化!类似于 R 语言
📘

可视化!类似于 R 语言 "plot (绘图)" 的 MQL5 图形库·进阶篇

第 2/2 篇

「用函数指针几行画出曲线」

MQL5 里函数指针只能绑全局或静态函数,且签名必须严格对齐。我们这套绘图接口把 CurveFunction 定义成接收 double 参数、返回 double 的形式,借它就能把任意数学函数直接变成图上的线。 构造曲线时真正要盯死的是三个量:起始 from、终止 to、步长 step。步长越小,采样点越密,曲线越顺;步长一大,关键形态可能直接被跳过。数据先用 CurveAdd() 灌进图形对象,再靠 CurvePlot() 或 CurvePlotAll() 刷出来。 下面这段直接画一条抛物线,左右两段用不同步长对比:左边 from=-5、to=0、step=1,右边 from=0、to=5、step=0.2。 [CODE] #include <Graphics\Graphic.mqh> //+------------------------------------------------------------------+

//抛物线

//+------------------------------------------------------------------+ double Parabola(double x) { return MathPow(x,2); } //+------------------------------------------------------------------+

//脚本的 start 函数

//+------------------------------------------------------------------+ void OnStart() { double from1=-5; double to1=0; double step1=1; double from2=0; double to2=5; double step2=0.2; CurveFunction function = Parabola; CGraphic graph; graph.Create(0, "Graph", 0, 30, 30, 780, 380); graph.CurveAdd(function,from1,to1,step1,CURVE_LINES); graph.CurveAdd(function,from2,to2,step2,CURVE_LINES); graph.CurvePlotAll(); graph.Update(); } [/CODE] 逐行拆解:第1行引图形库;Parabola 函数返回 x 平方,即抛物线本体;OnStart 里先定两段区间和步长,step1=1 较粗、step2=0.2 较细;CurveFunction 把 Parabola 当指针传进去;CGraphic 建一块 780×380 的画布;两次 CurveAdd 分别按两段参数加曲线;CurvePlotAll 一次性绘制;Update 刷新界面。 断点最容易翻车。库能处理坐标为正负无穷或 NaN 的函数,但若步长没设好,断点可能恰好落在采样间隙里。实测双曲线在 [-5.0, 5.0] 区间:步长 0.7 时断点被跳过,画出来几乎不像双曲线;步长收到 0.1 才正常显形。外汇与贵金属图表虽不直接画数学断点,但自定义指标里类似采样遗漏会让信号变形,属高风险操作误区。 除零错误有两种收拾法:在 metaeditor.ini 加 [Experts] FpNoZeroCheckOnDivision=1 关掉运行时检查;或更稳妥——在函数里主动判断分母并回有效值。后者的宏写法参考附带的 3Functions.mq5 与 bat.mq5,建议直接抄进自己的指标原型里验证。

MQL5 / C++
class="macro">#include <Graphics\Graphic.mqh>
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 抛物线                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">double Parabola(class="type">class="kw">double x) { class="kw">return MathPow(x,class="num">2); }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 脚本的 start 函数                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   class="type">class="kw">double from1=-class="num">5;
   class="type">class="kw">double to1=class="num">0;
   class="type">class="kw">double step1=class="num">1;

   class="type">class="kw">double from2=class="num">0;
   class="type">class="kw">double to2=class="num">5;
   class="type">class="kw">double step2=class="num">0.2;

   CurveFunction function = Parabola;

   CGraphic graph;
   graph.Create(class="num">0, "Graph", class="num">0, class="num">30, class="num">30, class="num">780, class="num">380);
   graph.CurveAdd(function,from1,to1,step1,CURVE_LINES);
   graph.CurveAdd(function,from2,to2,step2,CURVE_LINES);
   graph.CurvePlotAll();
   graph.Update();
  }

◍ 用 GraphPlot 把数组直接甩上图

MQL5 图形库提供了一批 GraphPlot() 全局函数,作用和 R 或 Python 里的 plot 类似:丢进去数据就能在图表上画出对象,返回的是图表对象名。它一共有 10 种重载,能在一张图上用不同样式画线,你只需要选一种合适的数据传入方式。 最省事的办法是直接传两个数组。下面这段 OnStart 里 x 和 y 各 10 个点,调用 GraphPlot(x,y) 就能出图,等效于 R 里 c() 构造向量再 plot(x,y)。它支持三种主显示模式:点状、线条、直方图。 [CODE]void OnStart () { double x[]={- 10 ,- 4 ,- 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }; double y[]={- 5 , 4 ,- 10 , 23 , 17 , 18 ,- 9 , 13 , 17 , 4 }; GraphPlot(x,y); }[/CODE] 和 R 的 plot 不同,GraphPlot 只收关键参数:曲线数据(四种格式之一)、绘制类型(默认 CURVE_POINTS)、对象名(默认 NULL)。每个图形都是「图表对象 + 图形资源」配对,资源名就是对象名前加 "::",比如对象叫 SomeGraphic,资源就是 ::SomeGraphic。 锚点和画布大小是写死的:固定锚点 x=65、y=45,宽取图表宽 60%、高取 65%。所以图表窗口若小于 65×45,函数直接不干活。想自定义画布,就先建一个 OBJ_BITMAP_LABEL 对象并 ResourceCreate 同名资源,把名字传给 GraphPlot,以后就不用每次写对象名。 下面例子把画布钉在左上角(0,0),尺寸锁成 750×350,并改画线条: [CODE]void OnStart () { //--- 在图表上创建对象和动态资源 string name= "Graphic" ; long x= 0 ; long y= 0 ; int width= 750 ; int height= 350 ; int data[]; ArrayResize (data,width*height); ZeroMemory (data); ObjectCreate ( 0 ,name, OBJ_BITMAP_LABEL , 0 , 0 , 0 ); ResourceCreate ( "::" +name,data,width,height, 0 , 0 , 0 , COLOR_FORMAT_XRGB_NOALPHA ); ObjectSetInteger ( 0 ,name, OBJPROP_XDISTANCE ,x); ObjectSetInteger ( 0 ,name, OBJPROP_YDISTANCE ,y); ObjectSetString ( 0 ,name, OBJPROP_BMPFILE , "::" +name); //--- 创建 x 和 y 数组 double arr_x[]={- 10 ,- 4 ,- 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }; double arr_y[]={- 5 , 4 ,- 10 , 23 , 17 , 18 ,- 9 , 13 , 17 , 4 }; //--- 绘制 x 和 y 数组 GraphPlot(arr_x,arr_y,CURVE_LINES); }[/CODE] 在 MT5 里跑这段代码,能看到 10 个点连成线,画布不再依赖图表比例。外汇和贵金属图表上叠加这类自定义图形时,注意窗口缩放可能让锚点偏移,属于高风险环境下的视觉误差,验证时建议固定图表尺寸。

MQL5 / C++
class="type">void OnStart()   {    class="type">class="kw">double x[]={- class="num">10 ,- class="num">4 ,- class="num">1 , class="num">2 , class="num">3 , class="num">4 , class="num">5 , class="num">6 , class="num">7 , class="num">8 };    class="type">class="kw">double y[]={- class="num">5 , class="num">4 ,- class="num">10 , class="num">23 , class="num">17 , class="num">18 ,- class="num">9 , class="num">13 , class="num">17 , class="num">4 };    GraphPlot(x,y);   }
class="type">void OnStart()   { class=class="str">"cmt">//--- 在图表上创建对象和动态资源    class="type">class="kw">string name= "Graphic" ;    class="type">long x= class="num">0 ;    class="type">long y= class="num">0 ;    class="type">int width= class="num">750 ;    class="type">int height= class="num">350 ;    class="type">int data[];    ArrayResize(data,width*height);    ZeroMemory(data);    ObjectCreate( class="num">0 ,name, OBJ_BITMAP_LABEL , class="num">0 , class="num">0 , class="num">0 );    ResourceCreate( "::" +name,data,width,height, class="num">0 , class="num">0 , class="num">0 , COLOR_FORMAT_XRGB_NOALPHA );    ObjectSetInteger( class="num">0 ,name, OBJPROP_XDISTANCE ,x);    ObjectSetInteger( class="num">0 ,name, OBJPROP_YDISTANCE ,y);    ObjectSetString( class="num">0 ,name, OBJPROP_BMPFILE , "::" +name); //--- 创建 x 和 y 数组    class="type">class="kw">double arr_x[]={- class="num">10 ,- class="num">4 ,- class="num">1 , class="num">2 , class="num">3 , class="num">4 , class="num">5 , class="num">6 , class="num">7 , class="num">8 };    class="type">class="kw">double arr_y[]={- class="num">5 , class="num">4 ,- class="num">10 , class="num">23 , class="num">17 , class="num">18 ,- class="num">9 , class="num">13 , class="num">17 , class="num">4 }; //--- 绘制 x 和 y 数组    GraphPlot(arr_x,arr_y,CURVE_LINES);   }

把MT5图表变成统计画板

标准库里的统计模块能直接调用多种概率分布函数,每个分布都自带样本图与取数代码。官方把这些示例塞在 MQL5.zip 里,解压后丢进 MQL5\Scripts 就能跑,不用自己写底层。 关键一步是先干掉价格图表本身:用 CHART_SHOW 属性把主图隐藏,窗口就空成一块纯画板,任意复杂的图形资源对象都能往上叠。对外汇、贵金属这类高波动品种做分布验证时,先关图再画,能避免K线干扰视觉判断。 之前有篇讲莫斯科交易所期货扩散策略的文章,就是借图形库把训练样本和 Alglib 的线性回归结果直接绘在同一窗口。思路可平移到 MT5:你本地解包脚本后,改两行参数就可能复现正态、卡方等分布的样本形态。

MQL5 / C++
class=class="str">"cmt">//--- 禁用价格图表
ChartSetInteger(class="num">0, CHART_SHOW, class="kw">false);

「收束」

这套图形库把科学绘图压到了极低成本:5 种图形显示类型、10 种行情图表类型,X/Y 轴自动缩放和按结构自动配色都在底层处理完了。线条平滑给了标准抗锯齿和 Bresenham 两种选法,还能用 x[]、y[] 数组一行出图,甚至挂函数指针动态绘制。 对做价格行为量化的人而言,重点不是‘画图好看’,而是能直接在 MT5 终端里跑 ALGLIB、模糊逻辑和统计函数,把计算结果就地可视化,不必再导去第三方包。外汇和贵金属波动大、杠杆高,这类图形仅用于辅助研判,不替代风控。 附带的 3Functions.mq5、Bat.mq5、IrisSample.mq5 和 iris.txt 可直接丢进 MT5 编译跑通,验证上面说的单行绘图和数组映射是否如描述般顺手。

常见问题

用 GraphPlot 类把数组传给绘图函数即可,几行代码就能把序列甩上图表,省去手动循环画线。
把曲线计算逻辑包成函数指针,传给绘图库的回调参数,切换时改指针指向即可,不用重写绘图代码。
可以,小布能读取你的交易记录并生成统计画板,自动输出盈亏分布曲线,你直接看结论就行。
多半是没绑定时间轴索引,绘图时需把数组下标映射到K线序号,并锁定右坐标跟随品种报价。
会,绘图前先过滤 EMPTY_VALUE 和极端值,否则曲线会断裂或抛出数组越界错误。