文章 "开发多币种 EA 交易(第 17 部分):为真实交易做进一步准备"

 

新文章 开发多币种 EA 交易(第 17 部分):为真实交易做进一步准备已发布:

目前,我们的 EA 使用数据库来获取交易策略单个实例的初始化字符串。然而,这个数据库相当大,包含许多实际 EA 操作不需要的信息。让我们尝试在不强制连接到数据库的情况下确保 EA 的功能。

在前面的一篇文章中,我们已经将注意力转向了处理真实账户所需的 EA 改进。到目前为止,我们的工作主要集中在在策略测试器中获得可接受的 EA 结果上。真实交易需要更多的准备。

除了在重启终端后恢复 EA 操作、使用略有不同的交易工具名称以及在达到指定指标时自动完成交易的能力外,我们还面临以下问题:为了形成初始化字符串,我们使用直接从数据库中获得的信息,该数据库存储了交易策略实例及其组的所有优化结果。

要运行 EA,我们必须在共享终端文件夹中有一个包含数据库的文件。数据库的大小已经达到几 GB,并且将来还会不断增长。因此,将数据库作为EA的一个组成部分是不合理的 — 只需要存储在那里的一小部分信息就可以启动。因此,有必要在 EA 中实现一种提取和使用此信息的机制。

开发多币种 EA 交易 (第 17 部分):为真实交易做进一步准备 


作者:Yuriy Bykov

 

尤里你好!我正在研究你的代码,但有一点不明白....。在 SimpleVolumesStrategy.mqh 文件的构造函数中有一个参数:

         // 在最小时间框架上注册新条形事件处理程序
         IsNewBar(m_symbol, PERIOD_M1);

为什么要这样做?为什么恰恰是周期 M1,而不是当前周期?我的理解是,在这种情况下,智能交易系统将不按给定 TF 的开仓量工作,而只是按 M1 工作。还是我理解错了?

第二点 - 在 SignalForOpen() 函数中:

      // 如果当前音量超过设定音量,则
      if(m_volumes[0] > avrVolume * (1 + m_signalDeviation + m_ordersTotal * m_signaAddlDeviation)) {
         // 如果烛台开盘价低于当前价(收盘价),则
         if(iOpen(m_symbol, m_timeframe, 0) < iClose(m_symbol, m_timeframe, 0)) {
            signal = 1; // 买入信号
         } else {
            signal = -1; // 否则就是卖出信号
         }
      }

您在计算中指出了第 0 条(当前),但在我看来应该是第 1 条(最后收盘)。只是第一个刻度线的第 0 个刻度线(如果以开盘价 计算)没有实体,因此开盘价总是等于收盘价。而且它不可能有任何成交量,因为它还没有形成。我可能误解了什么,但它能以某种方式运行....。我想知道为什么会这样?

另外,如果我想将某个参数(新参数)添加到该策略中,我是否需要在设置中的 SimpleVolumesStage1.mq5 Expert Advisor 中创建该参数,并将其传递给一个字符串变量,然后在该类(SimpleVolumesStrategy.mqh)的构造函数中以正确的顺序进行解析,仅此而已?还是我需要在其他地方规定?

 

你好,维克多。

Зачем Вы это делаете? Почему именно период М1, а не текущий на котором запускается этот экземпляр стратегии? Как я понимаю в этом случае советник будет работать не по открытиям баров заданного ТФ а просто по м1. Или я что-то не правильно понимаю?

Expert Advisor 的工作由两部分组成: 开立虚拟仓位和将开立的虚拟仓位与实际仓位同步。设定的 TF 仅在第一部分用于确定开仓信号。理想情况下,同步应在最小时间框架 M1 的每个刻度线或至少每个新的条形图上执行,因为虚拟仓位随时可能达到 TP 或 SL。

在 VirtualAdvisor::Tick() 方法中,开始时会检查所有监控符号和时间框架是否出现新的条形图,包括 M1。如果没有出现,则 Expert Advisor 不会执行任何其他操作。只有在 M1 上出现新条形图时,才会执行其他操作。在这种情况下,您可以在 M1 上以 OHLC 模式进行优化,并获得与 EA 在图表上运行时几乎相同的结果(图表上有所有刻度线)。而且这种方式优化速度更快。你提到的那行代码只是一个安全网,以防我们不需要在策略中跟踪 M1 上的新条形图。这样可以保证至少跟踪一个符号。

当然,如果你愿意,也可以通过变量 useOnlyNewBars_ = false 禁用这种操作模式。这样 Expert Advisor 就会在每个可用的刻度上检查并同步仓位。

只是第一个刻度的第 0 条(如果我们使用开盘价)没有正文,因此开盘价总是等于收盘价。而且它不可能有任何成交量,因为它还没有形成。我可能误解了一些东西,但它还是可以工作的......

一个新的 M1 条形图的开盘可能发生在更高时间框架的条形图内。请注意,SignalForOpen() 使用的是当前时间框架,通常是 H1、M30 或 M15。因此,当前时间框架的开盘价和收盘价将不再重合。此外,只有当当前时间框架上当前条形图的刻度线成交量大大超过一个条形图的典型刻度线成交量时,才会进行检查。这不可能发生在第一个刻度线,因为此时的刻度线交易量只有 1。

另外,如果我想在该策略中加入某个参数(新参数),我需要在设置中的 SimpleVolumesStage1.mq5 Expert Advisor 中创建该参数,并将其传递给一个字符串变量,然后在该类(SimpleVolumesStrategy.mqh)的构造函数中以正确的顺序进行解析,仅此而已?还是说你还需要在其他地方说明?

当然可以。

 
Yuriy Bykov #:

智能交易系统的工作由两部分组成:开立虚拟仓位和将开立的虚拟仓位与实际仓位同步。设定的 TF 仅在第一部分用于确定开仓信号。同步最好在最小时间框架 M1 的每个刻度线或至少每个新条形图上进行,因为虚拟仓位随时可能达到 TP 或 SL。

在 VirtualAdvisor::Tick() 方法中,开始时会检查所有监控符号和时间框架是否出现新的条形图,包括 M1。如果没有出现,则 Expert Advisor 不会执行任何其他操作。只有在 M1 上出现新条形图时,才会执行其他操作。在这种情况下,您可以在 M1 上以 OHLC 模式进行优化,并获得与 EA 在图表上运行时几乎相同的结果(图表上有所有刻度线)。而且这种方式优化速度更快。你提到的那行代码只是一个安全网,以防我们不需要在策略中跟踪 M1 上的新条形图。这样就能保证至少在一个符号上跟踪它。

当然,如果你愿意,也可以通过变量 useOnlyNewBars_ = false 禁用这种操作模式。然后,EA 将在每个可用的刻度上检查并同步仓位。

我明白了。但举个例子,我们能不能让仓位同步在每个刻度上都起作用,并在策略中指定的 TF(m15,m30,h1)上出现新的条形图时打开虚拟(新)仓位?

Yuriy Bykov#:
新 M1 条形图的开仓可能发生在更高时间框架的条形图内。请注意,SignalForOpen() 使用当前时间框架,通常是 H1、M30 或 M15。因此,当前时间框架的开盘价和收盘价将不再重合。此外,只有当当前时间框架上当前条形图的刻度线成交量大大超过一个条形图的典型刻度线成交量时,才会进行检查。这不可能发生在第一个刻度线,因为此时的刻度线交易量只有 1。

我有点不明白您的意思。是的,SignalForOpen() 使用的是当前虚拟策略实例设置中设置的 TF,我明白这一点。但举例来说,如果我想让 EA 严格按照最后收盘的条形图工作,那么我就必须在这里指定单位而不是零。

      if(m_volumes[0] > avrVolume * (1 + m_signalDeviation + m_ordersTotal * m_signaAddlDeviation)) {
         // 如果烛台开盘价低于当前价(收盘价),则
         if(iOpen(m_symbol, m_timeframe, 0) < iClose(m_symbol, m_timeframe, 0)) {

我应该指定单位而不是零吗?我的理解正确吗?

 
Viktor Kudriavtsev #:
例如,我们能否让仓位同步工作在每个刻度线,并在策略中指定的 TF(m15,m30,h1)上出现新的条形图时打开虚拟(新)仓位?

是的,如果useOnlyNewBars_ = false, 情况就是这样。策略不会使用该变量,它们自己决定何时检查开仓信号,以及何时在收到信号之前开仓。例如,仅当 H1 上出现新条形图时。在这种情况下,必须修改代码,使在条形图中间收到的信号持续到下一个条形图开始。现在接收到的信号会立即使用(导致虚拟仓位的开启),因此不会保存在任何地方。

我有点不明白您的意思。是的,SignalForOpen() 使用的是虚拟策略当前实例设置中设置的 TF,我明白这一点。但举个例子,如果我想让 EA 严格按照最后收盘的条形图工作,那么 我应该在这里 指定单位而不是零吗?我的理解正确吗?

如果您说的"EA 严格根据最后封闭的柱状图工作"是指当当前 柱状图上的刻度线成交量超过用于确定开仓信号方向的临界值时,我们将使用前一个柱状图并查看其方向,那么您的理解是正确的。

 

尤里 你好。在执行 Expert Advisor SimpleVolumesStage3.mq5 并将信息保存到数据库时,我遇到了一个错误:

2024.09.11 21:02:09.909 Core 1  2024.09.06 23:54:59   
2024.09.11 21:02:09.909 Core 1  2024.09.06 23:54:59   database error, FOREIGN KEY constraint failed
2024.09.11 21:02:09.909 Core 1  2024.09.06 23:54:59   CDatabase::Execute | ERROR: 5619 in query
2024.09.11 21:02:09.909 Core 1  2024.09.06 23:54:59   INSERT INTO strategy_groups VALUES(0, 'EA_EG_EU (H1, M30, M15, 9x16 items)')
2024.09.11 21:02:09.909 Core 1  final balance 24603.99 USD

这是什么意思,如何解决?该表是使用您在文章中的查询添加到数据库的。

 

尤里,我仔细查看了您的代码,发现错误发生在 CDatabase::Insert 函数的稍早部分,日志中写道

2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59   CDatabase::Insert | ERROR: Reading row for request 
2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59   INSERT INTO passes VALUES (NULL, 0, 0, 10000.00,0.00,11096.20,21542.31,-10446.11,92.51,-63.35,630.89,39.00,444.04,53.00,-376.27,52.00,-376.27,52.00,9430.69,569.31,5.69,5.69,569.31,9325.11,683.96,6.83,6.83,683.96,2.15,2.06,16.22,3.44,3736.76,8435.00,5170.00,3042.00,2128.00,2766.00,2404.00,1706.00,1336.00,6.00,4.00,99.11,8122.90,'class CVirtualStrategyGroup([
2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59           class CVirtualStrategyGroup([
2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59           class CVirtualStrategyGroup([
2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59           class CSimpleVolumesStrategy("CADCHF",16385,220,1.40,1.70,150,2200.00,200.00,46000,24)
2024.09.12 20:14:11.248 Core 1  2024.09.06 23:54:59          ],66.401062),class CVirtualStrategyGroup([

.....

2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59          ],13.365410),class CVirtualStrategyGroup([
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59           class CSimpleVolumesStrategy("CADJPY",15,132,0.40,1.90,0,7200.00,600.00,45000,27)
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59          ],13.365410),
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59          ],2.970797),
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59          ],1.462074)',
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59   '',
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59   '2024.09.06 23:54:59') RETURNING rowid;
2024.09.12 20:38:26.905	Core 1	2024.09.06 23:54:59   failed with code 5039

无法执行

      if(DatabaseReadBind(request, row)) {

这与什么有关?第二阶段通过了,测试本身也通过了(加载了数据库中的 Expert Advisor 交易和通行证)。

 

你好,维克多。

我很快就会回来继续这个项目的 工作,并会尽力整理我发现的错误。感谢您发现错误。我设法重现了您之前写到的一些错误。事实证明,这些错误与以下事实有关:在后来的部分中,针对某件事情进行了编辑,但却对下一篇文章中没有考虑到的其他事情产生了影响。这种影响造成了错误。在下一篇文章中,我们将再次回顾自动优化的所有步骤,消除所有发现的错误。