EA: 交易者的MQL5编程(MQL5 Programming for Traders) - 源代码第六部分

 

交易者的MQL5编程(MQL5 Programming for Traders) - 源代码第六部分:

在"交易者的MQL5编程(MQL5 Programming for Traders)"第六部分,我们将学习MQL5语言的一个关键组成部分 – 交易自动化。我们将首先介绍基本对象,如交易品种规格和交易账户设置。这些都是创建正常运行的EA交易的先决条件。

交易者的MQL5编程(MQL5 Programming for Traders) - 源代码第六部分

作者: MetaQuotes

 
伟大
 

插入代码 时请 使用代码 按钮 (Alt-S)

版主对错误粘贴的代码进行了格式化。通常,此类代码会被删除。

@StanislavKorotky 请您帮忙检查一下这个错误,我相信它是在 MT5 更新后开始出现的,因为我知道代码在前几个月没有任何修改的情况下也能正常工作。

参数转换类型 'long[][2]' 到 'string[][] &' 是不允许的 SymbolFilter.mqh 199 20

不允许将参数类型 'double[][2]' 转换为 'string[][] &' TradeFilter.mqh 332 20
不允许将参数类型 'long[][2]' 转换为 'string[][] &' TradeFilter.mqh 163 17


我怀疑下面的代码有助于复制该问题:

void printSymbols() {
   SymbolFilter f;                      // 过滤器对象
   string symbols[];                    // 名称数组 
   long permissions[][2];               // 数据(属性值)数组
   
   // 所请求的符号属性列表
   ENUM_SYMBOL_INFO_INTEGER modes[] = {
      SYMBOL_TRADE_MODE,
      SYMBOL_ORDER_MODE
   };
   
   // 应用过滤器,得到包含结果的数组
   f.let(SYMBOL_VISIBLE, true).select(true, modes, symbols, permissions);
   
   const int n = ArraySize(symbols);
   PrintFormat("===== Trade permissions for the symbols (%d) ===== ", n);
   for(int i = 0; i < n; ++i)  {
      Print(symbols[i] + ":");
      for(int j = 0; j < ArraySize(modes); ++j) {
         // "按原样 "显示位和数字说明
         PrintFormat("  %s (%d)",
            SymbolMonitor::stringify(permissions[i][j], modes[j]),
            permissions[i][j]);
      }
   }
}

Stanislav Korotky - marketeer - Trader's profile
Stanislav Korotky - marketeer - Trader's profile
  • 2025.07.05
  • www.mql5.com
Trader's profile
 
pauldic #:
@StanislavKorotky 请您帮忙检查一下这个错误,我相信它是在 MT5 更新之后开始出现的,因为我知道代码在前几个月没有任何修改的情况下也能正常工作。

参数转换类型 "long[][2]"到 "string[][] &"是不允许的 SymbolFilter.mqh 199 20
不允许将参数类型 'double[][2]' 转换为 'string[][] &' TradeFilter.mqh 332 20
不允许将参数类型 'long[][2]' 转换为 'string[][] &' TradeFilter.mqh 163 17


我怀疑下面的代码有助于复制该问题:


请找到这几行:

   // 我们需要这个重载,因为内置 ArraySort
   // 不支持字符串数组
   void ArraySort(string &s[][]) const
   {
      QuickSortTm<string> qt(s);
   }

在头文件SymbolFilter.mqhTradeFilter.mqh 中找到这两行,并在旁边添加以下方法重载:

   // 我们需要这个重载,因为内置 ArraySort
   // 不支持字符串数组
   void ArraySort(string &s[][]) const
   {
      QuickSortTm<string> qt(s);
   }
   
   template<typename T>
   void ArraySort(T &s[][]) const
   {
      ::ArraySort(s);
   }
PS.这个问题似乎与文章无关。
 
Stanislav Korotky #:

请找到这几行:

在头文件SymbolFilter.mqhTradeFilter.mqh 中找到这两行,并在旁边添加以下方法重载:

PS.这个问题似乎与文章无关。

感谢您的快速回复,在更新后,我收到了更多错误信息:

parameter convertion type 'double[][2]' to 'string[][] &' is not allowed                TradeFilter.mqh 338     20
cannot convert parameter 'double[][2]' to 'OrderMonitor&[][]'                   TradeFilter.mqh 338     20
parameter convertion type 'double[][2]' to 'string[][] &' is not allowed                TradeFilter.mqh 338     20
cannot convert parameter 'double[][2]' to 'PositionMonitor&[][]'                        TradeFilter.mqh 338     20
parameter convertion type 'long[][2]' to 'string[][] &' is not allowed          TradeFilter.mqh 163     17
cannot convert parameter 'long[][2]' to 'OrderMonitor&[][]'                             TradeFilter.mqh 163     17
parameter convertion type 'long[][2]' to 'string[][] &' is not allowed          TradeFilter.mqh 163     17
cannot convert parameter 'long[][2]' to 'PositionMonitor&[][]'                  TradeFilter.mqh 163     17
etc..

我注意到直接调用通用 QuickSortTm 而不是 ArraySort 可以暂时解决问题,但我认为这不是最佳解决方案。

QuickSortTm<V> qt(array);
/ArraySort(array);
 
pauldic #:

感谢您的快速回复。更新后,我收到了更多的错误提示:

这很奇怪,在按照上述建议进行修复后,我已在 build 5346 上成功编译并运行了此脚本/MQL5/Scripts/MQL5Book/p6/SymbolFilterTradeMode.mq5。您没有显示您的源代码。
 
Stanislav Korotky #:
这就奇怪了,按照上面的建议修复后,我在 build 5346 上成功编译并运行了此脚本/MQL5/Scripts/MQL5Book/p6/SymbolFilterTradeMode.mq5。您没有显示您的源代码。
请原谅我遗漏了源代码,因此我恢复了您建议的修复,这样我就可以再次出现错误,而且根据日志
,我在版本 5 build 5327

上运行时,我代码中的这些部分似乎是导致错误的部分。
void printActiveOrders() {
   
   OrderFilter filter;
   ENUM_ORDER_PROPERTY_DOUBLE properties[] = {ORDER_VOLUME_INITIAL, ORDER_PRICE_OPEN, ORDER_SL, ORDER_TP};
   double d[][4];
   ENUM_ORDER_TYPE types[];
   ulong tickets[], magics[];
   string symbols[], comments[];
   
   filter.select(properties, tickets, d);
   filter.select(ORDER_SYMBOL, tickets, symbols);
   filter.select(ORDER_COMMENT, tickets, comments);
   filter.select(ORDER_TYPE, tickets, types);
   filter.select(ORDER_MAGIC, tickets, magics);
   
   Print("Orders ..................  ", ArraySize(tickets));
   for (int i=0; i < ArraySize(tickets); i++) {
      Print(tickets[i], "\t", magics[i], "\t", symbols[i], "\t", EnumToString(types[i]), " \t", NormalizeDouble(d[i][0],3), "\t", d[i][1], " \t ",  d[i][2], " \t", d[i][3], "\t", comments[i]);
   }
}


void printPositions() {
   PositionFilter filter;
   
   ENUM_POSITION_PROPERTY_DOUBLE properties[] = {POSITION_PRICE_OPEN, POSITION_VOLUME, POSITION_SL, POSITION_TP, POSITION_PROFIT, POSITION_SWAP};
   
   ENUM_POSITION_TYPE types[];
   double d[][6];
   ulong tickets[], extIds[];
   string symbols[], comments[];
   
   filter.let(POSITION_MAGIC, sets.MagicNumber).select(properties, tickets, d);
   filter.select(POSITION_SYMBOL, tickets, symbols);
   filter.select(POSITION_COMMENT, tickets, comments);
   filter.select(POSITION_TYPE, tickets, types);
   filter.select(POSITION_IDENTIFIER, tickets, extIds);

   Print("Tickets\t  Parent Id\tSymbols \t Trade Type \t\t\t\t\t\tEntry \t Lots \t\t SL  \t\t\t TP \t\t\t\t Profit \tSwat \t\tComments");
   for ( int i =0; i < ArraySize(tickets); i++) {
      Print(tickets[i], "\t", extIds[i] == 0 ? "\t\t\t\t\t\t\t\t\t" : (string)extIds[i], "\t", symbols[i], "\t", EnumToString(types[i]), " \t", (string)NormalizeDouble(d[i][0],3), "\t", d[i][1], " \t ",  d[i][2], " \t", d[i][3], " \t", d[i][4], " \t ", d[i][5], "\t", comments[i]);
      //Print(tickets[i], "\t", extIds[i] == 0 ? "\t\t\t\t\t\t\t\t\t" : extIds[i], "\t", symbols[i], "\t", EnumToString(types[i]), " \t", NormalizeDouble(d[i][0],3), "\t", d[i][1], " \t ",  d[i][2], " \t", d[i][3], " \t", d[i][4], " \t ", d[i][5]);
   }
}


从侧面看,我经常看到这些信息:

This single line message always shows whenever I attach my EA to a chart:
Unresolved int value as enum: 8 for MonitorInterface<ENUM_POSITION_PROPERTY_INTEGER,ENUM_POSITION_PROPERTY_DOUBLE,ENUM_POSITION_PROPERTY_STRING>::TradeState


While these ones below shows when it is detached

2025.10.17 19:30:01.347 Deriv Trader (Volatility 10 (1 s) Index.0,M15)   8 leaked strings left
2025.10.17 19:30:01.347 Deriv Trader (Volatility 10 (1 s) Index.0,M15)   2 undeleted dynamic objects found:
2025.10.17 19:30:01.347 Deriv Trader (Volatility 10 (1 s) Index.0,M15)      1 object of class 'WebSocketConnectionHybi'
2025.10.17 19:30:01.347 Deriv Trader (Volatility 10 (1 s) Index.0,M15)      1 object of class 'MqlWebSocketTransport'
2025.10.17 19:30:01.347 Deriv Trader (Volatility 10 (1 s) Index.0,M15)   576 bytes of leaked memory found
附加的文件:
log.txt  34 kb
 
pauldic #:
请原谅我遗漏了源代码,因此我恢复了您建议的修复方法,这样我就能再次出现错误了。根据日志

,似乎我代码中的这些部分是导致错误的部分。在一旁,我经常看到这些信息:

我忽略了字母 T 已被用作类模板 typename(奇怪的是编译器在这种情况下并没有产生错误),因此将 T 改为任何其他空闲字母都可以,例如 X:

   template<typename X>
   void ArraySort(X &s[][]) const
   {
      ::ArraySort(s);
   }

至于第一个警告,这里有论坛上的解释(我之前给过你):

关于交易、自动交易系统和交易策略测试的论坛

专家:交易者的 MQL5 编程 - 书中的源代码。第七部分

Stanislav Korotky, 2025.06.14 16:26

这只是一个警告,因为在 MQL5 的相应内置枚举中,通常连续分配的常量出现了间隙。出现这种空白是因为 MQL5 在不断变化,一些常量可能会过时,然后被淘汰。您可以编辑源代码以防止此类警告。

关于内存泄露问题 - 恐怕您的自定义源代码中有遗漏,书中没有显示这种情况。您应该提供完整的测试代码来重现问题。

PS.对您感兴趣的所有属性执行一次选择 会更有效:

   // 示例:为仓位申请利润、符号和票据
   // 按具体的神奇数字,按利润排序
   
   #include <MQL5Book/Tuples.mqh>
   #include <MQL5Book/PositionFilter.mqh>
   #property script_show_inputs
   
   input ulong Magic;
   
   void OnStart()
   {
      int props[] = {POSITION_PROFIT, POSITION_SYMBOL, POSITION_TICKET};
      Tuple3<double,string,ulong> tuples[];
      PositionFilter filter;
      filter.let(POSITION_MAGIC, Magic).select(props, tuples, true);
      ArrayPrint(tuples);
   }



注:我认为版主应将所有关于本书的问题和答案(从 #41 开始)转移到适当的主题,例如这里- https://www.mql5.com/en/forum/459067。

 
Stanislav Korotky #:

我忽略了字母 T 已被用作类模板 typename(奇怪的是编译器在这种情况下没有出错),因此将 T 改为任何其他空闲字母都可以,例如 X:

至于第一个警告,这里有一个论坛上的解释(我之前给过你):

关于泄露内存的问题--恐怕是你的自定义源代码有遗漏,书中没有显示这种情况。你应该提供完整的测试代码来重现这个问题。

PS.对您感兴趣的所有属性执行一次选择 会更有效:



注:我认为版主应该将所有关于这本书的问答(从 #41开始)转移到合适的主题,例如这里- https://www.mql5.com/en/forum/459067。

非常感谢你对 T -> X 的小小改动。再次感谢您指出了我之前的问题(我忘了我之前问过),您的提醒让我看到 toyjson3.mqh 的更新, 我之前错过了,对于 "select",我会进行更正的。

相信您对泄漏的看法是对的,我想我已经知道泄漏来自哪里了。

非常感谢您,兄弟。
 
void printActiveOrders() {
   int properties[] = {ORDER_VOLUME_INITIAL, ORDER_PRICE_OPEN, ORDER_SL, ORDER_TP, ORDER_TICKET, ORDER_MAGIC, ORDER_TYPE, ORDER_SYMBOL, ORDER_COMMENT};
   Tuple9<double,double,double,double,long,long,long,string,string> values[]; 
   OrderFilter filter;
   filter.select(properties, values);
   Print("\nFound:  ", ArraySize(values), " Orders\n{ORDER_VOLUME_INITIAL, ORDER_PRICE_OPEN, ORDER_SL, ORDER_TP, ORDER_TICKET, ORDER_MAGIC, ORDER_TYPE, ORDER_SYMBOL, ORDER_COMMENT}");
   ArrayPrint(values);
}

void printDeals() {
   DealFilter filter;    
   int properties[] = {DEAL_TIME, DEAL_SYMBOL, DEAL_TICKET, DEAL_TYPE, DEAL_VOLUME, DEAL_PRICE, DEAL_COMMISSION, DEAL_PROFIT};
   
   Tuple8<long,string,long,long,double,double,double,double> data[];   
   filter.select(properties, data, true); // 按时间筛选
   Print("\nFound:  ", ArraySize(data), " Deals\nTIME, SYMBOL, TICKET, TYPE, VOLUME, PRICE, COMMISSION, PROFIT");
   ArrayPrint(data);
}

@StanislavKorotky
我可以使用此代码访问交易和订单,但我一直不知道如何访问特定时间段的交易和订单。请问您是否有任何文档或示例可以指导我如何在指定的时间范围内进行同样的操作?

 
pauldic #:

我可以使用此代码访问交易和订单,但我不知道如何访问特定时间段的交易和订单。请问您是否有任何文档或示例指导我如何在指定的时间范围内进行同样的操作?

无论如何,订单、交易、头寸都与时间框架无关。你要么误解了什么,要么用词不当。