程序库: MT4Orders - 页 82

 

我不知道是否有可能在不使用 MT5 语言功能的情况下以测试速度解决这个问题。 这个问题很久以前就出现了,但我现在才着手解决。

版本 3802, __MT4ORDERS__ "2022.07.20"

在 "智能交易系统 "中每个刻度调用条件函数。在 mt5 策略测试器中测试。

	 datetime get_last_order_close_time () {
                datetime last_close_time=0;

                for ( int i = OrdersHistoryTotal() - 1; i >= 0; i-- ) {
                        if ( !OrderSelect ( i, SELECT_BY_POS, MODE_HISTORY )) {
                                continue;
                        }
         		 last_close_time=OrderCloseTime();
		        return last_close_time;
                }

                return last_close_time;
        }

交易数量 约为 2.6 万。测试时间约为 1 小时 10 分钟。

从代码中移除该函数后,测试时间变为约 17 分钟。

我使用 MT5 功能重写了相同的函数:

	 datetime get_last_order_close_timeMT5 () {
                datetime last_close_time=0;
                HistorySelect(0,TimeCurrent()); 

                for ( int i = HistoryDealsTotal() - 1; i >= 0; i-- ) {
                        
                        ulong ticket=HistoryDealGetTicket(i);
                        
                        if((ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT)
                        {
                           last_close_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
                           return last_close_time;
                        }                       
                }

                return last_close_time;
        }

测试时间约为 18 分钟。

我将库回滚到 __MT4ORDERS__ 版本 "2020.01.12",并在 2980 版本中编译智能交易系统。

使用get_last_order_close_time 函数的智能交易系统时间约 20 分钟。

 
elavr #:

我不知道不使用 MT5 语言功能是否能解决测试速度问题。

在这三种情况下,最终结果都是一样的吗?
 
fxsaber #:
在这三种情况下,最终结果是一样的吗?

当然是一样的。

它是在另一次终端更新后开始出现的。我没有修改你的程序库,并在旧终端中编译了机器人,使它能像以前一样工作。

 
elavr #:

这种情况是在又一次更新终端后开始出现的。我没有更改您的库,并在旧终端中编译了机器人,使其能像以前一样工作。

我做了一些研究。


专家顾问。

#include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006

#define  VIRTUAL_SNAPSHOT_REFRESHTIME 1000
#include <fxsaber\Virtual\Virtual.mqh> //https://www.mql5.com/zh/code/22577

input int inMod = 5;
input int inRange = 0;
input bool inVirtual = false;

const bool Init = inVirtual ? VIRTUAL::SelectByHandle(VIRTUAL::Create()) : false;;

#define  Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

ulong lOnTester = 0;

void OnTick()
{  
  static int i = 0;
  
  VIRTUAL::NewTick();
  
  if (!(i++ % inMod))
    OrderClose(OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0), 0.1, Bid, 0);
    
// VIRTUAL::Snapshot(); 
  lOnTester += LastCloseTimeMQL4() % 100;
  
// lOnTester += LastCloseTimeMQL5() % 100;
}

double OnTester()
{
  if (HistorySelect(0, INT_MAX))
    Print(HistoryDealsTotal());
  
  return((double)lOnTester);
}

在每个 inMod tick 上都会打开和关闭一个仓位。每个 tick 都会计算 OrderCloseTime。

OnTester 用作检查不同配置下结果一致性的标准。


使用历史记录的相应功能。

datetime LastCloseTimeMQL4()
{  
  datetime Res = 0;
  
  for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      Res = OrderCloseTime();
      
      break;
    }

  return(Res);
}

datetime LastCloseTimeMQL5()
{
  datetime Res = 0;
  
  if (HistorySelect(0, INT_MAX))
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
    {
      const ulong Ticket = HistoryDealGetTicket(i);
      
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) != DEAL_ENTRY_IN)
      {
        Res = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);
        
        break;
      }
    }
    
  return(Res);
}

#define  MACROS(A, B)          \
  datetime A##_2()            \
  {                           \
    static datetime Res = 0;  \
    static int PrevTotal = 0; \
                              \
    const int Total = B;      \
                              \
    if (PrevTotal != Total)   \
    {                         \
      Res = A();              \
                              \
      PrevTotal = Total;      \
    }                         \
                              \
    return(Res);              \
  }

// LastCloseTimeMQL4_2
MACROS(LastCloseTimeMQL4, OrdersHistoryTotal())

// LastCloseTimeMQL5_2
MACROS(LastCloseTimeMQL5, HistorySelect(0, INT_MAX) ? HistoryDealsTotal() : 0)


方法。

按照源代码中的设置运行一次(inMod = 5)。

2023.07.06 23:59:59   28179
final balance 99996992.20 pips
OnTester result 2761115
EURUSD,M1: 274413 ticks, 70443 bars generated. Environment synchronized in 0:00:00.021. Test passed in 0:00:03.712 (including ticks preprocessing 0:00:00.031).

28K 个事务,耗时近 4 秒。由于我们需要在优化模式下测量性能,以下所有性能读数都是以这种方式得出的。

shortest pass 0:00:02.875, longest pass 0:00:03.094, average pass 0:00:02.919

运行前强制重新编译,并且只启用一个代理来顺序执行通过。



b3815 和 b2958 的性能表(以毫秒为单位的执行时间)。

MT5 版本 LastCloseTimeMQL4 LastCloseTimeMQL5 LastCloseTimeMQL4_2 LastCloseTimeMQL4+VIRTUAL::Snapshot LastCloseTimeMQL4+VirtualTester
b3815 2875 113 708 732 45
b2958 2718 107 675 715 50

各地均使用2022 年 7 月 20 日 的 MT4Orders。



  • OrderSelect 运行速度较慢。这是由于 OrderSelect 绝对是从历史记录中计算所选订单的所有数据(OrderPrint 是免费的)。这是 HistoryOrderGet* 和 HistoryDealGet* 函数的绝佳组合,可处理任何复杂的市场情况和大量陷阱。查看 MT4ORDERS::GetHistoryPositionData()。这是一个适用于终端和测试器的单一函数,但针对测试器进行了特别加速,因为许多终端陷阱在测试器中并不存在。配置示例:
  • 因此,有必要减少历史订单的订单选择调用。这可以通过表格右侧三列所示的方式实现。
  • 最快的工作(比纯 MQL5 更快)是在虚拟环境中进行交易。我建议在虚拟环境中进行优化,而在虚拟环境外进行单次优化。
  • 测试器 b2958 和 b3815 的性能几乎相同。
  • 我不建议将测试器的 TS 逻辑与交易历史绑定。例如,您可以知道 TS 的 OrderCloseTime,而无需参考历史记录。
 
elavr #:

测试时间约为1 小时 10 分钟

我将库回滚到 __MT4ORDERS__ 版本 "2020.01.12",并在版本 2980 中编译智能交易系统。

使用get_last_order_close_time 函数的智能交易系统的工作时间 20 分钟

请在旧版本库上尝试上述代码(我没有旧版本库)。

如果性能有差异,请发送至 PM。

 
非常感谢!我下周就去看看!
 

是否可能存在内存泄漏或内存使用超出需要?可能在 this.tickets 或 this.amount (::ArrayResize) 中,也可能在其他地方?

数组的大小只会随着时间的推移而增加。这是必须的吗?是否有可能清空数组或不加载之前的所有交易?

 
pcdeni #:

是否可能存在内存泄漏或内存使用超出需要?可能在 this.tickets 或 this.amount (::ArrayResize) 中,也可能在其他地方?

数组的大小只会随着时间的推移而增加。这是必须的吗?是否有可能清空数组或不加载之前的所有交易?

程序库没有完全缓存历史数据。内存不足在理论上是可能的,但在实践中是不可能的。

编写一个脚本,使用该库对整个交易历史进行排序,看看会消耗多少内存。

 
fxsaber #:

程序库不会完全缓存历史数据。内存不足只是理论上有可能,实际情况并非如此。

编写一个脚本,使用该库对整个交易历史进行排序,看看会消耗多少内存。

在策略测试中,EA 每个核心使用 25 GB。

编辑:这是一个 1 年时间框架的测试,所以并不多。
 
pcdeni #:

在策略测试中,EA 每个核心使用 25 GB。

编辑:这是一个 1 年时间框架的测试,所以并不多。

库(MT4Orders.mqh)消耗的内存没有那么多。例如,您可以运行此 EA 自己看看。

最有可能的是,您使用指标的方法不正确:您创建了新的指标句柄,但没有删除旧的指标句柄。