English Русский Español Deutsch 日本語 Português
针对交易的组合数学和概率论(第二部分):通用分形

针对交易的组合数学和概率论(第二部分):通用分形

MetaTrader 5交易 | 11 十月 2021, 10:08
2 554 0
Evgeniy Ilin
Evgeniy Ilin

内容


概述

在上一篇文章中,我们讨论了概率论的基础知识,这有助于我们理解运用分形函数进行交易任务的具体特征。 作为本主题的延续,我将展示一些自给自足的分形函数,它们可以描述全部所需的定价过程。 我们将尝试对它们进行概括和简化,并创建公式来回答各种缺乏明确定量评估和明确答案的问题。 


评估在交易中运用分形的可能性

我们来继续该主题,总结上一篇文章的结果,并以更紧凑和通用的形式表述材料。 您还记得上一篇文章中构建分形的例子吗? 那样的分形几乎没有实际用途,但在这种情况下,我们主要是对我们判定的结构构造规则感兴趣。 正如事实所证明,这些规则可以应用于三种类型的分形:

  1. 具有对称边界的分形
  2. 具有非对称边界的分形
  3. 具有上边界或下边界的分形

此类分形可用于描述以下过程:

  • 加速模拟交易,能够评估各种场景的可能性,同时考虑存款限制(因为下边界能表征无法进一步交易的存款底线)
  • 分形内平均步阶数的估算(例如,您可以估算在我们获得所需的利润或亏损之前我们平均有多少订单)
  • 评估每个步阶的总平均值(例如,您可以根据一笔较小持仓的统计数据来计算平均持仓时间,即较小止损点数或价格差异的持仓
  • 基于单边分形的盈利能力评估
  • 其它能力


构建通用分形的理论基础

我们运用在上一篇文章中导出的构造规则,并对其进行补充,从而了解分形是如何构造的。 此外,我在我的公式中发现了一个小错误,因为向下或向上的边界不对称是不可能的。 结果证明导出的公式是正确的,因此它们绝对适用于任何分形。 实际上,这个函数能绝对实现任何分形。 所有可能的分形都是一般分形的特例。 如果我们取上面定义的三种分形类型,那么实现这三种特殊情况的一般分形的条件如下:

  1. m = n & [ m > s & n > s ]
  2. ( m > n || n > m )  & [ m > s & n > s ]
  3. ( m > S && n <= S ) || ( n > S && m <= S )

示意性地,这三种类型的分形如下所示:

3 分形

理想情况下,“S” 应该趋于无穷大。 以下变量在我之前的文章中并未讲述。 我将在此处提供相关说明,从而能全面了解如何运用通用公式来得到特殊情况。 分形是根据链式反应原理工作的函数,就像在原子弹中一样。 如果设置的连锁反应太深,计算机可能无法应对如此庞大的计算。 如果情况不是特别严重,它简单地花费很长时间来计算 — 几分钟、几小时、甚至几天。 若要在分形中正确启动链式反应,我们应该找到两个基础值:

  • Half - 通道宽度的一半
  • Middle - 对应于中线的 “U” 值

针对我们在上一篇文章中判定的所有三种情况,可以轻松计算出 Half 值:它是 m 和 n 的算术平均值:

  • Half = ( n + m ) / 2

为了实现第二个值,我们将不得不用到三个逻辑变体。 不过,第一个和第二个变体可以合并为一个。 因此,我们有两个变体:

  1. n >= m
  2. n < m

接下来,假设 “U” 轴向上,n 值是通道的上边界,而 m 是下边界,我们得到两种可能情况的两个比率所对应的 m 和 n:

  1. Middle = Half - m
  2. Middle = - ( Half - n )

这些值将传递给分形函数,供其内部使用,因为没有它们就无法实现上一篇文章中讲述的内部分支逻辑。 函数原型如下:

  • double Fractal(double Half, double Middle, int m, int n, int s,double p,int S, int U, double P)

因此,为了调整分形起点,我们需要传递三个强制值:

  1. Half - 通道宽度的一半
  2. Middle - 对应于中线的 “U” 值
  3. m - 到下边界的步阶数
  4. n - 到上边界的步阶数
  5. s - 单个链在任何方向上允许的最大步阶数

其它值用大写字母表示,表明这些值是动态的,并且在不同的分形层上会有所不同。 这是它们的定义:

  • S - 当前概率链中累积的步阶数; 要被传递到下一个分形层
  • U - 链起点和终点之间的当前距离; 传递到下一个分形层
  • P - 基于伯努利规划案的完整概率链的累积乘积; 需要传递到下一个分形层

因此,为了调整分形起点,我们应在函数中输入以下值:

  • S = 0 (既然是起点,所以还没有步阶)
  • U = 0 (出于同样的原因)
  • P = 1 (因为它是一个零链,所有接下来的步阶应构成一个完整的组)

为了针对模拟定价或交易完成分形一般规则的开发,我们简略地重写在上一篇文章中获得的规则。 这些规则会在分形内部用到。 这些规则基于针对相同步阶的若干个公式:

  • f = u + d  — 它是未来组合树的步阶数(距离则由到分形范围最近边界的距离决定)
  • s = u - d  — 最终步阶数量,以下跌段落和上涨段落表示

我们已经确定我们将遍历 “u”。 此外,我们将用 “s” 值作为新的 “U”,如果剩余步阶能够支持,则它将被传递到下一个分形层。 为此目的,我们需要为 “u” 定义一个不包含 “d” 的公式。 为此,把来自第一个方程的 “d” 表达式,代入第二个方程:

  • s = 2*u - f

如果当前值等于零,该值也可作为 “U” 的新值进一步传递。 故此,我们需要将此 “s” 添加到 “U”,来获得应进一步传递的值:

  • NewU = s + U  - 我们要传递到下一个分形层的新 “U”

正如在上一篇文章中已经定义的那样,这个表达式采用三个可能的值,基于数字 “f ”的三个可能值。 我已经修改了上一篇文章中的一个示意图,来说明这个思路:

“f” 的三种场景

这幅示意图在这里相当合适,因为现在我们确定了所有可能的分形配置,也许在我们解决大多数问题时能用到。 根据这幅示意图,我们为 “f” 定义了三种情况:

  1. f = ( n - 1 ) - U
  2. f = ( m - 1 ) + U
  3. f = Half - 1

当满足以下条件时,就会出现这三种情况:

  1. U > Middle
  2. U < Middle
  3. U = Middle

现在我们要讲述传递到下一个分形层的最后两个值,并考虑如何在分形中收集数字。 最后两个值如下计算:

  • NewP = P * C(f,i) * Pow(p,i) * Pow(1-p,f-i)  — 我们的新链概率 “P” 要被传递到下一个分形层
  • NewS = S + f = S + (floor(Mid) - 1) — 我们的新 “S” 要被传递到下一个分形层

在开始往一个公用变量里收集数字之前,注意应该先把数字收集到一个类似的模块当中 — 但在这种情况下,我们只取一步,所以我们不需要伯努利规划案。 语句的顺序并不重要;它们只是应该在同一个模块。 只会收集情况 “1” 和 “2” 的数字,并带上一些说明:

  1. U = n - 1
  2. U = - ( m - 1 )

对于第一种情况,前三个值更容易计算,因为我们只取一步:

  • NewU = U - 1
  • NewP = P * p
  • NewS = S + 1

对于第二种情况,有一个细微的区别:

  • NewU = U + 1
  • NewP = P * ( 1 - p )
  • NewS = S + 1

基于所有分形的概括,这些分形中的每一个都划分为两种类型:

  • 分形计算跨越走廊上边界的总概率
  • 分形计算跨越走廊下边界的总概率

这些类型中的每一种都与另一种类型的分形相对应,即与原始分形相结合:

  • 分形计算跨越上边界的平均步阶数
  • 分形计算跨越下边界的平均步阶数

这四种分形类型的不同之处在于累加数字的形式。 在收集概率时,我们只能添加 “P*p” 和 “P*(1-p)”。 对于其它两种分形,我们需要额外的变量来传递到下一个分形层。 在这些分形中,我们利用大小相等的步阶,但方向相反,因此它们的概率是 “p” 或 “1-p”。 但是当 “p” 不等于 0.5 时,它事实上意味着这可能是两个具有不同特征的不同事件。 依据特征,我的意思是一组与给定事件相对应的随机变量。 其中一个值是持仓生存期。 此类值如有必要,可以有任意数量,且我们可以将它们视为时间。 这部分可以通过几个简单的步阶得以简化。 累加和的数字将具有以下形式:

  1.  P * p * NewS
  2.  P * ( 1 - p ) * NewS

如您所见,概率乘以该完整步阶链中的步阶数。 但这个公式只适用于上升和下降步阶可能性相等的情况。 在替代情况下,我们要用两种不同的结构来描述上升和下降,或者提供一个结构来同时存储这两个数字。 在第二种情况下,分形函数返回的不是数字,而是数据容器。 容器不需要扩展。 甚而,我提供了一个容器,可以存储所有需要的参数,这样就不需要用类似的代码来定义若干个函数了。 取而代之的是,我将所有函数合并为一,其可定义所有必需的参数。 分形类型和它能解决的任务将直接取决于函数的输入参数。 为了扩展这个概念,第一个 “S” 及其等效的 “NewS” 应替换为以下值:

  1. SU - 所选概率链的最后上升步阶
  2. SD - 所选概率链的最后下降步阶
  3. NewSU 和 NewSD - 要传递到下一个分形层的值
  4. SU + SD = S

这些值的定义应类似于 “S” 的定义。 当 "U > Middle":

  • NewSU = SU
  • NewSD = SD + 1

"U < Middle":

  • NewSU = SU + 1
  • NewSD = SD

最终的分形升级还需要六个值:

  1. UpperMidSDown - 到达上边界之前的总平均可能下降步阶数
  2. UpperMidSUp - 在到达上边界之前可能上升的总平均步阶数
  3. UpperSummProbability - 跨越上边界的概率
  4. LowerMidSDown - 到达下边界之前的总平均可能下降步阶数
  5. LowerMidSUp - 到达下边界之前的总平均可能上升步阶数
  6. LowerSummProbability - 跨越下边界的概率

值 “1”、“2”、“4”、“5” 表示相应步阶数及其概率的乘积之和。 这些值原本毫无意义,但它们是我们将进一步讨论的一些有价值公式的组成部分。 值 “3” 和 “6” 是跨越两个边界的假设概率,其形成一个完整组。 使用这些值,我们可以判定大量其它事情。


编写实现通用分形的代码

为了正确启动分形,我们需要一个函数,在分形启动之前执行所有准备操作,之后它根据预定义的规则正确启动分形。 我已经准备好了这个算法的实现,采用 MQL5 风格:

Container StartFractal(int m, int n, int s,double p)//preparing all variables and starting the fractal
   {
   int Minimum;
   if ( m <= n ) Minimum=m;
   else Minimum=n;
   double Middle;
   if ( n >= m ) Middle = (m+n)/2.0 - Minimum;
   else Middle = -((m+n)/2.0 - Minimum);   
   double Half = (m+n)/2.0;
   return Fractal(Half,Middle,m,n,s,p,0,0,0,1.0);
   }

计算分形后,该函数返回包含所有所需数据的容器:

struct Container//a container for collecting all the necessary data about the fractal
   {
   //values to be summed, for the upper bound
   double UpperMidSUp;//the sum of probabilities multiplied by the number of steps up of a specific chain (to cross the upper bound)
   double UpperMidSDown;//the sum of probabilities multiplied by the number of steps down of a specific chain (to cross the upper bound
   double UpperSummProbability;//the sum of the probabilities (to cross the upper border)
   //values to be summed, for the lower border
   double LowerMidSUp;//the sum of probabilities multiplied by the number of steps up of a specific chain (to cross the lower border)
   double LowerMidSDown;//the sum of probabilities multiplied by the number of steps down of a specific chain (to cross the lower border)
   double LowerSummProbability;//the sum of the probabilities (to cross the lower border)
   
   Container()//default constructor
      {
      UpperMidSUp=0.0;
      UpperMidSDown=0.0;
      UpperSummProbability=0.0;     
      LowerMidSUp=0.0;
      LowerMidSDown=0.0;
      LowerSummProbability=0.0;
      }
   
   //
   void Summ(Container &c0,const Container &c1) const//full sum for operator overloading
      {
      c0.UpperMidSUp=c0.UpperMidSUp+c1.UpperMidSUp;
      c0.UpperMidSDown=c0.UpperMidSDown+c1.UpperMidSDown;
      c0.UpperSummProbability=c0.UpperSummProbability+c1.UpperSummProbability;      
      c0.LowerMidSUp=c0.LowerMidSUp+c1.LowerMidSUp;
      c0.LowerMidSDown=c0.LowerMidSDown+c1.LowerMidSDown;
      c0.LowerSummProbability=c0.LowerSummProbability+c1.LowerSummProbability;
      }            
   void operator+=(Container &c) { Summ(this,c); }//operator += overload
   };

此容器包含 “+=” 运算符的重载,以便合并两个相同的结构。 这部分将用在主要函数。 这是分形函数:

Container Fractal(double Half, double Middle, int m, int n, int s,double p,int SU,int SD, int U, double P)//Fractal
   {
   Container C;
   ///to pass to the next fractal level
   int NewU;
   int NewSU;
   int NewSD;
   double NewP;
   ///
   
   if ( U > Middle && SU + SD < s )//case 1
      {
      if ( (n-1) - U > 0 )
         {
         for ( int u=0 ; u <= (n-1) - U; u++ )
            {
            NewU = -(n-1) + 2*u + 2*U;
            NewP = P * (Factorial((n-1) - U)/(Factorial(u)*Factorial((n-1) - U - u))) * pow(p,u)*pow(1.0-p,(n-1) - U - u);
            NewSU = SU + u;
            NewSD = SD + ((n-1) - U - u);
            C+=Fractal(Half,Middle,m,n,s,p,NewSU,NewSD,NewU,NewP);
            }         
         }
      if ( (n-1) - U == 0 )
         {
         NewU = U - 1;
         NewP = P * (1.0 - p);
         NewSU = SU;
         NewSD = SD + 1;
         Container ct;

         ct.UpperMidSDown=P*p*SD;
         ct.UpperMidSUp=P*p*(SU+1);
         ct.UpperSummProbability=P*p;
         
         C+=ct;
         C+=Fractal(Half,Middle,m,n,s,p,NewSU,NewSD,NewU,NewP);
         }         
      }   
   
   if ( U < Middle && SU + SD < s )//case 2
      {
      if ( (m-1) + U > 0 )
         {
         for ( int u=0 ; u <= (m-1) + U; u++ )
            {
            NewU = -(m-1) + 2*u;
            NewP = P * (Factorial((m-1) + U)/(Factorial(u)*Factorial((m-1) + U - u))) * pow(p,u)*pow(1.0-p,(m-1) + U - u);
            NewSU = SU + u;
            NewSD = SD + ((m-1) + U - u);
            C+=Fractal(Half,Middle,m,n,s,p,NewSU,NewSD,NewU,NewP);
            }         
         }
      if ( (m-1) + U == 0 )
         {
         NewU = U + 1;
         NewP = P * p;
         NewSU = SU + 1;
         NewSD = SD;  
         Container ct;

         ct.LowerMidSDown=P*(1.0 - p)*(SD+1);
         ct.LowerMidSUp=P*(1.0 - p)*SU;
         ct.LowerSummProbability=P*(1.0 - p);
         
         C+=ct;
         C+=Fractal(Half,Middle,m,n,s,p,NewSU,NewSD,NewU,NewP);
         }         
      }
  
   if ( U == Middle && SU + SD < s )//case 3
      {
      if ( int(MathFloor(Half))-1 > 0 )
         {
         for ( int u=0 ; u <= int(MathFloor(Half))-1; u++ )
            {
            NewU = -(int(MathFloor(Half))-1) + 2*u + U;
            NewP = P * (Factorial(int(MathFloor(Half))-1)/(Factorial(u)*Factorial(int(MathFloor(Half))-1 - u))) * pow(p,u)*pow(1.0-p,int(MathFloor(Half))-1 - u);
            NewSU = SU + u;
            NewSD = SD + (int(MathFloor(Half))-1 - u);
            C+=Fractal(Half,Middle,m,n,s,p,NewSU,NewSD,NewU,NewP);
            }         
         }
      }
   
   return C;
   }

代码已在 MetaTrader 5 中验证 - 它运行良好。 如果需要,这个逻辑可以进一步扩展,同时还有很多更高级的可能性。 但我决定保持函数输入参数列表的简短,因为实现的功能对于我们的目标来说已经足够了。 通过仔细研究代码,您会发现它完全符合上面概述的数学原理。 虽然很简短,这段代码可以创造奇迹。 我相信代码应该包含尽可能多的逻辑和数学。 这才是我们最终需要的。 如果不能完成预期目的,即使再漂亮的代码也无济于事。 在我们的案例中,预期目的就是交易的适用性。 这是作为确认的日志:

该日志包含所有容器数据

在本例中,我创建了一个简单的智能交易系统,它在第一次收到即时报价时计算整个分形。 计算一旦完成,则以后无需重新计算。 前六个数字是容器的一部分,其余的则是从它们派生出来的。 在此我只展示最重要的导数,它们有助于理解这六个变量如何能够接收我们可能需要的所有其它变量。 例如,看看“完整组”。 之所以如此命名,是因为根据先前的计算,其中一个边界交叉点的两个非重叠假设概率之和必须等于 1。 由我们的代码可以证实这一点。 接下来是两个相同的数字,它们是 “1”、“2” 与 “3”、“4” 的总和。 后一个数字是倒数第二个数字的总和 - 这是该链所经过的平均步阶数。 这就是我在设置 函数里为这些输入参数设置数值的原因,其中 “m” 和 “n” 是相等且对称的,稍后会有说明。


基于对称分形推导第一个公式

根据日志结果,该链所经过的平均步阶数趋于 “4”。 走廊相对于一个单位的步阶翻倍。 若“ n” 和 “m” 设置为 1,即一个单位的步阶。 换言之,如果我们要由较小走廊来计算组成走廊的平均步阶数(在这种情况下,较小走廊的整数适合放进一个较大的走廊,并且新走廊也是对称的),那么我们就可以做出假设:

  • P[n] = P[n-1] * 2  - 是新走廊宽度的递推式表达式,基于前一个较小走廊的宽度,新走廊由此组成
  • S[n] = S[n-1] * 4 - 是计算新走廊平均步阶数的递归表达式,由较小走廊的平均值表示

如果我们接受 “P[0]=1” 和 “S[0]=1”,并且如果我们从索引 “0” 开始递归编号,那么这个递归可以表示为两个非常相似的序列:

  • P[n] = 2^n , n = 0 ... + infinity
  • S[n] = 4^n = (2^2)^n = (2^n)^2 = P[n]^2

如果仔细观察第一个序列,并正确变换第二个序列,就会发现可以用第一个序列的元素来表示第二个序列。 换言之,我们得到以下依赖:S = S(P) = P^2。 现在这种依赖性仅适用于通道宽度的递归加倍。 当我见到这个公式时,我决定验证它对任意大数 “n” 和 “m” 的适用性。 从逻辑上讲,在第二步中我们设置 “n=3”、“m=3” 并计算相同的变量。 依据这些输入参数,平均步阶数趋向于数字 “9”。 您可以自行验证这部分,使用上面的代码或使用下面附带的 MathCad 15 程序。 相同的序列均可采用这些参数:

  • P[n] = 3^n , n = 0 ... + infinity
  • S[n] = 9^n = (3^2)^n = (3^n)^2 = P[n]^2

如您所见,我们得到了相同的关系 “S=S(P)=P^2”。 我们可以针对区间拆分相关的所有其它可能场景重复相同的操作,但这不是必需的。 这个事实意味着,如果我们知道,比方说,对称通道内价格的平均生存期,我们就可以计算任何其它通道内价格的平均生存期。 它可以计算如下:

  • S = S0 * K^2 - 新走廊的平均步阶数
  • T = S * T0 - 新走廊的平均生存期
  • T = T0 * K^2- 依据另一条走廊的平均生存期表示的新走廊的平均生存期(假设 S0 = 1 )
  • S0 - 旧走廊的平均步阶数
  • T0 - 旧走廊一个步阶的平均生存期
  • P = K * P0  --> K = P/P0 - 新走廊比旧走廊的放大倍数
  • P - 新走廊的宽度
  • P0 - 旧走廊的宽度

现在,我们可以利用 MathCad 15 检验假设。 首先,我们测试一下有关二次关系的假设:

检查二次关系

现在应该很清楚了。


评估所有正值和实数型参数的导出公式的性能

该公式适用于所有整数 “P”。 但是它可以用于浮点 “K” 吗? 我们需要实施一个技巧来提供一个浮点 “K”。 假设我们有一个平均生存期已知的价格走廊,我们还有一个容纳已知走廊 “N” 倍的走廊,但我们还不知道它的平均生存期。 此外,我们运用相同公式来查找它。 按照这个逻辑:

  • T = T0 * N^2 ---> T0 = T / N^2
  • T - 是我们走廊的生存期,我们已知其平均生存期
  • T0 - 是一个较小走廊的平均生存期,由我们的走廊组成

这意味着我们可以找到较小走廊的生存期,我们需要它来计算具有分数增加因子的第三条走廊的生存期。 现在我们已经找到了最小走廊的生存期,我们可以找到它的宽度(以点数为单位):

  • d = P / N

接下来,我们可以采用以下比率来计算有多少这样的走廊能容纳到加宽的走廊:

  • Smin = MathFloor( K * P / d ) = MathFloor( K * N )
  • Lim( N --> +infinity ) [ K * N/MathFloor( K * N ) ] = 1

如您所见,走廊宽度正在减少,且它不会影响结果。 第二行显示了一个非常重要的比率,将有助于理解下一步该做什么。 它表明,当我们将源走廊划分成尽可能多的段落时,我们可以忽略被 MathFloor 函数舍弃的小数部分。 这一点可由极限趋于统一来表明。 如果这种不准确性令人困惑,我们可以找到另一个值:

  • Smax = MathFloor( K * P / d ) + 1 =  MathFloor( K * N ) + 1 = Smin + 1

现在就很清晰了,“K * N” 的真实值正好在 “Smin” 和 “Smax” 之间。 如果 “N” 趋于无穷大,我们会得到两个非常近似的走廊,它们的平均生存期趋于相等,因为它们的大小仅相差一个段落。 因此,所需走廊的平均生存期可由这些走廊的平均生存期的算术平均值来更准确地确定:

  • T1 =( T0 * Smin^2 + T0 * Smax^2 ) / 2 =  T0 *( Smin^2 + Smax^2 ) / 2
  • T1 - 我们需要确定的走廊的平均生存期

下图梳理了我的思路:

证明浮点数思路的规划案

现在我们已经找到了计算走廊生存期的替代表达式,我们可以取其结果与整数 “K” 的函数值进行比较,用浮点数 “K” 代替。 如果两个表达式的结果值相同,我们可以得出结论,所发现函数得到的整数 “K” 值绝对适用于 “0 ... + 无穷大” 范围内的任何整数和浮点数。 我们针对 “N = 1000” 进行第一次验证。 我认为这种拆分足以看到两个数字的标识,如果有的话:

简单验证浮点数字

如您所见,这两个数字实际上是相同的。 从逻辑上讲,对于较大的 “N” 值,它们应该更加相同。 这也可以通过如下假设来证明:

  • Lim( N --> +infinity ) [  (T0 *( Smin^2 + Smax^2 ) / 2) / ( T * K^2 )  ] = 1

这个极限的分子是我们计算新走廊平均生存期的近似表达式,分母的的表达式则大体上能准确描述相同值。 我已创建了一个简单的函数,执行与上一个屏幕截图相同的计算。 但这一次它应用于数字 “N” 的整个范围内以 “1” 开头的那些数字。 现在我们来查看程序执行结果:

极限验证

所有假设都得到充分验证:我们为整数 “K” 找到的函数绝对适用于任何正数 “K”。 现在我们有了一个非常有用的函数,可作为进一步操作的基础,例如作为深入描述整个通用分形的数学基础。


自通用分形发展而来的高级分形

作为深入应用通用分形的一个有用的附加示例,我们可以采用单边界分形,例如 “n=1”、“m ---> +无穷”、“s = m+1” ,“p=0.5”。 到目前为止,我们正在研究在两个方向上具有等概率步长的分形,不过这仅适用于随机游走。 但这个分形提供了所有的可能性。 为了针对这种复杂结构进行更深入的分析,首先需要考虑基本面。 甚而,在这个初始步骤中,我们得到了有用的公式,且可对这些分形过程得出基础论断。 我已用不同的 “s” 值测试了分形,得到了以下数据:

  • s = 22 , FullSumm = 2.868 , UpperSummProbability = 0.831
  • s = 32 , FullSumm = 3.618 , UpperSummProbability = 0.860
  • s = 42 , FullSumm = 4.262 , UpperSummProbability = 0.877
  • s = 45 , FullSumm = 4.499 , UpperSummProbability = 0.882

进一步增加允许步数会导致计算时间拐点,换言之,计算时间爆增到需要数小时甚至数天。 但如果您查看平均概率总和增加的速度,您会发现采用这种类型的分形来估算该序列的收敛性是不可能的。 但基于先前导出的公式,我们可以采用不同但非常有用的分形类型来估算收敛性。 该分形还有助于计算一类名为“套利交易”的非常流行且有利可图的策略的时间。 先上个图,然后解释一下:

高级分形

想象一下,定价过程从边界开始第一步,无论边界在哪里,向上或向下。 上图展示了一个下边界的示例,因为它更容易感知。 仔细看看第一个分形。 每个灰色框内含有两个进一步事件的场景:

  1. 价格到达箱子的上边界
  2. 价格触及箱子的下边界

当价格到达走廊的上边界时,新的、更大的分形会在这一点位自动开始,如此往复。 如果我们如同通用分形那样来研究这个过程,我们将再次看到概率链。 但现在依据我们的公式得知,在对称走廊中将建造的步阶数是基于所能容纳走廊的步阶数来判定(现在我们看到的一个步阶是较小的走廊,即容纳在原始走廊)。

现在,您计算平均步阶数时无需考虑整个分形。 取而代之,将导出的公式应用于每个分形。 这里的步阶不是相同的值,但它是在我们到达下一个嵌套分形的上限或下限时进行的。 有基于此,我们可以非常简单地创建概率链。 在第一个分形 P[0] 处到达边界的概率等于 0.5。 这意味着还有第二种可能的情况,即当我们不得不创建下一个分形,寄希望价格会触及边界。 所有这些事件都是嵌套的,所有这些链构成一个完整的组。

在第二个分形 P[1] 处到达边界的概率等于前一个概率乘以 0.5。 这个过程可以无限地继续下去。 可以运用导出的公式和概率链来判定平均步阶数。 为此,我们首先给每条概率链定义一个公式,考虑到跨越上限和跨越下限的平均步阶数是相等的。 由此得出:

  • PUp = PDown = P - 示意触及分形上限和下限的概率对于所有嵌套分形的所有边界的概率相等的比率
  • P[j] = 0.5^(j+1) , j = 0 ... + infinity- 链 j 发生的概率
  • S[i] = S[i-1] + P[i] * ( S[i-1]/P[i-1] + F(D[i]) ),  i = 1... + infinity - 一个递归公式,计算所有分形层的总平均可能步阶数(而 S[0] = 1*0.5 = 0.5
  • F(K) = K^2 - 我们计算平均步阶数的导出公式
  • D(i) = 2^i - 下一个分形层容纳多少步阶
  • S[i-1]/P[i-1] - 其余未计分支的平均步阶数,前提是当前分支已经发生(因为除了当前嵌套分形之外,还需要考虑之前发生的所有步阶)

第二个分形实际上与第一个相同,即它们的链(P[] 数组)的概率相同。 我们为什么需要它? 假设我们有“套利交易”策略。 我们有两个账户,一个掉期账户和一个无掉期账户,用正掉期账户锁定持仓。 我们还需要一个公式来计算盈利所需的平均持仓时间。 这个平均持仓时间直接源于平均步阶数公式。 我不会在本文中详细全面地讨论这个问题。 我只是想表达数学的重要性。 该主题会在稍后详细讨论。 现在,我们为第二个分形的平均概率步阶定义一个公式:

  • S[j] = S[j-1] + P[j] * ( S[i-1]/P[i-1] + F(1) ) - 一个递归公式,计算所有分形层的总平均可能步阶数(而 S[0] = 1*0.5 = 0.5)

在此情况下,这个公式只是之前公式的一个特例,因为在第二个分形中 K=1,对于所有分形层,总是这样。 我们来找出针对这两个分形。这些量的累加和的极限是多少:

高级分形

第一个序列发散,其含义是当没有上限且交易无止境时,平均时间等于无穷大。 在第二种情况下,我们得到一个等于 2 的清晰极限。 这意味着,如果我们以正掉期开仓,平均而言我们需要在两步后平仓(因此平均持仓时间将等于 2*T,其中 T 是提供的平均持仓时间,当它触及边界之一时,我们就要平仓)。 在第二种也是最简单的情况下,我们j简单地把两个账户的持仓全部平仓,即便账户所示掉期为正数。 显然,第一个选项更具吸引力,但其实现需要两个账户均能快速、平稳地提款和存款。 如果此选项不可行,我们就需要用到经典选项,该选项产生的盈利较少,但稳定性更高。


总结成果

在本系列文章的第二部分,我们取得了非常有趣的结果,包括在交易中的实际应用结果。 更重要的是,现在很明显分形的可能应用领域是巨大的。 在本文中我们做了什么:

  • 为构建通用分形定义了清晰的数学规则
  • 根据所界定的数学原理创建了一套有效的 MQL5 风格的代码
  • 在两个平台 MetaTrader 5 和 MathCad 15 上成功验证原理,
  • 运用算法,得到首个计算任意走廊生存期的公式
  • 针对所有可能的情况,利用编程测试和验证公式
  • 基于所获公式得到一种更快速的分形新种类
  • 结果令我们能够加快计算,并判断通用分形无法判别的情况
  • 触及使用高级分形解决掉期交易问题的特例
  • 获得进一步发展理论的工具

另外我想提请注意的是,我的工具箱已经大大扩展了。 现在我们可以分析具有不同概率步阶的分形(趋势状况,及与交易统计分析相关的状况)。 再次提请注意,在本文中我们只考虑了 “p = 1 - p = q = 0.5” 的情况。 这意味着所有计算仅适用于曾讲述过的随机游走的情况。 当然了,还有更多潜在的可能性。

下面是在研究过分形后得到的公式。 我再简单解释一下:

  1. S = K^2 - 新走廊的平均步阶数,基于一个步阶与另一条走廊相等的事实
  2. T = S * T0 =  T0 * K^2- 未知走廊的平均生存期
  3. T0 - 已知走廊的平均生存期
  4. P = K * P0  --> K = P/P0 - 已知走廊比未知走廊大多少倍
  5. P - 生存期不明的走廊宽度
  6. P0 - 已知走廊的宽度

通过将 4 代入 1,我们可以通过已知值来表示未知走廊中的平均步阶数,将 1 代入 2 我们得到这条走廊的平均生存期,其值根据已知值计算得出:

  • T0, P0, P

读者在本文开头可能会遇到一个问题,我还为该问题加进了一些答案:

  • 如果我们可以从 MetaTrader 5 策略测试器里收集交易统计数据,为什么还需要公式?

答复:

  • 好吧,并非总能收集到统计数据,因为并非所有金融品种都拥有进行评估所需的足够交易历史。 这对于大型走廊来说是不可能的,在于总能从未跨越边界的走廊里选择其一。 使用较小宽度的走廊和公式,我们便可以获得统计中无法获得的数据。 此外,这种数学方法能为您提供无与伦比的准确性和灵活性。 还有更多其它优点。


结束语

在本文中,我尝试阐述计算逻辑,可作为进一步研究定价过程的基础。 到目前为止,实际应用还不多。 但我确信我们可以研究所有的通用分形变种,并获得描述非对称和单边界价格走廊的可能公式。 在下一篇文章中,我将继续研究通用分形,并尝试将所有结果以更简单的公式呈现。 此外,我将包括新的、非常有趣的数学,从而所获公式不仅能用于定价过程,还可用于描述回测和交易信号。 这将令我们能够绝对准确地依据时间或概率层面分析任何策略,从交易层面来说这才是终极要义。


参考


本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/9511

附加的文件 |
Materials.zip (270.97 KB)
针对交易的组合数学和概率论(第三部分):第一个数学模型 针对交易的组合数学和概率论(第三部分):第一个数学模型
早前所研讨主题的逻辑延续,即针对交易任务开发多功能数学模型。 在本文中,我将从头开始讲述与分形数学模型开发相关的整个过程。 这个模型应成为一个重要的构建模块,且其是多功能和通用的。 它将为我们遵循该思路深入开发奠定理论基础。
更好的程序员(第 02 部分):停止做这 5 件事变为一名成功的 MQL5 程序员 更好的程序员(第 02 部分):停止做这 5 件事变为一名成功的 MQL5 程序员
对于任何想要提高编程职业生涯的人来说,这是一篇必读文章。 本系列文章旨在尽最大可能令您成为最佳程序员,无论您有多少经验。 研讨的思路适用于 MQL5 编程萌新和专业人士。
更好的程序员(第 03 部分):放弃做这 5 件事成为一名成功的 MQL5 程序员 更好的程序员(第 03 部分):放弃做这 5 件事成为一名成功的 MQL5 程序员
这是任何想要提高编程职业生涯的从业者必读文章。 本系列文章旨在尽最大可能令您成为最佳程序员,无论您有多少经验。 研讨的思路适用于 MQL5 编程萌新和专业人士。
DoEasy 函数库中的图形(第八十一部分):将图形集成到函数库对象之中 DoEasy 函数库中的图形(第八十一部分):将图形集成到函数库对象之中
是时候开始把已创建的对象集成到先前所创建的函数库对象当中了。 这最终将会为每个函数库对象赋予自己的图形对象,便于用户与程序之间的交互。