多币种专家测试结果

 

在阅读了关于构建多币种EA的文章,提出问题并从社区的 "守门人 "那里得到答案后,我的问题仍然是:"如何构建EA代码,以使测试结果正确?"本课题的目的只是为了找出这个问题。

我使用社区成员建议的三种不同方法进行了测试。

-OnTick()。

- 这个方法是Konstantin Gruzdev在他的文章《MetaTrader 5中多货币模式的实现》中建议的。

-OnTimer()。

我从Nikolay Kositsin那里借用了多货币专家顾问的方案,他在他的文章《创建一个在不同符号上交易的专家顾问》中详细描述了这一方案。

为了测试,我写了一个简单的EA,因为本质是在比较测试结果。参考 "将是 2000年以来欧元兑美元 日线图的结果 。然后,这个具有相同参数的结果将与从英镑兑美元 图表中获得的结果进行比较。原则上,只有一台仪器参与测试,但无论哪台仪器被测试,其结果都应该是相同的。

OnTick()

int OnInit()
{
 return(0);
}

void OnDeinit()
{
}

void OnTick()
{  
 // Объявление массивов переменных для торговых сигналов
 static datetime New_Bar[1];  
 static bool UpSignal[1], DnSignal[1];
   
 // Получение торговых сигналов
 TradeSignalCounter(0,Symbol_01,Trade_01,Timeframe_01,UpSignal,DnSignal,New_Bar);

 // Совершение торговых операций
 TradePerformer(0,Symbol_01,Trade_01,Timeframe_01,Stop_Loss_01,Take_Profit_01,Slippage_01,UpSignal,DnSignal,New_Bar);
}

欧元兑美元 图表欧元兑美元 进行测试。

标签:01_tick

GBPUSD 图表中对EURUSD 进行测试。

标签:02_tick

测试的结果并不一致。

绘图事件(OnChartEvent)

enum ENUM_CHART_EVENT_SYMBOL
  {
   CHARTEVENT_NO        =0,          // События отключены
   CHARTEVENT_INIT      =0,          // Событие "инициализация" 
   
   CHARTEVENT_NEWBAR_M1 =0x00000001, // Событие "новый бар" на 1 -минутном графике
   CHARTEVENT_NEWBAR_M2 =0x00000002, // Событие "новый бар" на 2 -минутном графике
   CHARTEVENT_NEWBAR_M3 =0x00000004, // Событие "новый бар" на 3 -минутном графике
   CHARTEVENT_NEWBAR_M4 =0x00000008, // Событие "новый бар" на 4 -минутном графике
   
   CHARTEVENT_NEWBAR_M5 =0x00000010, // Событие "новый бар" на 5 -минутном графике
   CHARTEVENT_NEWBAR_M6 =0x00000020, // Событие "новый бар" на 6 -минутном графике
   CHARTEVENT_NEWBAR_M10=0x00000040, // Событие "новый бар" на 10-минутном графике
   CHARTEVENT_NEWBAR_M12=0x00000080, // Событие "новый бар" на 12-минутном графике
   
   CHARTEVENT_NEWBAR_M15=0x00000100, // Событие "новый бар" на 15-минутном графике
   CHARTEVENT_NEWBAR_M20=0x00000200, // Событие "новый бар" на 20-минутном графике
   CHARTEVENT_NEWBAR_M30=0x00000400, // Событие "новый бар" на 30-минутном графике
   CHARTEVENT_NEWBAR_H1 =0x00000800, // Событие "новый бар" на 1 -часовом графике
   
   CHARTEVENT_NEWBAR_H2 =0x00001000, // Событие "новый бар" на 2 -часовом графике
   CHARTEVENT_NEWBAR_H3 =0x00002000, // Событие "новый бар" на 3 -часовом графике
   CHARTEVENT_NEWBAR_H4 =0x00004000, // Событие "новый бар" на 4 -часовом графике
   CHARTEVENT_NEWBAR_H6 =0x00008000, // Событие "новый бар" на 6 -часовом графике
   
   CHARTEVENT_NEWBAR_H8 =0x00010000, // Событие "новый бар" на 8 -часовом графике
   CHARTEVENT_NEWBAR_H12=0x00020000, // Событие "новый бар" на 12-часовом графике
   CHARTEVENT_NEWBAR_D1 =0x00040000, // Событие "новый бар" на дневном графике
   CHARTEVENT_NEWBAR_W1 =0x00080000, // Событие "новый бар" на недельном графике
     
   CHARTEVENT_NEWBAR_MN1=0x00100000, // Событие "новый бар" на месячном графике   
   CHARTEVENT_TICK      =0x00200000, // Событие "новый тик"
   
   CHARTEVENT_ALL       =0xFFFFFFFF, // Все события включены
  };

...

int OnInit()
{
 if(iCustom("EURUSD",PERIOD_D1,"Spy Control panel MCM",ChartID(),0,CHARTEVENT_TICK) == INVALID_HANDLE)
   { Print("Ошибка установки шпиона на EURUSD"); return(true);}
   
 if(iCustom("GBPUSD",PERIOD_D1,"Spy Control panel MCM",ChartID(),1,CHARTEVENT_TICK) == INVALID_HANDLE)
   { Print("Ошибка установки шпиона на GBPUSD"); return(true);}
}

void OnDeinit()
{
}

void OnChartEvent(const int id,         // идентификатор события
                  const long&   lparam, // флаг события поступившего от агента панели.
                                        // Флаги соответствуют перечислению ENUM_CHART_EVENT_SYMBOL.
                  const double& dparam, // цена
                  const string& sparam  // инструмент 
                 )
{
 if(id >= CHARTEVENT_CUSTOM)      
   {
    // Объявление массивов переменных для торговых сигналов
    static datetime New_Bar[1];  
    static bool UpSignal[1], DnSignal[1];
      
    // Получение торговых сигналов
    TradeSignalCounter(0,Symbol_01,Trade_01,Timeframe_01,UpSignal,DnSignal,New_Bar);
   
    // Совершение торговых операций
    TradePerformer(0,Symbol_01,Trade_01,Timeframe_01,Stop_Loss_01,Take_Profit_01,Slippage_01,UpSignal,DnSignal,New_Bar);
   }
}

欧元 兑美元的图表 测试欧元兑美元

标签:01_event ==01_tick

其结果与标记为01_tick 的结果相同。

GBPUSD 图表上测试EURUSD

标签:02_event ~=02_tick

测试结果并不一致。

计时器上(OnTimer)。

int OnInit()
{
 EventSetTimer(10);

 return(0);
}

void OnDeinit()
{
 EventKillTimer();
}

void OnTimer()
{
 // Объявление массивов переменных для торговых сигналов
 static datetime New_Bar[1];  
 static bool UpSignal[1], DnSignal[1];
   
 // Получение торговых сигналов
 TradeSignalCounter(0,Symbol_01,Trade_01,Timeframe_01,UpSignal,DnSignal,New_Bar);

 // Совершение торговых операций
 TradePerformer(0,Symbol_01,Trade_01,Timeframe_01,Stop_Loss_01,Take_Profit_01,Slippage_01,UpSignal,DnSignal,New_Bar);
}

计时器设置为10秒。

欧元 兑美元图表 测试欧元兑美元 工具。

标签01_time==01_tick&& 01_time==01_ event

GBPUSD 图表中对EURUSD 进行测试。

标签02_time==01_tick&& 02_time==01_ event

测试结果是相同的。只有在一个地方,我看到了一个小小的不准确。我还注意到,计时器中的间隔越小,结果就越准确。也就是说,即使测试是在日线上进行的,而且测试器中的间隔时间被设置为例如1小时,测试的运行速度也会明显快于10秒,但测试结果却不一致。

------

这就是全部。对大家的意见很感兴趣,对解决方法更感兴趣。)


 

在我看来,将这些选项分开比较是不正确的。

我个人坚持认为,动画片中的计时器必须是,至于会加入什么内容(刻度或事件)则是另外一个问题。

在我看来,所有可用的处理程序都应该被使用,问题只在于它们的填充和一般算法的实施。

 
tol64:

"你如何把考官代码放在一起,以便测试结果是正确的?"。

我最初并不理解问题的表述。你说的 "正确的 "测试结果是什么意思,为什么要实现这些结果?
 
Interesting:

在我看来,将这些选项分开比较是不正确的。

我个人认为,动画片中的计时器必须存在,至于会在其中加入什么内容(滴答声或事件)则是另外一个问题。

我们的想法是,所有可用的处理程序都应该在骡子中使用,这只是它们的填充和实现一般算法的问题。


为什么比较这些选项是不正确的?在一个简单的专家顾问的范围内,当在必要的符号和必要的TF处形成条形后做出决定时,我认为这是正确的。

不正确的是下面提到的,如果增加一个更复杂的算法,用同样的tick来分析当前的情况,那就不正确了。但我只对成型的钢筋感兴趣。

 
Yedelkin:
起初我并不理解这个问题的表述。你说的 "正确的 "测试结果是什么意思,为什么要实现这些结果?

就是说,与现实相符的那些。无论我们从哪个角色开始测试,结果都应该是相同的。在这种情况下,只有通过使用OnTimer()函数才能获得相同的结果。

我对Konstantin Gruzdev的方法非常感兴趣。也许我做错了什么,这就是为什么我没有得到正确(可靠)的结果。我也希望得到他对这个问题的评论。

 
tol64:

为什么比较这些选项是不正确的?在这个简单的专家顾问的框架内,当在正确的符号和正确的TF上形成条形后做出决定,我认为是正确的。

不正确的是下面提到的,如果我们增加一个更复杂的算法,用同样的ticks来分析当前的情况。但我只对成型的酒吧感兴趣。

我不争辩,这在理论上是正确的,但在实践中却有很多问题。

例如,这里有一个--它是在ticks的处理程序中实现的,但与服务器的连接丢失。该系统将如何工作,如果出了问题,它将如何检测?

只在计时器中实现--或多或少可以接受的选择,但它需要在期限的选择上做出合理的妥协(但即使如此也会有一些困难)。

事件 - 事件本身的效率也不高。一般来说,处理刻度线和事件的方式应该是最有效地利用资源,使专家顾问能够相当迅速地切换到处理新的数据部分。

耶德尔金
我从一开始就不明白这个问题。什么是 "正确的 "测试结果,以及为什么应该获得这些结果?

我还认为,你不应该取得100%相同的结果。此外,把乘法的可能性限制在一个符号的交易上是很奇怪的。

假设至少有两个符号将被交易(其中一个有可能是图表符号)。

 
tol64:

就是说,与现实相符的那些。无论我们从哪一个符号开始测试,结果都应该是相同的。

相信我,找到100%的非同一性是自我欺骗和幻觉。就像永远在工作的GRAAL一样的幻觉。你必须始终考虑到一定的误差/不一致的幅度。

而且,就像现在这样,测试一幅漫画并不能很好地揭示问题。关于多头的讨论只应该是在多个符号上交易或在一个符号上用多个策略交易。

我的意思是,在一个多符号中,持续相同的结果并不重要,重要的是允许专家在考虑到头寸和历史的情况下做出交易决定的机制。

例如,尝试交易两个符号EURUSD 和GBPUSD,而交易应该使用对冲和第二个符号的信号。

 
Interesting:

相信我,对100%非同一性的追求是一种自欺欺人的幻觉。就像一直在工作的GRAAL一样的幻觉。你总是要考虑到一定的误差/不一致的幅度。

而且,就像现在这样,测试一幅漫画并不能很好地揭示问题。关于多头的讨论只应该是在多个符号上交易或在一个符号上用多个策略交易。

我的意思是,在一个多符号中,经常性的相同结果并不重要,重要的是允许专家在考虑到头寸和历史的情况下做出交易决定的机制。

例如,尝试交易两个符号EURUSD和GBPUSD,而交易应该使用对冲和第二个符号的信号。

现在你看到的是大画面,即EA应该如何工作。让我们跳过所有的困难和真实交易的程序实施 的技术细节。在这篇文章中,这个问题非常关键。

1.一个简单的交易系统。它的基础是成型的钢筋。

2.对一个符号的测试,但从另一个符号开始。

我有意将结构简化到最小。这样做是为了便于分析测试结果。你可以测试所有的符号,但结果不会变得更好。你会得到一个混乱的局面,将更难更久地进行分析。专家顾问会在它所在的符号上显示确切的行动,但它会在所有其他符号上制造混乱,这正是这些结果所显示的。测试结果应该是相同的,否则就会发现专家顾问在一个符号上做出了正确的输入,而在其他符号上却没有,或者没有完全遵循系统。这种差异是相当明显的。

到目前为止,只有通过OnTimer()函数才能实现身份识别。

P.S. 我不相信有GRAILS。或者说,我对它的理解与许多人不同)。

 

下面是通过OnTimer()函数在五个字符上一次的结果。

无论从哪个符号进行测试,结果都是一样的。

但在使用其他方法(OnTick()和OnChartEvent())时,当改变专家顾问所在的符号时,结果会有所不同。而这恰恰证实了专家顾问对其他符号执行了不正确的操作。

很明显,为什么会发生在OnTick()上。这一点已经讨论过很多次了。但OnChartEvent()方法仍然值得商榷。

 

tol64:

有了OnTick(),就很清楚为什么会发生这种情况。这一点已经讨论过很多次了。但OnChartEvent()方法仍然值得商榷。

我们需要考虑到事件处理 中可能出现的延迟,甚至可能出现事件的丢失。
Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
tol64:

就是说,与现实相符的那些。无论我们从哪个角色开始测试,结果都应该是相同的。在这种情况下,只有在使用OnTimer()时才会取得相同的结果。

我大致上看到了这一点。事实上,你正在选择一个 "引擎",你将在此基础上建立你的多货币专家顾问。为此,你采取一个原始的交易策略,首先按照 "信号源和信号处理程序在一个符号上 "的方案执行,然后再按照 "信号源和信号处理程序在不同符号上 "的方案执行。这是否正确?

如果是这样,我不太理解 " GBPUSD 图表上测试EURUSD 工具 "这样的短语。在这种情况下,哪个符号是信号源,哪个符号是连接到信号处理程序的?

原因: