股票量化交易软件:针对交易的组合数学和概率论2---通用分形
在上一篇文章中,我们讨论了概率论的基础知识,这有助于我们理解运用分形函数进行交易任务的具体特征。 赫兹量化股票期货交易软件作为本主题的延续,我将展示一些自给自足的分形函数,它们可以描述全部所需的定价过程。 我们将尝试对它们进行概括和简化,并创建公式来回答各种缺乏明确定量评估和明确答案的问题。
评估在交易中运用分形的可能性
我们来继续该主题,总结上一篇文章的结果,并以更紧凑和通用的形式表述材料。 您还记得上一篇文章中构建分形的例子吗? 赫兹量化股票期货交易软件那样的分形几乎没有实际用途,但在这种情况下,我们主要是对我们判定的结构构造规则感兴趣。赫兹量化股票期货交易软件 正如事实所证明,这些规则可以应用于三种类型的分形:
具有对称边界的分形
具有非对称边界的分形
具有上边界或下边界的分形
此类分形可用于描述以下过程:
加速模拟交易,能够评估各种场景的可能性,同时考虑存款限制(因为下边界能表征无法进一步交易的存款底线)
分形内平均步阶数的估算(例如,您可以估算在我们获得所需的利润或亏损之前我们平均有多少订单)
评估每个步阶的总平均值(例如,您可以根据一笔较小持仓的统计数据来计算平均持仓时间,即较小止损点数或价格差异的持仓赫兹量化股票期货交易软件
基于单边分形的盈利能力评估
其它能力
构建通用分形的理论基础
我们运用在上一篇文章中导出的构造规则,并对其进行补充,从而了解分形是如何构造的。 此外,我在我的公式中发现了一个小错误,因为向下或向上的边界不对称是不可能的。 结果证明导出的公式是正确的,因此它们绝对适用于任何分形。 实际上,这个函数能绝对实现任何分形。 所有可能的分形都是一般分形的特例。赫兹量化股票期货交易软件 如果我们取上面定义的三种分形类型,那么实现这三种特殊情况的一般分形的条件如下:
m = n & [ m > s & n > s ]
( m > n || n > m ) & [ m > s & n > s ]
( m > S && n <= S ) || ( n > S && m <= S )
示意性地,这三种类型的分形如下所示:

编辑搜图
理想情况下,“S” 应该趋于无穷大。 以下变量在我之前的文章中并未讲述。 我将在此处提供相关说明,从而能全面了解如何运用通用公式来得到特殊情况。 分形是根据链式反应原理工作的函数,就像在原子弹中一样。赫兹量化股票期货交易软件 如果设置的连锁反应太深,计算机可能无法应对如此庞大的计算。 如果情况不是特别严重,它简单地花费很长时间来计算 — 几分钟、几小时、甚至几天。 若要在分形中正确启动链式反应,我们应该找到两个基础值:
Half - 通道宽度的一半
Middle - 对应于中线的 “U” 值
针对我们在上一篇文章中判定的所有三种情况,可以轻松计算出 Half 值:它是 m 和 n 的算术平均值:
Half = ( n + m ) / 2
为了实现第二个值,我们将不得不用到三个逻辑变体。 不过,第一个和第二个变体可以合并为一个。 因此,我们有两个变体:
n >= m
n < m
接下来,假设 “U” 轴向上,n 值是通道的上边界,而 m 是下边界,我们得到两种可能情况的两个比率所对应的 m 和 n:
Middle = Half - m
Middle = - ( Half - n )
这些值将传递给分形函数,供其内部使用,因为没有它们就无法实现上一篇文章中讲述的内部分支逻辑。 函数原型如下:
double Fractal(double Half, double Middle, int m, int n, int s,double p,int S, int U, double P)
因此,为了调整分形起点,我们需要传递三个强制值:
Half - 通道宽度的一半
Middle - 对应于中线的 “U” 值
m - 到下边界的步阶数
n - 到上边界的步阶数
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 = ( n - 1 ) - U
f = ( m - 1 ) + U
f = Half - 1
当满足以下条件时,就会出现这三种情况:
U > Middle
U < Middle
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” 的数字,并带上一些说明:
U = n - 1
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 时,它事实上意味着这可能是两个具有不同特征的不同事件。 依据特征,我的意思是一组与给定事件相对应的随机变量。 其中一个值是持仓生存期。 此类值如有必要,可以有任意数量,且我们可以将它们视为时间。赫兹量化股票期货交易软件 这部分可以通过几个简单的步阶得以简化。 累加和的数字将具有以下形式:
P * p * NewS
P * ( 1 - p ) * NewS
如您所见,概率乘以该完整步阶链中的步阶数。 但这个公式只适用于上升和下降步阶可能性相等的情况。 在替代情况下,我们要用两种不同的结构来描述上升和下降,或者提供一个结构来同时存储这两个数字。 在第二种情况下,分形函数返回的不是数字,而是数据容器。 容器不需要扩展。 甚而,我提供了一个容器,可以存储所有需要的参数,这样就不需要用类似的代码来定义若干个函数了。 取而代之的是,我将所有函数合并为一,其可定义所有必需的参数。 赫兹量化股票期货交易软件分形类型和它能解决的任务将直接取决于函数的输入参数。 为了扩展这个概念,第一个 “S” 及其等效的 “NewS” 应替换为以下值:
SU - 所选概率链的最后上升步阶
SD - 所选概率链的最后下降步阶
NewSU 和 NewSD - 要传递到下一个分形层的值
SU + SD = S
这些值的定义应类似于 “S” 的定义。 当 "U > Middle":
NewSU = SU
NewSD = SD + 1
当 "U < Middle":
NewSU = SU + 1
NewSD = SD
最终的分形升级还需要六个值:
UpperMidSDown - 到达上边界之前的总平均可能下降步阶数
UpperMidSUp - 在到达上边界之前可能上升的总平均步阶数
UpperSummProbability - 跨越上边界的概率
LowerMidSDown - 到达下边界之前的总平均可能下降步阶数
LowerMidSUp - 到达下边界之前的总平均可能上升步阶数
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;
}
代码已在 赫兹股票期货量化软件 中验证 - 它运行良好。 如果需要,这个逻辑可以进一步扩展,同时还有很多更高级的可能性。 但我决定保持函数输入参数列表的简短,因为实现的功能对于我们的目标来说已经足够了。 通过仔细研究代码,您会发现它完全符合上面概述的数学原理。 虽然很简短,这段代码可以创造奇迹。 我相信代码应该包含尽可能多的逻辑和数学。赫兹量化股票期货交易软件 这才是我们最终需要的。 如果不能完成预期目的,即使再漂亮的代码也无济于事。 在我们的案例中,预期目的就是交易的适用性。 这是作为确认的日志:

编辑搜图
在本例中,我创建了一个简单的智能交易系统,它在第一次收到即时报价时计算整个分形。 计算一旦完成,则以后无需重新计算。 前六个数字是容器的一部分,其余的则是从它们派生出来的。 在此我只展示最重要的导数,它们有助于理解这六个变量如何能够接收我们可能需要的所有其它变量。 例如,看看“完整组”。 之所以如此命名,是因为根据先前的计算,其中一个边界交叉点的两个非重叠假设概率之和必须等于 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”。 现在我们有了一个非常有用的函数,可作为进一步操作的基础,例如作为深入描述整个通用分形的数学基础。