功能性睡眠替代品

 

你好,MQL4社区。

我在策略 测试器中运行包括Sleep()函数的EA时遇到了一个问题。很明显,在代码中包含Sleep()函数的情况下,测试器无法正常运行EA。

是否有在座的编码员从函数Sleep()中发现了另一种方法,以编码EA "等待 "一定的时间,同时EA在测试器中被运行?


谢谢你

 
WhooDoo22:

你好,MQL4社区。

我在策略测试器中运行包括Sleep()函数的EA时遇到了一个问题。很明显,在代码中包含Sleep()函数的情况下,测试器无法正常运行EA。

是否有在座的编码员从函数Sleep()中发现了另一种方法,以编码EA "等待 "一定的时间,同时EA在测试器中被运行?

如果你想为一个事件计时,那么就使用时间,不要只是试图暂停所需的时间,这不是sleep()的作用。
 

西蒙。

我选择使用函数'Sleep()'的一个原因是,Seconds()返回来自最后已知的服务器时间的值(从最后已知的服务器时间检索数据会导致秒跳过和/或暂停)。我希望的是可靠性,而不是通用性。

你对此有何看法?


谢谢你

 
WhooDoo22:

西蒙。

我选择使用函数'Sleep()'的原因是,Seconds()返回来自最后已知服务器时间的值 (从最后已知服务器时间检索数据会导致秒跳过和/或暂停)。

你有什么证据吗?你只能 "看到 "有刻度的时间,如果30秒内没有刻度,那么你将看到30秒的跳动。策略测试器中 的时间应该是合理统一的,因为这些时间不是真实的,而是合成的。
 

西蒙。

所以你写道,我可能把这些 "跳过 "和/或 "暂停 "称为秒,是因为在[秒x]和[秒y]之间没有产生刻度线。通俗地说,创建了一个刻度,现在'秒x'被保存。三秒内没有产生刻度线,然后又产生了一个刻度线。现在'秒y'被保存。('seconds y'=(seconds x +three seconds)) as ('seconds x'=(seconds y-three seconds))。

你对此有何看法?


我将暂时考虑我的选择。

非常感谢您的回答。

 
  1. 直到你从开始返回。在测试器中永远不会创建任何刻度。将TimeCurrent()保存在一个静态/通用(全局)变量中。下一个刻度 int deltaSec = TimeCurrent() - previous.
  2. https://www.mql5.com/en/forum/127483 报告说,DayOfWeek()在测试器中总是返回5(在指标中肯定不一样,如Ask和Bid)。我从不使用任何Seconds()、DayOfWeek()等,因为你不想要当前的服务器时间,你想要的是测试器的tick时间。 Now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ...
 
WhooDoo22:

西蒙。

所以你写道,我可能把这些 "跳过 "和/或 "暂停 "称为秒,是因为在[秒x]和[秒y]之间没有产生刻度线。通俗地说,创建了一个刻度,现在'秒x'被保存。三秒钟内没有产生刻度线,然后又产生了一个刻度线。现在'秒y'被保存。('秒y'=(秒x+三秒))为('秒x'=(秒y-三秒))。

你对此有何看法?

是的,刻度线之间很容易有3秒,就像在现实世界中,看看任何货币对在格林威治标准时间午夜时分,你会看到大量的刻度线之间的大的多秒时间......你甚至可以得到超过一分钟的无刻度线和错过M1条......这不是一件罕见的事情。
 

威廉。

非常感谢您的答复。

1.直到你从开始返回。在测试器中永远不会创建任何ticks。 将TimeCurrent()保存在一个静态/通用(全局)变量中。下一个刻度 int deltaSec = TimeCurrent() - previous.

我不明白你说的 "直到你从开始返回 "是什么意思。能否请你解释一下?


"在测试器中永远不会创建任何刻度线"

你的意思是不是说,在测试器中永远不会有真正的 刻度线产生。难道你不同意在测试器中创建人工 刻度吗?


"将TimeCurrent()保存在一个静态/普通(全局)变量中。下一个刻度 int deltaSec = TimeCurrent() - previous."

将TimeCurrent()保存到一个变量中。当下一个tick到来时,int deltaSec =TimeCurrent() - previous。

上一个 "变量不就是TimeCurrent()保存的变量吗......

deltaSec = TimeCurrent() -(TimeCurrent() saved to a variable previously)

请澄清一下威廉。


https://www.mql5.com/en/forum/127483 报告说,DayOfWeek()在测试器中总是返回5。我从不使用任何Seconds()、DayOfWeek()等,因为你现在想要的是当前的服务器时间,你想要的是测试器的tick时间。 Now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) 。


"你想要测试者的刻度时间"。

是的,我相信这正是我在策略测试器中测试EA时想要的,因为西蒙的帖子描述了为什么秒数会出现跳动和/或暂停的原因。


now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ...。

换句话说...

sec = TimeSeconds(TimeCurrent()); and DOW = TimeDayOfWeek(TimeCurrent())。

你对此有何看法?


谢谢你
 
WhooDoo22:

now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) 。

换言之...

sec = TimeSeconds(TimeCurrent()); and DOW = TimeDayOfWeek(TimeCurrent())。

看看TimeSeconds()给你什么,然后想想TimeCurrent()给你什么。.你需要哪一个,为什么?
 
WhooDoo22:

我不明白你说的 "直到你从起点回来 "是什么意思。能否请你解释一下?"

你的意思是不是说,在测试器中永远不会产生真正的 虱子。难道你不同意在测试器中产生人工 虱子吗?

  1. int start(){
       // do something
       return; // Return from start.
    }
    int start(){
       // do something
       // Fall off the end is a Return from start.
    }

  2. 在你返回之前,任何种类的 刻度都不会被创建,它会创建下一个刻度并调用你的start()。如果你计算了5分钟并返回,那么下一次调用时的成交量(tick数)将是+1。在实时图表中,如果你计算了5分钟,那么你将错过5分钟的ticks,而在M1上将形成几个新的柱子。
 
RaptorUK:
在策略测试器中,没有逻辑理由让sleep()发挥作用......

小心这样的说法。在测试器中,甚至在指标中,总是有逻辑上的理由来运行sleep()。对,对于OP的使用情况,你不应该玩sleep,但你不能把它概括为所有MQL。

例如,如果我测试一个与测试中的EA交互的脚本,我可能需要同步状态,我说的是mutexes。

如果两个线程需要同步,它们都需要有 "睡眠 "的能力。如果你需要等待一定数量的CPU周期,sleep()是唯一干净的解决方案,"for "结构只是表明你缺乏知识。

好吧,让我们举个实际的例子:我的EA可以显示订单状态(自画的箭头等)。它们通过响应通过图表对象的文本描述(1-挂单,2-开仓,3-平仓,4-全部)"发送 "的外部命令来做到这一点,这就是为什么我称之为图表命令。或者它们可以通过响应其他命令("开始"、"停止"、"恢复")来启动/停止/恢复交易序列。为了读取这些命令,它们需要同步访问这些图表对象(创建图表对象+设置文本属性并不是一个原子操作)。

如果它们做了类似的事情,我 "必须 "停止UI线程以获得一个干净的状态,10毫秒并不重要。

int seconds;

// run until the lock is aquired
while (true) {
   ...
   // warn every second and cancel after 10 seconds
   duration = GetTickCount() - startTime;
   if (duration >= seconds*1000) {
      if (seconds >= 10)
         return(_false(catch("AquireLock(5)   failed to get lock for mutex \""+ mutexName +"\" after "+ DoubleToStr(duration/1000.0, 3) +" sec., giving up", ERR_RUNTIME_ERROR)));
      warn(StringConcatenate("AquireLock(6)   couldn't get lock for mutex \"", mutexName, "\" after ", DoubleToStr(duration/1000.0, 3), " sec., retrying..."));
      seconds++;
   }
   //debug("AquireLock()   couldn't get lock for mutex \""+ mutexName +"\", retrying...");

   if (IsTesting() || IsIndicator()) SleepEx(100, true);          // expert or indicator under test
   else                              Sleep(100);
}

我通过写一个脚本并给它指定一个热键来使用这些命令。或者我在收藏夹里有一个 "开始 "和一个 "停止 "脚本,通过鼠标点击来启动/停止/恢复一个EA。

例如,在测试器中,全速运行的VisualMode=On的EA如果没有适当的同步,几乎会立即崩溃。