OrderSend()函数是任何MQL4专家顾问的心脏。然而许多进阶用户仍然误用其参数或忽略返回值验证,导致回测隐藏偏差和实盘交易失败。本文涵盖生产级用法、错误处理模式及滑点控制。1. 函数原型与各参数详解
``
cpp
int OrderSend(
string symbol, // 品种名称
int cmd, // 交易指令
double volume, // 手数
double price, // 订单价格
int slippage, // 允许滑点(点数)
double stoploss, // 止损价
double takeprofit, // 止盈价
string comment, // 订单注释
int magic, // EA标识码
datetime expiration, // 挂单有效期
color arrow_color // 图表箭头颜色
);
`
关键细节:slippage以点为单位,而非大点。对于5位报价经纪商,10个点=1个大点。使用Point转换:滑点数 = 10 * Point。
2. 返回值与验证逻辑
OrderSend()成功返回订单号,失败返回-1。切勿假定成功。立即检查订单号并调用GetLastError()。
生产模式:
`cpp
int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, slippage, stopLoss, takeProfit, "EA", magic, 0, clrNONE);
if(ticket < 0) {
int error = GetLastError();
Print("OrderSend失败。错误码:", error, " | ", ErrorDescription(error));
// 可选:带指数退避的重试逻辑
return;
}
`
常见错误码:130(无效止损/止盈)、148(订单过多)、146(交易上下文繁忙)。对于错误146,使用Sleep(50)并最多重试5次。
3. 滑点数学模型
滑点不只是一个安全缓冲,它影响成交概率。对于市价单,成交条件:
卖出订单:Ask - price <= slippage Point
买入订单:price - Bid <= slippage Point
根据历史数据计算统计安全的滑点:
slippage = max(3, ceil( (avg_slippage + 2 * stddev_slippage) / Point ))
其中avg_slippage和stddev_slippage来自分笔数据。
4. 在回测中用OrderSend避免未来函数
常见错误:在引用Close[0]的循环内使用OrderSend()而不验证K线是否完整。这会产生前视偏差。正确做法:
`cpp
static datetime lastBarTime = 0;
if(Time[0] != lastBarTime) {
lastBarTime = Time[0];
// 仅在新K线开仓,避免日内未来数据泄露
OrderSend(...);
}
`
这确保了回测准确性,与实时K线收盘对齐。
5. 挂单与有效期
MQL4允许为挂单(OP_BUYLIMIT、OP_SELLLIMIT、OP_BUYSTOP、OP_SELLSTOP)设置expiration参数。有效期计算公式:
expiration = TimeCurrent() + 有效秒数
最大有效期为当前时间后1个月。超出范围的值会被静默截断。
带自动取消的示例:
`cpp
datetime expiry = TimeCurrent() + 3600; // 1小时
int ticket = OrderSend(Symbol(), OP_BUYLIMIT, 0.1, buyLimitPrice, 3, 0, 0, "Limit", magic, expiry, clrBlue);
`
6. OrderSend与OrderSendAsync(MQL5提及)
MQL4没有异步下单。每次OrderSend()都会阻塞直到经纪商响应或超时。MQL5中存在OrderSendAsync()但语义不同。迁移到MQL5时,用CTrade::PositionOpen()替代OrderSend(),详见跨平台迁移说明。
7. 对优化性能的影响
在EA参数优化期间,如果每次调用都包含大量计算,OrderSend()会成为瓶颈。将止损/止盈的计算移到调用外部:
`cpp
double sl = Ask - stopLossPoints Point;
double tp = Ask + takeProfitPoints Point;
int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, slippage, sl, tp, comment, magic, 0, clrNONE);
`
减少OrderSend`上下文内的运算可使MT4优化速度提升高达30%。参考来源