有朋友私信问我,说MQL5的类库到底怎么搞,能不能别整那些官方文档里绕来绕去的说法。确实,MT4上写EA习惯了面向过程,一转到MT5的面向对象,总觉得别扭。今天咱就聊聊这个,我拿自己最近写的一个资金管理模块当例子,说说怎么从零搭一个能复用的类库。
先说个最坑的地方,MQL5里没有析构函数重载,也没有真正的多态继承链,你要是拿C++那套思维硬套,编译能过但跑起来就莫名崩。我踩过的第一个坑就是构造函数里开了文件句柄,结果EA在回测中反复初始化,句柄泄漏直接把内存干爆了。解决方案是把资源释放放在OnDeinit里手动调,别指望类自己清理。
具体步骤我理一下,你照着搭就行:
实操里有个参数特别注意,类库里的数组动态分配要用ArrayResize(),但每次调用前必须清零,不然历史数据会残留。我一开始偷懒直接复用,回测结果前三年正常,后面突然曲线变直线,查了两天才发现是数组越界没报错,数据被覆盖了。
另外,VPS部署MQL5类库时,记得把编译选项里的“允许DLL导入”关掉,我有个EA在本地跑得好好的,放VPS上就报“cannot call function”,最后发现是VPS环境策略组禁了DLL。类库本身没问题,纯粹环境配置坑。
还有一个容易忽略的,用类库时别在全局作用域里new对象,MQL5的全局对象初始化顺序不保证,我试过两个类互相引用,结果一个先初始化另一个还没建好,直接崩。正确做法是在OnInit()里用指针new,然后OnDeinit里delete,配合CPointer模板类管理生命周期。
最后问一句,你们在写MQL5类库的时候,有没有遇到过继承类里重载运算符失效的情况?我这边试了重载operator=给自定义结构体,结果编译过了但运行时赋值就是没反应,后来只能用Copy()函数替代,有碰到过的朋友说说你们咋解决的?🤔
先说个最坑的地方,MQL5里没有析构函数重载,也没有真正的多态继承链,你要是拿C++那套思维硬套,编译能过但跑起来就莫名崩。我踩过的第一个坑就是构造函数里开了文件句柄,结果EA在回测中反复初始化,句柄泄漏直接把内存干爆了。解决方案是把资源释放放在OnDeinit里手动调,别指望类自己清理。
具体步骤我理一下,你照着搭就行:
- 第一步,定义基础抽象类,比如[CBaseSignal],只留纯虚函数virtual int Calculate() = 0,这样后面加RSI、MACD信号类都能继承。
- 第二步,写派生类时,所有成员变量初始化必须放在构造函数初始化列表,别在函数体里赋值,否则多线程回测下状态会乱。
- 第三步,类库内部通信用事件标志位而不是直接调用,比如信号类算完置个m_signalReady,资金管理类轮询这个标志,这样解耦后调试方便太多。
实操里有个参数特别注意,类库里的数组动态分配要用ArrayResize(),但每次调用前必须清零,不然历史数据会残留。我一开始偷懒直接复用,回测结果前三年正常,后面突然曲线变直线,查了两天才发现是数组越界没报错,数据被覆盖了。
另外,VPS部署MQL5类库时,记得把编译选项里的“允许DLL导入”关掉,我有个EA在本地跑得好好的,放VPS上就报“cannot call function”,最后发现是VPS环境策略组禁了DLL。类库本身没问题,纯粹环境配置坑。
还有一个容易忽略的,用类库时别在全局作用域里new对象,MQL5的全局对象初始化顺序不保证,我试过两个类互相引用,结果一个先初始化另一个还没建好,直接崩。正确做法是在OnInit()里用指针new,然后OnDeinit里delete,配合CPointer模板类管理生命周期。
最后问一句,你们在写MQL5类库的时候,有没有遇到过继承类里重载运算符失效的情况?我这边试了重载operator=给自定义结构体,结果编译过了但运行时赋值就是没反应,后来只能用Copy()函数替代,有碰到过的朋友说说你们咋解决的?🤔
