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

 
Stanislav Korotky #:
无论如何,订单、交易、头寸都与时间框架无关。你不是误解了什么,就是用词不当。
对不起,我想我用词不当,我说的"时间 范围 "是指 "日期范围"。如果我想选择在给定日期范围内成交的交易/订单,比如从 2025-10-01 00:00:00 到 2025-10-22 23:59:59 的交易。
 
pauldic #:
对不起,我想我用词不当,我说的"时间 范围 "是指 "日期范围"。如果我想选择在给定日期范围内成交的交易/订单,比如从 2025-10-01 00:00:00 到 2025-10-22 23:59:59 的交易。

如果要分析交易历史的子范围,在不影响过滤代码本身的情况下,在过滤之前只请求这部分历史记录会更有效:

input datetime SubrangeFrom = 0;
input datetime SubrangeTo = 0;

...

{
   HistorySelect(SubrangeFrom, SubrangeTo);
   // ......过滤器代码在这里保持不变
}

如果出于某种原因,您想在HistorySelect 应用的全局范围内选择一个(更窄的)子范围,那么您仍然可以在过滤代码中这样做:

{
      // 其中一些在这里

      // HistorySelect(0, LONG_MAX);
      // HistorySelectByPosition(PositionID);
      ...
      DealTuple deals[];
      if(SubrangeFrom != SubrangeTo && SubrangeFrom < SubrangeTo)
      {
         filter.let(DEAL_TIME, SubrangeFrom - 1, IS::GREATER).let(DEAL_TIME, SubrangeTo + 1, IS::LESS);
      }
      filter.let(DEAL_POSITION_ID, PositionID).select(deals, true);
      ...
}

黄线高亮部分使用额外的限定符 IS::GREATER 和 IS::LESS(默认情况下,在调用let() 时不会指定这两个限定符,而 IS::EQUAL 通常用于单值字段)为日期时间范围 [SubrangeFrom, SubrangeTo] 设置了两个条件。

我只知道一个按日期范围应用子过滤器的原因,那就是订单的设置时间 (ORDER_TIME_SETUP),因为HistorySelect 应用于订单的另一个日期时间属性,即订单执行时间 (ORDER_TIME_DONE)。此外,如果有很多有效订单,过滤有效订单的子范围(不在历史中)可能会很有趣。

您可以从MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 示例脚本开始。
 
Stanislav Korotky #:

如果要分析交易历史的一个子范围,在不影响过滤代码本身的情况下,在过滤前只请求分析这部分历史记录会更有效:

如果出于某种原因,您想在HistorySelect 应用的全局范围内选择一个(更窄的)子范围,那么您仍然可以在过滤代码中这样做:

黄线高亮部分使用额外的限定符 IS::GREATER 和 IS::LESS(默认情况下,在其他调用let() 时不指定这两个限定符,而 IS::EQUAL 通常用于单值字段)为日期时间范围 [SubrangeFrom, SubrangeTo] 设置了两个条件。

我只知道一个按日期范围应用子过滤器的原因,那就是订单的设置时间 (ORDER_TIME_SETUP),因为HistorySelect 应用于订单的另一个日期时间属性,即订单执行时间 (ORDER_TIME_DONE)。此外,如果有很多有效订单,过滤有效订单的子范围(不在历史中)可能会很有趣。

您可以从MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 示例脚本开始。
@StanislavKorotky 再次感谢...这对我来说是一个很好的起点,我将开始使用它。
 

修正MQL5/Include/MQL5Book/TradeUtils.mqh.

   bool Equal(const double v1, const double v2)
   {
      return v1 == v2 || fabs(v1 - v2) < DBL_EPSILON * fmax(1.0, fmax(fabs(v1), fabs(v2)));
   }
附加的文件:
TradeUtils.mqh  12 kb
 
pauldic #:

插入代码 时请 使用代码 按钮 (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


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


你好@Paul Dick

请尝试使用https://www.mql5.com/zh/code/57233 对数组进行排序

Introsort (Introspective sort) using Function Pointers
Introsort (Introspective sort) using Function Pointers
  • 2025.03.18
  • www.mql5.com
A hybrid sorting algorithm that provide fast performance for sorting arrays of simple types, structures or object pointers.
 

现附上基于 R2 -RSquared.mqh 的自定义优化 准则计算文件的更新版本,其中对变量手数的计算进行了修正。

估算质量有了明显改善--从优化结果 表中可以看出,已经获得了恢复系数和夏普参数的组合。

使用示例

double OnTester()
{
   HistorySelect(0, LONG_MAX);
   
   #define  STAT_PROPS 5
   
   const ENUM_DEAL_PROPERTY_DOUBLE props[STAT_PROPS] =
   {
      DEAL_PROFIT, DEAL_SWAP, DEAL_COMMISSION, DEAL_FEE, DEAL_VOLUME
   };
   double expenses[][STAT_PROPS];
   ulong tickets[]; // 仅用于匹配 "选择 "原型,但对调试很有用
   
   DealFilter filter;
   filter.let(DEAL_TYPE, (1 << DEAL_TYPE_BUY) | (1 << DEAL_TYPE_SELL), IS::OR_BITWISE)
      .let(DEAL_ENTRY, (1 << DEAL_ENTRY_OUT) | (1 << DEAL_ENTRY_INOUT) | (1 << DEAL_ENTRY_OUT_BY), IS::OR_BITWISE)
      .select(props, tickets, expenses);

   const int n = ArraySize(tickets);
   
   double balance[];
   double volumes[]; // 使用 R2 标准时考虑贸易量
   
   ArrayResize(balance, n + 1);
   balance[0] = 0;
   ArrayResize(volumes, n + 1);
   volumes[0] = 0;
   
   for(int i = 0; i < n; ++i)
   {
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j)
      {
         result += expenses[i][j];
      }
      // 以数量为模型 - 更多投资 - 更多预期回报
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef  STAT_PROPS
   
   return r2 * 100;
}
附加的文件:
RSquared.mqh  4 kb
 

我最近在学习 Frame,并测试了您的代码 FrameTransfer.mq5。在当前的 MT5 编译器中,这一行出现了错误。请验证:#property tester_set "FrameTransfer.set" (invalid tester set file extension, '*.set' expected FrameTransfer.mq5)

必须这样修改才能成功编译:#property tester_set "\\Presets\FrameTransfer.set"

甚至 `#property tester_set "/Presets/FrameTransfer.set"` 也会失败。

也许你可以修改算法书中的描述:


 
hini #属性 tester_set "FrameTransfer.set"(测试器设置文件扩展名无效,"*.set "应为 FrameTransfer.mq5)

若要成功编译,应作如下更改:#property tester_set "\\Presets\\FrameTransfer.set"

即使是 `#property tester_set "/Presets/FrameTransfer.set"` 也会失败。

也许你可以修改算法书中的描述:


这是一个明显的编译器错误--它给代码带来了错误:"无效的 tester set 文件扩展名,'*.set'预期":

#property tester_set "FrameTransfer.set"

其中文件具有所需的扩展名。文件位置路径与此无关。

这个错误由来已久,至少从 2024 年就存在了。我不知道为什么 MQ 不急于修复它。

至于图书编辑,在这种情况下并不需要,但无论如何,图书现在完全由 MQ 控制。

 
Stanislav Korotky 控制。
已确认并报告。让我们看看是否会得到修复。
 
Stanislav Korotky #:

这是一个明显的编译器错误 - 它给出了错误:代码中出现了 "无效的测试仪设置文件扩展名,预计为 '*.set'"的错误:

谢谢,已修复!

要保持你的 MetaEditor 版本,请在文件名末尾添加 0:"myset.set\0