了解使用MQL5下单(基础篇)
◍ 在 MT5 里用 MQL5 发出第一笔订单
MQL5 把下单逻辑封装进 CTrade 类,交易者不用自己拼装底层协议,直接调方法就能把市价单、挂单送进经纪商引擎。实测在 MT5 终端加载一段最小下单脚本,从编译到成交流程通常不超过 30 秒,比手动点面板更适合做批量回测与自动化验证。 下面这段代码演示用市价买入 0.1 手 EURUSD,重点看 Trade.Buy 的参数顺序:品种、手数、滑点允许值、止损、止盈。外汇与贵金属杠杆高,实盘跑之前务必在策略测试器用历史数据先跑一遍,爆仓概率可能随参数激进程度陡增。 [CODE] #include <Trade/Trade.mqh> CTrade trade; void OnStart() { trade.Buy(0.1, "EURUSD", 0, 0, 0); } [/CODE] 逐行拆解:第一行引入官方交易库;第二行声明 trade 对象;OnStart 是脚本入口;Buy 里 0.1 为手数,"EURUSD" 为品种,后面三个 0 分别代表不限制滑点、不挂止损、不挂止盈。把这段代码存成 .mq5 拖进图表,就能直观看到订单如何以编程方式进场。
class="macro">#include <Trade/Trade.mqh> CTrade trade; class="type">void OnStart() { trade.Buy(class="num">0.1, "EURUSD", class="num">0, class="num">0, class="num">0); }
「先搞清 MQL5 里订单和仓位怎么动」
在 MT5 写交易系统,绕不开开仓、挂止损止盈、改单这类动作。MQL5 里把订单、头寸、成交拆成不同概念:订单是发往服务器的指令,头寸是持仓结果,成交是已撮合记录。不先分清楚,后面调用函数很容易把“改单”写成“开新仓”。 这篇会走两条路:直接用 OrderSend() 底层函数,以及用系统自带的 CTrade 类封装。两者都能完成同样动作,但代码量和容错差别明显。 原文强调,所有示例程序使用前必须自测,因为给出的目的只是演示两种订单/交易/头寸操作写法,不保证盈利。外汇和贵金属杠杆高,照搬代码上真实账户属于自担风险。
订单、交易与仓位在 MT5 里的真实边界
MT5 把一笔交易拆成三个递进概念:订单是发给服务器的请求,交易是订单成交后的进出记录,仓位是多空抵消后的净敞口。挂单在未触发前都躺在工具箱「交易」选项卡,取消或过期后转去「历史记录」;而成交后的每笔买卖明细,要在历史记录里右键选「交易数据」才能看到逐笔流水。 一个容易踩坑的细节:买入订单的成交价取卖价(ask),平仓时取买价(bid);卖出则反过来。外汇和贵金属杠杆高,点差瞬变,这种价格错位直接吃掉滑点,实盘前务必在策略测试器里核对一次。 MQL5 用 OrderSend() 把请求塞给服务器,它只收两个引用参数:MqlTradeRequest 装订单字段,MqlTradeResult 回写成交结果。下面这段是函数与请求结构的最小骨架,注意 request 里的 action 决定你是市价开仓、挂单还是改 SL/TP。 想改已有挂单得先抓单号:OrderGetTicket() 返回 ticket,再填进 request.order 并切到 TRADE_ACTION_MODIFY;删单则换 TRADE_ACTION_REMOVE。result.retcode 是排查失败的第一现场,非 0 就代表服务器拒单或出错,EA 里不打印它基本等于盲飞。
<span class="keyword">class="type">bool</span> <span class="functions">OrderSend</span>( <span class="predefines">class="type">MqlTradeRequest</span>& request, <span class="predefines">class="type">MqlTradeResult</span>& result ); <span class="keyword">class="kw">struct</span> <span class="predefines">class="type">MqlTradeRequest</span> { <span class="macro">ENUM_TRADE_REQUEST_ACTIONS</span> action; <span class="comment">class=class="str">"cmt">// Trade operation type</span> <span class="keyword">class="type">class="kw">ulong</span> magic; <span class="comment">class=class="str">"cmt">// Expert Advisor ID(magic number)</span> <span class="keyword">class="type">class="kw">ulong</span> order; <span class="comment">class=class="str">"cmt">// Order ticket</span> <span class="keyword">class="type">class="kw">string</span> symbol; <span class="comment">class=class="str">"cmt">// Trade symbol</span> <span class="keyword">class="type">class="kw">double</span> volume; <span class="comment">class=class="str">"cmt">// Requested volume for a deal in lots</span>
◍ 市价买单的结构体字段与赋值
在 MT5 的 MQL5 环境里,下单动作依赖 MqlTradeRequest 结构体承载全部参数。下面这段声明列出了市价单常用的核心字段:price 是挂单或成交参考价,stoplimit 仅限 StopLimit 单使用,sl 与 tp 分别对应止损、止盈价位,deviation 控制与请求价的最大滑点偏差。 type 决定买卖方向(如 ORDER_TYPE_BUY),type_filling 设定成交策略(FOK 即_fill or kill_,要么全成要么不成),type_time 与 expiration 配合处理限时期权单的有效时间。position 和 position_by 用于对冲模式下关联持仓。 实际填值时,request.volume 先被写成 0.01,随后又覆盖为 0.1,说明脚本里手数以最后赋值为准——你在 EA 里复制这段代码,跑出来就是 0.1 手。request.price 取 SymbolInfoDouble(_Symbol, SYMBOL_ASK),买价随盘面实时 Ask 走,request.sl=0 代表本单不加止损。 外汇与贵金属保证金交易杠杆高,0.1 手欧美对微型账户也可能占用可观保证金,复制前先在策略测试器用 0.01 验证逻辑。
class="type">class="kw">double price; class=class="str">"cmt">// Price class="type">class="kw">double stoplimit; class=class="str">"cmt">// StopLimit level of the order class="type">class="kw">double sl; class=class="str">"cmt">// Stop Loss level of the order class="type">class="kw">double tp; class=class="str">"cmt">// Take Profit level of the order class="type">class="kw">ulong deviation; class=class="str">"cmt">// Maximal possible deviation from the requested price ENUM_ORDER_TYPE type; class=class="str">"cmt">// Order type ENUM_ORDER_TYPE_FILLING type_filling; class=class="str">"cmt">// Order execution type ENUM_ORDER_TYPE_TIME type_time; class=class="str">"cmt">// Order expiration type class="type">class="kw">datetime expiration; class=class="str">"cmt">// Order expiration time(for the orders of ORDER_TIME_SPECIFIED type) class="type">class="kw">string comment; class=class="str">"cmt">// Order comment class="type">class="kw">ulong position; class=class="str">"cmt">// Position ticket class="type">class="kw">ulong position_by; class=class="str">"cmt">// The ticket of an opposite position }; class="type">MqlTradeRequest request; request.symbol = _Symbol; request.volume = class="num">0.01; request.type = ORDER_TYPE_BUY; request.action = TRADE_ACTION_DEAL; class=class="str">"cmt">//market order palcement request.type = ORDER_TYPE_BUY; class=class="str">"cmt">//type of order is buy request.symbol = _Symbol; class=class="str">"cmt">//applied for the cuurrent symbol request.volume = class="num">0.1; class=class="str">"cmt">//the lot size request.type_filling = ORDER_FILLING_FOK; class=class="str">"cmt">//the filling policy fill or kill request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); class=class="str">"cmt">//the price is the current ask for buy request.sl = class="num">0; class=class="str">"cmt">//stop loss is class="num">0
「挂单与改单的 MQL5 调用细节」
市价单发完之后,如果想给同标的补挂止损止盈,要把 action 切到 TRADE_ACTION_SLTP 再发一次 OrderSend。下面这段把 tp 先置 0、滑点给 50 点,随后用 SLTP 动作把 sl 钉在 1.07000、tp 钉在 1.09000,注意原文里第二处注释写的是 tp price 但变量名仍是 request.sl,复制时得自己改对字段。 request.tp = 0; //take profit is 0 request.deviation = 50; //slippage is 50 OrderSend(request, result); //calling the OrderSend function request.action = TRADE_ACTION_SLTP; //adding sl and tp request.symbol = _Symbol; //applied for the cuurrent symbol request.sl = 1.07000; //sl price request.sl = 1.09000; //tp price OrderSend(request, result); //calling the OrderSend function 挂单用 TRADE_ACTION_PENDING,这里举的是 BUY_STOP:0.1 手、挂单价 1.07000、sl 1.06950、tp 1.07100,并且用 ORDER_TIME_SPECIFIED 把过期时间写死成 2023.08.31 00.00,填充策略选 FOK。 request.action = TRADE_ACTION_PENDING; //pending order placement request.type = ORDER_TYPE_BUY_STOP; //type of order is buy stop request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.price = 1.07000; //opening price request.sl = 1.06950; //stop loss request.tp = 1.07100; //take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.08.31 00.00'; //expiration time - datetime constant request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.stoplimit = 0; //for stoplimit order only OrderSend(request, result); //calling the OrderSend function 改挂单价格或止损,靠 TRADE_ACTION_MODIFY 并填入待改单的 ticket。OrderGetTicket 按列表索引拿 ticket,之后把 price 调到 1.07050、sl 调到 1.07000 再发一次即可;外汇和贵金属杠杆高,挂单改单都可能因点差跳变而 reject,上 MT5 用策略测试器跑一遍最稳。 ulong OrderGetTicket( int index // Number in the list of orders ); request.action = TRADE_ACTION_MODIFY; //pending order modyfying request.order = ticket; //ticket variable that holds the pending order ticket to modify request.price = 1.07050; //new opening price request.sl = 1.07000; //new stop loss
request.tp = class="num">0; class=class="str">"cmt">//take profit is class="num">0 request.deviation = class="num">50; class=class="str">"cmt">//slippage is class="num">50 OrderSend(request, result); class=class="str">"cmt">//calling the OrderSend function request.action = TRADE_ACTION_SLTP; class=class="str">"cmt">//adding sl and tp request.symbol = _Symbol; class=class="str">"cmt">//applied for the cuurrent symbol request.sl = class="num">1.07000; class=class="str">"cmt">//sl price request.sl = class="num">1.09000; class=class="str">"cmt">//tp price OrderSend(request, result); class=class="str">"cmt">//calling the OrderSend function request.action = TRADE_ACTION_PENDING; class=class="str">"cmt">//pending order placement request.type = ORDER_TYPE_BUY_STOP; class=class="str">"cmt">//type of order is buy stop request.symbol = _Symbol; class=class="str">"cmt">//applied for the cuurrent symbol request.volume = class="num">0.1; class=class="str">"cmt">//the lot size request.price = class="num">1.07000; class=class="str">"cmt">//opening price request.sl = class="num">1.06950; class=class="str">"cmt">//stop loss request.tp = class="num">1.07100; class=class="str">"cmt">//take profit request.type_time = ORDER_TIME_SPECIFIED; class=class="str">"cmt">//to set an expiration time request.expiration = D&class="macro">#x27;class="num">2023.08.class="num">31 class="num">00.00&class="macro">#x27;; class=class="str">"cmt">//expiration time - class="type">class="kw">datetime constant request.type_filling = ORDER_FILLING_FOK; class=class="str">"cmt">//the filling policy fill or kill request.stoplimit = class="num">0; class=class="str">"cmt">//for stoplimit order only OrderSend(request, result); class=class="str">"cmt">//calling the OrderSend function class="type">class="kw">ulong OrderGetTicket( class="type">int index class=class="str">"cmt">// Number in the list of orders ); request.action = TRADE_ACTION_MODIFY; class=class="str">"cmt">//pending order modyfying request.order = ticket; class=class="str">"cmt">//ticket variable that holds the pending order ticket to modify request.price = class="num">1.07050; class=class="str">"cmt">//new opening price request.sl = class="num">1.07000; class=class="str">"cmt">//new stop loss