
MQL5 交易工具包(第 3 部分):开发挂单管理 EX5 库
概述
在第一篇和第二篇文章中,您从头开始了解了EX5库的开发和编程,如何创建详细的文档来帮助最终用户在他们的 MQL5 项目中实现它们,并收到了一个关于如何在各种 MQL5 应用程序中导入和实现它们的实用分步演示。
在本文中,我们将开发一个全面的挂单管理 EX5 库,并创建一个图形用户界面(GUI)面板,以演示如何导入和实现该库,作为一个实践示例。此挂单管理库将仅使用 MQL5 标准函数来打开、修改和删除不同类型的挂单。对于希望学习如何编写简单到高级挂单管理模块的新 MQL5 程序员来说,它将成为一个宝贵的学习资源。您还将学习如何根据不同类别筛选和排序挂单。
我们下面创建的函数将被导出并编译到 EX5 库中,使其成为一项宝贵的资产,将大大缩短未来 MQL5 项目的开发时间。只需导入挂单管理 EX5 库,您就可以实现这些功能,从而显著缩短代码库和整体开发和编码过程。
创建一个新的 EX5 库源代码文件 (.mq5)
首先,打开您的 MetaEditor IDE ,然后使用 “新建” 菜单项按钮启动 MQL 向导。您需要创建一个新的库源代码文件,我们将其命名为 PendingOrdersManager.mq5 。该文件将包含管理挂单的核心函数。将其保存在我们在第一篇文章中设置的Libraries\Toolkit文件夹中。这与我们之前保存 Positions Manager EX5 库的目录相同,可使我们的项目保持井然有序和一致。
如果您需要复习如何在 MQL5 中创建EX5 库,我建议您回到第一篇文章。在那里,我们详细介绍了设置文件夹结构和创建库的分步过程。遵循这种方法不仅有助于简化开发,而且可以在未来的 MQL5 项目中更容易地维护和重用您的库。
预处理器指令、全局变量和仓位管理器 EX5 库的导入
在我们新创建的 PendingOrdersManager.mq5 库源代码文件中,我们将首先定义所有预处理器指令、全局变量、库导入和交易结构。这确保它们在我们的整个挂单管理库中可用,并且可以根据需要在各种函数中重复使用。
我们将首先使用 #define 定义预处理器宏来创建一个表示空白字符串的常量。这个名为 ALL_SYMBOLS 的常量将作为需要交易品种字符串作为输入参数的挂单管理函数中的占位符。通过传递这个空字符串,函数将把它解释为一个命令,将指定的操作应用于所有可用的交易品种,而不仅仅是一个交易品种。
这种方法简单但非常有效,特别是在管理多种工具时,因为它简化了处理不同交易品种的挂单的过程。为了实现这一点,定义 ALL_SYMBOLS 常量并将其直接放在代码中的 #property 指令下方。
#define ALL_SYMBOLS "" //-- Used as a function parameter to select all symbols
我们还需要创建两个额外的常量:一个用于定义如果订单失败,我们可以重试向交易服务器发送订单的最大次数,另一个用于设置重试尝试之间的延迟时间。这有助于防止交易服务器因快速、连续的请求而不堪重负。我们将第一个常量命名为 MAX_ORDER_RETRIES 并将其值设置为 600 。第二个常量是 ORDER_RETRY_DELAY ,其值为 500 (毫秒)。
这意味着,如果没有发生严重错误,我们可以尝试打开、修改或删除订单最多 600 次。每次尝试后,该函数将暂停半秒( 500 毫秒)然后再试一次。这种延迟确保了我们不会使服务器过载,并且资源得到了有效利用。它还允许在所有重试尝试用尽之前解决任何延迟,如市场不活跃或分时数据不可用,从而增加了成功执行订单的可能性。
#define MAX_ORDER_RETRIES 600 //-- Sets the order sending retry limit #define ORDER_RETRY_DELAYS 500//-- Sets the duration to pause before re-sending a failed order request in milliseconds
接下来,添加 MQL5 MqlTradeRequest 和 MqlTradeResult 数据结构。这些结构很重要,因为当我们打开、修改和删除不同的挂单时,它们将处理与交易服务器的所有通信。tradeRequest 结构将负责存储我们将执行的交易操作的详细信息,包括价格、止损和止盈等订单参数。同时, tradeResult 结构将捕获并保存交易操作的结果,并为我们提供服务器的反馈,告诉我们请求是否成功或遇到错误。
//-- Trade operations request and result data structures global variables MqlTradeRequest tradeRequest; MqlTradeResult tradeResult;
为了跟踪和存储各种挂单的状态,我们需要创建几种类型的变量来保存这些状态信息。这些订单状态变量将被声明为全局变量,以确保它们可以从我们库中的每个作用域访问,允许任何函数根据需要引用和更新它们。我们将在声明这些变量时使用默认值对其进行初始化,然后在 GetPendingOrdersData(...) 函数中使用实时准确的数据更新它们,我们将在本文后面开发该函数。这将确保所有挂单的状态在调用函数执行过程中保持一致并准确更新。
//-- Pending orders status global variables //------------------------------------------------------------------------------------------------------------------- int accountBuyStopOrdersTotal = 0, accountSellStopOrdersTotal = 0, accountBuyLimitOrdersTotal = 0, accountSellLimitOrdersTotal = 0, symbolPendingOrdersTotal = 0, symbolBuyStopOrdersTotal = 0, symbolSellStopOrdersTotal = 0, symbolBuyLimitOrdersTotal = 0, symbolSellLimitOrdersTotal = 0, magicPendingOrdersTotal = 0, magicBuyStopOrdersTotal = 0, magicSellStopOrdersTotal = 0, magicBuyLimitOrdersTotal = 0, magicSellLimitOrdersTotal = 0; double accountPendingOrdersVolumeTotal = 0.0, accountBuyStopOrdersVolumeTotal = 0.0, accountSellStopOrdersVolumeTotal = 0.0, accountBuyLimitOrdersVolumeTotal = 0.0, accountSellLimitOrdersVolumeTotal = 0.0, symbolPendingOrdersVolumeTotal = 0.0, symbolBuyStopOrdersVolumeTotal = 0.0, symbolSellStopOrdersVolumeTotal = 0.0, symbolBuyLimitOrdersVolumeTotal = 0.0, symbolSellLimitOrdersVolumeTotal = 0.0, magicPendingOrdersVolumeTotal = 0.0, magicBuyStopOrdersVolumeTotal = 0.0, magicSellStopOrdersVolumeTotal = 0.0, magicBuyLimitOrdersVolumeTotal = 0.0, magicSellLimitOrdersVolumeTotal = 0.0;
在打开、修改或删除订单时,经常会遇到各种类型的错误。为了有效地处理和解决这些错误,我们需要一个专门的函数来管理它们。此外,我们需要一个函数来检查关键的交易许可,例如我们的 EA 交易是否被授权交易,终端是否启用了算法交易,或者我们的经纪商是否允许该账户进行算法交易。
幸运的是,我们已经在之前的文章中的 PositionsManager.ex5 库中开发了类似的函数。我们不需要重新创建这些函数,而只需导入这个库,这样这些错误处理和权限检查函数就可以在我们的挂单管理器库中随时使用。导入 ErrorAdvisor(...) 和 TradingIsAllowed() 函数。
//+----------------------------------------------------------------------------+ //| PositionsManager.ex5 imports | //+----------------------------------------------------------------------------+ #import "Toolkit/PositionsManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Error Handling and Permission Status Functions bool ErrorAdvisor(string callingFunc, string symbol, int tradeServerErrorCode); bool TradingIsAllowed(); #import //--- Closing import directive
打印订单详情函数
PrintOrderDetails(...) 函数在 MetaTrader 5 中的专家日志中记录有关交易请求和服务器响应的详细信息。它需要两个字符串参数: header ,包含自定义消息,以及 symbol ,代表正在处理的交易品种或工具。该函数输出一份综合报告,其中包括必要的订单详细信息,例如交易品种、订单类型、交易量、价格、止损、止盈、注释、幻数和任何偏差。此外,它还记录有关交易结果的重要信息,包括服务器响应和任何运行时错误。此函数的主要目的是通过提供每个订单的参数和状态的清晰、格式化的概述来协助调试和监控交易操作。
void PrintOrderDetails(string header, string symbol) { string orderDescription; int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); //-- Print the order details orderDescription += "_______________________________________________________________________________________\r\n"; orderDescription += "--> " + tradeRequest.symbol + " " + EnumToString(tradeRequest.type) + " " + header + " <--\r\n"; orderDescription += "Volume: " + StringFormat("%d", tradeRequest.volume) + "\r\n"; orderDescription += "Price: " + DoubleToString(tradeRequest.price, symbolDigits) + "\r\n"; orderDescription += "Stop Loss: " + DoubleToString(tradeRequest.sl, symbolDigits) + "\r\n"; orderDescription += "Take Profit: " + DoubleToString(tradeRequest.tp, symbolDigits) + "\r\n"; orderDescription += "Comment: " + tradeRequest.comment + "\r\n"; orderDescription += "Magic Number: " + StringFormat("%d", tradeRequest.magic) + "\r\n"; orderDescription += "Order filling: " + EnumToString(tradeRequest.type_filling)+ "\r\n"; orderDescription += "Deviation points: " + StringFormat("%G", tradeRequest.deviation) + "\r\n"; orderDescription += "RETCODE: " + (string)(tradeResult.retcode) + "\r\n"; orderDescription += "Runtime Code: " + (string)(GetLastError()) + "\r\n"; orderDescription += "---"; Print(orderDescription); }
开启限价买入函数
OpenBuyLimit(...) 函数将负责在 MetaTrader 5 交易终端中设置新的买入限价挂单。此函数确保在提交订单请求之前满足所有必要条件,并具有内置错误处理功能来管理潜在问题。它验证所有参数是否有效并符合经纪商的要求。此外,它还实现了重试循环,增加了成功下单的可能性,使其成为管理挂单的可靠而高效的工具。该函数的全面错误处理和日志记录功能进一步有助于识别和解决订单下达过程中可能出现的问题。 如果成功开立买入限价单,该函数将返回布尔值 true ,如果订单请求不成功,则返回 false 。
什么是买入限价单?
买入限价单是指以等于或低于指定订单入场价的卖价买入的请求。买入限价入场价格仅在当前市场价格高于订单入场价格时有效。当您预期交易品种的价格将下降到您期望的入场水平然后上升时,这种类型的订单很有用,可让您从上涨趋势中获利。
让我们首先定义该函数,它将接受七个参数,每个参数在下达买入限价订单的过程中都有特定的作用。该函数将是可导出的,允许在 EX5 库中从外部访问。这些参数是:
- magicNumber(unsigned long) :交易的唯一标识符,用于区分我们的 EA 交易所下的订单与其他订单。
- symbol (string):将下订单的交易工具或交易品种(例如 EURUSD )。
- entryPrice(double) :买入限价单将被触发的价格水平。这是您想要购买资产的目标价格。
- lotSize(double) :要下达的订单的交易量大小,代表将交易多少手资产。
- sl(int) :止损值,以点为单位。这定义了交易在自动平仓之前可能遭受的最大损失。
- tp(int) :止盈值,也以点数衡量。这定义了通过平仓自动获得利润的价格水平。
- orderComment(string) :为了识别或跟踪目的而附加在订单上的注释或说明。
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export {
定义函数及其参数后,函数中的第一步是检查 MetaTrader 5 中是否启用了算法交易或 EA 交易。如果禁用,我们将立即退出该函数,从而阻止下订单。
if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function }
接下来,我们创建 tpPrice 和 slPrice 变量来保存止盈和止损价格值,然后检索有关交易品种的关键信息,例如小数位数(digits)、最低止损水平和点差。这些详细信息将帮助我们确保为所选交易品种正确设置入场价格和订单参数。
double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT;
在发送订单之前,我们需要检查入场价格是否有效,确保价格不太接近市场价格或低于经纪商的止损水平。如果价格无效,我们将记录错误并退出该函数。
//-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) < entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false }
让我们确保止损( SL )和止盈( TP )值满足经纪商的最低要求。如果有必要,我们会在继续操作之前调整 SL 和 TP 以符合这些规则。
//-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0;
一旦我们验证了价格和其他参数,我们将准备 tradeRequest 结构,其中包含订单类型、交易品种、价格、交易量、止损、止盈和注释等详细信息。我们还将确保手数在经纪商允许的范围内,并重置任何之前的交易结果或错误。
//-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError();
如果订单请求有效,我们将尝试将其发送到经纪商的交易服务器。若下单失败,我们会重试重新发送下单请求最多 600 次,每次暂停半秒( 500 毫秒)后再重试,进行多次尝试以确保下单成功。这种重试机制大大增加了成功打开订单的机会,特别是在临时网络或服务器问题的情况下。
如果订单成功下达,我们将记录订单的详细信息,并确认交易服务器已处理该订单。如果多次尝试后订单仍然失败,我们将使用从 PositionsManager.ex5 库导入的 ErrorAdvisor(..) 函数来诊断问题并返回 false 以指示未下订单。
for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } }
这是完整的函数,其中所有代码段都按正确的顺序排列。确保您的 OpenBuyLimit(...) 函数包含以下完整代码。
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) < entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
开启买入止损函数
OpenBuyStop(...) 函数负责下达新的买入止损挂单。它遵循与前面描述的 OpenBuyLimit(...) 函数类似的方法。如果成功下达买入止损订单,该函数将返回 true ,如果订单请求失败,则返回 false 。
什么是买入止损单?
买入止损单是指以等于或高于指定订单入场价的卖价买入的请求。买入止损入场价仅当当前市场价格低于订单的入场价时才有效。当您预期交易品种的价格将上涨至指定的入场水平,然后继续上涨时,这种类型的订单很有用,可让您从看涨趋势中获利。
下面是 OpenBuyStop(...) 函数,其中添加了解释性注释,以帮助您快速理解代码各部分的工作原理。
bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_STOP; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //--- Validate Stop Loss (sl) and Take Profit (tp) if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy stop order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
开仓限价卖出函数
OpenSellLimit(...) 函数负责下达新的卖出限价挂单。当卖出限价订单下达成功时,该函数返回 true ,如果订单请求不成功,则返回 false 。
什么是卖出限价单?
卖出限价单是指以等于或高于指定订单入场价的买入价卖出的请求。卖出限价入场价仅当当前市场价格低于订单入场价时才有效。当您预期交易品种的价格将上涨至指定的入场价格水平然后反转方向时,这种类型的订单很有用,可让您从预期的下跌趋势或看跌趋势中获利。
下面是 OpenSellLimit(...) 函数,附有解释性注释,以帮助您更好地理解代码的每个部分如何运行。
bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_LIMIT; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_BID) + (symbolStopLevel * symbolPoint) > entryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a sell limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
开设卖出止损函数
OpenSellStop(...) 函数用于下达新的卖出止损挂单。当卖出止损订单成功下达时,该函数返回 true ,表明请求处理顺利。如果订单下达因任何原因失败,则返回 false ,表示尝试失败。
什么是卖出止损单?
卖出止损订单是指以等于或低于指定订单入场价的买入价卖出的请求。卖出止损入场价仅当当前市场价格高于订单的入场价时才有效。当您预期某个交易品种的价格将跌至指定的入场水平然后继续下跌时,这种类型的订单很有用,可让您从预期的下跌趋势或看跌趋势中获利。
下面提供了 OpenSellStop(...) 函数,以及详细的注释,以指导您了解代码每个部分的功能。
bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double slPrice = 0.0, tpPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_STOP; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < entryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a sell stop order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
根据编号修改挂单函数
ModifyPendingOrderByTicket(...) 函数用于修改活动挂单的止损价( SL )、止盈价( TP )或入场价。它执行验证以确保修改符合经纪商的规则,记录进度和可能发生的任何错误,并在出现故障或不利的订单输入条件时使用重试机制多次尝试修改。
该函数接受四个参数:
- orderTicket(ulong) :订单的唯一标识符。此单号用于引用您要修改的具体订单。
- newEntryPrice(double) :挂单的新入场价格。如果该值设置为 0,则该函数将保留当前的入场价格。
- newSl (int) :新的止损(SL)值,以点数表示。如果该值设置为 0,则 SL 将被删除或保持不变。
- newTp (int) :新的止盈(TP)值,以点数表示。如果该值设置为 0,则 TP 将被删除或保持不变。
此函数为 bool 类型,如果订单修改成功,则返回布尔值 true;如果修改失败(由于参数无效、选择订单时出现错误或服务器问题),则返回布尔值 false 。让我们从编写下面的函数定义开始。
bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export {
在修改订单之前,我们必须确保交易环境允许算法交易。我们将使用 TradingIsAllowed() 函数来确认这一点。
if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function }
为了确保我们修改的是正确的订单,我们需要使用标准 MQL5 OrderSelect() 函数和提供的 orderTicket 函数参数来选择订单。如果订单无效或未成功选择,我们将记录此错误并退出该函数,返回布尔值 false 。如果订单单号选择成功,我们将打印一条简短的日志消息并继续处理订单。
//--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP."); } else { Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function }
一旦选择了订单,我们将创建一些 double 类型的变量来存储我们的止盈价格和止损价格,并用默认值零( 0.0 )初始化它们。然后,我们将获取有关订单的详细信息(如交易品种、交易量、当前 SL/TP等),这些信息将需要进行验证和修改。
double newTpPrice = 0.0, newSlPrice = 0.0; //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN); double volume = OrderGetDouble(ORDER_VOLUME_INITIAL); double currentOrderSlPrice = OrderGetDouble(ORDER_SL); double currentOrderTpPrice = OrderGetDouble(ORDER_TP); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT); //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD);
接下来,我们验证新的入场价格,以确保它根据订单类型(例如买入限价、买入止损、卖出止损和卖出限价)是正确的。这将确保我们及早发现并拒绝无效价格。
if(newEntryPrice > 0.0) { if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if( SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > newEntryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP) { if( SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < newEntryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } } else { newEntryPrice = currentEntryPrice; //-- Do not modify the entry price }
我们还需要根据输入参数计算新的止损价和止盈价,并根据经纪商的止损水平验证这些值。
if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice - (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice + (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice + (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice - (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } }
由于我们现在已经验证了所有值,我们将继续准备交易请求,通过设置适当的参数来修改挂单。我们将首先重置 tradeRequest 数据结构,然后使用我们验证过的有效订单数据对其进行初始化。
ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to set the sltp tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order tradeRequest.order = orderTicket; tradeRequest.symbol = orderSymbol; tradeRequest.price = newEntryPrice; tradeRequest.sl = newSlPrice; tradeRequest.tp = newTpPrice; tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2;
接下来,我们实现重试机制,如果初次尝试失败,则多次重新发送修改请求,以增加成功修改订单的可能性。如果发生严重错误或所有重试尝试都已用尽,该函数将返回 false 并退出。如果订单修改成功,函数将返回 true 并退出。为了避免交易服务器因一系列连续的快速请求而变得不堪重负,我们还将使用 Sleep(...) 函数在迭代之间引入延迟。
ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________\r\n\r\n"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- Order request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } }
这是完整的函数代码,包括一些缺失的部分,所有代码段的顺序正确。
bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } //--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP."); } else { Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function } //-- create variables to store the calculated tp and sl prices to send to the trade server double newTpPrice = 0.0, newSlPrice = 0.0; //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN); double volume = OrderGetDouble(ORDER_VOLUME_INITIAL); double currentOrderSlPrice = OrderGetDouble(ORDER_SL); double currentOrderTpPrice = OrderGetDouble(ORDER_TP); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT); //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD); //-- Check the validity of the newEntryPrice if(newEntryPrice > 0.0) { if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if( SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > newEntryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP) { if( SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < newEntryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } } else { newEntryPrice = currentEntryPrice; //-- Do not modify the entry price } //-- Calculate and store the non-validated sl and tp prices if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice - (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice + (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice + (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice - (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } //-- Print order properties before modification string orderProperties = "--> " + orderSymbol + " " + EnumToString(orderType) + " SLTP Modification Details" + " <--\r\n"; orderProperties += "------------------------------------------------------------\r\n"; orderProperties += "Ticket: " + (string)orderTicket + "\r\n"; orderProperties += "Volume: " + DoubleToString(volume, symbolDigits) + "\r\n"; orderProperties += "Price Open: " + DoubleToString(currentEntryPrice, symbolDigits) + " -> New Proposed Price Open: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n"; orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) + " -> New Proposed SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n"; orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) + " -> New Proposed TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n"; orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n"; orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n"; orderProperties += "---"; //-- Print verified order properties before modification orderProperties += "--> Validated and Confirmed NewEntry, SL, and TP Prices: <--\r\n"; orderProperties += "Order Price Current: " + DoubleToString(orderPriceCurrent, symbolDigits) + "\r\n"; orderProperties += "Current Entry Price: " + DoubleToString(currentEntryPrice, symbolDigits) + ", New Entry Price: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n"; orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) + " -> New SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n"; orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) + " -> New TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n"; Print(orderProperties); //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to set the sltp tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order tradeRequest.order = orderTicket; tradeRequest.symbol = orderSymbol; tradeRequest.price = newEntryPrice; tradeRequest.sl = newSlPrice; tradeRequest.tp = newTpPrice; tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2; ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________\r\n\r\n"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- Order request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
根据单号删除挂单函数
DeletePendingOrderByTicket(...) 函数负责使用其唯一单号删除挂单。它首先检查是否启用了算法交易,选择订单,然后尝试从交易服务器中删除它。在整个过程中,该函数会在不同阶段记录订单的重要细节,并采用重试机制来最大限度地提高成功删除的机会,必要时会重试多次。
该函数接受一个 ulong 类型的参数,即 orderTicket,表示要删除的订单的唯一单号。它返回一个 bool 值,其中 true 表示挂单已成功删除, false 表示删除失败或遇到严重错误。
下面是完整的函数代码,并附有详细的注释以确保更容易理解。
bool DeletePendingOrderByTicket(ulong orderTicket) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } //--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("..........................................................................................."); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to be deleted."); } else { Print("..........................................................................................."); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function } //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double orderVolume = OrderGetDouble(ORDER_VOLUME_CURRENT); int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); //-- Print order properties before deleting it string orderProperties; orderProperties += "-- " + orderSymbol + " " + EnumToString(orderType) + " Details" + " -------------------------------------------------------------\r\n"; orderProperties += "Ticket: " + (string)orderTicket + "\r\n"; orderProperties += "Volume: " + DoubleToString(orderVolume) + "\r\n"; orderProperties += "Price Open: " + DoubleToString(OrderGetDouble(ORDER_PRICE_OPEN), symbolDigits) + "\r\n"; orderProperties += "SL: " + DoubleToString(OrderGetDouble(ORDER_SL), symbolDigits) + "\r\n"; orderProperties += "TP: " + DoubleToString(OrderGetDouble(ORDER_TP), symbolDigits) + "\r\n"; orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n"; orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n"; orderProperties += "_______________________________________________________________________________________"; Print(orderProperties); //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the trade reqiest parameters to delete the order tradeRequest.action = TRADE_ACTION_REMOVE; //-- Trade operation type for deleting an order tradeRequest.order = orderTicket; ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try deleting the order until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print(__FUNCTION__, "_________________________________________________________________________"); PrintFormat("Successfully deleted order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- order deleting request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { Print(__FUNCTION__, "_________________________________________________________________________"); PrintFormat("ERROR deleting order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
删除所有挂单函数
DeleteAllPendingOrders(...) 函数用于删除给定交易品种和幻数的所有挂单。它首先确保算法交易已启用,然后再继续。该函数将遍历所有未结订单,检查它们是否与指定的交易品种和幻数匹配,并尝试逐一删除它们。当某些订单无法立即删除时,该函数会使用回调和重试机制不断尝试删除,直到所有目标订单都被删除。在整个过程中,它会记录错误并检查关键问题,以避免无限循环中的潜在锁定。
该函数接受两个可选参数:
- symbol (string):代表交易品种的字符串型参数。它默认为 ALL_SYMBOLS ,这意味着它将针对所有交易品种的订单,除非提供了特定的 交易品种。
- magicNumber(ulong) :一个无符号长整数型参数,代表订单的唯一幻数。其默认值为0 ,这意味着该函数将针对所有订单,而不管其幻数是多少,除非给出特定值。
该函数返回一个布尔值( bool ),其中 true 表示所有目标挂单均已成功删除, false 表示删除部分或全部订单失败,或者遇到严重错误。
以下是完整的函数代码,为了便于理解添加了注释:
bool DeleteAllPendingOrders(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number for the specified orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); //-- Filter orders by symbol and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Delete the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllPendingOrders(symbol, magicNumber); //-- We still have some open orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } //-- Final confirmations that all targeted orders have been closed if(SymbolOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; //-- Save this status for the function return value } return(returnThis); }
为了使删除所有待处理订单变得更快、更简单,我们将使用不带参数的第二个版本重载 DeleteAllPendingOrders(...) 函数。当调用时,它将删除帐户中所有挂单。以下是重载的 DeleteAllPendingOrders() 函数:
bool DeleteAllPendingOrders() export { return(DeleteAllPendingOrders(ALL_SYMBOLS, 0)); }
删除所有买入止损函数
DeleteAllBuyStops(...) 函数负责删除给定交易品种和幻数的所有待处理的买入止损订单。与其他删除函数类似,它首先检查是否启用算法交易。然后,该函数会扫描所有未结订单,识别出与交易品种、幻数和订单类型(买入止损)相匹配的订单,并尝试删除它们。如果在初始传递期间未删除任何订单,则该函数使用回调和重试机制不断尝试删除。它通过设置安全措施和检查错误来确保不会发生无限循环。在整个过程中,该函数会记录相关信息并管理严重错误。
该函数接受两个可选参数:
- symbol (string):代表交易品种的字符串。它默认为 ALL_SYMBOLS ,这意味着它将针对所有交易品种的买入止损订单,除非提供了特定的交易品种。
- magicNumber(ulong) :一个无符号长整数,代表分配给订单的唯一幻数。它默认为 0 ,这意味着该函数将针对所有买入止损订单,而不管其幻数是什么,除非指定了特定的幻数。
该函数返回一个布尔值( bool ),其中 true 表示所有目标买入止损订单均已成功删除, false 表示该函数未能删除部分或全部订单或遇到严重问题。
以下是完整的函数代码,其中包含有用的注释,以便于理解:
bool DeleteAllBuyStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific buy stop orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_STOP) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the buy stop orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolBuyStopOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllBuyStops(symbol, magicNumber); //-- We still have some open buy stop orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolBuyStopOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
删除所有买入限价挂单函数
DeleteAllBuyLimits(...) 函数的任务是删除给定交易品种和幻数的所有待处理的买入限价订单。该函数返回一个布尔值( bool ),其中 true 表示所有定向买入限价订单均已成功删除, false 表示该函数未能删除部分或全部订单或遇到严重问题。
bool DeleteAllBuyLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific buy limit orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_LIMIT) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the buy limit orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolBuyLimitOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllBuyLimits(symbol, magicNumber); //-- We still have some open buy limit orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolBuyLimitOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
删除所有卖出止损挂单函数
DeleteAllSellStops(...) 函数负责删除与特定交易品种和幻数相关的所有待处理的卖出止损订单。它返回一个布尔值( bool ),其中 true 表示所有目标卖出止损订单都已成功删除,而 false 表示该函数未能删除部分或全部订单,或者遇到严重错误。
bool DeleteAllSellStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific sell stop orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_STOP) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the sell stop orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolSellStopOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllSellStops(symbol, magicNumber); //-- We still have some open sell stop orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolSellStopOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
删除所有卖出限价挂单函数
DeleteAllSellLimits(...) 函数负责删除与特定交易品种和幻数相关的所有待处理的卖出限价订单。如果所有指定的卖出限价订单均已成功删除,则返回布尔值 ( bool ) true ;如果函数无法删除部分或全部订单或遇到严重错误,则返回 false 。
bool DeleteAllSellLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific sell limit orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_LIMIT) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the sell limit orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolSellLimitOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllSellLimits(symbol, magicNumber); //-- We still have some open sell limit orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolSellLimitOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
删除所有幻数挂单函数
DeleteAllMagicOrders(...) 函数负责删除与特定幻数相关的所有挂单。它返回一个布尔值( bool ), true 表示所有相关的魔术订单都已成功删除, false 表示该函数未能删除部分或全部订单,或者遇到了严重错误。
bool DeleteAllMagicOrders(ulong magicNumber) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Variables to store the selected orders data ulong orderTicket, orderMagicNo; string orderSymbol; //-- Scan for magic number specific orders and delete them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties orderTicket = OrderGetTicket(x); //-- Get ticket to select the order orderMagicNo = OrderGetInteger(ORDER_MAGIC); orderSymbol = OrderGetString(ORDER_SYMBOL); //-- Filter orders by magic number if(magicNumber == orderMagicNo) { //-- Delete the order DeletePendingOrderByTicket(orderTicket); } } //-- Confirm that we have deleted all the orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(MagicOrdersTotal(magicNumber) > 0) { breakerBreaker++; DeleteAllMagicOrders(magicNumber); //-- We still have some open orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, orderSymbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(MagicOrdersTotal(magicNumber) == 0) { returnThis = true; } return(returnThis); }
获取挂单数据函数
任何自主算法交易系统或 EA 交易要想最终可靠并持续盈利,就必须了解账户中的所有仓位和订单状态。在第二篇文章中,我们开发了一个监控仓位的函数,收集所有未平仓仓位的数据。由于本文重点介绍挂单,我们将创建一个函数来扫描和存储所有挂单的数据,以便整个库中的其他函数可以使用它。我们将使用本文开头建立的全局变量来实现这一点。
由于这些全局变量无法在库源代码文件或 .EX5 二进制文件之外导出或访问,我们将它们传递给各种可导出的挂单状态函数,以便它们可以在最终的 .EX5 库中访问。我们将首先创建一个函数来检索所有挂单的数据,我们将其命名为 GetPendingOrdersData(...) 。
GetPendingOrdersData(...) 函数将检索并保存与账户、特定交易品种和 EA 的幻数相关的未结挂单的状态详细信息。它将首先重置存储不同类型挂单的总数和交易量的各种全局变量,包括买入止损、买入限价、卖出止损和卖出限价。重置后,该函数将检查任何未结挂单,并对其进行迭代以收集相关数据。然后,它将根据提供的交易品种和幻数过滤订单,并累计匹配的挂单的总数和交易量。这种综合方法将确保该函数获取挂单状态的实时数据,这些数据可供“EA 交易”中的其他函数使用。
该函数将接受两个参数:
- symbol (string):表示将检索挂单数据的交易品种的字符串。它将默认为 ALL_SYMBOLS ,表示除非提供特定交易品种,否则它将收集所有交易品种的数据。
- magicNumber(ulong) :一个无符号长整数,代表分配给 EA 交易挂单的唯一幻数。此参数默认为 0,允许该函数检索所有挂单的数据,无论其幻数是多少,除非指定了特定的幻数。
该函数不会返回任何值( void ),因为其主要目的是使用挂单的详细信息填充和更新全局状态变量。然后,库的其他部分将访问这些变量,以通知决策和交易策略。
以下是完整的函数代码,并附有详细的注释以增强理解:
void GetPendingOrdersData(string symbol, ulong magicNumber) { //-- Reset the account open pending orders status accountBuyStopOrdersTotal = 0; accountBuyLimitOrdersTotal = 0; accountSellStopOrdersTotal = 0; accountSellLimitOrdersTotal = 0; accountPendingOrdersVolumeTotal = 0.0; accountBuyStopOrdersVolumeTotal = 0.0; accountBuyLimitOrdersVolumeTotal = 0.0; accountSellStopOrdersVolumeTotal = 0.0; accountSellLimitOrdersVolumeTotal = 0.0; //-- Reset the EA's magic open pending orders status magicPendingOrdersTotal = 0; magicBuyStopOrdersTotal = 0; magicBuyLimitOrdersTotal = 0; magicSellStopOrdersTotal = 0; magicSellLimitOrdersTotal = 0; magicPendingOrdersVolumeTotal = 0.0; magicBuyStopOrdersVolumeTotal = 0.0; magicBuyLimitOrdersVolumeTotal = 0.0; magicSellStopOrdersVolumeTotal = 0.0; magicSellLimitOrdersVolumeTotal = 0.0; //-- Reset the symbol open pending orders status symbolPendingOrdersTotal = 0; symbolBuyStopOrdersTotal = 0; symbolBuyLimitOrdersTotal = 0; symbolSellStopOrdersTotal = 0; symbolSellLimitOrdersTotal = 0; symbolPendingOrdersVolumeTotal = 0.0; symbolBuyStopOrdersVolumeTotal = 0.0; symbolBuyLimitOrdersVolumeTotal = 0.0; symbolSellStopOrdersVolumeTotal = 0.0; symbolSellLimitOrdersVolumeTotal = 0.0; //-- Update and save the open pending orders status with realtime data int totalOpenPendingOrders = OrdersTotal(); if(totalOpenPendingOrders > 0) { //-- Scan for symbol and magic number specific pending orders and save their status for(int x = 0; x < totalOpenPendingOrders; x++) { //--- Get the pending orders properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the pending order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); //-- Filter pending orders by magic number if(magicNumber != 0 && orderMagicNo != magicNumber) { continue; } //-- Save the account pending orders status first accountPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { //-- Account properties ++accountBuyStopOrdersTotal; accountBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { //-- Account properties ++accountBuyLimitOrdersTotal; accountBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { //-- Account properties ++accountSellStopOrdersTotal; accountSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { //-- Account properties ++accountSellLimitOrdersTotal; accountSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } //-- Filter pending orders openend by EA and save their status if( OrderGetInteger(ORDER_REASON) == ORDER_REASON_EXPERT && orderMagicNo == magicNumber ) { ++magicPendingOrdersTotal; magicPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { //-- Magic properties ++magicBuyStopOrdersTotal; magicBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { //-- Magic properties ++magicBuyLimitOrdersTotal; magicBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { //-- Magic properties ++magicSellStopOrdersTotal; magicSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { //-- Magic properties ++magicSellLimitOrdersTotal; magicSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } } //-- Filter positions by symbol if(symbol == ALL_SYMBOLS || selectedSymbol == symbol) { ++symbolPendingOrdersTotal; symbolPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { ++symbolBuyStopOrdersTotal; symbolBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { ++symbolBuyLimitOrdersTotal; symbolBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { ++symbolSellStopOrdersTotal; symbolSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { ++symbolSellLimitOrdersTotal; symbolSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } } } } }
买入止损订单总数函数
返回代表账户中未结买入止损订单总数的整数。
int BuyStopOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyStopOrdersTotal); }
买入限价订单总数函数
返回代表账户中未结买入限价订单总数的整数。
int BuyLimitOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyLimitOrdersTotal); }
卖出止损订单总数函数
返回一个整数,表示账户中未结卖出止损订单的总数。
int SellStopOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellStopOrdersTotal); }
卖出限价订单总数函数
返回代表账户中未结卖出限价订单总数的整数。
int SellLimitOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellLimitOrdersTotal); }
订单总量函数
返回一个双精度值,表示账户中所有未结订单的总交易量/手数/数量。
double OrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountPendingOrdersVolumeTotal); }
买入止损订单总量函数
返回一个双精度值,表示账户中所有未平仓买入止损订单的总交易量/手数/数量。
double BuyStopOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyStopOrdersVolumeTotal); }
买入限价订单总量函数
返回一个双精度值,表示账户中所有未平仓买入限价订单的总交易量/手数/数量。
double BuyLimitOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyLimitOrdersVolumeTotal); }
卖出止损订单总量函数
返回一个双精度值,表示账户中所有未平仓卖出止损订单的总交易量/手数/数量。
double SellStopOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellStopOrdersVolumeTotal); }
卖出限价订单总量函数
返回一个双精度值,表示账户中所有未平仓卖出限价订单的总交易量/手数/数量。
double SellLimitOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellLimitOrdersVolumeTotal); }
幻数订单总数函数
返回帐户中指定幻数的所有未结挂单总数的整数值。
int MagicOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicPendingOrdersTotal); }
幻数买入止损订单总数函数
返回帐户中指定幻数的所有未平仓买入止损订单总数的整数值。
int MagicBuyStopOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyStopOrdersTotal); }
幻数买入限价订单总数函数
返回帐户中指定幻数的所有未结买入限价订单总数的整数值。
int MagicBuyLimitOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyLimitOrdersTotal); }
幻数卖出止损订单总数函数
返回帐户中指定幻数的所有未结卖出止损订单总数的整数值。
int MagicSellStopOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellStopOrdersTotal); }
幻数限价卖单总数函数
返回帐户中指定幻数的所有未结卖出限价订单总数的整数值。
int MagicSellLimitOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellLimitOrdersTotal); }
幻数订单总量函数
返回一个双精度值,表示账户中指定幻数的所有未结挂单的总交易量/手数/数量。
double MagicOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicPendingOrdersVolumeTotal); }
幻数买入止损订单总量函数
返回一个双精度值,表示账户中指定幻数的所有未平仓买入止损订单的总交易量/手数/数量。
double MagicBuyStopOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyStopOrdersVolumeTotal); }
幻数买入限价订单总量函数
返回一个双精度值,表示账户中指定幻数的所有未平仓买入限价订单的总交易量/手数/数量。
double MagicBuyLimitOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyLimitOrdersVolumeTotal); }
幻数卖出止损订单总量函数
返回一个双精度值,表示账户中指定幻数的所有未平仓卖出止损订单的总交易量/手数/数量。
double MagicSellStopOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellStopOrdersVolumeTotal); }
幻数卖出限价订单总量函数
返回一个双精度值,表示账户中指定幻数的所有未平仓卖出限价订单的总交易量/手数/数量。
double MagicSellLimitOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellLimitOrdersVolumeTotal); }
交易品种订单总数函数
返回一个整数值,表示帐户中指定交易品种和幻数的所有未结挂单总数。
int SymbolOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolPendingOrdersTotal); }
交易品种买入止损单总数函数
返回一个整数值,表示账户中指定交易品种和幻数的所有未结买入止损订单的总数。
int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyStopOrdersTotal); }
交易品种买入限价单总数函数
返回一个整数值,表示账户中指定交易品种和幻数的所有未结买入限价订单的总数。
int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyLimitOrdersTotal); }
交易品种卖出止损单总数函数
返回一个整数值,表示账户中指定交易品种和幻数的所有未结卖出止损订单的总数。
int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellStopOrdersTotal); }
交易品种卖出限价单总数函数
返回一个整数值,表示账户中指定交易品种和幻数的所有未结卖出限价订单的总数。
int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellLimitOrdersTotal); }
交易品种订单总量函数
返回一个双精度值,表示账户中指定交易品种和幻数的所有未结挂单的总交易量/手数/数量。
double SymbolOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolPendingOrdersVolumeTotal); }
交易品种买入止损单总量函数
返回一个双精度值,表示账户中指定交易品种和幻数的所有未平仓买入止损订单的总交易量/手数/数量。
double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyStopOrdersVolumeTotal); }
交易品种买入限价单总量函数
返回一个双精度值,表示账户中指定交易品种和幻数的所有未平仓买入限价订单的总交易量/手数/数量。
double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyLimitOrdersVolumeTotal); }
交易品种卖出止损单总量函数
返回一个双精度值,表示账户中指定交易品种和幻数的所有未平仓卖出止损订单的总交易量/手数/数量。
double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellStopOrdersVolumeTotal); }
交易品种卖出限价单总量函数
返回一个双精度值,表示账户中指定交易品种和幻数的所有未平仓卖出限价订单的总交易量/手数/数量。
double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellLimitOrdersVolumeTotal); }
账户订单状态函数
返回包含帐户订单状态的预格式化字符串,可以打印到日志中或显示在图表注释中。该函数采用一个名为 formatForComment 的布尔参数。如果 formatForComment 设置为 true ,则该函数会格式化数据以在图表窗口中显示;如果设置为 false ,则它会格式化 EA 日志选项卡的数据。
string AccountOrdersStatus(bool formatForComment) export { GetPendingOrdersData(ALL_SYMBOLS, 0); //-- Update the orders status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string accountOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| " + (string)AccountInfoInteger(ACCOUNT_LOGIN) + " - ACCOUNT ORDERS STATUS \r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)OrdersTotal() + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountPendingOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountBuyStopOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountBuyStopOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountBuyLimitOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountBuyLimitOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountSellStopOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountSellStopOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountSellLimitOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountSellLimitOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "\r\n"; return(accountOrdersStatus); }
幻数订单状态函数
返回一个预格式化的字符串,指示幻数订单的状态,可以打印到日志中或显示在图表注释中。该函数接受两个参数:一个名为 magicNumber的无符号长整型,用于指定目标幻数,以及一个名为 formatForComment 的布尔值,用于确定格式类型。如果 formatForComment 为 true ,则该函数会格式化数据以在图表窗口中显示;如果为 false ,则该函数会格式化 EA 日志选项卡的数据。
string MagicOrdersStatus(ulong magicNumber, bool formatForComment) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); //-- Update the order status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string magicOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| " + (string)magicNumber + " - MAGIC ORDERS STATUS \r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicPendingOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicPendingOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicBuyStopOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicBuyStopOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicBuyLimitOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicBuyLimitOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicSellStopOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicSellStopOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicSellLimitOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicSellLimitOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "\r\n"; return(magicOrdersStatus); }
交易品种订单状态函数
返回一个预格式化的字符串,指示交易品种订单的状态,可以打印到日志中或显示在图表注释中。该函数接受三个参数:一个名为 symbol 的字符串、一个名为 magicNumber 的无符号长整型(用于指定目标幻数(零 (0) 值将禁用幻数过滤器))以及一个名为 formatForComment 的布尔值(用于确定格式类型)。如果 formatForComment 为 true ,则该函数会格式化数据以在图表窗口中显示;如果为 false ,则该函数会格式化 EA 日志选项卡的数据。
string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment) export { GetPendingOrdersData(symbol, magicNumber); //-- Update the order status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string symbolOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| " + symbol + " - SYMBOL ORDERS STATUS \r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolPendingOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolPendingOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolBuyStopOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolBuyStopOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolBuyLimitOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolBuyLimitOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolSellStopOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolSellStopOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolSellLimitOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolSellLimitOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "\r\n"; return(symbolOrdersStatus); }
我们上面创建的广泛的库函数构成了我们的待处理订单管理 EX5库。在本文的底部,您将找到源代码文件 PendingOrdersManager.mq5 以及编译后的二进制可执行文件 PendingOrdersManager.ex5 ,您可以轻松地将其导入并在您的 MQL5 项目中使用。
如何导入和实现我们的挂单管理 EX5 库
我们开发了一个强大的挂单管理 EX5 库,其中包括处理挂单、检索其状态和显示相关信息的基本函数。现在,是时候记录并演示如何在任何 MQL5 项目中正确导入和使用这个库了。
为了使实施过程更容易,我们将首先概述待处理订单管理库中的所有功能和模块,以及下面文档部分中的实际代码示例。这将使用户清楚地了解 PendingOrdersManager.ex5 二进制文件中包含的组件。
挂单管理器 EX5 库文档
步骤 1:复制库可执行文件( PositionsManager.ex5和PendingOrdersManager.ex5 )将 PositionsManager.ex5 和 PendingOrdersManager.ex5 文件放在 MQL5/Libraries/Toolkit 文件夹或同一文件夹中,作为导入库的源代码文件。如果这些文件尚未存在,请确保已下载并复制到指定位置。为了您的方便,本文末尾附上了这两个文件的副本。
步骤 2:导入函数原型描述
在源代码的标题部分,添加用于挂单管理器库的 import 指令及其函数原型描述。使用以下代码段可以有效地从 PendingOrdersManager.ex5 库中导入所有函数或模块。我还创建了一个包含此代码段的空白 EA 交易模板( PendingOrdersManager_Imports_Template.mq5 )。您可以注释掉或删除项目不需要的任何函数描述。 PendingOrdersManager_Imports_Template.mq5文件也附加在本文末尾。
//+------------------------------------------------------------------------------------------+ //-- Copy and paste the import derictives below to use the Pending Orders Manager EX5 Library //--- //+-------------------------------------------------------------------------------------+ //| PendingOrdersManager.ex5 imports template | //+-------------------------------------------------------------------------------------+ #import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Pending Orders Execution and Modification Functions bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp); bool DeletePendingOrderByTicket(ulong orderTicket); bool DeleteAllPendingOrders(string symbol, ulong magicNumber); bool DeleteAllPendingOrders(); bool DeleteAllBuyStops(string symbol, ulong magicNumber); bool DeleteAllBuyLimits(string symbol, ulong magicNumber); bool DeleteAllSellStops(string symbol, ulong magicNumber); bool DeleteAllSellLimits(string symbol, ulong magicNumber); bool DeleteAllMagicOrders(ulong magicNumber); //-- Pending Orders Status Monitoring Functions int BuyStopOrdersTotal(); int BuyLimitOrdersTotal(); int SellStopOrdersTotal(); int SellLimitOrdersTotal(); double OrdersTotalVolume(); double BuyStopOrdersTotalVolume(); double BuyLimitOrdersTotalVolume(); double SellStopOrdersTotalVolume(); double SellLimitOrdersTotalVolume(); //-- Pending Orders Filtered By Magic Number Status Monitoring Functions int MagicOrdersTotal(ulong magicNumber); int MagicBuyStopOrdersTotal(ulong magicNumber); int MagicBuyLimitOrdersTotal(ulong magicNumber); int MagicSellStopOrdersTotal(ulong magicNumber); int MagicSellLimitOrdersTotal(ulong magicNumber); double MagicOrdersTotalVolume(ulong magicNumber); double MagicBuyStopOrdersTotalVolume(ulong magicNumber); double MagicBuyLimitOrdersTotalVolume(ulong magicNumber); double MagicSellStopOrdersTotalVolume(ulong magicNumber); double MagicSellLimitOrdersTotalVolume(ulong magicNumber); //-- Pending Orders Filtered By Symbol and/or Magic Number Status Monitoring Functions int SymbolOrdersTotal(string symbol, ulong magicNumber); int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber); int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber); int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber); int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber); double SymbolOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber); //-- Log and Data Display Functions string AccountOrdersStatus(bool formatForComment); string MagicOrdersStatus(ulong magicNumber, bool formatForComment); string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment); #import //--- Closing import directive //+-------------------------------------------------------------------------------------+
现在,.EX5 库原型函数已导入您的 MQL5 项目或源代码,下表提供了有关如何在代码中实现和使用这些函数的详细文档和实际示例。
函数原型描述 | 描述 | 用例示例 |
---|---|---|
bool OpenBuyLimit( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | 打开一个符合指定参数的新买入限价订单。 | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Buy Limit Order"; OpenBuyLimit( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenBuyStop( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | 打开一个符合指定参数的新买入止损订单。 | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Buy Stop Order"; OpenBuyStop( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenSellLimit( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | 打开一个符合指定参数的新卖出限价订单。 | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Sell Limit Order"; OpenSellLimit( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenSellStop( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | 打开一个符合指定参数的新卖出止损订单。 | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Sell Stop Order"; OpenSellStop( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool ModifyPendingOrderByTicket( ulong orderTicket, double newEntryPrice, int newSl, int newTp ); | 使用指定的参数修改挂单。 | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); int totalOpenOders = OrdersTotal(); for(int x = 0; x < totalOpenOders; x++) { ulong orderTicket = OrderGetTicket(x); if(orderTicket > 0) { //-- Modify a buy stop order if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { double newEntryPrice = OrderGetDouble( ORDER_PRICE_OPEN) + ((spread * 40) * symbolPoint ); int newSl = 0; //-- Do not modify the stop loss level int newTp = 0; //-- Don not modify the take profit level ModifyPendingOrderByTicket( orderTicket, newEntryPrice, newSl, newTp ); break; } } } |
bool DeletePendingOrderByTicket( ulong orderTicket ); | 根据提供的单号参数删除待处理的订单。 | for(int x = 0; x < totalOpenOders; x++) { ulong orderTicket = OrderGetTicket(x); if(orderTicket > 0) { DeletePendingOrderByTicket(orderTicket); break; } } |
bool DeleteAllPendingOrders( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | 根据提供的交易品种名称和幻数参数删除所有挂单。 | //Deletes all orders in the account DeleteAllPendingOrders("", 0); //Deletes all orders belonging to the symbol DeleteAllPendingOrders(_Symbol, 0); //Deletes all orders that have a magic number 101 DeleteAllPendingOrders("", 101); //Deletes all EURUSD orders that have a magic number 101 DeleteAllPendingOrders("EURUSD", 101); |
bool DeleteAllPendingOrders() | 只需删除帐户中所有未结订单即可。 | //Deletes all orders in the account
DeleteAllPendingOrders(); |
bool DeleteAllBuyStops( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | 根据提供的交易品种名称和幻数参数删除所有买入止损订单。 | //Deletes all buy stops in the account DeleteAllBuyStops("", 0); //Deletes all buy stops belonging to the symbol DeleteAllBuyStops(_Symbol, 0); //Deletes all buy stops that have a magic number 101 DeleteAllBuyStops("", 101); //Deletes all EURUSD buy stops that have a magic number 101 DeleteAllBuyStops("EURUSD", 101); |
bool DeleteAllBuyLimits( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | 根据提供的交易品种名称和幻数参数删除所有买入限价订单。 | //Deletes all buy limits in the account DeleteAllBuyLimits("", 0); //Deletes all buy limits belonging to the symbol DeleteAllBuyLimits(_Symbol, 0); //Deletes all buy limits that have a magic number 101 DeleteAllBuyLimits("", 101); //Deletes all GBPUSD buy limits that have a magic number 101 DeleteAllBuyLimits("GBPUSD", 101); |
bool DeleteAllSellStops( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | 根据提供的交易品种名称和幻数参数删除所有卖出止损订单。 | //Deletes all sell stops in the account DeleteAllSellStops("", 0); //Deletes all sell stops belonging to the symbol DeleteAllSellStops(_Symbol, 0); //Deletes all sell stops that have a magic number 101 DeleteAllSellStops("", 101); //Deletes all JPYUSD sell stops that have a magic number 101 DeleteAllSellStops("JPYUSD", 101); |
bool DeleteAllSellLimits( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | 根据提供的交易品种名称和幻数参数删除所有卖出限价订单。 | //Deletes all sell limits in the account DeleteAllSellLimits("", 0); //Deletes all sell limits belonging to the symbol DeleteAllSellLimits(_Symbol, 0); //Deletes all sell limits that have a magic number 101 DeleteAllSellLimits("", 101); //Deletes all AUDJPY sell limits that have a magic number 101 DeleteAllSellLimits("AUDJPY", 101); |
bool DeleteAllMagicOrders( ulong magicNumber ); | 根据提供的幻数参数删除所有挂单。 | //-- Deletes all orders open in the account DeleteAllMagicOrders("", 0); //-- Deletes all orders that have a magic number 101 DeleteAllMagicOrders(101); |
int BuyStopOrdersTotal(); | 返回未平仓买入止损订单的总数。 | //Get the total number of open buy stops in the account
BuyStopOrdersTotal(); |
int BuyLimitOrdersTotal(); | 返回未平仓买入限价订单的总数。 | //Get the total number of open buy limits in the account
BuyLimitOrdersTotal(); |
int SellStopOrdersTotal(); | 返回未平仓卖出止损订单的总数。 | //Get the total number of open sell stops in the account SellStopOrdersTotal(); |
int SellLimitOrdersTotal(); | 返回未平仓卖出限价订单的总数。 | //Get the total number of open sell limits in the account
SellLimitOrdersTotal(); |
double OrdersTotalVolume(); | 返回所有未平仓订单的总量。 | //Get the total volume/lot of open orders in the account
OrdersTotalVolume(); |
double BuyStopOrdersTotalVolume(); | 返回所有买入止损订单的总量。 | //Get the total volume/lot of open buy stops in the account
BuyStopOrdersTotalVolume(); |
double BuyLimitOrdersTotalVolume(); | 返回所有买入限价订单的总量。 | //Get the total volume/lot of open buy limits in the account
BuyLimitOrdersTotalVolume(); |
double SellStopOrdersTotalVolume(); | 返回所有卖出止损订单的总量。 | //Get the total volume/lot of open sell stops in the account
SellStopOrdersTotalVolume(); |
double SellLimitOrdersTotalVolume(); | 返回所有卖出限价订单的总量。 | //Get the total volume/lot of open sell limits in the account
SellLimitOrdersTotalVolume(); |
int MagicOrdersTotal( ulong magicNumber ); | 返回与指定幻数匹配的未结订单数量。 | //Get the total open pending orders for magic number 101 MagicOrdersTotal(101); |
int MagicBuyStopOrdersTotal( ulong magicNumber ); | 返回与指定幻数匹配的未结买入止损订单的数量。 | //Get the total open buy stop orders for magic number 101 MagicBuyStopOrdersTotal(101); |
int MagicBuyLimitOrdersTotal( ulong magicNumber ); | 返回与指定幻数匹配的未结买入限价订单的数量。 | //Get the total open buy limit orders for magic number 101 MagicBuyLimitOrdersTotal(101); |
int MagicSellStopOrdersTotal( ulong magicNumber ); | 返回与指定幻数匹配的未结卖出止损订单的数量。 | //Get the total open sell stop orders for magic number 101 MagicSellStopOrdersTotal(101); |
int MagicSellLimitOrdersTotal( ulong magicNumber ); | 返回与指定幻数匹配的未结卖出限价订单的数量。 | //Get the total open sell limit orders for magic number 101 MagicSellLimitOrdersTotal(101); |
double MagicOrdersTotalVolume( ulong magicNumber ); | 返回与指定幻数匹配的所有未结订单的总量。 | //Get the total volume/lot of all open orders for magic 101 MagicOrdersTotalVolume(101); |
double MagicBuyStopOrdersTotalVolume( ulong magicNumber ); | 返回与指定幻数匹配的所有未结买入止损订单的总量。 | //Get the total volume/lot of all buy stop orders for magic 101 MagicBuyStopOrdersTotalVolume(101); |
double MagicBuyLimitOrdersTotalVolume( ulong magicNumber ); | 返回与指定幻数匹配的所有未结买入限价订单的总量。 | //Get the total volume/lot of all buy limit orders for magic 101 MagicBuyLimitOrdersTotalVolume(101); |
double MagicSellStopOrdersTotalVolume( ulong magicNumber ); | 返回与指定幻数匹配的所有未结卖出止损订单的总量。 | //Get the total volume/lot of all sell stop orders for magic 101 MagicSellStopOrdersTotalVolume(101); |
double MagicSellLimitOrdersTotalVolume( ulong magicNumber ); | 返回与指定幻数匹配的所有未结卖出限价订单的总量。 | //Get the total volume/lot of all sell limit orders for magic 101 MagicSellLimitOrdersTotalVolume(101); |
int SymbolOrdersTotal( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的未结订单数量。 | //Get the total open orders for the symbol SymbolOrdersTotal(_Symbol, 0); //Get the total open orders for the symbol and magic 101 SymbolOrdersTotal(_Symbol, 101); |
int SymbolBuyStopOrdersTotal( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的未结买入止损订单的数量。 | //Get the total buy stop orders for the symbol SymbolBuyStopOrdersTotal(_Symbol, 0); //Get the total buy stop orders for the symbol and magic number 101 SymbolBuyStopOrdersTotal(_Symbol, 101); |
int SymbolBuyLimitOrdersTotal( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的未结买入限价订单的数量。 | //Get the total buy limit orders for the symbol SymbolBuyLimitOrdersTotal(_Symbol, 0); //Get the total buy limit orders for the symbol and magic number 101 SymbolBuyLimitOrdersTotal(_Symbol, 101); |
int SymbolSellStopOrdersTotal( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的未结卖出止损订单的数量。 | //Get the total sell stop orders for the symbol SymbolSellStopOrdersTotal(_Symbol, 0); //Get the total sell stop orders for the symbol and magic 101 SymbolSellStopOrdersTotal(_Symbol, 101); |
int SymbolSellLimitOrdersTotal( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的未结卖出限价订单的数量。 | //Get the total sell limit orders for the symbol SymbolSellLimitOrdersTotal(_Symbol, 0); //Get the total sell limit orders for the symbol and magic 101 SymbolSellLimitOrdersTotal(_Symbol, 101); |
double SymbolOrdersTotalVolume( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的所有未结订单的总量。 | //Get the total orders volume/lot for the symbol SymbolOrdersTotalVolume(_Symbol, 0); //Get the total orders volume/lot for the symbol and magic 101 SymbolOrdersTotalVolume(_Symbol, 101); |
double SymbolBuyStopOrdersTotalVolume( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的所有未结买入止损订单的总量。 | //Get the total buy stops volume/lot for the symbol SymbolBuyStopOrdersTotalVolume(_Symbol, 0); //Get the total buy stops volume/lot for the symbol and magic 101 SymbolBuyStopOrdersTotalVolume(_Symbol, 101); |
double SymbolBuyLimitOrdersTotalVolume( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的所有未结买入限价订单的总量。 | //Get the total buy limits volume/lot for the symbol SymbolBuyLimitOrdersTotalVolume(_Symbol, 0); //Get the total buy limits volume/lot for symbol and magic 101 SymbolBuyLimitOrdersTotalVolume(_Symbol, 101); |
double SymbolSellStopOrdersTotalVolume( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的所有未结卖出止损订单的总量。 | //Get the total sell stops volume/lot for symbol SymbolSellStopOrdersTotalVolume(_Symbol, 0); //Get the total sell stops volume/lot for symbol and magic 101 SymbolSellStopOrdersTotalVolume(_Symbol, 101); |
double SymbolSellLimitOrdersTotalVolume( string symbol, ulong magicNumber ); | 返回与指定交易品种和幻数匹配的所有未结卖出限价订单的总量。 | //Get the total sell limits volume/lot for symbol SymbolSellLimitOrdersTotalVolume(_Symbol, 0); //Get the total sell limits volume/lot for symbol and magic 101 SymbolSellLimitOrdersTotalVolume(_Symbol, 101); |
string AccountOrdersStatus( bool formatForComment ); | 在 MetaTrader 5 中的交易品种图表或专家选项卡上打印所有未结订单的字符串格式状态。 | //Print the status of all open orders //formatted for the chart comments Comment(AccountOrdersStatus(true)); //Print the status of all open orders //formatted for the Experts tab Print(AccountOrdersStatus(false)); //Activate an alert with the status of all //open orders formatted for printing Print(AccountOrdersStatus(false)); |
string MagicOrdersStatus( ulong magicNumber, bool formatForComment ); | 在 MetaTrader 5 中的交易品种图表或专家选项卡上打印与指定幻数匹配的所有未结订单的字符串格式的状态。 | //Print the status of all open orders matching //magic number 101 formatted for the chart comments Comment(MagicOrdersStatus(101, true)); //Print the status of all open orders matching //magic number 101 formatted for the Experts tab Print(MagicOrdersStatus(101, false)); //Activate an alert with the status of all open orders //matching magic number 101 formatted for printing Print(MagicOrdersStatus(101, false)); |
string SymbolOrdersStatus( string symbol, ulong magicNumber, bool formatForComment ); | 在 MetaTrader 5 中的交易品种图表或专家选项卡上打印与指定交易品种和幻数匹配的所有未结订单的字符串格式状态。 | //Print the status of all open orders matching //the symbol and magic number 101 formatted for the chart comments Comment(SymbolOrdersStatus(_Symbol, 101, true)); //Print the status of all open orders matching //the symbol and magic number 101 formatted for the Experts tab Print(SymbolOrdersStatus(_Symbol, 101, false)); //Activate an alert with the status of all open orders //matching the symbol and magic number 101 formatted for printing Print(SymbolOrdersStatus(_Symbol, 101, false)); |
导入库后,您现在可以通过简单的函数调用轻松打开、修改、删除或检索挂单状态数据。为了证明这一点,让我们在下一节中创建一个实用的图形用户界面 (GUI) 交易面板来管理挂单。
如何开发由挂单管理器 EX5 库支持的挂单面板 (GUI)
在本节中,我们将为Pending Orders Panel(挂单面板)EA 交易开发一个图形用户界面 (GUI),该界面利用挂单管理器 EX5 库来打开、删除和监控与面板绑定的指定幻数相关的所有订单。此示例提供了一个实际演示,说明如何在真实的 MQL5 应用程序中导入和实现我们刚刚创建的 EX5 库。
挂单面板将利用 MQL5 标准库作为面板和对话框,使我们能够保持代码库的精简和高效。下面是最终的“挂单面板”GUI 的图片。
要开始构建 GUI,请使用 MetaEditor IDE 的 MQL 向导创建一个新的 EA 交易,并将其命名为 PendingOrdersPanel.mq5 。由于我们的“挂单面板”EA 交易将集成 PendingOrdersManager.ex5 库,因此第一步是导入并包含该库的函数原型描述,如前所述。将库导入代码放在 #property 指令的正下方。鉴于该库包含大量函数,我们将仅导入所需的特定函数原型,这些函数原型在下面的代码中列出。
#import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Pending Orders Execution and Modification Functions bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); //-- int MagicOrdersTotal(ulong magicNumber); int MagicBuyStopOrdersTotal(ulong magicNumber); int MagicBuyLimitOrdersTotal(ulong magicNumber); int MagicSellStopOrdersTotal(ulong magicNumber); int MagicSellLimitOrdersTotal(ulong magicNumber); //-- bool DeleteAllBuyStops(string symbol, ulong magicNumber); bool DeleteAllBuyLimits(string symbol, ulong magicNumber); bool DeleteAllSellStops(string symbol, ulong magicNumber); bool DeleteAllSellLimits(string symbol, ulong magicNumber); bool DeleteAllMagicOrders(ulong magicNumber); #import //--- Closing import directive
创建用于存储订单属性的全局变量。
//-- Global variables //----------------------- ulong magicNo = 10101010; double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); long symbolDigits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); double volumeLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); int sl = (int)spread * 50; int tp = (int)spread * 100;
接下来,我们需要定义一些常量来存储所有图形对象属性。如果我们想对订单面板的外观进行任何更改,这将使我们更容易在一个中心位置更新或修改它们的值。
//-- Define some values for the main panel #define MAIN_PANEL_NAME string("Orders Panel - Trading: " + _Symbol + " - Magic No: " + IntegerToString(magicNo)) #define MAIN_PANEL_SUBWINDOW 0 #define MAIN_PANEL_X1 350 #define MAIN_PANEL_Y1 10 #define MAIN_PANEL_WIDTH int(800 + MAIN_PANEL_X1) #define MAIN_PANEL_X2 MAIN_PANEL_WIDTH //-- Define the GUI objects general properties #define GUI_OBJECTS_MARGIN 5 #define GUI_OBJECTS_HEIGHT 40//40 #define GUI_OBJECTS_WIDTH int((MAIN_PANEL_WIDTH) / 7) #define GUI_OBJECTS_FONT_SIZE 9//10 #define GUI_OBJECTS_HEADER_FONT_SIZE GUI_OBJECTS_FONT_SIZE //----- #define MAIN_PANEL_HEIGHT int(((GUI_OBJECTS_HEIGHT + (GUI_OBJECTS_MARGIN * 2)) * 10) + MAIN_PANEL_Y1) #define MAIN_PANEL_Y2 MAIN_PANEL_HEIGHT //-- Define the GUI objects colors #define GUI_OBJECTS_HEADING_COLOR clrNavy #define GUI_OBJECTS_BUY_BTN_COLOR clrWhite #define GUI_OBJECTS_BUY_BTN_BG_COLOR clrBlue #define GUI_OBJECTS_BUY_EDIT_COLOR clrBlue #define GUI_OBJECTS_BUY_EDIT_BG_COLOR clrAliceBlue #define GUI_OBJECTS_SELL_BTN_COLOR clrWhite #define GUI_OBJECTS_SELL_BTN_BG_COLOR clrCrimson #define GUI_OBJECTS_SELL_EDIT_COLOR clrMaroon #define GUI_OBJECTS_SELL_EDIT_BG_COLOR clrMistyRose /*------------------------------------------------------ * Define GUI components for the heading labels **** *-----------------------------------------------------*/ //-- Define values for the lotVolHeaderLabel #define VOLUME_LOT_LABEL_NAME "Volume Lot Header Label" #define VOLUME_LOT_LABEL_SUBWINDOW 0 #define VOLUME_LOT_LABEL_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define VOLUME_LOT_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define VOLUME_LOT_LABEL_TEXT "VOLUME/LOT" //-- Define values for the openPriceHeaderLabel #define OPEN_PRICE_LABEL_NAME "Open Price Header Label" #define OPEN_PRICE_LABEL_SUBWINDOW 0 #define OPEN_PRICE_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 2) #define OPEN_PRICE_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define OPEN_PRICE_LABEL_TEXT "OPENING PRICE" //-- Define values for the slHeaderLabel #define SL_LABEL_NAME "Sl Header Label" #define SL_LABEL_SUBWINDOW 0 #define SL_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3) #define SL_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define SL_LABEL_TEXT "SL (Pips)" //-- Define values for the tpHeaderLabel #define TP_LABEL_NAME "Tp Header Label" #define TP_LABEL_SUBWINDOW 0 #define TP_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3.75) #define TP_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define TP_LABEL_TEXT "TP (Pips)" /*------------------------------------------------------ * Define Buy Stop Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the buyStopBtn #define BUY_STOP_BTN_NAME "Buy Stop Button" #define BUY_STOP_BTN_SUBWINDOW 0 #define BUY_STOP_BTN_X1 GUI_OBJECTS_MARGIN #define BUY_STOP_BTN_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) #define BUY_STOP_BTN_TEXT "BUY STOP" //-- Define values for the buyStopVolumeLotEdit #define BUY_STOP_VOLUME_LOT_EDIT_NAME "Buy Stop Volume Lot Edit" #define BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0 #define BUY_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define BUY_STOP_VOLUME_LOT_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopOpenPriceEdit #define BUY_STOP_OPEN_PRICE_EDIT_NAME "Buy Stop Open Price Edit" #define BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0 #define BUY_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define BUY_STOP_OPEN_PRICE_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopSlEdit #define BUY_STOP_SL_EDIT_NAME "Buy Stop SL Edit" #define BUY_STOP_SL_EDIT_SUBWINDOW 0 #define BUY_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define BUY_STOP_SL_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopTpEdit #define BUY_STOP_TP_EDIT_NAME "Buy Stop TP Edit" #define BUY_STOP_TP_EDIT_SUBWINDOW 0 #define BUY_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define BUY_STOP_TP_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) /*------------------------------------------------------ * Define Sell Stop Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the sellStopBtn #define SELL_STOP_BTN_NAME "Sell Stop Button" #define SELL_STOP_BTN_SUBWINDOW 0 #define SELL_STOP_BTN_X1 GUI_OBJECTS_MARGIN #define SELL_STOP_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) #define SELL_STOP_BTN_TEXT "SELL STOP" //-- Define values for the sellStopVolumeLotEdit #define SELL_STOP_VOLUME_LOT_EDIT_NAME "Sell Stop Volume Lot Edit" #define SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0 #define SELL_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define SELL_STOP_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopOpenPriceEdit #define SELL_STOP_OPEN_PRICE_EDIT_NAME "Sell Stop Open Price Edit" #define SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0 #define SELL_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define SELL_STOP_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopSlEdit #define SELL_STOP_SL_EDIT_NAME "Sell Stop SL Edit" #define SELL_STOP_SL_EDIT_SUBWINDOW 0 #define SELL_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define SELL_STOP_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopTpEdit #define SELL_STOP_TP_EDIT_NAME "Sell Stop TP Edit" #define SELL_STOP_TP_EDIT_SUBWINDOW 0 #define SELL_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define SELL_STOP_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) /*------------------------------------------------------ * Define Buy Limit Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the buyLimitBtn #define BUY_LIMIT_BTN_NAME "Buy Limit Button" #define BUY_LIMIT_BTN_SUBWINDOW 0 #define BUY_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN #define BUY_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) #define BUY_LIMIT_BTN_TEXT "BUY LIMIT" //-- Define values for the buyLimitVolumeLotEdit #define BUY_LIMIT_VOLUME_LOT_EDIT_NAME "Buy Limit Volume Lot Edit" #define BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0 #define BUY_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define BUY_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buySLimitOpenPriceEdit #define BUY_LIMIT_OPEN_PRICE_EDIT_NAME "Buy Limit Open Price Edit" #define BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0 #define BUY_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define BUY_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buyLimitSlEdit #define BUY_LIMIT_SL_EDIT_NAME "Buy Limit SL Edit" #define BUY_LIMIT_SL_EDIT_SUBWINDOW 0 #define BUY_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define BUY_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buyLimitTpEdit #define BUY_LIMIT_TP_EDIT_NAME "Buy Limit TP Edit" #define BUY_LIMIT_TP_EDIT_SUBWINDOW 0 #define BUY_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define BUY_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) /*------------------------------------------------------ * Define Sell Limit Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the sellLimitBtn #define SELL_LIMIT_BTN_NAME "Sell Limit Button" #define SELL_LIMIT_BTN_SUBWINDOW 0 #define SELL_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN #define SELL_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) #define SELL_LIMIT_BTN_TEXT "SELL LIMIT" //-- Define values for the sellLimitVolumeLotEdit #define SELL_LIMIT_VOLUME_LOT_EDIT_NAME "Sell Limit Volume Lot Edit" #define SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0 #define SELL_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define SELL_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitOpenPriceEdit #define SELL_LIMIT_OPEN_PRICE_EDIT_NAME "Sell Limit Open Price Edit" #define SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0 #define SELL_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define SELL_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitSlEdit #define SELL_LIMIT_SL_EDIT_NAME "Sell Limit SL Edit" #define SELL_LIMIT_SL_EDIT_SUBWINDOW 0 #define SELL_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define SELL_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitTpEdit #define SELL_LIMIT_TP_EDIT_NAME "Sell Limit TP Edit" #define SELL_LIMIT_TP_EDIT_SUBWINDOW 0 #define SELL_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define SELL_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) /*------------------------------------------------------ * Define Order Status GUI components **** *-----------------------------------------------------*/ //-- Define values for the orders status #define STATUS_HEADER_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1) #define STATUS_EDIT_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1) #define STATUS_EDIT_WIDTH int((MAIN_PANEL_WIDTH / 1.485) - (GUI_OBJECTS_MARGIN * 2)) #define STATUS_EDIT_COLOR clrBlack #define STATUS_EDIT_BG_COLOR clrLemonChiffon #define STATUS_EDIT_BORDER_COLOR clrMidnightBlue #define DELETE_ORDERS_BTN_COLOR clrLightYellow #define DELETE_BUY_ORDERS_BTN_BG_COLOR clrRoyalBlue #define DELETE_SELL_ORDERS_BTN_BG_COLOR clrCrimson #define DELETE_ALL_ORDERS_BTN_BG_COLOR clrMediumVioletRed #define DELETE_ORDERS_BTN_BORDER_COLOR clrBlack #define DELETE_ORDERS_BTN_WIDTH int((STATUS_EDIT_WIDTH / 1.93) - (GUI_OBJECTS_MARGIN * 3)) #define DELETE_ORDERS_BTN_FONT_SIZE int((GUI_OBJECTS_FONT_SIZE))// / 1.05) //-- Define values for the magicOrderStatusLabel #define MAGIC_ORDER_STATUS_LABEL_NAME "Magic Order Status Label" #define MAGIC_ORDER_STATUS_LABEL_SUBWINDOW 0 #define MAGIC_ORDER_STATUS_LABEL_X1 int(GUI_OBJECTS_MARGIN * 3) #define MAGIC_ORDER_STATUS_LABEL_Y1 int((GUI_OBJECTS_HEIGHT * 6) + (GUI_OBJECTS_MARGIN * 2)) #define MAGIC_ORDER_STATUS_LABEL_TEXT string("MAGIC No: " + IntegerToString(magicNo) + " - TOTAL OPEN ORDERS: ") //-- Define values for the magicOrdersStatusEdit #define MAGIC_ORDER_STATUS_EDIT_NAME "Magic Order Status Edit" #define MAGIC_ORDER_STATUS_EDIT_SUBWINDOW 0 #define MAGIC_ORDER_STATUS_EDIT_X1 int(GUI_OBJECTS_MARGIN * 2) #define MAGIC_ORDER_STATUS_EDIT_Y1 int((MAGIC_ORDER_STATUS_LABEL_Y1) + (GUI_OBJECTS_HEIGHT / 1.7)) //-- Define values for the deleteAllMagicBuyStopsBtn #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME "Delete All Magic Buy Stops Btn" #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT "DELETE ALL MAGIC BUY STOPS" //-- Define values for the deleteAllMagicSellStopsBtn #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME "Delete All Magic Sell Stops Btn" #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH) #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT "DELETE ALL MAGIC SELL STOPS" //-- Define values for the deleteAllMagicBuyLimitsBtn #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME "Delete All Magic Buy Limits Btn" #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT "DELETE ALL MAGIC BUY LIMITS" //-- Define values for the deleteAllMagicSellLimitsBtn #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME "Delete All Magic Sell Limits Btn" #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH) #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1 DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1//int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT "DELETE ALL MAGIC SELL LIMITS" //-- Define values for the deleteAllMagicOrdersBtn #define DELETE_ALL_MAGIC_ORDERS_BTN_NAME "Delete All Magic Orders Btn" #define DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_ORDERS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_ORDERS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_ORDERS_BTN_TEXT "DELETE ALL MAGIC PENDING ORDERS"
在我们的代码中添加或包含面板和对话框的 MQL5 标准类。
//-- Include the MQL5 standard library for panels and dialogs #include <Controls\Dialog.mqh> #include <Controls\Button.mqh> #include <Controls\Label.mqh> #include <Controls\Edit.mqh>
随着面板和对话框类现在包含在我们的文件中并可用,我们可以继续创建它们的对象,以在我们的代码中扩展它们的功能。
//-- Create objects for the included standard classes CAppDialog mainPanelWindow; //-- Create the header label components CLabel lotVolHeaderLabel; CLabel openPriceHeaderLabel; CLabel slHeaderLabel; CLabel tpHeaderLabel; //-- Create the buy stop GUI components //--BuyStopBtn CButton buyStopBtn; //--BuyStopEdits CEdit buyStopVolumeLotEdit; CEdit buyStopOpenPriceEdit; CEdit buyStopSlEdit; CEdit buyStopTpEdit; //-- Create the sell stop GUI components //--SellStopBtn CButton sellStopBtn; //--sellStopEdits CEdit sellStopVolumeLotEdit; CEdit sellStopOpenPriceEdit; CEdit sellStopSlEdit; CEdit sellStopTpEdit; //-- Create the buy limit GUI components //--BuyLimitBtn CButton buyLimitBtn; //--BuyLimitEdits CEdit buyLimitVolumeLotEdit; CEdit buyLimitOpenPriceEdit; CEdit buyLimitSlEdit; CEdit buyLimitTpEdit; //-- Create the sell limit GUI components //--sellLimitBtn CButton sellLimitBtn; //--sellLimitEdits CEdit sellLimitVolumeLotEdit; CEdit sellLimitOpenPriceEdit; CEdit sellLimitSlEdit; CEdit sellLimitTpEdit; //-- Create the order status GUI components //--magic order status CLabel magicOrderStatusLabel; CEdit magicOrdersStatusEdit; //--Magic orders delete buttons CButton deleteAllMagicBuyStopsBtn; CButton deleteAllMagicSellStopsBtn; CButton deleteAllMagicBuyLimitsBtn; CButton deleteAllMagicSellLimitsBtn; CButton deleteAllMagicOrdersBtn;
创建负责存储订单输入价格的变量和一个字符串,用于存储我们的智能交易系统打开的所有订单的订单状态。
//-- Default starting entry prices for different pending orders double buyStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint); double buyLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint); double sellStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint); double sellLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint); //-- String values for the orders status string magicOrderStatus;
代码头部部分完成后,下一步是创建负责在 EA 交易初始化期间生成和加载图形用户界面的函数。我们将此函数命名为 CreateGui() 。
void CreateGui() { //-- Create the orders panel mainPanelWindow.Create( 0, MAIN_PANEL_NAME, MAIN_PANEL_SUBWINDOW, MAIN_PANEL_X1, MAIN_PANEL_Y1, MAIN_PANEL_X2, MAIN_PANEL_Y2 ); /*------------------------------------------------------ * Header Labels GUI components creation **** *-----------------------------------------------------*/ //--Create the lot volume header label lotVolHeaderLabel.Create( 0, VOLUME_LOT_LABEL_NAME, VOLUME_LOT_LABEL_SUBWINDOW, VOLUME_LOT_LABEL_X1, VOLUME_LOT_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); lotVolHeaderLabel.Text(VOLUME_LOT_LABEL_TEXT); lotVolHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); lotVolHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(lotVolHeaderLabel); //--Create the open price header label openPriceHeaderLabel.Create( 0, OPEN_PRICE_LABEL_NAME, OPEN_PRICE_LABEL_SUBWINDOW, OPEN_PRICE_LABEL_X1, OPEN_PRICE_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); openPriceHeaderLabel.Text(OPEN_PRICE_LABEL_TEXT); openPriceHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); openPriceHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(openPriceHeaderLabel); //--Create the sl header label slHeaderLabel.Create( 0, SL_LABEL_NAME, SL_LABEL_SUBWINDOW, SL_LABEL_X1, SL_LABEL_Y1, int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT ); slHeaderLabel.Text(SL_LABEL_TEXT); slHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); slHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(slHeaderLabel); //--Create the tp header label tpHeaderLabel.Create( 0, TP_LABEL_NAME, TP_LABEL_SUBWINDOW, TP_LABEL_X1, TP_LABEL_Y1, int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT ); tpHeaderLabel.Text(TP_LABEL_TEXT); tpHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); tpHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(tpHeaderLabel); /*------------------------------------------------------ * Buy Stop Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open buy stop button buyStopBtn.Create( 0, BUY_STOP_BTN_NAME, BUY_STOP_BTN_SUBWINDOW, BUY_STOP_BTN_X1, BUY_STOP_BTN_Y1, 0, 0 ); buyStopBtn.Text(BUY_STOP_BTN_TEXT); buyStopBtn.Width(GUI_OBJECTS_WIDTH); buyStopBtn.Height(GUI_OBJECTS_HEIGHT); buyStopBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR); buyStopBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR); buyStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(buyStopBtn); //--Create the buy stop volume lot edit to get the buy stop volume/lot user input buyStopVolumeLotEdit.Create( 0, BUY_STOP_VOLUME_LOT_EDIT_NAME, BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW, BUY_STOP_VOLUME_LOT_EDIT_X1, BUY_STOP_VOLUME_LOT_EDIT_Y1, 0, 0 ); buyStopVolumeLotEdit.Text(DoubleToString(volumeLot)); buyStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); buyStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); buyStopVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopVolumeLotEdit); //--Create the buy stop price edit to get the buy stop opening price user input buyStopOpenPriceEdit.Create( 0, BUY_STOP_OPEN_PRICE_EDIT_NAME, BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW, BUY_STOP_OPEN_PRICE_EDIT_X1, BUY_STOP_OPEN_PRICE_EDIT_Y1, 0, 0 ); buyStopOpenPriceEdit.Text(DoubleToString(buyStopEntryPrice, int(symbolDigits))); buyStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); buyStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); buyStopOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopOpenPriceEdit); //--Create the buy stop sl edit to get the buy stop sl user input buyStopSlEdit.Create( 0, BUY_STOP_SL_EDIT_NAME, BUY_STOP_SL_EDIT_SUBWINDOW, BUY_STOP_SL_EDIT_X1, BUY_STOP_SL_EDIT_Y1, 0, 0 ); buyStopSlEdit.Text(IntegerToString(sl)); buyStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); buyStopSlEdit.Height(GUI_OBJECTS_HEIGHT); buyStopSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopSlEdit); //--Create the buy stop tp edit to get the buy stop tp user input buyStopTpEdit.Create( 0, BUY_STOP_TP_EDIT_NAME, BUY_STOP_TP_EDIT_SUBWINDOW, BUY_STOP_TP_EDIT_X1, BUY_STOP_TP_EDIT_Y1, 0, 0 ); buyStopTpEdit.Text(IntegerToString(tp)); buyStopTpEdit.Width(GUI_OBJECTS_WIDTH); buyStopTpEdit.Height(GUI_OBJECTS_HEIGHT); buyStopTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopTpEdit); /*------------------------------------------------------ * Sell Stop Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open sell stop button sellStopBtn.Create( 0, SELL_STOP_BTN_NAME, SELL_STOP_BTN_SUBWINDOW, SELL_STOP_BTN_X1, SELL_STOP_BTN_Y1, 0, 0 ); sellStopBtn.Text(SELL_STOP_BTN_TEXT); sellStopBtn.Width(GUI_OBJECTS_WIDTH); sellStopBtn.Height(GUI_OBJECTS_HEIGHT); sellStopBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR); sellStopBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR); sellStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(sellStopBtn); //--Create the sell stop volume lot edit to get the sell stop volume/lot user input sellStopVolumeLotEdit.Create( 0, SELL_STOP_VOLUME_LOT_EDIT_NAME, SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW, SELL_STOP_VOLUME_LOT_EDIT_X1, SELL_STOP_VOLUME_LOT_EDIT_Y1, 0, 0 ); sellStopVolumeLotEdit.Text(DoubleToString(volumeLot)); sellStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); sellStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); sellStopVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopVolumeLotEdit); //--Create the sell stop price edit to get the sell stop opening price user input sellStopOpenPriceEdit.Create( 0, SELL_STOP_OPEN_PRICE_EDIT_NAME, SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW, SELL_STOP_OPEN_PRICE_EDIT_X1, SELL_STOP_OPEN_PRICE_EDIT_Y1, 0, 0 ); sellStopOpenPriceEdit.Text(DoubleToString(sellStopEntryPrice, int(symbolDigits))); sellStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); sellStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); sellStopOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopOpenPriceEdit); //--Create the sell stop sl edit to get the sell stop sl user input sellStopSlEdit.Create( 0, SELL_STOP_SL_EDIT_NAME, SELL_STOP_SL_EDIT_SUBWINDOW, SELL_STOP_SL_EDIT_X1, SELL_STOP_SL_EDIT_Y1, 0, 0 ); sellStopSlEdit.Text(IntegerToString(sl)); sellStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); sellStopSlEdit.Height(GUI_OBJECTS_HEIGHT); sellStopSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopSlEdit); //--Create the sell stop tp edit to get the sell stop tp user input sellStopTpEdit.Create( 0, SELL_STOP_TP_EDIT_NAME, SELL_STOP_TP_EDIT_SUBWINDOW, SELL_STOP_TP_EDIT_X1, SELL_STOP_TP_EDIT_Y1, 0, 0 ); sellStopTpEdit.Text(IntegerToString(tp)); sellStopTpEdit.Width(GUI_OBJECTS_WIDTH); sellStopTpEdit.Height(GUI_OBJECTS_HEIGHT); sellStopTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopTpEdit); /*------------------------------------------------------ * Buy Limit Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open buy limit button buyLimitBtn.Create( 0, BUY_LIMIT_BTN_NAME, BUY_LIMIT_BTN_SUBWINDOW, BUY_LIMIT_BTN_X1, BUY_LIMIT_BTN_Y1, 0, 0 ); buyLimitBtn.Text(BUY_LIMIT_BTN_TEXT); buyLimitBtn.Width(GUI_OBJECTS_WIDTH); buyLimitBtn.Height(GUI_OBJECTS_HEIGHT); buyLimitBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR); buyLimitBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR); buyLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(buyLimitBtn); //--Create the buy limit volume lot edit to get the buy limit volume/lot user input buyLimitVolumeLotEdit.Create( 0, BUY_LIMIT_VOLUME_LOT_EDIT_NAME, BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW, BUY_LIMIT_VOLUME_LOT_EDIT_X1, BUY_LIMIT_VOLUME_LOT_EDIT_Y1, 0, 0 ); buyLimitVolumeLotEdit.Text(DoubleToString(volumeLot)); buyLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); buyLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitVolumeLotEdit); //--Create the buy limit price edit to get the buy limit opening price user input buyLimitOpenPriceEdit.Create( 0, BUY_LIMIT_OPEN_PRICE_EDIT_NAME, BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW, BUY_LIMIT_OPEN_PRICE_EDIT_X1, BUY_LIMIT_OPEN_PRICE_EDIT_Y1, 0, 0 ); buyLimitOpenPriceEdit.Text(DoubleToString(buyLimitEntryPrice, int(symbolDigits))); buyLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); buyLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitOpenPriceEdit); //--Create the buy limit sl edit to get the buy limit sl user input buyLimitSlEdit.Create( 0, BUY_LIMIT_SL_EDIT_NAME, BUY_LIMIT_SL_EDIT_SUBWINDOW, BUY_LIMIT_SL_EDIT_X1, BUY_LIMIT_SL_EDIT_Y1, 0, 0 ); buyLimitSlEdit.Text(IntegerToString(sl)); buyLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); buyLimitSlEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitSlEdit); //--Create the buy limit tp edit to get the buy limit tp user input buyLimitTpEdit.Create( 0, BUY_LIMIT_TP_EDIT_NAME, BUY_LIMIT_TP_EDIT_SUBWINDOW, BUY_LIMIT_TP_EDIT_X1, BUY_LIMIT_TP_EDIT_Y1, 0, 0 ); buyLimitTpEdit.Text(IntegerToString(tp)); buyLimitTpEdit.Width(GUI_OBJECTS_WIDTH); buyLimitTpEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitTpEdit); /*------------------------------------------------------ * Sell Limit Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open sell limit button sellLimitBtn.Create( 0, SELL_LIMIT_BTN_NAME, SELL_LIMIT_BTN_SUBWINDOW, SELL_LIMIT_BTN_X1, SELL_LIMIT_BTN_Y1, 0, 0 ); sellLimitBtn.Text(SELL_LIMIT_BTN_TEXT); sellLimitBtn.Width(GUI_OBJECTS_WIDTH); sellLimitBtn.Height(GUI_OBJECTS_HEIGHT); sellLimitBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR); sellLimitBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR); sellLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(sellLimitBtn); //--Create the sell limit volume lot edit to get the sell limit volume/lot user input sellLimitVolumeLotEdit.Create( 0, SELL_LIMIT_VOLUME_LOT_EDIT_NAME, SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW, SELL_LIMIT_VOLUME_LOT_EDIT_X1, SELL_LIMIT_VOLUME_LOT_EDIT_Y1, 0, 0 ); sellLimitVolumeLotEdit.Text(DoubleToString(volumeLot)); sellLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); sellLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitVolumeLotEdit); //--Create the sell limit price edit to get the sell limit opening price user input sellLimitOpenPriceEdit.Create( 0, SELL_LIMIT_OPEN_PRICE_EDIT_NAME, SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW, SELL_LIMIT_OPEN_PRICE_EDIT_X1, SELL_LIMIT_OPEN_PRICE_EDIT_Y1, 0, 0 ); sellLimitOpenPriceEdit.Text(DoubleToString(sellLimitEntryPrice, int(symbolDigits))); sellLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); sellLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitOpenPriceEdit); //--Create the sell limit sl edit to get the sell limit sl user input sellLimitSlEdit.Create( 0, SELL_LIMIT_SL_EDIT_NAME, SELL_LIMIT_SL_EDIT_SUBWINDOW, SELL_LIMIT_SL_EDIT_X1, SELL_LIMIT_SL_EDIT_Y1, 0, 0 ); sellLimitSlEdit.Text(IntegerToString(sl)); sellLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); sellLimitSlEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitSlEdit); //--Create the sell limit tp edit to get the sell limit tp user input sellLimitTpEdit.Create( 0, SELL_LIMIT_TP_EDIT_NAME, SELL_LIMIT_TP_EDIT_SUBWINDOW, SELL_LIMIT_TP_EDIT_X1, SELL_LIMIT_TP_EDIT_Y1, 0, 0 ); sellLimitTpEdit.Text(IntegerToString(tp)); sellLimitTpEdit.Width(GUI_OBJECTS_WIDTH); sellLimitTpEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitTpEdit); /*------------------------------------------------------------- * Status Labels and readonly edits GUI components creation **** *------------------------------------------------------------*/ //--Create the order magic status label magicOrderStatusLabel.Create( 0, MAGIC_ORDER_STATUS_LABEL_NAME, MAGIC_ORDER_STATUS_LABEL_SUBWINDOW, MAGIC_ORDER_STATUS_LABEL_X1, MAGIC_ORDER_STATUS_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + " - (Total Open Orders: " + (string(MagicOrdersTotal(magicNo))) + ")"); magicOrderStatusLabel.Color(STATUS_EDIT_COLOR); magicOrderStatusLabel.FontSize(STATUS_HEADER_FONT_SIZE); mainPanelWindow.Add(magicOrderStatusLabel); //--Create the magic order status edit to display the magic orders status magicOrdersStatusEdit.Create( 0, MAGIC_ORDER_STATUS_EDIT_NAME, MAGIC_ORDER_STATUS_EDIT_SUBWINDOW, MAGIC_ORDER_STATUS_EDIT_X1, MAGIC_ORDER_STATUS_EDIT_Y1, 0, 0 ); magicOrdersStatusEdit.ReadOnly(true); magicOrdersStatusEdit.Text(magicOrderStatus); magicOrdersStatusEdit.Width(STATUS_EDIT_WIDTH); magicOrdersStatusEdit.Height(GUI_OBJECTS_HEIGHT); magicOrdersStatusEdit.Color(STATUS_EDIT_COLOR); magicOrdersStatusEdit.ColorBackground(STATUS_EDIT_BG_COLOR); magicOrdersStatusEdit.FontSize(STATUS_EDIT_FONT_SIZE); magicOrdersStatusEdit.ColorBorder(STATUS_EDIT_BORDER_COLOR); mainPanelWindow.Add(magicOrdersStatusEdit); //--Create the delete all magic buy stops button deleteAllMagicBuyStopsBtn.Create( 0, DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME, DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1, DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1, 0, 0 ); deleteAllMagicBuyStopsBtn.Text(DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT); deleteAllMagicBuyStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicBuyStopsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicBuyStopsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); deleteAllMagicBuyStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicBuyStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicBuyStopsBtn); //--Create the delete all magic sell stops button deleteAllMagicSellStopsBtn.Create( 0, DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME, DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1, DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1, 0, 0 ); deleteAllMagicSellStopsBtn.Text(DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT); deleteAllMagicSellStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicSellStopsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicSellStopsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); deleteAllMagicSellStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicSellStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicSellStopsBtn); //--Create the delete all magic buy limits button deleteAllMagicBuyLimitsBtn.Create( 0, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1, 0, 0 ); deleteAllMagicBuyLimitsBtn.Text(DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT); deleteAllMagicBuyLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicBuyLimitsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicBuyLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); deleteAllMagicBuyLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicBuyLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicBuyLimitsBtn); //--Create the delete all magic sell limits button deleteAllMagicSellLimitsBtn.Create( 0, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1, 0, 0 ); deleteAllMagicSellLimitsBtn.Text(DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT); deleteAllMagicSellLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicSellLimitsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicSellLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); deleteAllMagicSellLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicSellLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicSellLimitsBtn); //--Create the delete all magic orders button deleteAllMagicOrdersBtn.Create( 0, DELETE_ALL_MAGIC_ORDERS_BTN_NAME, DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_ORDERS_BTN_X1, DELETE_ALL_MAGIC_ORDERS_BTN_Y1, 0, 0 ); deleteAllMagicOrdersBtn.Text(DELETE_ALL_MAGIC_ORDERS_BTN_TEXT); deleteAllMagicOrdersBtn.Width(STATUS_EDIT_WIDTH); deleteAllMagicOrdersBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicOrdersBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR); deleteAllMagicOrdersBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicOrdersBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicOrdersBtn); //--Call the Run() method to load the main panel window mainPanelWindow.Run(); }
我们现在需要通过填充 OnChartEvent(...) 函数来检测任何按钮按下或激活。此函数将作为所有用户交互的事件处理程序,使其成为我们面板响应性的核心组件。在本节中,我们将调用从 PendingOrdersManager.ex5 库导入的原型函数,使我们能够根据用户输入管理和操作挂单。例如,如果用户单击按钮下一个新的待处理订单,相应的库函数将被触发以执行该操作。
为了进一步增强用户对挂单面板的体验,我们还将整合听觉反馈。将播放不同的声音来表示操作的结果,例如订单是否成功下达或是否因某些错误而失败。这提供了实时反馈,并增加了额外的交互性,使面板更加直观和用户友好。结合视觉和听觉线索将确保用户能够轻松跟踪他们的行为状态并做出相应的反应。
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--Detect any clicks or events performed to the orders panel window and make it moveable mainPanelWindow.ChartEvent(id, lparam, dparam, sparam); //--Detect any click events on the chart if(id == CHARTEVENT_OBJECT_CLICK) { //--Detect when the buyStopBtn is clicked and open a new buy stop order if(sparam == buyStopBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Buy Stop Order with the details below: "); Print("Volume: ", buyStopVolumeLotEdit.Text()); Print("Open Price: ", buyStopOpenPriceEdit.Text()); Print("Sl (Pips): ", buyStopSlEdit.Text()); Print("Tp (Pips): ", buyStopTpEdit.Text()); if( OpenBuyStop( magicNo, _Symbol, StringToDouble(buyStopOpenPriceEdit.Text()), StringToDouble(buyStopVolumeLotEdit.Text()), (uint)StringToInteger(buyStopSlEdit.Text()), (uint)StringToInteger(buyStopTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the sellStopBtn is clicked and open a new sell stop order if(sparam == sellStopBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Sell Stop Order with the details below: "); Print("Volume: ", sellStopVolumeLotEdit.Text()); Print("Open Price: ", sellStopOpenPriceEdit.Text()); Print("Sl (Pips): ", sellStopSlEdit.Text()); Print("Tp (Pips): ", sellStopTpEdit.Text()); if( OpenSellStop( magicNo, _Symbol, StringToDouble(sellStopOpenPriceEdit.Text()), StringToDouble(sellStopVolumeLotEdit.Text()), (uint)StringToInteger(sellStopSlEdit.Text()), (uint)StringToInteger(sellStopTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the buyLimitBtn is clicked and open a new buy limit order if(sparam == buyLimitBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Buy Limit Order with the details below: "); Print("Volume: ", buyLimitVolumeLotEdit.Text()); Print("Open Price: ", buyLimitOpenPriceEdit.Text()); Print("Sl (Pips): ", buyLimitSlEdit.Text()); Print("Tp (Pips): ", buyLimitTpEdit.Text()); if( OpenBuyLimit( magicNo, _Symbol, StringToDouble(buyLimitOpenPriceEdit.Text()), StringToDouble(buyLimitVolumeLotEdit.Text()), (uint)StringToInteger(buyLimitSlEdit.Text()), (uint)StringToInteger(buyLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the sellLimitBtn is clicked and open a new sell limit order if(sparam == sellLimitBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Sell Limit Order with the details below: "); Print("Volume: ", sellLimitVolumeLotEdit.Text()); Print("Open Price: ", sellLimitOpenPriceEdit.Text()); Print("Sl (Pips): ", sellLimitSlEdit.Text()); Print("Tp (Pips): ", sellLimitTpEdit.Text()); if( OpenSellLimit( magicNo, _Symbol, StringToDouble(sellLimitOpenPriceEdit.Text()), StringToDouble(sellLimitVolumeLotEdit.Text()), (uint)StringToInteger(sellLimitSlEdit.Text()), (uint)StringToInteger(sellLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the deleteAllMagicBuyStopsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicBuyStopsBtn.Name() && MagicBuyStopOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the buy stop orders with magic number: ", magicNo); if(DeleteAllBuyStops("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicSellStopsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicSellStopsBtn.Name() && MagicSellStopOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the sell stop orders with magic number: ", magicNo); if(DeleteAllSellStops("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicBuyLimitsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicBuyLimitsBtn.Name() && MagicBuyLimitOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the buy limit orders with magic number: ", magicNo); if(DeleteAllBuyLimits("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicSellLimitsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicSellLimitsBtn.Name() && MagicSellLimitOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the sell limit orders with magic number: ", magicNo); if(DeleteAllSellLimits("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicOrdersBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicOrdersBtn.Name() && MagicOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the open peding orders with magic number: ", magicNo); if(DeleteAllMagicOrders(magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } } }
您会注意到,一旦加载 EA 交易,它就会根据当前点差自动使用预定义值填充订单量/手数、入场价、止损(SL)和止盈(TP)字段。这些值为用户下单提供了一个起点,简化了交易流程,并最大限度地减少了手动输入。此外,如果未检测到与 EA 交易系统分配的幻数匹配的未结或活动订单,则位于幻数订单状态下方的订单删除按钮最初会变灰并禁用。一旦 EA 交易识别出匹配的订单,按钮就会激活并改变颜色,表示它们现在可以运行并准备执行删除命令。
当 EA 交易检测到与分配的幻数匹配的订单被打开时,订单删除按钮被激活,并改变颜色以指示它们已启用并可以使用。
为了实现此功能,我们需要在 OnTick() 函数中添加以下代码。这将使我们能够使用导入的 EX5 库函数持续实时监控和更新图形用户界面,确保它与每次传入的订单状态保持同步。
void OnTick() { //--- magicOrderStatus = " Buy Stops: " + (string(MagicBuyStopOrdersTotal(magicNo))) + ", Sell Stops: " + (string(MagicSellStopOrdersTotal(magicNo))) + ", Buy Limits: " + (string(MagicBuyLimitOrdersTotal(magicNo))) + ", Sell Limits: " + (string(MagicSellLimitOrdersTotal(magicNo))) + " "; magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + (string(MagicOrdersTotal(magicNo)))); magicOrdersStatusEdit.Text(magicOrderStatus); //-- Disable and change the background color of the deleteAllMagicBuyStopsBtn depending on the open orders status if(MagicBuyStopOrdersTotal(magicNo) == 0) { deleteAllMagicBuyStopsBtn.Disable(); deleteAllMagicBuyStopsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicBuyStopsBtn.Enable(); deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicSellStopsBtn depending on the open orders status if(MagicSellStopOrdersTotal(magicNo) == 0) { deleteAllMagicSellStopsBtn.Disable(); deleteAllMagicSellStopsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicSellStopsBtn.Enable(); deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicBuyLimitsBtn depending on the open orders status if(MagicBuyLimitOrdersTotal(magicNo) == 0) { deleteAllMagicBuyLimitsBtn.Disable(); deleteAllMagicBuyLimitsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicBuyLimitsBtn.Enable(); deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicSellLimitsBtn depending on the open orders status if(MagicSellLimitOrdersTotal(magicNo) == 0) { deleteAllMagicSellLimitsBtn.Disable(); deleteAllMagicSellLimitsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicSellLimitsBtn.Enable(); deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicOrdersBtn depending on the open orders status if(MagicOrdersTotal(magicNo) == 0) { deleteAllMagicOrdersBtn.Disable(); deleteAllMagicOrdersBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicOrdersBtn.Enable(); deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR); } }
最后,我们必须确保在 EA 交易终止时所有资源都得到正确释放和清理。为此,请将以下代码添加到 OnDeinit(...) 函数中。
void OnDeinit(const int reason) { //--- //-- Delete and garbage collect the graphical user interface and other graphical objects mainPanelWindow.Destroy(); //-- Clear any chart comments Comment(""); }
PendingOrdersPanel.mq5 文件附加在本文末尾。
结论
我们构建了一个全方位的挂单管理 EX5库,展示了如何打开、修改、删除、排序和过滤不同类型的挂单。对于任何需要灵活且易于使用的工具来管理挂单的 MQL5 开发人员来说,这个库都是一个有用的资源,使他们能够通过简单的函数调用快速获取状态或对订单采取行动。
该库功能丰富,并配有清晰的文档和真实世界的示例。在下一篇文章中,我们将应用类似的方法创建历史管理 EX5库,这将使在 MQL5 中处理交易和订单历史变得更加容易。
感谢您的关注,并祝您在交易和 MQL5 编程中一切顺利!
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/15888
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.



