了解使用MQL5下单
概述
在任何交易系统中,我们都需要处理订单及其操作,如开仓、止损和获利以及修改订单。因此,在为MetaTrader5创建交易系统时,了解如何在mql5中处理订单操作非常重要。本文的目的是为大多数订单和仓位操作提供一个简单的指导,以便能够有效地处理有关此主题的所有内容。我们将在本文中介绍以下主题:
我希望您会发现这篇文章对顺利开发您的MetaTrader5交易系统有帮助和价值。本文中的所有应用程序,在使用之前都必须对其进行测试,以确保它们是有利可图的或适合您的交易,因为提及它们的主要目的只是提供一个使用两种不同方法创建交易系统的示例,这两种方法涉及订单、交易和头寸操作。
订单、仓位和交易术语
在这一部分中,我们将讨论如何有效处理订单的重要术语。我们将了解MetaTrader 5中与订单相关的三个术语之间的差异。这些术语是订单、交易和仓位,我们可以将这些术语视为执行交易的步骤。
订单:是交易服务器收到的以特定价格打开特定手数或交易量的买卖交易的请求。订单有两种类型,市场订单和挂单。
- 市场订单:可以立即以当前市场价格执行的订单。
- 挂单:在预定条件下执行交易的订单,该条件涉及在其水平上执行交易的价格和执行交易的时间。
这些挂单可以是以下其中一种:
- 止损买入(Buy stop):以高于市场中当前价格的特定价格下订单。
- 限价买入(Buy limit):以低于市场当前价格的特定价格下订单。
- 止损卖出(Sell stop):以低于市场当前价格的特定价格下一个待销售订单。
- 限价卖出:以高于市场当前价格的特定价格下一个待卖出订单。
下单后,无论是市场订单还是挂单,都可以在MetaTrader 5工具箱的交易选项卡中找到。以下是一个示例:
当订单在未执行的情况下关闭或取消时,我们可以在工具箱的“历史记录”选项卡中找到它们。
当我们想通过MQL5修改当前头寸时,我们需要处理这些订单,就像我们稍后处理订单修改时看到的一样。
交易:这是执行或成交交易订单时的结果。我们可以根据交易的执行情况将其视为进出活动。假设有一个执行了一手的买入订单。之后,我们关闭了一部分0.5手的仓位,然后关闭了剩余的0.5手。因此,交易将与以下内容相同:
- 1手买入
- 0.5手卖出
- 0.5手卖出
我们可以在MetaTrader 5工具箱的历史记录选项卡中找到这些交易,方法是右键单击并选择交易数据。
仓位:它是基于买卖金融资产的多头或空头交易的净额。如果我们选择要显示的仓位,我们可以在交易选项卡或历史选项卡中找到它作为活跃交易。
值得一提的是,买入订单的可执行价格是卖出价,平仓时的可执行价是买入价。另一方面,卖出订单的可执行价格是买入价,平仓时的可执行价是卖出价。
OrderSend()
在了解了MetaTrader 5中有关交易执行的重要术语后,我们需要了解如何在MQL5中自动执行订单。首先,您可以在MQL5参考中查看交易函数,以了解有关用于管理活动的函数的更多信息。
我们将讨论OrderSend()函数,该函数可用于通过向交易服务器发送请求来执行交易操作。换句话说,它可以用于设置、修改和关闭订单。
以下是此函数的格式:
bool OrderSend( MqlTradeRequest& request, MqlTradeResult& result );
正如我们所看到的,该函数有两个参数:
- MqlTradeRequest结构:它包含订单参数和执行交易所需的所有字段或变量。根据与符号通过引用传递的对象。TradeRequest是客户端和交易服务器之间执行订单的交互方法。
- MqlTradeResult结构:TradeResult返回订单请求的结果。也通过引用传递的对象。
MqlTradeRequest 结构:
该结构是一组不同类型的相关数据。我们可以发现MqlTradeRequest结构定义如下:
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type ulong magic; // Expert Advisor ID (magic number) ulong order; // Order ticket string symbol; // Trade symbol double volume; // Requested volume for a deal in lots double price; // Price double stoplimit; // StopLimit level of the order double sl; // Stop Loss level of the order double tp; // Take Profit level of the order ulong deviation; // Maximal possible deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type ENUM_ORDER_TYPE_TIME type_time; // Order expiration type datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type) string comment; // Order comment ulong position; // Position ticket ulong position_by; // The ticket of an opposite position };
如果我们想声明一个MqlTradeRequest对象,我们可以通过以下代码行来完成:
MqlTradeRequest request;
然后,我们可以通过在创建的请求对象后面添加一个点(.),将交易参数分配给该对象的变量,如下例所示:
request.symbol = _Symbol; request.volume = 0.01; request.type = ORDER_TYPE_BUY;
以下是MqlTradeRequest结构的所有成员或变量的列表,以及它们可接受的赋值。
变量 | 描述 | 可以接受的赋值 |
---|---|---|
action | 它代表了交易操作的类型 | ENUM_TRADE_REQUEST_ACTIONS之一(TRADE_ACTION_DEAL、TRADE_AACTION_PENDING、TRADE_ACTION_SLTP、TRADE-ACTION_MODIFY、TRADE_REACTION_REMOVE、TRADE_CLOSE_BY) |
magic | 它表示 EA 交易的 ID,用于识别某个 EA 交易下的订单 | 任何 ulong 型数值 |
order | 它表示订单的单号在 action 变量中使用 TRADE_ACTION_MODIFY 或 TRADE_AACTION_REMOVE 时需要 | 任何 ulong 型数值 |
symbol | 指定的交易品种或交易资产,_SYMBOL 表示当前的那个 | 任何字符串型交易品种 |
volume | 它指定交易量或手数 | 任何允许的 double 型数值 |
price | 开单的价格 | double 型数值 |
stoplimit | 限价挂单的开单价格action 变量必须是 TRADE_ACTION_PENDING,type 变量必须是 ORDER_TYPE_BUY_STOP_LIMIT 或 ORDER_TYPE_SELL_STOP_LIMIT,并且是限价订单所必需的 | double 型数值 |
sl | 交易的止损价格 | double 型数值 |
tp | 交易的获利价格 | double 型数值 |
deviation | 最大价格偏移点数 | ulong 型数值 |
type | 订单的类型 | ENUM_ORDR_TYPE 枚举中的一个(ORDER_TYPE_BUY、ORDER_TYPE_SELL、ORDER_YPE_BUY_STOP、ORDER_TYPE _SELL_STOP, ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT) |
type_filling | 订单执行类型或者订单的成交原则 | ENUM_ORDER_TYPE_FILLING 枚举中的一个 (ORDER_FILLING_FOK, ORDER_FILLING_IOC, ORDER_FILLING_BOC, ORDER_FILLING_RETURN) |
type_time | 挂单过期时间类型 | ENUM_ORDER_TYPE_TIME 枚举中的一个 (ORDER_TIME_GTC, ORDER_TIME_DAY, ORDER_TIME_SPECIFIED, ORDER_TIME_SPECIFIED_DAY) |
expiration | 挂单的过期时间。type_time 为 ORDER_TIME_SPECIFIED 时需要 | datetime 型数值 |
comment | 订单备注 | string 型值 |
position | 仓位的编号。当仓位被修改或关闭以识别它时,它是必需的 | ulong 型数值 |
position_by | 反向仓位的编号。当仓位被同一交易品种的相反方向上的相反打开仓位关闭时使用 | ulong 型数值 |
现在,我们将提到在MQL5中下订单时需要使用的一些重要操作。
- 市场订单
- 增加止损和获利
- 挂单
- 修改挂单
- 删除挂单
市场订单:
在这种类型的操作中,我们需要下一个市场订单,这意味着订单将以当前市场价格下发,我们将使用(TRADE_ACTION_DEAL)action。如果订单是买入订单,则订单将按当前要价(ask)下发;如果订单是卖出订单,则将按当前出价(bid)下发。以下是如何做到这一点:
在声明了 MqlTradeRequest 和 MqlTradeResult 对象之后,我们可以将以下值分配给以下变量:
request.action = TRADE_ACTION_DEAL; &nbsthe p; //market order palcement request.type = ORDER_TYPE_BUY; //type of order is buy request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); //the price is the current ask for buy request.sl = 0; //stop loss is 0 request.tp = 0; //take profit is 0 request.deviation = 50; //slippage is 50 OrderSend(request, result); //calling the OrderSend function
正如我们在前面的代码中所看到的,我们没有添加止损和获利值。我们可以将它们的值与其他变量一起添加到代码中,也可以通过另一个操作添加它们,我们将在下一点中看到。
加上止损和获利:
当我们需要添加止损和获利时,我们将TRADE_ACTION_SLTP分配给变量 action,如下例所示。
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
挂单:
如果我们想下一个挂单,我们可以使用另一个 action(TRADE_ACTION_PENDING)。然后,我们确定订单的类型。如果我们需要挂单的到期时间,我们可以设置时间。
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
修改挂单:
如果我们需要修改挂单,我们需要获得待修改挂单的订单单号。我们可以使用OrderGetTicket函数来获取订单单号。此函数返回相应订单的单号,我们可以使用它来选择订单并使用它。
ulong OrderGetTicket( int index // Number in the list of orders );
让我们探讨一下,我们有一个名为(ticket)的变量,它保存订单编号。我们可以使用此变量将订单编号分配给请求对象的 order 变量,然后,我们可以使用操作(TRADE_ACTION_MODIFY)修改订单,与以下示例相同。
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 = 1.07150; //new take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.09.01 00.00'; //new expiration time - datetime constant OrderSend(request, result); //calling the OrderSend function
删除挂单:
如果我们需要删除挂单,我们可以使用(TRADE_ACTION_REMOVE)的 action 来完成。我们还需要我们需要删除的挂单的单号。我们可以使用 ticket 变量,假设它包含所需的挂单编号。
request.action = TRADE_ACTION_REMOVE; //pending order remove request.order = ticket; //ticket variable that holds the pending order ticket to remove OrderSend(request, result); //calling the OrderSend function
MqlTradeResult 结构:
一旦OrderSend()函数下了订单,MqlTradeResult结构就会返回订单是否成功的结果。它包含来自交易服务器的交易信息,如单号、交易量和价格。
以下是 MqlTradeResult 结构的定义:
struct MqlTradeResult { uint retcode; // Operation return code ulong deal; // Deal ticket, if it is performed ulong order; // Order ticket, if it is placed double volume; // Deal volume, confirmed by broker double price; // Deal price, confirmed by broker double bid; // Current Bid price double ask; // Current Ask price string comment; // Broker comment to operation (by default it is filled by description of trade server return code) uint request_id; // Request ID set by the terminal during the dispatch int retcode_external; // Return code of an external trading system };
我们可以声明一个名为 result 的对象,将其作为第一个参数(请求)之后的第二个参数传递给OrderSend()函数调用。
MqlTradeResult result;
正如我们在 MqlTradeResult 结构的变量中看到的那样,retcode变量非常重要,因为它从交易服务器返回代码,以指示请求是否成功。
如果未进行交易,则返回代码指示错误状态。有关详细信息,您可以从MQL5参考中查看返回代码的列表。在我们的交易系统中包含一个代码以报告是否返回错误是至关重要的,例如以下示例:
if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) { Print("Trade Placed Successfully"); } else { Print("Trade Not Placed, Error ", result.retcode); }
正如我们在前面的代码中所看到的,它将在请求后打印一条带有结果的消息,并填写结果变量。如果进行了交易,它会向我们发送一条消息,或者如果出现问题,它会打印一条存在错误的消息,并返回错误代码以帮助解决问题。
OrderSend()应用程序
我们需要创建一个可以使用OrderSend()函数执行交易的简单交易系统。我们需要创建的交易系统是一个简单的移动平均线交叉,操作只是下一个市场订单。
这里的目标是了解使用OrderSend()和CTrade类创建同一交易系统时的差异。以下是使用OrderSend()函数创建此MA交叉的步骤。
在全局作用域中,创建两个整数变量(simpleMA、barsTotal)而不进行赋值,它们稍后将在OnInit部分中进行赋值。
int simpleMA; int barsTotal;
simpleMA将被分配给iMA函数,该函数返回移动平均技术指标的句柄。它的参数是:
- symbol:用于指定交易品种名称,_Symbol 指的是当前交易品种。
- period:用于指定时段,我们将使用 PERIOD_H1,它指的是一小时的时间框架。
- ma_period:移动平均线的周期,我们将使用 50。
- ma_shift:指定所需的水平偏移。
- ma_method:用于指定移动平均线类型,我们将指定简单类型。
- applied_price:用于指定将在MA计算中使用的价格类型,我们将设置收盘价。
barsTotal 将分配给 iBars 函数,该函数返回柱数。它的参数是:
- symbol:交易品种名称
- timeframe:时间框架时段
simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1);
在OnTick部分,我们将创建两个数组,一个用于使用 MqlRates 类型的价格,该类型存储有关价格、交易量和价差的信息,另一个用于 double 类型的移动平均值
MqlRates priceArray[]; double mySMAArray[];
定义要价(ask)和出价(bid)
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
为OrderSend()函数创建两个对象,一个用于使用MqlTradeReuest的请求,另一个用于通过MqlTradeResult的结果,然后通过引用重置请求变量
ZeroMemory(request);
使用 ArraySetAsSeries 函数将 AS_SERIES 标志设置为这两个创建的数组 priceArray 和 mySMAArray。它的参数:
- array[]:指定所需的数组
- flag:数组索引的方向。
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);
使用 CopyRates 函数获取 MqlRates 的历史数据。它的参数是:
- symbol:交易品种名称或者使用 _Symbol 代表当前交易品种或资产。
- time frame:时间框架时段或者使用 _Period 代表当前时段。
- start position::起始位置。
- count:要复制的数据量。
- rates_array:要复制的目标数组。
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
使用 CopyBuffer 函数获取指标数据缓冲区。它的参数:
- indicator_handle:用于指定指标句柄,本例是MA。
- buffer_num:用于指定指标缓冲区编号。
- start_pos:开始计数的起始位置。
- count:复制的数量。
- buffer[]:目标数组。
CopyBuffer(simpleMA,0,0,3,mySMAArray);
定义最后、以前的收盘价、最后和以前的SMA值
double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
创建一个整数型 bars 变量并将其分配给iBars
int bars=iBars(_Symbol,PERIOD_H1);
如果 barsTotal 不等于 bars 变量,则检查 bars
if(barsTotal != bars)
如果 barsTotal 和 bars 数值不相等,就更新 barsTotal
barsTotal=bars;
如果上一次收盘大于上一次SMA值,则检查开启交易策略的条件
if(prevClose<prevSMAVal && lastClose>SMAVal)
使用与 MqlTradeRequest 函数相关的适当变量打开市场买入订单
request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result);
如果上次收盘小于上次SMA值,则检查开启卖出交易的策略的条件。上次收盘大于上次SMA值之后
if(prevClose>prevSMAVal && lastClose<SMAVal)
使用与 MqlTradeRequest 函数相关的适当变量打开市场卖出订单 request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result);
以下是一个块中的完整代码,用于使用OrderSend()函数创建这种类型的交易系统
//+------------------------------------------------------------------+ //| OrderSend_Trading_system.mq5 | //+------------------------------------------------------------------+ int simpleMA; int barsTotal; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result); } if(prevClose>prevSMAVal && lastClose<SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result); } } }
CTrade 类
在学习了如何通过OrderSend()函数下订单后,我们有了一个访问交易函数的简单方法。我们可以使用MQL5提供的CTrade现成类,也可以创建自己的类以获得更多个人偏好。现在,我们将介绍如何在MQL5中使用CTrade现成类。您可以从MQL5参考中查看关于CTrade类的所有信息。
首先,我们可以在MetaTrader 5安装文件的 include 文件夹中的 Trade 文件夹中找到CTrade类的include文件。我们所需要的只是将此文件包含在 EA 交易中,以便调用和使用与以下相同的所有交易功能:
#include <Trade\Trade.mqh>
从CTrade类创建对象
CTrade trade;
之后,我们将能够通过在句点(.)和所需函数之前使用trade来使用CTrade类中的所有交易函数。我们可以使用订单操作、仓位操作、最后一个请求参数访问、最后一次请求检查结果访问、最后请求执行结果访问等所有功能。
我们将提到一些与OrderSend()相同的重要函数,以了解这两种方法之间的差异。我们将了解如何执行以下操作:
- 市场订单
- 增加止损和获利
- 挂单
- 修改挂单
- 删除挂单
市场订单:
创建交易对象后,我们可以使用PositionOpen函数下市场订单,其参数为:
- symbol:用于指定所需的交易品种
- order_type:用于指定打开仓位的订单类型
- volume:用于指定手数大小
- price:用于指定打开仓位的价格
- sl:用于指定止损价格
- tp:用于指定获利价格
- comment:用于指定备注或者为空(NULL)
以下是一个例子:
trade.PositionOpen( _Symbol, //to be applied for the current symbol ORDER_TYPE_BUY, //to place buy order 0.1, //lot size or volume Ask, //opening price of the order - current ask Ask-(500*_Point), //sl Ask+(1000*_Point), //tp NULL //NULL );
我们也可以使用 CTrade 中的其他方法,如Buy、Sell而不是PositionOpen来打开市场订单。
加上止损和获利:
我们可以使用PositionModify函数通过交易品种或编号修改仓位。它的参数是:
- symbol or ticket::用于指定我们需要修改的仓位,如果通过交易品种进行修改,我们将指定交易品种名称;如果通过单号进行修改,则我们将指定订单编号。
- sl:新的止损价格
- tp:获利价格
按交易品种修改的示例:
trade.PositionModify( EURUSD, //the symbol name 1.06950, //the new sl 1.07100, //the new tp );
按单号修改示例:
trade.PositionModify( ticket, //the ticket variable that holds the needed ticket number to modify 1.06950, //the new sl 1.07100, //the new tp );
挂单:
如果我们需要使用CTrade类下一个挂单,我们可以使用OrderOpen函数。它的参数是:
- symbol:确定交易品种名称
- order_type:确定挂单类型
- volume:指定手数大小
- limit_price:指定止损限价
- price:指定挂单的执行价格
- sl:指定止损
- tp:指定获利的价格
- type_time:指定过期类型
- expiration: 指定过期 datetime 变量
- comment:根据需要指定备注
以下示例用于使用OrderOpen函数下订单
trade.OrderOpen( "EURUSD", // symbol ORDER_TYPE_BUY_LIMIT, // order type 0.1, // order volume 0, // StopLimit price 1.07000, // execution price 1.06950, // Stop Loss price 1.07100, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration "" // comment );
修改挂单:
如果我们需要修改已下的挂单,我们可以通过OrderModify函数使用CTrade类来完成。它的参数是:
- ticket:用于指定需要修改的挂单
- price:新的执行价格
- sl:新的止损价格
- tp:新的获利价格
- type_time:指定过期类型
- expiration:用于指定过期时间 datetime 变量
- stoplimit:用于确定限价订单价格
以下是挂单修改的示例
trade.OrderModify( ticket, // ticket number of the pending order to modify 1.07050, // execution price 1.07000, // Stop Loss price 1.07150, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration 0, // StopLimit price );
删除挂单:
如果您需要删除挂单,您可以使用OrderDelete函数来执行此操作,并且它需要删除该挂起订单的编号。以下是该函数的示例。
trade.OrderDelete(
ticket, // tick number of the pending order to delete
);
CTrade 类应用程序
我们需要创建与使用OrderSend()创建的相同的交易系统。我们将使用CTrade类来了解两者在函数工作方式上的差异。
以下是使用CTrade类创建此交易系统的唯一不同步骤,其余步骤与之前相同。
使用预处理器#include包含Trade 包含文件
#include <Trade\Trade.mqh>
从CTrade类创建交易对象
CTrade trade;
当满足买入条件时,我们可以使用PositionOpen,订单类型将为 ORDER_TYPE_BUY 或与以下代码相同的 Buy 方法
trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL);
当满足卖出条件时,我们可以使用 PositionOpen 和订单类型 ORDER_TYPE_SELL 或与以下代码相同的 Sell 方法
trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL);
以下是使用CTrade类创建交易系统的完整代码:
//+------------------------------------------------------------------+ //| CTrade_Trading_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> int simpleMA; int barsTotal; CTrade trade; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL); } } }
结论
如果您已经阅读完这篇文章,那么您应该了解MQL5中的订单、仓位和交易是如何工作的。除了了解我们如何使用两种交易操作方法(OrderSend方法和CTrade方法)顺利创建交易系统之外,
我们还确定了如何使用这两种方法下市场订单和挂单、添加止损和获利、修改挂单以及删除挂单。
假设您了解如何应用前面的所有内容来创建应用程序,因为我们提供了两个简单的应用程序来使用这两种方法创建相同的移动平均交叉交易系统。
- OpenSend_Trading_System
- CTrade_Trading_System
上述应用程序的目的只是为了实际了解它们之间的差异,因此,请注意,在任何实时账户中使用它们之前,您必须对它们进行测试,以确保它们能够获利,适合您的交易。
我相信你已经发现了在处理交易操作时使用现成的CTrade类是多么容易,因为它节省了很多时间和精力。使用类编程时还会有其它的功能。
如果你想了解更多关于这一点以及MQL5中的面向对象编程的信息,你可以阅读我之前的文章了解MQL5面向对象编程(OOP),我希望你觉得它很有用。MQL5做了很多值得赞赏的工作和努力,为我们提供了顺利轻松地开发和创建交易软件的工具。
我希望你能发现这篇文章很有用,并获得许多有用的见解,以便在这些见解之后轻松理解和完成你的工作。如果你想为我阅读更多文章,你可以查看我的出版物,了解许多关于如何使用最流行的技术指标和其他指标创建交易系统的文章,我希望你会发现它们很有用。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/13229
你好、
文字很棒,谢谢。
我发现了一个小错误:
在TRADE_ACTION_SLTP 下的方框中,您写了两次 request.sl,第二个应该是 request.tp,正如行尾注释中指出的那样。
致以最崇高的敬意、
冈瑟
你好
文字很棒,谢谢。
我发现了一个小错误:
在TRADE_ACTION_SLTP 下的方框中,你写了两次 request.sl,第二个应该是 request.tp,正如行尾的注释所示。
致以最崇高的敬意、
冈瑟
您好、
感谢您的友好评论。您说得没错,这是一个错误,我们会考虑的。
谢谢、