免费股票量化交易软件策略_沃尔夫波形 (Wolfe Waves)

概述

沃尔夫波形 (Wolfe Wave) Bill Wolfe 发现并描述的图形分析形态。此图案看起来像一个三角形或楔形 (沃尔夫称之为 '上升的楔子'), 并具有一些特殊的细微差别。比尔·沃尔夫 (Bill Wolfe) 提出的图形化方法可以检测到一种形态, 根据此形态可以找到入场的时刻和方向, 并且还有益于预测价格应达到的目标, 以及达到目标的时间。

在本文中, 赫兹量化交易软件将详细研究沃尔夫波形的检测和解释规则。赫兹量化交易软件将根据 通用之字折线 文章中的之字折线指标, 创建自动检测并显示波形的指标。赫兹量化交易软件还将根据结果指标创建一个简单的专家交易系统。此 EA 将允许赫兹量化交易软件测试指标绩效, 并得到比尔·沃尔夫所提出的图形分析的第一印象, 之后会在本文中讨论。 

检测沃尔夫波形的规则

赫兹量化交易软件来研究买入示例中的沃尔夫波形 (图例.1)。价格形成两个连续下降的低峰 (蓝线, 1 3), 以及两个连续下降的高峰 ( 2 4)。在点 4 逆转并形成高峰之后, 价格继续下滑。一旦价格触及点 1 — 3 的延长线, 就进行买入操作 ( 5) https://c.mql5.com/2/26/001.gif
图例. 1. 买入沃尔夫波形。蓝线是价格, 红线是形成的检测目标。在点 5 执行入场, 目标是点 7

1—3 2—4 延长线的交汇点 6 则为检测目标的到达时间。目标价位 ( 7) 的定义是 1—4 延长线与通过点 6 绘制的垂直线的交点。此方法不提供止损计算算法, 通常建议是您自行决定使用止损。以上是沃尔夫书中讲述的波形检测规则。 

当开发本文的指标时, 还会发现更多的规则。

  1.   3 必须远低于点 1, 以下条件应予以检查:

v3<v1-d1

此处:

    • v3 — 点 3 的价位;
    • v1 — 点 1 的价位;
    • d1 — 点 1 和 点 2 (线段 1''-2'') 之间的垂直距离乘以 K1 (K1 是属性窗口的参数, 其默省缺值为 0.1)。


 

  1. 检测目标的 1—4 延长线必须向上, 即点 4 必须远高于 点 1。以下条件应予以检查:

v4>v1+d1;

v4 — 4 的价位。 

  1. 4 必须远低于点 2, 以下条件应予以检查:

v4<v2-d2;

此处 v2 是点 2 的价位, d2 是点 2 和点 3 (线段 2''-3'') 之间的垂直距离乘以 K2 (K2 是属性窗口的参数, 其默省缺值为 0.1)

  1. 检测目标到达时间的 2-4 1-3 延长线必须交汇点于右侧, 所以 2-2' 的高度必须远高于 4-4' 的高度。在此必须执行以下检查:

h2-h4>K3*h2;

此处 h2 是线段 2-2' 的高度, h4 是线段 4-4' 的高度, K3 是比率 (K3 是属性窗口的参数, 其默省缺值为 0.1)

这些规则声明并未假定绝对正确。以后我们在指标的创建过程中还要详细描述。基于这些素材, 您可以根据自己的想法调整代码。 

选择使用的之字折线

开始之前, 我们下载 附件, 它包含许多 通用之字折线 一文中的多种版本之字折线指标。我们需要从中选择一个在我们的文章中使用。我们不使用 iUniZigZagPrice iUniZigZagPriceSW, 它们设计时基于图表上运行的其它指标进行计算, 因此它们仅对视觉分析有用。其它指标似乎更有趣。它们当中的每一个都可用来创建专家交易系统。此外, 我们不会使用 iCloseZigZag iHighLowZigZag, 它们只是如何创建之字折线的初始示例。剩下两个版本, iUniZigZag iUniZigZagSW。在子窗口中工作的 iUniZigZagSW 指标更适合我们, 因为它提供了更广泛的功能。附件中也包含 iUniZigZagSWEvents 指标, 并展示了使用 iCustom() 函数访问 iUniZigZagSW 指标的示例。我们将使用此变体, 因为它将允许我们使用 iUniZigZagSW 指标的所有可能性, 且可另行将沃尔夫波形的检测代码与之字折线代码分离。

iUniZigZagSWEvents 指标显示在价格图表上, 四个缓冲区用于绘制指标: 两个带箭头的缓冲区, 另外两个画点。这些就是我们检测定沃尔夫波形所需要的。箭头将指示形态识别位置, 点则用于目标。我们的指标将用到 图形对象, 特别是 趋势线 绘制波形和构型以检测目标。如果您将其绘制为线段而非延伸射线, 那么它会是显示不同构型的非常方便的工具。  

除了检测入场时刻和方向外, 沃尔夫波形也用于预测目标。所以, 当使用 iUniZigZagSW 时会出现困难。指标带有 SrcSelect 参数, 可以根据所绘制的之字折线选择分析数据的来源。可以选择以下四个选项之一:

  • Src_HighLow — 按照最高价和最低价;
  • Src_Close — 按照收盘价;
  • Src_RSI — 按照 RSI 指标;
  • Src_MA — 按照移动均线。

基于我们现正创建的指标创建专家交易系统。此即为什么如果赫兹量化交易软件利用价格来构建之字折线, 那么预测的目标就可以用来放置止盈位。在图表上显示目标没有任何问题。但是如果使用RSI (SrcSelect=Src_RSI) 计算之字折线, 则预测目标将是 RSI 指标, 而非价格。所以, 一旦 RSI 指标达到目标值, 我们就需要市价平仓, 而不可能在图表上显示目标价格和附加构型。

当使用基于价格 (Src_HighLow 或 Src_Close) 绘制的之字折线时, 目标价格和附加构型将显示在图表上。在所有其它情况下, 只会显示一个箭头, 表示已发现的结构及其方向。目标值仍然在适相应的价格缓冲区中提供 (为了能够让专家交易系统以市价平仓来应对任何其它目的), 但不会显示。

很有可能在实践中, 当指标达到目标价位时, 市价平仓的想法无法实现。大多数指标的值在一定范围内变化, 目标结果可能在此范围之外。但是, 在任何情况下, 缓冲区都将包含目标值。

收集关于之字折线峰值的数据

我们现在开始创建指标。我们在编辑器中打开 iUniZigZagSWEvents, 文件并将其保存为 iWolfeWaves。我们将操控这个指标。

直接访问所有的之字折线峰值非常方便 — 在此情况下, 我们不必每次都在历史中搜索它们。我们来创建一个数组保存数值。现在, 每当之字折线改变方向时, 一个新的元素将被添加到数组中。如果指标简单地延伸最后一个线段 (更新极值), 则数组的最后一个元素将被更新。

对于每个峰值, 我们将保存峰值、方向和所在柱线的索引 (索引从左到右)。为此目的, 我们将使用一个含有三个字段的 结构:

struct SPeackTrough{
   double   Val; // 峰值
   int      Dir; // 方向
   int      Bar; // 柱线索引
};

我们来创建一个这些结构的数组:

SPeackTrough PeackTrough[];

如果之字折线仅仅基于最高价和最低价 (SrcSelect = Src_HighLow), 当方向改变的情况下将数组递增就足够了, 设置数值并用指标最后延伸的一段更新最后的元素。基于收盘价 (SrcSelect = Src_Close) 或任何其它指标数据的之字折线更难办。在柱线形成期间, 方向改变, 之字折线可以返回原来的状态 (即当前柱线开盘之前)。这意味着对于相同柱线的每次重新计算, 峰值数组需要返回到前一根柱线的初始状态。如果我们经常更改数组大小, 这可能会减慢指标的运行。因此, 我们来引入一个附加的变量, 所用数组大小将被保存其内。必要时, 数组将以块为单位进行修改, 只允许尺寸增长。重新计算同一根柱线之前, 我们要返回此变量的初始值。

我们将使用两个变量来存储数组大小。在一个变量中, 存储前一根柱线时的数组大小。当前计算的柱线时的大小将存储在第二个变量当中:

int PreCount; // 前一根柱线时 PeackTrough 数组的大小
int CurCount; // 当前计算柱线时 PeackTrough 数组的大小

在柱线形成并计算完成后, 或计算历史柱线之后, CurCount 变量的值应转移到 PreCount 变量。然后, 在每次计算新形成的柱线之前, 我们要把数值从 PreCount 移动到 CurCount。只有 CurCount 变量将会用于所有的计算。PreCount 变量只是辅助。关于柱线结构完毕的信息只能在下一根柱线开盘 (或计算切换到历史中的下一根柱线) 时才知道。新柱线的出现将由时间决定: 如果柱线时间已经改变, 则会出现一根新柱线 (或计算历史中的下一根柱线已经开始)。需要一个辅助变量以便确定新的柱线:

datetime LastTime;

PreCount, LastCount 和 LastTime 是指标的全局变量。但是它们也可以在 OnCalculate() 指标函数里声明为静态变量。 

我们转进到 OnCalculate() 函数。基于 prev_calculated 的值, 判断是第一次执行指标计算还是仅计算新的柱线。0 意即全部计算。在此情况下, 变量 PreCount, CurCount 和 LastTime 需要初始化。以下代码位于 OnCalculte() 函数的最上面, 定义计算的柱线范围, 并初始化辅助变量:

int start; // 起始计算的柱线的索引变量

if(prev_calculated==0){ // 计算全部的柱线
   start=1;
   CurCount=0;   
   PreCount=0;
   LastTime=0;
}
else{ // 计算新柱线
   start=prev_calculated-1;
}

现在我们来处理标准的指标循环。在一开始, 我们要将变量 PreCount, CurCount 中的数值组织转移:

for(int i=start;i<rates_total;i++){

   if(time[i]>LastTime){ // 计算新 (下一次) 柱线
      LastTime=time[i];
      PreCount=CurCount;
      PreDir=CurDir;
   }
   else{ // 柱线重新计算
      CurCount=PreCount;
      CurDir=PreDir;
   }

在所有的计算当中, 仅适用 CurCount 变量, 而 PreCount is 仅设计用于维护当前的 CurCount 值。在新柱线开盘伊始, CurCount 首先包含前一根柱线计算后获得的数值。这就是为什么我们要把这个数值移动到 PreCount。在新柱线计算之后, CurCount 的数值可以改变。但是, 我们只能在下一根柱线的开盘时才能确定该值是最终的。这就是为什么在重新计算同一柱线的情况下, PreCount 变量的数值被放置到 CurCount。

猜你喜欢

转载自blog.csdn.net/herzqthz/article/details/131791218
今日推荐