介绍
在本文中,我们将搜索市场模式,根据确定的模式创建 EA 交易,并检查这些模式,如果它们保持有效的话,保持有效的时间有多少。我认为这篇文章将对那些创建自适应交易系统的人非常有用。我想首先解释一下在外汇交易中我所说的暴力概念是什么意思。一般来说,在暴力方法中,我们要确定一个代码或任何其他目的的数字序列,这最终将允许使用该序列以最大概率或最大可用概率实现所需结果。预期的结果可能是获得加密货币或黑客帐户或Wi-Fi密码。应用领域很广。在外汇交易的例子中,我们的序列应该给最大的利润,同时尽可能长时间地工作。序列可以是任何类型和长度。唯一需要的条件是它的效率。序列类型最终取决于我们的算法
这项技术有什么特别之处使得我决定探讨一下呢?
我总是尽量表达我的想法,以便它们对其他交易者有最大的实际应用。我为什么要这么做?这是个好问题。我想和其他交易者分享我的经验。如果有人能利用我的想法,实施一些有趣和有利可图的东西,我会很高兴,不管我从中得到什么。我当然明白,这些想法可能不完全是我的,我可能会重新发明轮子。我认为我们应该分享经验,尽可能富有成效地合作。也许这就是成功的秘诀。孤立地工作是很难取得任何重大成就的。在我看来,模式这个话题对于理解市场的物理特性是非常重要的。你作为交易者的职业生涯可以依赖于对基本思想的理解,即使“作为交易者的职业生涯”这个短语听起来很有趣。我希望我能对研究这些问题的人有所帮助。
关于暴力及其与神经网络的区别
神经网络本质上也是一种暴力。但是它的算法与简单的暴力算法有很大的不同。我将不提供具体的神经网络结构及其元素的细节,但将尝试提供一个一般性的描述。我认为,如果我们坚持某种架构,我们就提前限制了算法的能力。固定的架构是无法弥补的限制。在我们的例子中,神经网络是一种可能策略的架构。因此,神经网络的配置总是与具有网络图的某个文件相对应,这总是指向特定元的集合。它就像一台3D打印机:设置项目参数,打印机就会产生它。因此,神经网络是一种通用代码,没有图纸就没有意义。这就像使用任何高级编程语言,只创建一个空项目,而不利用它的所有功能。结果,空模板什么也不做。神经网络也是如此。与暴力不同,神经网络可以提供几乎无限的策略变化、任意数量的准则和更高的效率。这种方法的唯一缺点是效率在很大程度上取决于代码质量。系统复杂性的增加可能导致程序的资源密集度的增加。结果,我们的策略被转换成一个网络图,这是它的等价物。暴力方法也是如此,但这里我们使用一些简单的数字序列。这个序列比网络图简单得多,它更容易计算,但在效率方面也有限制。下面的方案显示了上述说明。
换句话说,使用暴力方法,我们选择一个与代码交互并产生不同结果的数字序列。但是由于算法是固定的,所以它的灵活性就包含在数字数组中。其长度固定,结构简单。当使用神经网络时,我们搜索一个能给出最佳结果的网络图。在任何情况下,我们搜索特定的字节序列,或最终转换成结果算法的数据。唯一的区别在于它们的能力和复杂性。
我的暴力与优化算法
我在算法中使用了多元泰勒展开。这就是我选择这种方法的原因:我想提供一个算法,将尽可能可变,但非常简单。我不想拘泥于任何具体的公式,因为任何函数最终都可以展开成泰勒级数或傅里叶级数。我认为傅里叶级数不太适合这个目的。此外,我不熟悉多维等价物。这就是为什么我决定使用第一种方法。而且,它的实现要容易得多。一维泰勒级数如下:
Y = Cs[0]+Cs[1]*(x-x0)^1 + Cs[2]*(x-x0) ^2 + ... + Cs[i]*(x-x0)^n
其中幂之前的系数作为从0到n阶的导数。可以通过展开括号将其转换为更简单的形式:
Y = C[0]+C[1]*x^1 + C[2]*x^2 + ... + C[i]*x^n + ...= Sum(0,+infinity)(C[i]x^i)
在这种情况下,我们只有一个变量。这个级数可以模拟任意点附近的连续可微函数。公式中的项越多,就越能准确地描述我们的函数。如果它们的数目等于无穷大,那么这就是我们函数的绝对等价。在这里,我将不展示如何在任何点附近将任何函数展开为泰勒级数,这些信息在任何一本数学书上都有。但是一维变量对我们来说是不够的,因为我们想要使用来自多个柱的数据来增加一般公式的可变性。这就是为什么应该使用多维变量:
Y = Sum(0,+Infinity)( C[i]*Product variant(x1^p1*x2^p2...*xN^pN) )
这个公式的其他变体相当困难。它与一维变量方法具有相同的逻辑。我们必须提供所有可能的偏导数。如果我们限制了这些项的最高幂,那么我们就可以用组合和和来计算这些项的总数。我们的算法将利用最高阶的限制来限制计算资源的消耗。
但这仍然不足以使我们的暴力行动更加方便。最好去掉第一项C[0],让函数对于我们要输入的负值或正值具有最大对称性。另外,一个方便的解决方案是将正值函数值解释为买入信号,将负值函数值解释为卖出信号。理想情况下,增加该信号模的下限应导致预期收益和利润系数的增加,但也将不可避免地导致信号数量的减少。功能越接近这些要求越好。我们将特定烛形的值作为变量输入到函数(Close[i]-Open[i])。
我们现在需要做的是随机生成这些系数的变体,并检查变体在测试器中的行为。当然,没有人会手动迭代这些系数。因此,我们需要一个EA交易,它可以产生这样的变体,同时维护数千个这样的变体,或者一个第三方解决方案实现一些策略测试器的功能。最初,我不得不在MQL4中编写这样一个专家顾问—这个EA随附在文章中,并附有说明,因此每个人都可以使用它。但我将使用另一个应用程序,它是我用C#开发的。不幸的是,很明显我不能免费提供这个应用程序。它的能力远远超出了研究领域。但是我将描述并演示它的所有功能,以便每个知道如何编程的人都可以复制这个应用程序。截图将在本文后面提供,我们将在这里分析操作结果。
下面是应用程序的主要功能。系数数组的搜索分两个阶段进行。第一个阶段只是在加载的报价中搜索数组,这些数组在下一个烛形上产生最大预期收益或最大利润因子。过程的执行与策略测试器类似。事实上,它只是试图找到一个公式,以最大的准确性预测下一个柱的方向。一定数量的最佳结果作为数组变量存储在内存和磁盘中。只能测试部分报价-此处应指定相对于已加载报价文件的百分比。这用于允许在第二阶段丢弃随机值。第二阶段模拟市场订单和平衡曲线-这是为整个载入区域完成的。同时,执行信号幅度的平滑增加,同时搜索更好的质量选项。这个阶段也有各种各样的过滤器,通过使用这些过滤器我们可以得到更平滑的图表。图表越平滑,找到的公式就越好。在完成第二个搜索阶段后,在列表中可以看到一定数量的最佳选项。选择了所需的选项后,可以在第三个选项卡中为 MetaTrader 4 和 MetaTrader 5 生成一个交易机器人。EA是根据一个预编译的模板生成的,在这个模板中,接收到的数字在某些地方指定。
为任务构建简单模板
模板最初是在MQL4中创建的,然后转换为MQL5。该代码适用于这两种平台(类似于上一篇文章中的代码)。我试图提供这种兼容性,以便花更少的时间来适应解决方案。要像在MQL4中那样使用预定义的数组,应该向EA交易中添加一些额外的代码,这在我的前一篇文章中有描述。所以,请查看这篇文章的细节,本文需要这些知识。实际上,这并不困难,任何开发人员都可以实现这种兼容性。让我们从描述机器人生成时自动填充的变量和数组开始。
double C1[] = { %%%CVALUES%%% };//array of coefficients int CNum=%%%CNUMVALUE%%%;//number of candlesticks in the formula int DeepBruteX=%%%DEEPVALUE%%%;//formula depth int DatetimeStart=%%%DATETIMESTART%%%;//start point in time input bool bInvert=%%%INVERT%%%;//inverted trading input double DaysToTrade=%%%DAYS%%%;//number of days into the future to trade
这里C1是我们选择的次数前面的系数数组。CNum是价格表上用于计算多项式值的最近烛形数。接下来是公式的深度,即多维多项式的最大次数。我通常使用1,因为与一维泰勒级数不同,多维泰勒级数的计算复杂度随着阶数的增加而增加,因为系数总数随着阶数的增加而显著增加。为了限制EA操作时间,需要时间上的起始点,因为这样的限制使用关于操作开始位置的信息。inversion(反转)函数用于确保多项式在正确的方向上工作。如果我们把阶系数前面的所有符号都反转,那么多项式本身就不会改变,而只有多项式输出的数字才有不同的符号。这里最重要的部分是系数的比值。如果多项式的负值表示卖出,而正值表示买入,则 inverse = false。如果不是,那么就是 true。因此,我们指示算法“使用带相反符号的多项式的值”。另外,最好将此变量作为输入值,因为我们可能需要能够反转交易以及未来交易的天数。
如果需要使用系数计算数组的大小,可以按以下步骤进行:
int NumCAll=0;//size of the array of coefficients void DeepN(int Nums,int deepC=1)//intermediate fractal { for ( int i=0; i<Nums; i++ ) { if (deepC > 1) { DeepN(Nums,deepC-1); } else { NumCAll++; } } } void CalcDeepN(int Nums,int deepC=1)//to launch calculations { NumCAll=0; for ( int i=0; i<deepC; i++ ) { DeepN(Nums,i+1); } }
中间分形函数计算所有因子的总阶数相同的项数。这样做是为了简单,因为对我们来说,术语的求和顺序并不重要。第二个函数简单地调用循环中的第一个函数,次数与术语类型相同。例如,如果多维级数展开被限制在,比如说,4,那么我们用从1到4的所有自然数调用第一个函数。
计算多项式值的函数几乎相同。但是,在这种情况下,数组是自己生成的,不需要设置其大小。下面是它的样子:
double ValW;//the number where everything is multiplied (and then added to ValStart) uint NumC;//the current number for the coefficient double ValStart;//the number where to add everything void Deep(double &Ci0[],int Nums,int deepC=1,double Val0=1.0)//calculate the sum of one degree { for ( int i=0; i<Nums; i++ ) { if (deepC > 1) { ValW=(Close[i+1]-Open[i+1])*Val0; Deep(Ci0,Nums,deepC-1,ValW); } else { ValStart+=Ci0[NumC]*(Close[i+1]-Open[i+1])*Val0/Point; NumC++; } } } void CalcDeep(double &Ci0[],int Nums,int deepC=1)//calculate the entire polynomial { NumC=0; ValStart=0.0; for ( int i=0; i<deepC; i++ ) { Deep(Ci0,Nums,i+1); } }
所有计算的结果都将添加到ValStart中,也就是说,结果将添加到全局变量中。需要另一个全局变量-ValW,它用于将已有的乘积乘以某个值。在我们的例子中,这是相应柱的移动点数。这个移动可以是上下两种,这是由标志显示的。所以,这些函数有一个非常有趣的结构。他们在内部调用自身,这些调用的数量和结构总是不同的。这是一种调用树。我真的很喜欢使用这些函数,因为它们非常多变。这次我们用一种简单而优雅的方式实现了多维泰勒级数。
对于仅使用一维多项式的情况,也可以实现附加函数。在这种情况下,整个系列大大简化了。它变成了一个系数的总和乘以一阶柱的运动。它们的数量与所用柱的数量相同。这简化了所有的计算。如果次数为1,则使用简化版本。否则,就使用任何次数都统一的方法。
double Val; double PolinomTrade()//optimized polynomial { Val=0; if ( DeepBruteX <= 1 ) { for ( int i=0; i<ArraySize(C1); i++ ) { Val+=C1[i]*(Close[i+1]-Open[i+1])/Point; } return Val; } else { CalcDeep(C1,CNum,DeepBruteX); return ValStart; } }
使用简单变量时,结果将添加到Val变量中。
现在,让我们编写一个新柱出现时将调用的主要方法:
void Trade() { double Value; Value=PolinomTrade(); if ( Value > ValueCloseE) { if ( !bInvert ) { CloseBuyF(); } else { CloseSellF(); } } if ( Value < -ValueCloseE) { if ( !bInvert ) { CloseSellF(); } else { CloseBuyF(); } } if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToTrade && Value > ValueOpenE && Value <= ValueOpenEMax ) { if ( !bInvert ) SellF(); else BuyF(); } if ( double(TimeCurrent()-DatetimeStart)/86400.0 <= DaysToTrade && Value < -ValueOpenE && Value >= -ValueOpenEMax ) { if ( !bInvert ) BuyF(); else SellF(); } }
这个函数非常简单,您所需要做的就是实现我们所期望的仓位打开和关闭功能。
柱的出现可以按下面的方法来检测:
void CalcTimer() { if ( Time[1] > PrevTimeAlpha ) { if ( PrevTimeAlpha > 0 ) { Trade(); } PrevTimeAlpha=Time[1]; } }
我觉得代码非常简单明了。
我的代码生成的系数是使用上面解释的四个模型创建的。为了方便起见,所有这些系数都在[-1,1]范围内,因为值的比率比值本身更重要。从MQL5程序原型生成这些数字的函数如下所示:
void GenerateC() { double RX; if ( DeepBrute > 1 ) CalcDeepN(CandlesE,DeepBrute); else NumCAll=CandlesE; for ( int j=0; j<VariantsE; j++ ) { ArrayResize(Variants[j].Ci,NumCAll,0); Variants[j].CNum=CandlesE; Variants[j].ANum=NumCAll; Variants[j].DeepBruteX=DeepBrute; RX=MathRand()/32767.0; for ( int i=0; i<Variants[j].ANum; i++ ) { if ( RE == RANDOM_TYPE_1 ) Variants[j].Ci[i]=double(MathRand())/32767.0; if ( RE == RANDOM_TYPE_2 ) { if ( MathRand()/32767.0 >= 0.5 ) { Variants[j].Ci[i]=double(MathRand())/32767.0; } else { Variants[j].Ci[i]=double(-MathRand())/32767.0; } } if ( RE == RANDOM_TYPE_3 ) { if ( MathRand()/32767.0 >= RX ) { if ( MathRand()/32767.0 >= RX+(1.0-RX)/2.0 ) { Variants[j].Ci[i]=double(MathRand())/32767.0; ///Print(Variants[j].Ci[i]); } else { Variants[j].Ci[i]=double(-MathRand())/32767.0; } } else { Variants[j].Ci[i]=0.0; } } if ( RE == RANDOM_TYPE_4 ) { if ( MathRand()/32767.0 >= RX ) { Variants[j].Ci[i]=double(MathRand())/32767.0; } else { Variants[j].Ci[i]=0.0; } } } } }
MQL4和MQL5中的暴力算法原型可以在文章附件中找到。这里我不提供我的交易函数实现,因为目的只是展示如何在模板框架内实现该方法。如果您有兴趣查看整个实现,请查看附件。所有的EA交易和其他必要的材料都可以在本文的附件中找到。我的模板有很多多余的东西,包括不必要的函数或变量,可以通过某种方式进行优化。我个人不介意。如果有什么干扰操作,我就把它移走。对我来说更重要的是现在一切正常。我一直在开发一些东西,所以我没有时间把每一个细节都做到完美。我也认为没有理由将所有过程和变量存储在类中,而这可以提高代码顺序和可读性。模板非常简单。程序将使用的带引号的文件将由一个专门的EA交易生成,该EA根据历史运行,并将柱形图数据写入一个文本文件,该文件的结构便于程序读取。我不会提供这个EA的代码在这里,因为它可以很容易地开发。
使用程序查找和分析模式
我选择了三个市场区域进行分析,它们各有一个月的长度,并相互跟随。EURUSD, M5.
- 第一个时间段: 2020.01.13 - 2020.02.16
- 第二个时间段: 2020.02.13 - 2020.03.15
- 第三个时间段: 2020.03.13 - 2020.04.18
时间间隔已选定,因此最后一天总是星期五。你知道,星期五是本周最后一个交易日。以这种方式选择区间可以让你有整整两天的时间来搜索模式,直到交易所重新开始交易。这是一个小的生存技巧。在我们的例子中,这并不重要,因为我们在测试器中测试EA。我决定在这里描述所发现模式的12种变体。其中六个是最大次数为1的多项式。其他六个的最大次数为2。我觉得这就够了。
我的程序的第一个选项卡如下所示:
它提供了更改数字生成类型的功能,例如,仅正、正和负、正和零、正和负和零。搜索条件在第二个组合框中配置。有两种可能的选择:以点数表示的期望值和我对利润系数公式的模拟。在我的公式中,这个值的范围是-1到+1。此外,它也不存在由于除零错误而无法计算利润系数的情况。
P_Factor=(Profit-Loss)/(Profit+Loss).
然后是多项式的最大次数和用于计算的处理器核数。在文本块中,指定多项式的柱数或计算数,以及我自己发明的处理不对称系数,这与前面的公式非常相似:
D_Asymmetry=|(BuyTrades-SellTrades)|/(BuyTrades+SellTrades).
其值在0到1之间。当我们需要指示程序具有相似数量的买入和卖出信号时,需要使用此过滤器,以避免在全局趋势期间所有交易都在同一方向执行的情况。接下来是所有找到的变量中最好的变量的数量,这些变量应该存储在内存中,以及加载的引用的百分比将用于暴力迭代。这一部分是从最后一根柱开始测量的开放时间,它后面的部分将用于优化。我将不解释其余的指标和变量列表,因为它们足够简单。
第二个选项卡如下所示:
选项卡对应于机器人第一部分的第一个变体。你可以比较我的程序中的图表和测试器的图表,这将在下面介绍。报价单中执行暴力的部分用黄色显示,其他部分用红色显示。我不会在这里提供所有变体的截图-所有这些都可以在附件中找到。
让我们看看标签上有什么。Interval Points — 分解多项式值的区间。当我们在第一个选项卡上使用暴力算法时,它计算变量的主要参数以及该多项式的模极大值。因此,我们知道多项式的值的窗口,可以把这个窗口分成相等的部分,逐渐增加值,试图检测出更强的信号。这在第二个选项卡中完成。此选项卡还具有存储在优化内存中的搜索类型和最佳变体数。进一步的过滤器允许我们过滤掉不符合模式定义的不必要的变体。“线控制”为每个变量启用一个附加的运行,其中它计算图形线与连接图形起点和终点的直线的相对偏差。
Deviation = Max(|Profit[i]-LineProfit[i]|)/EndProfit.
这里,Profit[i]是第i阶平衡曲线的值,LineProfit[i]是直线上的相同值,EndProfit是图表末尾的值。
所有值均以点为单位测量。使用百分比控制是图表中红色部分的百分比(在本例中我没有使用此筛选器)。还有一个过滤器用于过滤最小订单数。
下图显示了生成机器人选项卡:
工作原理:在“优化”选项卡中选择所需的变量,切换到此选项卡并生成专家顾问。
现在,让我们在 MetaTrader 4 策略测试器中测试生成的机器人。我之所以选择它,是因为它允许将 spread(点差) 设置为1,从而实际上消除了它对图表显示的影响。实际上,通过这种方式发现的大多数机器人的预期收益将略高于一对机器人的平均收益,因此我们无法直观地分析预期收益很小的模式。每一个变体都是在大约两个小时内进行暴力强制和优化的,这还不足以找到高质量的模式。最好花一两天时间。但这对于本文来说已经足够了,本文的目的是分析发现的模式,而不是找到其中最好的。如果您要在测试器中测试我的机器人,请注意 DaysToTrade 变量。其值默认设置为3天。因此,暴力部分之后可能几乎没有交易。
首先,看看基于一次多项式生成的机器人。
第一部分. 2020.01.13 - 2020. 02.16
机器人 1:
暴力期间
未来10天
第一个图表显示了我的程序的第二个选项卡的屏幕截图中的一个变体。第二张图是同一个机器人未来10天的测试。我想10天就足够看它是怎么工作的了。正如你所看到的,这个模式持续了一段时间,然后突然转向相反的方向。这种模式似乎足以产生两三天的利润。让我们来看看同一市场区域的第二个机器人:
暴力期间
未来10天
在这里,结果并不那么顺利。为什么?原本预计这种模式会持续一两天,但从第一秒开始就开始下降,尽管反转相当顺利。可能这不是你预期的结果,但这是可以解释的,我们稍后再谈。
现在,转到第二个测试区间。 2020.02.13 - 2020.03.15
第三个机器人:
暴力期间
未来10天
这次情况看起来好多了。这张图是平的,非常接近一条直线。这表明这种模式是稳定的,并可能持续一段时间。它确实还在继续。未来的运动也类似于一条线,这意味着许多模式参数在未来继续工作。
这是第四个机器人:
暴力期间
未来10天
它有一个相当好的上升运动,一切看起来平稳,除了在图表开始急剧上升。但这种上升不应被忽视:这种不对称性表明,这可能只是巧合或意外的结果。当然,在未来,我们会看到整个格局朝着相反的方向逆转。
现在转到第三个测试区间。 2020.03.13 - 2020.04.18
第五个机器人:
暴力期间
未来10天
情况类似,它显示出明显的不对称性,开始时有波,结束时有衰减。这看起来不像一个可靠的模式,我不会继续交易。同样,在未来我们会看到整个公式的即时图形反转和反转。我不会在这里展示第六个机器人-它的图表可以在档案中找到。这与上面的图表非常相似。
现在,让我们测试基于二次多项式的机器人。
第一部分. 2020.01.13 - 2020. 02.16
第七个机器人如下:
暴力期间
未来10天
这些机器人的具体特点是,他们在暴力间隔工作得更好。在暴力部分之前的时间间隔内,结果不是很好。蛮力间隔总是呈现一个尖锐的正半波。但剩下的时间间隔是一团糟。这些都是某个公式的结果,行为是相似的。开始时有一点随机性,然后是相反方向的运动。
第8个机器人:
暴力期间
未来10天
更糟的是,虽然没有全局模式,但它仍然在蛮力间隔中向上移动。它不是一个模式,所以图形变为向下了。
现在检查第二个测试间隔。 2020.02.13 - 2020.03.15
第9个机器人:
暴力期间
未来10天
我在第一张图中看到了波的开始,在未来看到了波的结束。目前还没有任何全局模式,但这种逆转已经足够顺利,可以从中获利。
第十个机器人如下:
暴力期间
未来10天
这次的图表更好,这一次它像一个模式。这种模式最多持续一两天。然而,我不会冒险交易这样的图表。它与直线有很大的偏差。
现在转到第三个测试区间. 2020.03.13 - 2020.04.18
第11个机器人:
暴力期间
未来10天
这张图不太漂亮,但与直线有些相似。这种模式一直延续到未来,但我认为这是运气,而不是常规的结果,因为它有太多的随机噪音。或者这不是噪音,而是小浪。
第12个机器人:
暴力期间
未来10天
相当难看的图形,但它有一个明显的结束一个波和另一个巨大的波浪跟随它。在未来,这股巨浪会慢慢反转,最后在某个点上反转。在我看来,在多项式次数高于2次的机器人身上,趋势逆转发生得更顺利。所以它们的意外少了。我认为花点时间来测试三次多项式是有道理的,更高次数的多项式按理来说可以更好地描述规则。
我们研究的结论和数学原理
现在我们可以总结一下我们的EA交易的所有测试结果。这似乎很难做到,因为暴力和优化间隔显示了模式,而未来的片段显示了一个不清楚的画面。并非如此:
- 在以后的每个测试中,总有一个点是图表反转,然后公式反转。
- 反转可以平稳发生,也可以瞬间发生,但它总是存在的。
- 绝大多数图形通常在将来会下降,
- 有时,这种模式在开始时会持续一段时间。
- 未来的所有测试都表明,这种模式的工作方向是相反的。
- 如果余额曲线偏离了直线,那么延续的可能性就要低得多。
- 在发现的最好的测试中,这种模式持续工作了一两天。
我现在就来解释这些事实。我很久以前就发现了第一个也是最重要的事实,那时我还没有这样的程序。这是一个简单的数学真理。我在下面画了一个套利策略的余额图。黑线是有小模式的,紫线是有模式的。图表显示了它们的近似行为,如果我们在整个历史中交易它们,而不仅仅是在暴力间隔上:
我在这里不加报价,因为我们案例中分析的基础是余额图。不管报价是怎样画出来的,我们在报价中看到的不会比我们的策略更多。
想象一下,如果我们从历史的一开始就测试我们所有的机器人,再进一步,到未来。即使我们没有未来的报价,我们仍然可以100%准确地假设会发生什么。听起来像胡说八道?不,这不是胡说。首先,让我们假设我们正在使用引用的整个可用历史来测试机器人。我们会看到什么?一些混乱的移动,上上下下等等。在这里我们应该认识什么?波浪。它们的形状、波长和振幅并不重要。它不是正弦曲线,但我们不在乎。重要的是这个过程是周期性的。此外,根据我在上一篇文章中介绍的数学研究,如果历史数据的数量趋于无穷大,则基于随机公式的策略的期望值将趋于零。这有什么影响?基于上述假设,我们可以说,任何一条交易数量无限的平衡曲线,都会无数次越过起始平衡线。即使,由于某种原因,余额立即上升或下降,并一直保持在那里,我们可以稍微移动这条线下降或上升,找到这个余额点,在附近的余额波动。
我们不会考虑那些导致历史上明显得失的公式,尽管这些变体也可以归结为这一类——它只是一个巨浪的正负半波,比我们整个历史都要大。根据这些假设,所发现的模式只是正半波的一部分。发现的部分越大,余额点就越有可能低得更远。据此,如果现在有一个正半波,那么负半波应该很快就会出现。从数学角度看,探测到的半波越大,负方向运动的概率越大。反之亦然,如果我们探测到负半波,那么这半波越大,正半波开始的概率就越大。它可以更简单:如果我们有一个在整个历史中预期收益为零的策略,那么整个故事是由负预期收益和正预期收益的部分组成的,它们相互跟随,不断交替。我有一个 EA 交易来实现这个原则,它适用于报价历史上的任何货币对。因此,上述假设也得到了 EA 交易的证实。一般来说,这个原理不仅可以缩放,而且可以无限分层,提高了系统的效率。当然,交易趋势延续是可能的,但我建议只有在模式非常明显且均匀的情况下,才这样做,并且在未来交易最多达到所发现模式的5-10%,风险很高。而且,和数学反着做交易是愚蠢的。如果有可能估计出这个模式的大致剩余寿命的话,你可以试试。但这是不可能的,因为这种模式的性质尚不清楚。即使模式的性质很清楚,这样的分析也极难进行。
如何确定波动发生的相对水平?
至于波动,我将试图回答如何定义水平,相对于你的波和他们的运动应该被确定。答案很简单,无法确定。这并不意味着水平不存在,我们不能进行适当的交易。这个水平不是固定的,它只存在于我们的头脑中。更重要的是要理解以下几点:当半波的大小趋于无穷大时,这半波的大小与水平面到起始天平的距离之比趋于无穷大。换言之,半波越强,我们就越不能思考这个水平在哪里,因为随着交易数量的增加,这个水平趋于零点。我们要做的就是找到非常强的半波。另一个事实显示了同样的情况,那就是半波越大越好,那么在虚拟测试的其余部分中找到具有类似大小的波的可能性就越小。我将尝试直观地展示图中所说的内容:
这个水平不能保证模式以100%的概率转向。更重要的是,作为半波的一部分的模式的存在的事实告诉我们,很可能会有不止一个这样的波,它们甚至可能在整个历史中都存在。在这种情况下,出现大幅回调的可能性很大,我们应该设法抓住它。即使我测试了不同的EA交易,这些EA在全局范围内都不起作用,但它们在局部的作用是直接的或相反的。波浪生动,图表结构清晰。
为了完成这张图片,
我将试图说明,在我看来,这些波浪应该如何以最有效的方式进行交易。我先给你举几个例子:
第一种选择是反转交易,第二种选择是延续交易。如果我们考虑第一种选择,那么理想情况下,你应该总是达到一定的水平,停止那里的交易周期,然后等待下一个。当使用部分马丁格尔时,会有一个改进,但那是知道图表如果很快就会反转的情况下。否则,预期收益仍为“0”。只有当模式接近理想时,你才能交易趋势延续。但这种交易应该是短期的。在第二种变体中,我认为,可以使用逆马丁格尔。老实说,我测试过的所有策略都证明了一个数学事实:如果你交易一个固定的手数,而你不知道未来的价格走势(这几乎是不知道的),那么结果总是“0”。
但有些情况下,我们意外地发现了一种全局模式,而且效果非常好。不过,在我看来,最好不要等到这种情况。最好选择一个交易方案并遵循它。没有统一的解决方案。我还没有时间来测试,即使在演示帐户,因为这将需要2-3个月。一个月有四个星期,每个周末都要进行为期两天的暴力活动。然后应该在一台24小时工作的电脑上进行测试。我现在不可能这么做,也许在将来,我会在一个演示帐户上进行实验,并发布一个单独的信号。
结论
在本文中,我们对应用于市场的模式及其物理机制得出了简单但非常重要的结论。它们是这样的:市场并不混乱,在不同时期的图表中隐藏着许多模式。它们叠加在一起,造成混乱的假象。模式是一个可以重复和反转的周期性过程。由于这些模式是重复的,那么这些波动的振幅可能是有限的,这可以用于交易策略。我试图使这篇文章尽可能清楚,并提供最低限度的数学要求程度。我希望这些信息能帮助你开发交易系统。如果您有任何其他结论,请添加您的意见。不幸的是,我无法在更高的时间范围内使用暴力,因为这需要太多的时间。如果读者对更深入的分析感兴趣,我准备在以后的文章中继续这个话题。本文提供的只是一个主题介绍和演示。