交易策略概念:蜡烛够用吗?
赫兹量化将利用来自上述文章中的元柱线获取十字星指标。 不幸的是,不可能简单地根据该指标的读数开立和了结交易。 原因既不在于指标,也非归因元柱线。 十字星烛条形态通常并非设计用作独立交易信号。
因为它是一个潜在的趋势逆转信号。 这意味着在十字星蜡烛出现之前应该有相应方向的趋势。 如果没有趋势,那么基于十字星蜡烛进行交易就没有意义了。
添加图片注释,不超过 140 字(可选)
将趋势和元柱线结合在一起
解决这项任务并不像乍一看那么困难。 事实上,它恰恰很容易。 十字星烛条是一根元柱线,但趋势不一定出现在元柱线上,它也可以建立在常规柱线上。 对于烛条,柱线内最大和最小价格偏差的比率很重要,并且(正如我们在上一篇文章中发现的)它们在很大程度上取决于元柱线的宽度(即其中包含的普通柱线的数量),及其时间偏移。 然而,趋势线没有显示出任何极端比率,它只是穿过一组柱线中的平均价格值。 为了计算平均值,将柱线组按部分划分大小并不是特别重要。
一般来说,赫兹量化将在常规柱线上建立趋势。
我们唯一需要知道的是趋势的结束时间,即指标检测到的十字星蜡烛已经开始的柱线数量,因为该蜡烛的宽度可以在很宽的范围内变化(在指标设置中指定)。 构成烛台元柱线的柱线不应被视为趋势的一部分。 十字星烛条是它的潜在转折点,这意味着它不再是旧趋势,但也不是新趋势。 或者它既是旧趋势又是新趋势,这取决于您如何看待它。 一般来说,它也可以被认为是一段横盘,因为它的收盘价接近开盘价。
因此,我们不会将含有十字星烛条的元柱线包含在构建趋势的柱线组中,从而避免统计趋势特征时造成误差。
在计算趋势时,找出十字星蜡烛何时开始的最简单方式是在绘制该蜡烛的同一指标中计算趋势。 换言之,我们将修改上一篇文章中的指标,令其包含一个过滤器,仅显示之前有相应趋势的十字星蜡烛。 此外,拥有此类设置的指标变得更适合交易:可以利用其信号执行交易,而无需任何额外的分析。
目前,该指标的输入其名称均以 “Candle_” 开头。 这些是各种蜡烛参数。 现在我们需要向指标代码添加各种趋势输入。 至少,应该有以下两个参数。
-
最小趋势宽度(柱线数量):
input int Trend_WidthMin = 10;
-
最大趋势宽度(柱线数量):
input int Trend_WidthMax = 50;
当检测到十字星蜡烛时,指标将分析其前面的一组柱线,其数量为这两个参数指定的范围。 它还将评估柱线是否有对应的趋势。
稍后将提及要设置的其它趋势输入。 与此同时,赫兹量化关注一个微小,但技术上很重要的细微差别。
由于现在指标需要分析大量以前的柱线,才能在图表上绘制信号(因为建立烛条的元柱线宽度也已扩展到趋势的宽度),赫兹量化需要在指标代码中进行小的修正。 OnInit 函数中有一行,用于计算价格历史开始时应该跳过多少根柱线。 换言之,指标无法在这些柱线上计算和绘制(由于历史数据不足):
SkipBars = Candle_WidthMax;
现在这句代码应该如下所示:
SkipBars = Candle_WidthMax + Trend_WidthMax;
计算相应趋势的方法
我们可以利用各种算法检测趋势。 其中一些很容易,有些则很复杂。 对于十字星蜡烛的运用,我认为不仅要检测趋势,还要为其定义一些特征,这一点很重要。 我们在图表上展示这一点:
添加图片注释,不超过 140 字(可选)
十字星蜡烛之前的趋势示例
上图显示了两个趋势示例。 在左边,我们看到一根十字星蜡烛,其高度与之前趋势中的价格走势相当,甚至略高于。 可以假设,这根十字星蜡烛内部确实发生了一些重大事件,导致对立力量的严重冲突。 其中一股力量以前所未有的力量推动价格上涨(在整个趋势发展期间),但另一股力量不允许价格保持在顶部,并将价格打回到蜡烛开盘的初始水平。 换言之,在这根蜡烛上,我们可以看出一股可以抵抗趋势增长的力量发挥作用的时刻。 因此,我们可以假设趋势已经耗尽,并准备扭转。
在右边,我们看到与趋势内部发生的走势相比,十字星蜡烛的高度并不特别。 这意味着在这根烛台内逆转价格的力量几乎不足以扭转整个趋势。 在这样的十字星蜡烛上进行交易可能要冒一种不合理的风险。 我们的交易策略有机会以某种方式区分这两种情况那就好了。
这可以通过使用线性回归方法判定趋势来完成。 在这种情况下,我们不仅会检测趋势,还会定义穿过趋势通道中间的直线方程:
y = A + B * x
方程组成:
x — 图表沿水平轴的点坐标(在我们的例子中,这些是柱线编号)。 y — 沿垂直(价格)轴的坐标。 这些是由这个线性回归方程计算出的坐标,以便在价格图表上为每根柱线建立一个点,并通过这些点画一条直线。 这样就是一条趋势线。 B — 表征趋势线斜率的比率。 这个比率越高,趋势就越陡峭和强劲。 如果比率为正,则趋势线将从左到右增加,这对应于上升趋势。 负比率值对应于下降趋势。 A 只是将趋势线定位在所需图表高度的辅助系数。 它在交易层面没有任何意义。
计算线性回归的算法是众所周知的。 它是数理统计设备基础的一部分,除交易外还用于许多应用领域。 作为算法操作的结果,计算上述系数 A 和 B。
在指标代码中,它简约地看起来像这样(完整的指标代码附在文后)。 在循环内,累加所衡量趋势中包含的所有柱线的各种中间总和:
double BarPrice = (open[CurBar] + close[CurBar] + high[CurBar] + low[CurBar])/4; X = TrendBarNum; Y = BarPrice; N = TrendBarNum; S1 += X; S2 += Y; S3 += X * Y; S4 += X * X;
当收集趋势柱线的所有总和时,将显示回归方程的比率:
B = (N * S3 - S1 * S2) / (N * S4 - S1 * S1); A = (S2 - B * S1) / N;
当我们计算线性回归方程时,通过分析比率 B,我们可以找出这组柱线中是否存在趋势,以及它是否与蜡烛的方向一致:
if ((CandleDir < 0)&&(B < 0)) continue; if ((CandleDir > 0)&&(B > 0)) continue;
评估趋势是否足够强劲,即倾斜的陡峭程度也是有用的。 趋势斜率太小可能只是噪声,一个横盘误差。 此外,微小的价格走势产生的收益太少,无法偿付交易费用。 因此,我们在指标代码中添加一个参数,用于设置最小允许的趋势斜率。 它以每分钟点数为单位:
input double Trend_PowerMin = 0.01;
在代码中,该参数被转换为与回归方程中的比率 B 相同的单位,并取它们进行比较:
if (MathAbs(B) < (Trend_PowerMin*_Point*PeriodSeconds()/60)) continue;
现在,我们继续讨论我们利用线性回归来判定趋势的最重要事情。
由于回归线穿过趋势通道的中心,我们现在可以计算该通道本身的宽度。 趋势通道的宽度是柱线价格相对于回归线的最大分布。 更准确地说,它是向上和向下最大偏差的总和:
添加图片注释,不超过 140 字(可选)
为了计算通道宽度,您需要遍历趋势的所有柱线,计算每根柱线的回归值(与之前获得的线性回归方程中的 “y” 相同),计算该值与柱线价格之间的差值,并累积这些差值的最大值:
for (X=1; X<=TrendBarNum; X++) { int TmpCurBar=CandleStartBar+X; Y = A + B*X; DH=high[TmpCurBar]-Y; DL=low [TmpCurBar]-Y; if ((DH > maxDH)||(X==1)) maxDH=DH; if ((DL < minDL)||(X==1)) minDL=DL; }
我们可以将通道的宽度与十字星蜡烛的高度进行比较,从而得出结论,该蜡烛的走势是否足够强大,以至扭转这一趋势。 为此,向指标里再添加一个趋势输入参数,该参数设置通道宽度与找到的十字星烛条高度的最大允许比率:
input double Trend_ChanelPowerMax = 1;
在指标代码中,参考如下:
if ((maxDH-minDL) > Trend_ChanelPowerMax*CandleHeight) break;
完整的指标代码附在下面。
策略的最终指标算法
现在我们有了检测趋势存在的代码,我们将其作为过滤器连接。 如此,只有那些十字星蜡烛才能显示在指标图表上,在指标图表前面有一个与所有层面相适的趋势 — 方向、长度和宽度。
我们将所有与趋势特征可接受性的计算和评估相关的代码放入指标代码中的一个单独函数当中:
bool DetectTrend( int CandleStartBar, int CandleDir, double CandleHeight, const double& open[], const double& high[], const double& low[], const double& close[] )
它返回的逻辑值,指示是否存在相适的趋势。 每次找到十字星蜡烛时,我们都会调用此函数:
if (DojiExists) { if (DetectTrend(CurBar, CandleDir, CandleHeight, open, high, low, close)) break; // there is a candle and a trend, there is no need to expand the metabar further else DojiExists=false; }
完整的指标代码附在下面。 稍后我们将一并检查它与 EA 的工作状况。