开发自适应算法 (第二部分): 提高效率

Maxim Romanov | 8 三月, 2021

介绍

在阅读这篇文章之前, 我推荐您研究一下第一篇文章 "开发自适应算法 (第一部分): 寻找基本模式"。这并不是必需的,因为要点仍然很清楚,但阅读会更有趣。

在上一篇文章中,我检测到一个简单的模式,并开发了一个非常简单的算法来利用它。但是该算法没有灵活的结构,期望从中得到任何优秀的结果是没有意义的。

我们需要对它进行很大的改进,使它变得更加灵活,并根据市场情况调整其运行参数,以便取得更好的效果和稳定性。

分析缺点

让我们通过分析前一个版本的缺点来开始新算法的开发。我强调了以下缺点:

简化工作算法

让我提醒你算法的第一个版本是如何工作的。在新版本中,工作保持不变,但每一步都有待修改和改进。

改进

这个机器人是在 2016 年为 MetaTrader 4 开发的。它的代码附在下面。

在开发过程中,我将消除所有已识别的缺点,因此我将把整个开发划分为不同的任务。

  1. 动态阈值序列开始百分比

随着分析窗口中烛形数量的增加,或者随着下跌或上涨烛形过多阈值百分比的增加,第一个版本的算法变得更加稳定。我不得不做出妥协,并设置一个更大的样本量进行分析或更大的烛形超额百分比。试验表明,在几乎任何数量的烛形中,最佳超额百分比都可以调整,但当烛形数量增加时,超额百分比应减小。

在固定阈值百分比的情况下,增加分析窗口中烛形的数量会降低这种组合的可能性。因此,我们可以在分析窗口中设置任何烛形的最大数量,因为这对结果几乎没有影响,因为遇到这种组合的概率正在迅速下降。为了增加序列启动信号的数量,我们需要降低阈值超额百分比,以便随着样本中烛形数量的增加,组合的概率保持大致相同。

我做了一个假设,在给定数量的烛形中,给定的超额百分比的概率可以用组合数学来计算。

CP,

其中

事件概率P应该乘以2,因为P是针对同一方向的烛形较多的情况计算的-看跌或看涨。不管方向如何,我们都对总概率感兴趣。只有当看跌烛形的数量=看涨烛形的数量时,才不需要将概率乘以2。

作为一个例子,让我们计算一个事件的概率,当30支蜡烛中有24支在一个方向,6支在另一个方向。为了实现这一点,我准备了下面图1所示的表格。

概率表格

图 1. 概率表格

30个烛形中有24个同一方向的烛形对应80%以上的烛形。这种组合的概率为0.11%。现在让我们参考下表,看看样本中100个烛形的必要超额百分比,这样它出现的概率是0.11%。我们可以看到,对于100个烛形,这样的组合概率是找不到的。概率是 0.172% 和 0.091%. 我会选择一个更稀有的选择。它对应的是一种烛形与另一种烛形的比率66/34,或一个方向烛形的66%。

显然,30个烛形和80%的上涨/下跌烛形组合的概率与100个烛形和66%的上涨/下跌烛形组合的概率相同。超额百分比与烛形数量的关系是非线性的。因此,应采用非线性函数,随着烛形数量的增加调整百分比。我已经开发了这样的一个函数:

非线性函数

其中:

图2显示了使用组合方法,随着烛形数量的增加,过剩百分比如何减少(组合发生的静态概率)。它还允许评估所开发功能的适用性。

图表函数

图 2

紫色的图表显示,在固定的组合发生概率下,当增加样本中烛形的数量时,超额百分比减少。红色图形属于基于样本中烛形数量的超额百分比递减函数。这两个函数都是非线性的,但开发出的函数衰减得更慢。这是故意的,因为样本中烛形越多,当返回到50%时,序列中的仓位就越多。仓位越多,意味着存款的负载越重,回撤的资金越多。 

它的排列方式使得信号在大量烛形上出现的频率较低。此外,只有在给定烛形数的情况下,超额百分比确实很高时,才会发生这种情况。

2. 提高信号质量

为了提高信号质量,样本不应该由严格固定数量的烛形组成。我们可以看到,30个烛形中,上涨烛形的超额率是65%,但我们如何定义它是多还是少呢?如果100个烛形中的上涨烛形超额,那么这一事实应该会使信号更强烈,但是如果没有过多,或者相反,下跌烛形超额,那么信号应该减弱。我开发了两种增强或减弱信号的机制。

a) 应用加权平均百分比。从 Min_diap_bar 和 Max_diap_bar 参数中设置的范围中查找所有样本的加权平均百分比。取样应该间隔一些步数,我倾向于2这样的偶数步数。对于第一个样本中较大的烛形类型,将确定加权平均百分比。如果第一个样本有更多的上涨烛形,我们应该计算上涨烛形在所有其他样本中的百分比。最大或最小的样本可以制成第一个样本。为此,Bigin_pereb_bar 开关已添加到设置中。权重比可以使用任何函数,但我已经使它们与样本中烛形的数量成比例。 

如果第一个样本的烛形数最少,则其权重比为W1,对于第二个样本,权重比为W2,依此类推,直至Wn。

加权平均

  • W1 - 第一个样本的权重比;
  • W2 - 第二个样本的权重比;
  • Wn - 第n个样本的权重比;
  • Nb1 - 第一个样本的烛形数量;
  • Nbn - 第n个样本的烛形数量;
  • Pw - 加权平均烛形超额百分比;
  • P1 - 第一个样本的下跌/上涨烛形百分比;
  • Pn - 第n个样本的下跌/上涨烛形百分比;
  • Nbm - 最大样本的烛形数量.

如果第一个样本的烛形数最多,则权重比应相反

 反转权重
要获得序列启动信号,应将加权平均百分比与 Porog_weighted_proc 设置中指定的单独值进行比较。

b) 使用多个样本. 应从范围中选择多个超过阈值的烛形类型的样本。在这里,我们假设样本数越大,其中超额百分比大于阈值,则信号质量越高。这里使用非线性百分比作为阈值百分比。换言之,对于每个烛形数不同的样本,应采用单独的超额阈值百分比。
Kol_vibor 参数设置样本上超过阈值的最小量。定义超额百分比的烛形类型取决于第一个样本中的烛形类型。检测到超过阈值的样本被认为是第一个样本。我可以在从最小到最大的范围内迭代,反之亦然,这样来比较它们的工作。
这允许在更宽的窗口中考虑信号,而无需绑定到固定的分析窗口。例如,分析窗口范围设置为30到300个烛形,步长为2。为了形成信号,我们需要从超过阈值的范围内采集至少5个样本。超额可在 30、52、100、101 和 200 烛形上形成,通过使用非线性百分比将每个样本与其阈值百分比进行比较。这使我们能够更有效地评估宽烛光范围内的变化,而不必绑定到固定值。

价格图表

图 3

图 3 提供了一个实例. 我们可以看到,在这个区域上涨烛形更加普遍,并有一个信号来开启卖出仓位。这不是一个明确的烛形数目,而是一个区域。  

在第一篇文章中,我写道,烛形的数量(以及相应的,序列中的位置数量),理论上会得到补偿,是根据烛形所出现的数量来计算的。多亏了这种方法,才朝着自适应迈出了第一步。该算法还远远不能自适应,但利用当前市场参数对运行参数进行小幅度调整,已经使其更接近目标。
一个完美的算法不应该包含可配置的参数。应根据当前市场参数准确计算每个参数。我们需要准确地知道在每个时刻应该设置哪些参数,以便算法保持盈利。
3. 减少序列中开启的仓位数

算法的第一个版本有一个问题:当序列开始时,EA在每个蜡烛上都开启仓位。这种方法效率不高,因为它会导致大量回撤,并增加对存款的要求。通常情况下,仓位开启,但样本中的超额百分比继续增长或下降的速度不够快。这个不确定因素导致了稳定性的丧失。我们需要考虑这个因素,提高算法的稳定性。

我制定了两项措施来减少系列中的仓位数量。

a) 如果是卖出仓位,新仓位只在上涨烛形上开启。如果是买入仓位,仓位只在下跌烛形上开启。这样一种机制使我们能够更有效地从一种烛形胜过另一种烛形的事实中赚取利润。

在下跌烛形上打开卖出头寸会导致平均持仓开启价格的下降,如果价格上升,则会增加存款的负载。同时,“额外仓位”几乎不增加利润,也不会加速获利平仓。买入头寸的逻辑与此类似。

b) 以超额百分比控制开启仓位。这是用于序列中打开仓位的附加过滤器。有必要在每个新烛形上检查整个样本的过剩百分比。当新烛形出现时,样本量增加一个。只有当新烛形出现时,超额百分比增加时,才能打开仓位。

这种方法与(a)类似,有些细微差别。这种想法类似于(a)中所述的:防止卖出头寸系列的平均开盘价下降,防止买入头寸系列的平均开盘价上升。

如果使用加权平均值作为阈值百分比,则该方法可以通过将当前加权百分比值与上一烛形上的值进行比较来调整期初额外头寸。

这两项可以同时使用,也可以分开使用。它们降低了盈利能力,但显著提高了稳定性,这对我来说更为重要。这样,我们就消除了一个未知因素,提高了稳定性。

开启仓位前

开启仓位后

图 4. 减少序列中的仓位数

在图4中,打开仓位没有限制,而在下图中,使用(b)中的算法打开位置。我们可以看到,打开的仓位数更少了,下表列出了该交易的比较结果。


利润 Maximum loss (最大亏损) 仓位数 Profit factor(利润因子)
每个烛形上都开启仓位 (上图) +$71.99 -$463.96 92 1.56
根据超额百分比控制开启仓位 (下图) +$42.26 -$263.86 48 1.68

从表中可以看出,最大回撤有所下降,盈利能力也有所下降。最重要的是,持仓数量减少了1.91倍,最终在市场参数偏离其典型值的时刻对算法的稳定性产生了积极影响。

其他减少序列中仓位数量的方法也被开发出来了,它们在需求规范中有描述。我已经展示了我认为最有效的方法。 

4. 改进获利平仓

算法的第一个版本引入了每手利润的概念。此值是以等于1手存款货币设置的。之后,根据序列的未平仓计算手数,将设置值乘以当前序列未平仓的总手数。假设设置指示在每手利润超过15美元时关闭头寸序列。目前,我们有11个0.01手的仓位,这意味着总仓位为0.01*11=0.11。此外,每手利润乘以获得的手数 $15*0.11=$1.65。如果未平仓利润总额达到 $1.65,则应关闭该系列头寸。

以存款货币设定每手的固定利润额并不是最有效的解决办法。当工具波动性降低时,错过正确平仓点的风险增加。相反,当波动性上升时,机器人就会失去利润。因此,优化产生的每手平均利润,这是不够有效的。 

最简单的解决方案是根据当前的波动率调整“profit per lot”参数。波动性越高,每手利润就越多,反之亦然。应用平均波动率也不是一个完美的解决方案,但它比固定值更好。

这是另一个小的自适应函数,参数没有严格配置,但依赖于当前的市场状态设置。众所周知,系列中的利润直接取决于烛形的大小,这种依赖性应该用来增加稳定性。

我决定不以存款货币管理利润,因为点价对于美元/XXX这样的货币对不是恒定的,而是从当前价格值变化而来。利润将按点数管理。为此,获取 ATR 指标的当前值(以点为单位)并将其乘以 Koef_multi_ATR 值。结果是要以利润结清的点数。接下来,计算从开盘价传递到当前值的点数,并找到所有头寸的平均值。将所得平均值与平仓时的利润点数进行比较。如果平均点数超过或等于平仓点数,则序列完成。如果没有,则在下一个烛形上重复此过程。 

当前的利润应该在每一个报价点或由定时器监测。为了避免过多的计算,对于这种系统合理的检查利润计时器是每秒一次甚至每10秒一次。

  5. 使用多种交易工具

以前的 EA 版本能够同时交易10种工具。这是不够的,因此必须同时启动几个EA实例。新版本可以同时交易28种工具,以更好地控制交易。

如前所述,不同工具上的系列启动信号略有关联。这导致不同工具的回撤同步,存款要求增加,相对盈利能力下降。 

理想情况下,不同交易工具上的系列启动信号之间的相关性应为负。一种金融工具当前的大量回撤应与任何其他金融工具的小额盈利交易相吻合。禁止在多个工具上同时打开系列也不是最佳解决方案,因为这会降低整体盈利能力。

由于其中一种货币相对于其他货币可能开始下跌或上涨,新系列启动信号的相关性出现。买入或卖出一种货币相对于其他货币的信号可能同时出现在几对货币上。所以,我们应该保护自己不受这种情况的影响。

为了尽可能降低不同工具上的系列启动信号之间的相关性,我们需要将货币对划分为不同的货币,并假设头寸是以不同的货币开立的。如果卖出头寸是以 EURUSD 打开的,则分为 EUR 卖出头寸和 USD 买入头寸。在每个新系列开始之前,我们需要检查组成货币对的货币是否存在头寸。如果 EUR 有卖出头寸,我们应该禁止推出任何卖出 EUR 的系列。然而,我们不应取消需要购买 EUR 的信号。 


图 5

将货币成对划分如图5所示。下面的图6显示了如果买入 EURUSD 可以打开哪些头寸。对于其他选项,所有方法都是相同的。 

货币 2

图 6

采用这种方法,不再需要限制同时开仓的最大工具数量。尽管如此,我还是把这个功能留在了设置中。

6. 根据当前波动性修正手数

在第二个版本的算法中,我放弃了自动再融资,因此当改变存款规模时,手数不会改变。我已经开发了这个真正的交易EA,我不需要这个功能。相反,我开发了另一个手数修正函数。这种算法的盈亏取决于烛形的大小或波动性。使获利图表尽可能平坦,没有突然的下陷和突起,这样是更加符合逻辑的。 

为了稳定盈利能力图,我们需要根据当前的波动性改变手数大小。波动性越强,我们需要的手数越小,波动性越小,手数更能就要越大。手数的变化与当前的波动成比例。为了实现这一点,在设置中定义了正常手数和波动率。

要计算当前批次,让我们取当前ATR值,然后除以设置中的 Norm_ATR。之后,将设置中的 Lot 除以得到的比率。将得到的值四舍五入到正确的值。这就是为什么手数会随着烛形的增长而减少,而盈利能力图则尽可能保持稳定。

在系列开始之后,波动性可能会发生变化,因此我引入了两种选择。在第一种方法中,手数在序列开始前确定,并在序列结束前保持稳定。

在第二种选择中,在系列开始后,手数会随着当前的波动性变化。在这种情况下,在计算当期利润时,头寸会影响以存款货币表示的利润总额,从而改善或恶化结果。这个功能是实验性的,如果您喜欢它的工作方式,我可以在下个版本中修改它。

测试

本文只描述了最基本和最有趣的修改和操作模式。在现实中,已经实现了更多,所有模式都可以相互结合。算法的需求规范和所有细节附在下面。 

我将在用于测试算法第一个版本的相同货币对上运行测试,以便直观地突出显示差异。与第一个版本一样,该算法通过关闭烛形来工作,因此您可以在“控制点”模式下安全地测试它。在烛形内部,它只控制当前利润,并确保当前资金不低于设置中定义的阈值。与以前一样,测试将以高估的点差中进行,我将为 GBPUSD 设置40个点的点差。

就像第一个算法版本一样,我们可以在任何时间框架内进行交易和优化。最短的时间范围是由烛形的大小相对于点差和佣金的限制。时间框架越短,对信号质量和预期收益的要求就越高。随着时间框架的增加,烛形的尺寸也随之增大,相应地,回撤的水平也随之上升。因此,最大事件框架受到交易风格偏好的限制。

我在2017年使用机器人进行真实账户交易时进行了优化。因此,我只是采用了以前的设置,而没有执行新的优化。

GBPUSD 2000 测试图表

GBPUSD 2000 测试报告

图 7. GBPUSD H1 2000.01.01 - 2020.12.08, 固定手数

图7显示了从2000年1月1日到2020年12月8日近21年期间 GBPUSD H1 上的测试。这里使用了范围内的多重采样,分析的范围是 68-200 个烛形,使用了15个样本。

如果第一个算法版本从2001年开始才通过测试,那么第二个版本从2000年开始就很容易通过测试。与第一版相比,仓位数量增加了3倍,利润增加了1.9倍。利润因子已从7.5降至2.74,但仍处于一个不错的水平。序列开始信号生成的频率更高,而序列中的平均仓位数已减少。也许,我们可以找到更好的设置,但我已经采取了我用来交易的那些设置。

先前已经开发了基于当前ATR值的手数调整功能。图8显示了与图7相同的测试,但是基于波动性的动态手数。因为 $3000 所使用的手数是0.01,我就把手数调整算法增加为 $30,000 使用0.1手。

GBPUSD 2000 动态手数测试图表

GBPUSD 2000 动态手数测试报告

图 8. GBPUSD H1 2000.01.01 - 2020.12.08, 根据 ATR 使用动态手数 

正如我们在图8中所看到的,盈利能力图已经变得更加线性,正如开发过程中所预期的那样。与此同时,盈利能力略有下降,而最大回撤有所增加。这个模式很有趣,这将有助于获得最大的预测利润率与高夏普比值。

我们需要检查我在上述测试中使用的参数的稳定性。为了实现这一点,我将使用与H1相同的设置在 GBPUSD M15上启动测试。由于在较小的时间段内,波动性的不均匀性要大得多,利润率应该稍微降低。既然我知道为什么要这样做,这个参数应该是自适应的。但是,当前的EA版本没有这样的功能,所以我手动调整它。 

GBPUSD M15 测试图表

GBPUSD 2009 m15 测试报告

图 9. GBPUSD M15 2009.01.01 - 2020.12.08

图9显示了使用H1设置对 GBPUSD M15 2009.01.01-2020.12.08的测试。自2009年以来,该测试一直通过。考虑到时段设置没有为 M15 特别优化过,结果还是不错的。为了找到M15的最佳设置,从2008年1月1日到2009年6月1日的1.5年中,对最困难的部分进行优化就足够了。如果我们为这一部分优化参数,EA将通过21年的测试而没有任何问题。

对于第一个版本,我展示了 EURUSD H1 的测试,让我们比较结果。图10显示了2000.01.01至2020.12.08期间 EURUSD H1的结果。

EURUSD 2000 测试图表

EURUSD 2000 测试报告

图 10. EURUSD H1 2000.01.01 - 2020.12.08

第一个版本从2007年才通过了回溯测试,新版本从2000年就已经通过了测试,稳定性显著提高。同时,最大回撤减少了1.2倍,利润增加了3倍,交易数量增加了2.3倍。

既然我们想知道第二个版本已经变得好了多少,那么让我们看看对 GBPJPY H1 的测试。第一个版本从2009年开始测试。

GBPJPY 2000 测试图表

GBPJPY 2000 测试报告

图 11. GBPJPY H1 2000.01.01 - 2020.12.08

如图11所示,该算法现在通过了2000年以来的回溯测试。回撤减少了1.8倍,而利润系数增加到3.3倍。

我优化了28 种货币对,包括8种主要货币 USD, GBP, EUR, CHF, CAD, AUD, NZD 和 JPY。 一些货币对显示出最好的结果,而一些显示出最差的结果,但所有这些货币对都得到了很好的优化,通常从2004年起就通过了测试。也有些货币对是从2007年开始通过测试的。

MetaTrader 4 无法一次在多个工具上进行测试,因此,我分别对28个交易品种中的每一个进行了测试,并使用第三方软件来组合报告。因为我是在2017年做的,所以合并报告涵盖了2010年到2017年。

完整报告

图 12. 2010年至2017年28个货币对的联合回溯测试

图12显示盈利能力图相当平坦,年收益率约为100%。结果令人印象深刻,但实际上,由于多个货币对同时交易的限制,盈利能力较低。我用这个机器人在真实账户上交易了两年,实际利润率是每年56%。 

实际盈利能力低于计算的盈利能力,因为测试是在增加点差的情况下进行的。该算法的工作原理是,点差越大,盈利能力就越高。这可以用点差越大,稳定性越低来解释。此外,在现实中,禁止单向交易导致信号数量减少的效果也很明显。

在交易时,我使用了最保守的设置。然而,有可能使算法的行为更加激进。 

附加功能

我添加了按其他时间段对序列开始信号进行排序的功能。例如,可以在H1上执行交易,但是在所有标准时间段上额外检查信号。仅当M1、M5、M15、M30、H1、H4和D1时间段也具有这样的信号时,才形成序列开始信号。使用附加时间段的序列确认信号使用与主时间段相同的规则和模式生成。其他时间段可以彼此独立地启用或禁用。

很遗憾,我无法验证这个模式,因为正确的功能运行存在问题。

EA 有许多我没有提到的附加功能,因为它们没有基本机制那么有趣。例如下面这些:

EA为28种交易工具提供了2337种设置,因此所有用户都能够找到自己感兴趣的操作模式。

结论和进一步开发

在下一篇文章中,我将继续进行算法开发,并对理论模型进行重大修改。新算法是为MetaTrader 5设计的,因为它是一个更强大、更灵活、更高效的平台。

EA代码、需求规范、测试设置、28种货币对的设置示例以及用于计算事件概率的 Excel 表格附在下面。

思路和需求规格的作者是 Maxim Romanov. 代码是由 Vyacheslav Ivanov 书写的.

相关这个主题的之前文章:

开发自适应算法(第一部分):寻找基本模式