刚接触MQL5的朋友,是不是觉得语法比MQL4复杂很多?我刚开始从MT4转MT5时,也踩了不少坑,尤其是对象指针和事件处理这块。今天结合自己实际写EA的经验,分享几个最基础但容易出错的点,
先说一个最关键的误区:MQL5里没有MQL4那种全局变量数组,所有数据都需要通过结构体或类来管理。我第一次写趋势跟踪EA时,想把多个开仓条件存成数组,结果编译直接报错。后来才明白,MQL5强制要求用 类对象或结构体 来封装数据,比如用CArrayObj来动态管理订单。新手别急着写复杂逻辑,先搞懂怎么定义结构体:
struct TradeSignal {
double entryPrice;
double stopLoss;
double takeProfit;
datetime signalTime;
};
然后通过TradeSignal signals[]数组来存储,这样在OnTick里调用时才不会乱。
接下来是EA的执行流程。MQL5的入口函数是 OnTick(),但注意它和MT4不同,不会自动处理订单历史。我踩过的一个坑是:用OrderSend直接下单后,忘记检查返回的ticket值,结果EA在回测时重复开仓。正确的做法是:
这里特别注意:MQL5的OrderSend返回的是 ulong类型 的ticket,不是int。我第一次用int接收,编译没报错但运行时一直返回0,排查了两天才发现是类型不匹配。
再说一个新手容易忽略的点:MQL5的 指标句柄 概念。比如你想用均线判断趋势,不能像MQL4那样直接iMA(NULL,0,14,0,MODE_SMA,PRICE_CLOSE),而是要先创建句柄:
int maHandle = iMA(_Symbol, PERIOD_CURRENT, 14, 0, MODE_SMA, PRICE_CLOSE);
double maBuffer[];
ArraySetAsSeries(maBuffer, true);
CopyBuffer(maHandle, 0, 0, 3, maBuffer);
这里 ArraySetAsSeries 必须设为true,否则数组索引0是最新数据,容易搞反方向。我刚开始做欧美日内策略时,就因为没设置这个,导致信号延迟了一根K线,回测结果直接翻车。
再说调试工具要用好。MQL5的 Print() 输出在“专家”标签页,但别滥用。我习惯在关键位置打印当前时间、价格和信号值,比如:
if(maBuffer[0] > maBuffer[1] && maBuffer[1] > maBuffer[2]) {
Print("上升趋势确认,当前价格: ", SymbolInfoDouble(_Symbol, SYMBOL_BID));
}
这样跑回测时能快速定位逻辑漏洞。另外,建议用 Strategy Tester 里的“可视化模式”单步执行,配合Print输出,比单纯看回测报告直观得多。
暂时想到这些基础点。你在写第一个MQL5 EA时,有没有遇到什么卡住的地方?比如指针传递或者订单修改报错?欢迎贴代码片段,我帮你看看具体问题。
先说一个最关键的误区:MQL5里没有MQL4那种全局变量数组,所有数据都需要通过结构体或类来管理。我第一次写趋势跟踪EA时,想把多个开仓条件存成数组,结果编译直接报错。后来才明白,MQL5强制要求用 类对象或结构体 来封装数据,比如用CArrayObj来动态管理订单。新手别急着写复杂逻辑,先搞懂怎么定义结构体:
struct TradeSignal {
double entryPrice;
double stopLoss;
double takeProfit;
datetime signalTime;
};
然后通过TradeSignal signals[]数组来存储,这样在OnTick里调用时才不会乱。
接下来是EA的执行流程。MQL5的入口函数是 OnTick(),但注意它和MT4不同,不会自动处理订单历史。我踩过的一个坑是:用OrderSend直接下单后,忘记检查返回的ticket值,结果EA在回测时重复开仓。正确的做法是:
- 在OnTick开头用 PositionSelect(_Symbol) 检查当前持仓
- 如果无持仓,再用 OrderSend() 并赋值给ulong ticket变量
- 用 HistorySelect(0, TimeCurrent()) 加载历史订单,避免重复触发
这里特别注意:MQL5的OrderSend返回的是 ulong类型 的ticket,不是int。我第一次用int接收,编译没报错但运行时一直返回0,排查了两天才发现是类型不匹配。
再说一个新手容易忽略的点:MQL5的 指标句柄 概念。比如你想用均线判断趋势,不能像MQL4那样直接iMA(NULL,0,14,0,MODE_SMA,PRICE_CLOSE),而是要先创建句柄:
int maHandle = iMA(_Symbol, PERIOD_CURRENT, 14, 0, MODE_SMA, PRICE_CLOSE);
double maBuffer[];
ArraySetAsSeries(maBuffer, true);
CopyBuffer(maHandle, 0, 0, 3, maBuffer);
这里 ArraySetAsSeries 必须设为true,否则数组索引0是最新数据,容易搞反方向。我刚开始做欧美日内策略时,就因为没设置这个,导致信号延迟了一根K线,回测结果直接翻车。
再说调试工具要用好。MQL5的 Print() 输出在“专家”标签页,但别滥用。我习惯在关键位置打印当前时间、价格和信号值,比如:
if(maBuffer[0] > maBuffer[1] && maBuffer[1] > maBuffer[2]) {
Print("上升趋势确认,当前价格: ", SymbolInfoDouble(_Symbol, SYMBOL_BID));
}
这样跑回测时能快速定位逻辑漏洞。另外,建议用 Strategy Tester 里的“可视化模式”单步执行,配合Print输出,比单纯看回测报告直观得多。
暂时想到这些基础点。你在写第一个MQL5 EA时,有没有遇到什么卡住的地方?比如指针传递或者订单修改报错?欢迎贴代码片段,我帮你看看具体问题。