利用 EX5 库来推动您的项目开发(基础篇)
📘

利用 EX5 库来推动您的项目开发(基础篇)

第 1/3 篇

◍ 用 EX5 库给 MT5 项目提速

在 MT5 里做指标或 EA 开发,把可复用的逻辑编译成 EX5 库(.ex5 格式的 library),能让主程序体积更小、迭代更快。库函数通过 #import 调用,编译期就绑定符号,比运行时动态加载更稳。 社区里一篇 2014 年 1 月 9 日发布的 EX5 库示例帖,累计浏览 2803、评论 21,说明这类底层复用方案在早期就有真实需求。现在开 MT5 按 F4 进 MetaEditor,新建 Library 工程编译出 ex5,再在主 EA 里 #import "yourlib.ex5" 即可直接调函数。 外汇与贵金属品种波动大、杠杆高,任何基于库的自动化逻辑都先在策略测试器用历史数据跑一遍,再上模拟盘验证,实盘风险自行承担。

把算法塞进 ex5 库里卖

做过协作开发的人都清楚,把核心逻辑直接摊在 mq5 源码里,别人拿到就能照抄。把类与函数的实现编译进 .ex5 库文件,等于把专有算法锁进二进制,只暴露接口——你既能拿去跟其他开发者搭共同项目,也能在圈子里宣传变现,而对方摸不到内部细节。 MetaQuotes 这几年一直在给 ex5 库加直接继承的能力,不是纸上规划,是已经能跑的特性。本篇就从这个点切入,不绕弯子,直接看怎么落地。 系列后面会拆到函数导入导出、类隐藏实施、库内变量初始化、导出类继承,以及最终怎么把 ex5 库发出去。这一节先建立认知:库的核心价值是‘可复用且不可见’。

「把函数扔进 ex5 给别人用」

想让一段 MQL5 逻辑被别的 EA、脚本或指标直接调用,核心就三件事:源文件扩展名必须是 .mq5(不是 .mqh),文件头写 #property library,导出函数名后面挂一个 export 关键字。编译完得到 library.ex5,别的程序就能通过 #import 把它拉进来。 编译器默认只去 MQL5\Libraries 翻 .ex5。若库文件丢在 Include\MyLib 或 Experts 目录下,就得在 #import 里写相对路径,例如 "..\Include\MyLib\library.ex5",否则链接阶段直接报错。 函数不仅能导进目标 .mq5,也能塞进 .mqh 当公共头,团队复用更干净。下面这段是最朴素的导出+导入示范,开 MT5 建两个文件就能跑通。 下面 SetEdit 是实际画图库里的一个导出函数模板,参数涵盖了角落锚点、坐标偏移、尺寸和字体——挂了 export 后,Spiro.mq5 那边 #import 进来就能在图表上直接生成编辑框对象,EA 启动后对象出现在图表上方。外汇与贵金属自动化涉及高风险,复用库前先在策略测试器跑一遍空图验证对象创建是否如预期。

MQL5 / C++
Example class="num">1. Let us create a function to be used in other programs
class=class="str">"cmt">//--- library.mq5
class="macro">#class="kw">property library
class="type">int libfunc(class="type">int a, class="type">int b) class="kw">export
{
  class="type">int c=a+b;
  Print("a+b="+class="type">class="kw">string(с));
  class="kw">return(с);
}
Example class="num">2. We will use the class="kw">export function libfunc() in our script
class=class="str">"cmt">//--- uses.mq5
class="macro">#class="kw">import "library.ex5"
  class="type">int libfunc(class="type">int a, class="type">int b);
class="macro">#class="kw">import
class="type">void OnStart()
{
  libfunc(class="num">1, class="num">2);
}
class="macro">#class="kw">import "..\Include\MyLib\library.ex5" class=class="str">"cmt">// the file is located in the MQL5\Include\MyLib folder
class="macro">#class="kw">import "..\Experts\library.ex5" class=class="str">"cmt">// the file is located in the MQL5\Experts\ folder
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| SetEdit                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void SetEdit(class="type">long achart,class="type">class="kw">string name,class="type">int wnd,class="type">class="kw">string text,class="type">color txtclr,class="type">color bgclr,class="type">color brdclr,
             class="type">int x,class="type">int y,class="type">int dx,class="type">int dy,class="type">int corn=class="num">0,class="type">int fontsize=class="num">8,class="type">class="kw">string font="Tahoma",class="type">bool ro=false) class="kw">export
  {
  ObjectCreate(achart,name,OBJ_EDIT,wnd,class="num">0,class="num">0);
  ObjectSetInteger(achart,name,OBJPROP_CORNER,corn);
  ObjectSetString(achart,name,OBJPROP_TEXT,text);
  ObjectSetInteger(achart,name,OBJPROP_COLOR,txtclr);
  ObjectSetInteger(achart,name,OBJPROP_BGCOLOR,bgclr);
  ObjectSetInteger(achart,name,OBJPROP_BORDER_COLOR,brdclr);
  ObjectSetInteger(achart,name,OBJPROP_FONTSIZE,fontsize);
  ObjectSetString(achart,name,OBJPROP_FONT,font);
  ObjectSetInteger(achart,name,OBJPROP_XDISTANCE,x);
  ObjectSetInteger(achart,name,OBJPROP_YDISTANCE,y);
  ObjectSetInteger(achart,name,OBJPROP_XSIZE,dx);
  ObjectSetInteger(achart,name,OBJPROP_YSIZE,dy);
  ObjectSetInteger(achart,name,OBJPROP_SELECTABLE,false);
  ObjectSetInteger(achart,name,OBJPROP_READONLY,ro);
  ObjectSetInteger(achart,name,OBJPROP_BORDER_TYPE,class="num">0);
  ObjectSetString(achart,name,OBJPROP_TOOLTIP,"");
  }
Example class="num">3. Using imported functions
class=class="str">"cmt">//--- Spiro.mq5 – the target file of the Expert Advisor
class=class="str">"cmt">//--- importing some graphics functions

◍ 用外部模块给图表挂上参数输入框

想在 MT5 图表上直接手填螺线半径、偏移和精度,而不是改代码重编译,就得借一个编译好的 Graph.ex5 库。通过 #import 把 SetLabel、SetEdit、SetButton、HideChart 四个接口拉进 EA,图表交互层的活儿就外包出去了。 HideChart(0, clrWhite) 在 OnInit 里先把主图背景刷成白底,sID 赋值为 "spiro." 作为对象名前缀,避免和多图表上的其他脚本撞名。随后 DrawParam 一口气摆出四组标签+编辑框:大半径 R 默认 100、小半径 r 默认 30、中心距 D 默认 40、角度步长 Alfa 默认 0.04。 坐标写法是写死的——比如 R 的标签在 x=10,y=13,输入框在 x=40,y=10,宽 50 高 20。你复制去用的时候,若想加一组参数,照着 SetLabel 加文字、SetEdit 给初值的节奏往后叠 y 坐标(每次 +25 左右)就能扩。外汇和贵金属图表加载此类 EA 属高风险操作,参数误填可能导致图形渲染异常。

MQL5 / C++
class="macro">#class="kw">import "Graph.ex5"
  class="type">void SetLabel(class="type">long achart, class="type">class="kw">string name, class="type">int wnd, class="type">class="kw">string text, class="type">color clr,
class="type">int x, class="type">int y, class="type">int corn=class="num">0, class="type">int fontsize=class="num">8, class="type">class="kw">string font="Tahoma");
  class="type">void SetEdit(class="type">long achart, class="type">class="kw">string name, class="type">int wnd, class="type">class="kw">string text, class="type">color txtclr, class="type">color bgclr, class="type">color brdclr, class="type">int
x, class="type">int y, class="type">int dx, class="type">int dy, class="type">int corn=class="num">0, class="type">int fontsize=class="num">8, class="type">class="kw">string font="Tahoma", class="type">bool ro=false);
  class="type">void SetButton(class="type">long achart, class="type">class="kw">string name, class="type">int wnd, class="type">class="kw">string text, class="type">color txtclr, class="type">color bgclr,
class="type">int x, class="type">int y, class="type">int dx, class="type">int dy, class="type">int corn=class="num">0, class="type">int fontsize=class="num">8, class="type">class="kw">string font="Tahoma", class="type">bool state=false);
  class="type">void HideChart(class="type">long achart, class="type">color BackClr);
class="macro">#class="kw">import
class=class="str">"cmt">//--- prefix for chart objects
class="type">class="kw">string sID;
class="type">void OnInit()
{
  HideChart(class="num">0, clrWhite);
  sID="spiro.";
  DrawParam();
}
class="type">void DrawParam()
{
  class="type">color bgclr=clrWhite, clr=clrBlack;
class=class="str">"cmt">//--- bigger radius
  SetLabel(class="num">0, sID+"stR.", class="num">0, "R", clr, class="num">10, class="num">10+class="num">3);
  SetEdit(class="num">0, sID+"R.", class="num">0, "class="num">100", clr, bgclr, clr, class="num">40, class="num">10, class="num">50, class="num">20);
class=class="str">"cmt">//--- smaller radius
  SetLabel(class="num">0, sID+"str.", class="num">0, "r", clr, class="num">10, class="num">35+class="num">3);
  SetEdit(class="num">0, sID+"r.", class="num">0, "class="num">30", clr, bgclr, clr, class="num">40, class="num">35, class="num">50, class="num">20);
class=class="str">"cmt">//--- distance to the center
  SetLabel(class="num">0, sID+"stD.", class="num">0, "D", clr, class="num">10, class="num">60+class="num">3);
  SetEdit(class="num">0, sID+"D.", class="num">0, "class="num">40", clr, bgclr, clr, class="num">40, class="num">60, class="num">50, class="num">20);
class=class="str">"cmt">//--- drawing accuracy
  SetLabel(class="num">0, sID+"stA.", class="num">0, "Alfa", clr, class="num">10, class="num">85+class="num">3);
  SetEdit(class="num">0, sID+"A.", class="num">0, "class="num">0.04", clr, bgclr, clr, class="num">40, class="num">85, class="num">50, class="num">20);
}

把控件摆上图表坐标

在面板收尾阶段,真正决定交易者能不能一眼用上的,是控件落点。下面这段把标签、输入框和按钮按像素坐标钉在图表左上区域,坐标体系以图表窗口左上角为 (0,0),y 轴向下递增。 标签放在 x=10、y=113 处,显示『Rotor』字样,字号 10,颜色用 clr 变量;紧挨其右的编辑框从 x=40 起、宽 50 高 20,默认填『10』,用来接收转子周期参数。 按钮『DRAW』定位在 x=39、y=135,尺寸 51×20,底色 bgclr、文字色 clr,点击后触发绘制逻辑。外汇与贵金属图表上叠这类控件需注意:高频重绘可能拖累老机型 MT5 的帧率,建议先在模拟盘验证响应延迟。

MQL5 / C++
  SetLabel(class="num">0, sID+"stN.", class="num">0, "Rotor", clr, class="num">10, class="num">110+class="num">3);
  SetEdit(class="num">0, sID+"N.", class="num">0, "class="num">10", clr, bgclr, clr, class="num">40, class="num">110, class="num">50, class="num">20);
class=class="str">"cmt">//--- draw button
  SetButton(class="num">0, sID+"draw.", class="num">0, "DRAW", bgclr, clr, class="num">39, class="num">135, class="num">51, class="num">20);
}

常见问题

在开发环境里把函数编译成 ex5 库文件,只导出接口头文件给对方,对方引用头文件即可调用,源码不会泄露。
通常是头文件里的函数声明和库里导出名不一致,或库没放到对方项目的依赖目录。核对导出修饰和路径即可。
小布可以读取你的项目结构,指出适合抽离的函数并给出 ex5 库拆分建议,你照着改就能少写很多重复代码。
外部模块本身不挂输入框,需要在调用它的主程序里声明 input 参数,再由主程序把值传进库函数。
用图表的可见区域宽高做比例换算,先把控件锚点设成相对比例再乘像素尺寸,比写死坐标稳得多。