在讲解下单函数之前,我们先了解下单流程。在EA程序中提交一个交易订单,通常需要经过以下准备步骤,确定好所有必要信息:
- 订单类型:确定是买单 (Buy) 还是卖单 (Sell),是市价单还是挂单,如果是挂单,是止损挂单 (Stop) 还是限价挂单 (Limit)
- 交易品种:确定要交易哪个货币对。通常是EA当前所附加的图表对应的品种。
- 交易手数:确定下单量。可以是固定的手数,也可以是根据资金管理规则动态计算得出。
- 开仓价格:
- 市价单:通常使用当前的Bid或Ask价格。
- 挂单:必须指定一个具体的触发价格,该价格需要满足与当前市场价格有最小距离的要求(由经纪商设定,可通过
MarketInfo(Symbol(), MODE_STOPLEVEL)
查询),并且其位置(高于或低于当前价)必须符合所选挂单类型的规则。
- 止损价格:设定风险控制的止损位。可以是预设的固定价格,某个技术指标的计算值,距离开仓价固定点数,或者是通过风险管理算法动态计算的价格。止损可以在提交订单时一同设置,也可以在订单成交后通过修改订单的方式添加。
- 止盈价格:设定盈利目标位。通常是距离开仓价固定点数,但也可以基于其他逻辑计算。止盈同样可以在下单时设置,或之后再添加。
- 订单标识:
- 订单注释:可选的文本信息,会显示在交易终端的订单列表中,可用于记录下单原因等。
- 魔术数字:一个整数值,强烈建议使用。它用于区分由不同EA或同一EA的不同策略所下的订单,是管理订单的关键。
- 订单到期时间:对于挂单,如果经纪商支持且策略需要,可以设置一个可选的到期时间。
OrderSend() 函数
EA中用于执行开仓和平仓操作的核心函数是 OrderSend()
。其完整的语法结构如下:
int OrderSend(
string symbol, // 交易品种名称 ("EURUSD")
int cmd, // 订单类型 (OP_BUY, OP_SELL)
double volume, // 交易手数
double price, // 开仓价格 (市价单用 Ask/Bid, 挂单用指定价)
int slippage, // 最大允许滑点
double stoploss, // 止损价格 (0 表示不设置)
double takeprofit, // 止盈价格 (0 表示不设置)
string comment=NULL, // 订单注释 (可选)
int magic=0, // 魔术数字 (可选, 但强烈建议EA使用)
datetime expiration=0, // 订单到期时间 (挂单可选, 0表示不过期)
color arrow_color=clrNONE // 开仓箭头颜色 (可选, clrNONE表示不绘制)
);
symbol
: 字符串类型,指定要交易的品种,例如"GBPUSD"
。通常使用Symbol()
内置函数获取当前图表的品种。cmd
: 整数类型,指定订单的类型。必须使用预定义的常量,如下:OP_BUY
(0): 买入市价单OP_SELL
(1): 卖出市价单OP_BUYSTOP
(2): 买入止损挂单OP_SELLSTOP
(3): 卖出止损挂单OP_BUYLIMIT
(4): 买入限价挂单OP_SELLLIMIT
(5): 卖出限价挂单
volume
: 双精度浮点数类型,指定交易手数。price
: 双精度浮点数类型,指定订单的开仓价格。- 买入市价单 (
OP_BUY
): 用当前的Ask
价格。 - 卖出市价单 (
OP_SELL
): 用当前的Bid
价格。 - 挂单 (
OP_BUYSTOP
等): 设定的挂单触发价格。
- 买入市价单 (
slippage
: 整数类型,指定允许的最大滑点,建议设置一个合理的值。不支持滑点的经纪商会忽略此参数。stoploss
: 双精度浮点数类型,指定止损价格。买单的止损价必须低于开仓价,卖单的止损价必须高于开仓价。0 表示不设置止损。takeprofit
: 双精度浮点数类型,指定止盈价格。买单的止盈价必须高于开仓价,卖单的止盈价必须低于开仓价。0 表示不设置止盈。comment
: 字符串类型,可选参数,用于添加订单注释。magic
: 整数类型,可选参数,但对于EA交易极其重要。用于为订单打上一个独特的标识号(魔术数字),以便 EA 能够区分哪些订单是由自己下的,从而进行后续管理。expiration
:datetime
类型,可选参数,用于设置挂单的到期时间。0 表示挂单永不过期。arrow_color
:color
类型,可选参数,指定在图表上标记开仓位置的箭头颜色。clrNONE
(默认值)则不绘制箭头。
返回值: OrderSend()
函数执行后会返回一个整数值。
- 成功: 返回新创建订单的订单号,这是一个正整数。
- 失败: 返回 -1。如果返回 -1,可以通过调用
GetLastError()
函数获取具体的错误代码,以分析失败原因。
建议将 OrderSend()
返回的订单号保存到一个变量中(如全局变量或静态变量),以便后续需要对该订单进行修改或查询。同时,检查返回值是否为 -1 是处理下单失败情况(如网络问题、参数错误、保证金不足等)的标准做法。
下市价单示例
以下是一个下达买入市价单的示例代码。假设变量 LotSize
, Slippage
, BuyStopLoss
(止损价格), BuyTakeProfit
(止盈价格) 和 MagicNumber
都已经被正确计算或赋值。
int ticket = OrderSend(
Symbol(), // 当前图表品种
OP_BUY, // 买入市价单
LotSize, // 交易手数
Ask, // 使用当前卖价作为开仓价格
Slippage, // 允许的最大滑点 (points)
BuyStopLoss, // 止损价格
BuyTakeProfit, // 止盈价格
"My EA Buy Order", // 订单注释
MagicNumber, // 魔术数字
0, // 市价单无到期时间
Green // 在图表上绘制绿色开仓箭头
);
if (ticket < 0)
{
Print("买入市价单失败,错误代码: ", GetLastError());
}
else
{
Print("成功下达买入市价单,订单号: ", ticket);
}
Symbol()
: 获取当前图表的交易品种名称。绝大多数情况下,EA 都是在当前图表对应的品种上进行交易。OP_BUY
: 指定订单类型为买入市价单。Ask
: MQL 内置的预定义变量,实时存储当前最新的卖价。切记:买单是在 Ask 价开仓!Slippage
:Slippage参数表示下单时可接受的最大价格滑动范围,单位为点(Points),即“最小价格变动单位”。在 MQL4 中Point 是价格的最小单位,对于使用 5位小数报价的品种(如 EURUSD 报价为 1.12345),1pip = 10points。对于使用 3位小数报价的日元对(如 USDJPY 报价为 123.456),同样 1pip = 10points。因此如果你希望允许的滑点为3个pip:5位报价的EURUSD,应设置 Slippage = 30;对于3位报价的 USDJPY,同样 Slippage=30;"My EA Buy Order"
: 自定义订单注释。Expiration = 0
: 市价单不需要设置到期时间。Green
: 内置颜色常量Green
,在图表上标记买单开仓位置。
以下是一个类似的卖出市价单示例:
int ticket = OrderSend(
Symbol(), // 当前图表品种
OP_SELL, // 卖出市价单
LotSize, // 交易手数
Bid, // 使用当前买价作为开仓价格
Slippage, // 允许的最大滑点 (points)
SellStopLoss, // 止损价格 (卖单止损价 > 开仓价)
SellTakeProfit, // 止盈价格 (卖单止盈价 < 开仓价)
"My EA Sell Order", // 订单注释
MagicNumber, // 魔术数字
0, // 市价单无到期时间
Red // 在图表上绘制红色开仓箭头
);
if (ticket < 0)
{
Print("卖出市价单失败,错误代码: ", GetLastError());
}
else
{
Print("成功下达卖出市价单,订单号: ", ticket);
}
和多单主要区别在于:
OP_SELL
: 指定为卖出市价单。Bid
: 使用内置变量Bid
(当前买价)。切记:卖单是在 Bid 价开仓!"My EA Sell Order"
: 不同的注释。Red
: 使用红色箭头标记卖单。
下止损挂单(突破单)示例
挂单与市价单的区别在于,其开仓价格 (Price
参数) 不是当前的市价,而是您预先设定的未来某个价位。同时,止损和止盈价格的计算也必须相对于这个挂单价格,而不是当前市价。
在以下示例中,我们假设变量 PendingPrice
存储了计算好的挂单触发价格。
-
对于买入止损单 (Buy Stop),
PendingPrice
必须设置在当前Ask价之上。假设BuyStopLoss
和BuyTakeProfit
已根据PendingPrice
正确计算。int ticket = OrderSend( Symbol(), OP_BUYSTOP, LotSize, PendingPrice, Slippage, BuyStopLoss, BuyTakeProfit, "My EA Buy Stop", MagicNumber, 0, Green ); // ... 错误检查 ...
注意:订单类型为
OP_BUYSTOP
,开仓价格为PendingPrice
。此例中未设置到期时间 (Expiration = 0
)。 -
对于卖出止损单 (Sell Stop),
PendingPrice
必须设置在当前 Bid 价之下。假设SellStopLoss
和SellTakeProfit
已根据PendingPrice
正确计算。此例中我们还加入了一个到期时间,存储在Expiration
变量中(其值必须晚于当前服务器时间TimeCurrent()
)。datetime expirationTime = TimeCurrent() + (60 * 60 * 24); // 例如,设置 24 小时后到期 int ticket = OrderSend( Symbol(), OP_SELLSTOP, LotSize, PendingPrice, Slippage, SellStopLoss, SellTakeProfit, "My EA Sell Stop", MagicNumber, expirationTime, Red ); // ... 错误检查 ...
注意:订单类型为
OP_SELLSTOP
,开仓价格为PendingPrice
,并提供了expirationTime
下限价单(低买高卖)示例
限价挂单与止损挂单类似,但挂单价格相对于当前市价的位置要求是相反的。
-
对于买入限价单 (Buy Limit),
PendingPrice
必须设置在当前 Bid 价之下。int ticket = OrderSend( Symbol(), OP_BUYLIMIT, LotSize, PendingPrice, Slippage, BuyStopLoss, BuyTakeProfit, "My EA Buy Limit", MagicNumber, 0, Green ); // ... 错误检查 ...
注意:订单类型为
OP_BUYLIMIT
。 -
对于卖出限价单 (Sell Limit),
PendingPrice
必须设置在当前 Ask 价之上。datetime expirationTime = TimeCurrent() + (60 * 60 * 24); // 例如,设置 24 小时后到期 int ticket = OrderSend( Symbol(), OP_SELLLIMIT, LotSize, PendingPrice, Slippage, SellStopLoss, SellTakeProfit, "My EA Sell Limit", MagicNumber, expirationTime, Red ); // ... 错误检查 ...
注意:订单类型为
OP_SELLLIMIT
。
借用前一篇教学的一段话,买入止损单 (Buy Stop)是向上做突破单,卖出止损单 (Sell Stop)是向下做下破单;买入限价单 (Buy Limit)是低买,卖出限价单 (Sell Limit)是高卖;而是市价单是现在就进场。理解了这句话就会明白什么情况下价格设置市价之上,什么情况下价格设置市价之下。