我对毫秒时间变量的影响有一些看法,特别是关于 MQL5 版本的CHistoryCollection::GetListByTime(...) 函数。
它们是(按相关性递减顺序排列):
1) 日期 变量和长 毫秒时间变量都表示自 1970 年 1 月 1 日以来经过的时间。但是,有效存储的值之间相差 1000 倍。因此,这两种类型不能直接互相赋值。因此,GetListByTime(...) 在更改后停止工作,因为它直接将日期时间 参数存储在COrder m_order_instance 的毫秒时间属性中。可能的解决方案是加入两个新的转换函数(可能在delib.mqh 中)来处理这个 1000 因子:
//+------------------------------------------------------------------+ //} 将毫秒时间转换为日期时间。 //+------------------------------------------------------------------+ datetime TimeMSCtoDate(const long time_msc) { return datetime(time_msc/1000); } //+------------------------------------------------------------------+ //} 将日期时间转换为以毫秒为单位的时间。 //+------------------------------------------------------------------+ long DatetoTimeMSC(const datetime time_sec) { return long(time_sec * 1000); }
如果 MetaQuotes 在一开始就将日期时间 变量定义为以毫秒甚至微秒为单位的经过时间(谁说十年后机器人的交易时间 不会小于毫秒?),那么这类问题就不会发生。
总之,这个问题至少在CEventsCollection 和CMarketCollection 类的GetListByTime(...) 函数中也存在,或许在其他地方也是如此......
2) History 集合是一个知道是否排序的对象,如果排序,则知道排序属性(.SortMode() 函数),而GetListByTime(...) 函数假定集合已经 根据ORDER_PROP_TIME_OPEN 或ORDER_PROP_TIME_CLOSE 属性排序(在CEventsCollection 和CMarketCollection 版本中只是ORDER _PROP_TIME _OPEN)。根据 OOP 理念,GetListByTime(...) 在继续之前应检查集合是否已正确排序。
事实上,程序示例TestDoEasyPart03_1.mq5 创建了一个按ORDER_PROP_TIME_OPEN 排序的历史记录集合(MT5 默认),然后调用GetListByTime(...,SELECT_BY_TIME_CLOSE) 。通过这种检查,就会出现这种情况!
3) 虽然不是什么大问题,但既然 MT5 应该是新标准,为什么不让SELECT_BY_TIME_OPEN 成为CHistoryCollection::GetListByTime(...) 函数select_time_mode 参数的默认值呢?
根据前述建议,这将是CHistoryCollection::GetListByTime(...) 函数的代码:
public: ....... //--- 从时间范围为 begin_time 到 end_time 的集合中选择订单 CArrayObj *GetListByTime(const datetime begin_time=0,const datetime end_time=0, const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN); ....... //+------------------------------------------------------------------+ //| 从集合中选择有时间限制的订单 //| 从开始时间到结束时间| //+------------------------------------------------------------------+ CArrayObj *CHistoryCollection::GetListByTime(const datetime begin_time=0,const datetime end_time=0, const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN) { ENUM_ORDER_PROP_INTEGER property=(select_time_mode==SELECT_BY_TIME_CLOSE ? ORDER_PROP_TIME_CLOSE : ORDER_PROP_TIME_OPEN); if(property != (ENUM_ORDER_PROP_INTEGER)m_list_all_orders.SortMode()) { ::Print(DFUN+"History list not prpperly sorted"); //或许应将信息添加到 ENUM_MESSAGES_LIB 中 return NULL; } CArrayObj *list=new CArrayObj(); if(list==NULL) { ::Print(DFUN+CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_TEMP_LIST)); return NULL; } datetime begin=begin_time,end=(end_time==0 ? END_TIME : end_time); if(begin_time>end_time) begin=0; list.FreeMode(false); ListStorage.Add(list); //--- this.m_order_instance.SetProperty(property,DatetoTimeMSC(begin)); int index_begin=this.m_list_all_orders.SearchGreatOrEqual(&m_order_instance); if(index_begin==WRONG_VALUE) return list; this.m_order_instance.SetProperty(property,DatetoTimeMSC(end)); int index_end=this.m_list_all_orders.SearchLessOrEqual(&m_order_instance); if(index_end==WRONG_VALUE) return list; for(int i=index_begin; i<=index_end; i++) list.Add(this.m_list_all_orders.At(i)); return list; }
Alvaro Arioni :
我对毫秒时间变量的影响有一些看法,特别是关于 MQL5 版本的CHistoryCollection::GetListByTime(...) 函数。
它们是(按相关性递减顺序排列):
1) 日期 变量和长 毫秒时间变量都表示自 1970 年 1 月 1 日以来的时间。但是,有效存储的值之间相差 1000 倍。因此,这两种类型不能直接互相赋值。因此,GetListByTime(...) 在更改后停止工作,因为它直接将日期时间 参数存储在COrder m_order_instance 的毫秒时间属性中。可能的解决方案是加入两个新的转换函数(可能在delib.mqh 中)来处理这个 1000 因子:
如果 MetaQuotes 在一开始就将日期时间 变量定义为以毫秒甚至微秒为单位的经过时间(谁能保证十年后机器人的交易时间不会小于毫秒?)
总之,这个问题至少在CEventsCollection 和CMarketCollection 类中的GetListByTime(...) 函数中也存在,或许在其他地方也是如此.
.....
2) 历史记录集合是一个对象,它知道自己是否排序,如果排序,排序属性是什么(.SortMode()函数)。SortMode() 函数),而GetListByTime(...) 函数假定该集合已 按ORDER_PROP_TIME_OPEN 或ORDER_PROP_TIME_CLOSE 属性排序(在CEventsCollection 和CMarketCollection 版本中仅按ORDER_PROP_TIME_OPEN 排序)。根据 OOP 哲学,GetListByTime(...) 在继续之前应检查集合是否正确排序。
事实上,程序示例TestDoEasyPart03_1.mq5 按ORDER_PROP_TIME_OPEN(MT5 的默认值)创建了一个历史记录集合,然后调用GetListByTime(...,SELECT_BY_TIME_CLOSE)。通过这种检查,就会出现这种情况!
3) 不是什么大问题,但既然 MT5 应该是新标准,为什么不让SELECT_BY_TIME_OPEN 成为CHistoryCollection::GetListByTime(...) 函数select_time_mode 参数的默认值呢?
按照前述建议,这将是CHistoryCollection::GetListByTime(...) 函数的代码:
谢谢。在后续版本的库中(在上面 XI 的文章中),似乎已经使用了时间转换(我一般不使用日期时间--所有内容都是 long)。
我对集合有点不理解--请举例说明错误的排序。最好在最新的文章中提供(因为这些文章描述了创建库的顺序,而一切都在变化)
新文章 轻松快捷开发 MetaTrader 程序的函数库(第十一部分)。 与 MQL4 的兼容性 - 平仓事件已发布:
我们继续大型跨平台函数库的开发,简化 MetaTrader 5 和 MetaTrader 4 平台程序的开发。 在第十部分中,我们重启与 MQL4 函数库兼容性的工作,并定义了开仓和激活挂单的事件。 在本文中,我们将定义平仓事件,并剔除未使用的订单属性。
现在,部分平仓和挂单删除的事件被定义为单独的事件。
再次启动 EA 并单击观察事件定义的按钮:

正如我们所见,事件定义正确。 定义了一个平仓事件,止损价位和挂单价格的修改也一并进行了跟踪。作者:Artyom Trishkin