请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3365785 新帖:17

一个绘制支撑和阻力线的指标实例

耶伦发表于:4 月 17 日 15:23回复(1)

简介

通过这篇文章,技术分析中最古老的价格水平预测方法就将可以使用了。它还包含了可用的指标用于绘制趋势线 (支撑和阻力线), 您将会看到指标的创建过程有多么简单。您还将学到如何通过修改指标代码来构建用于绘制任何所需线形的条件。

注意: 本文中所书写的内容都不是推荐的交易方法,而只是用于提供信息的目的。作者不会为您的行为负责,包括使用所描述方法后造成的任何利润损失。


什么是支撑和阻力线?

首先,我们需要定义研究对象,以下是支撑和阻力线的描述,以我的观点,它已经全面反映了它们的含义。

阻力线是指在一定时间内,价格的变化不会超过的一条线,

支撑线是指在一定时间内,价格的下跌不会低于的一条线。

支撑线可以是水平的或者有任何方向的倾斜。线的角色可能根据我们如何观察图表而有所改变。让我们讨论一下支撑线,这对阻力线也是如此,它们的区别就像在镜子两边。

  • 当线形是水平时,价格在通道中运行,线的角色是建立买入订单以及卖出订单的获利。
  • 当线形上升时,价格是上涨趋势,线的角色是建立买入订单。
  • 当线形下降时,价格是下跌趋势,线的角色是用于卖出订单的获利。

从定义中可以看出,这些线的任何一条都是一种障碍,不允许价格向某个方向变化。这就提示价格将会从线形反弹并将转向想要的方向:支撑线向上而阻力线向下。如果线形被突破而价格超过了它的限制,我们就可以下结论,这个方向的趋势结束了。这不是意味着价格的方向会改变,但是您可以说趋势的持续有些问题。阻力线在逻辑上可以关联到价格的下降,而支撑线可以关联到上升变化,在这种情况下,这些线可以给交易者提供提示,市场将走向何方,上涨还是下跌。

我们也可以绘制水平线,这些线表明价格是运行在某个通道之中的。比如,在某个时间段内,价格不会下跌低于1.1545或者上涨超过 1.1834。也可以在上涨趋势中划出阻力线或者在下跌趋势中划出支撑线,在这种情况下,这些线将用作您在价格方向上进行交易的获利点。我们将会探讨倾斜的支撑线和阻力线的构建,以及绘制水平的支撑和阻力水平。


选择倾斜线形起始点的条件

为了正确自动构建图表上的线形,应该选择怎样的参数呢?

因为阻力线阻止价格的上涨,它应该是基于峰值构建的,而支撑线阻止价格的下跌,它将通过谷值画出。让我们使用来自 MetaTrader 5 的比尔.威廉姆的分形(Fractals)指标来看是否能够构建这些点,我们将在图表上看到,分形将被用作我们的起始点。所需阻力线的起始点就是图表上的上方分形点,在它之上没有另外的分形,价格也没有上涨超过它,对于支撑线,我们将使用最下方的分形点,在那之下没有另外的分形点了。我们在此不是观察全部图表,而是我们将要分析的可见的部分。在此,我们展开如下的绘图逻辑条件: 顶部分形必须高于两个临近的分形,而底部分形必须低于它的临近分形. 这样,我们就有了起始点。

用于在倾斜线中选择第二个点的条件

我们至少需要两个点才能画出一条线,所以我们需要构建在线形中选择第二个点的规则。

应当使用什么样的标准来选择第二个点呢?首先,我们可以考虑跟在第一个点后的第二个分形点: 这会画出最近的线。但是我们也可以使用其它规则,例如图表上的最高点,如果价格没有穿过这个点继续向上的话,就可以用作阻力线,对于支撑线则是相反。您可以定义您自己的第二个点的选择规则。我们将使用第二个最近的分形。  

线形构建点的选择


用于重置线形并搜索倾斜线的新点的规则

我们已经有了构建线形的点,现在我们需要定义我们的线应该在哪里结束。对于阻力线,自然的条件是向上突破,而对于支撑线则是向下突破。但是有的时候价格只是在线形上突破了几个点然后就又回滚了,所以我们将设置一个允许的偏差,它将不会被视为突破。这会防止错误取消线形。

另外,我们还应该考虑价格有时候会长时间远离水平并不再回头,让我们设置最大允许的线形长度,以柱数表示。. 这样,如果前面的线突然"在空气中冻结",我们也能画出一条新线了。价格的变化不能同时有两条阻力线和支撑线,所以线形只在它被突破之前有效,而只能在前面的线形结束后才应该根据条件搜索新线。

当前线一旦被突破,我们就等待新线的条件。我们会为每条新线的构建单独分配独立的缓冲区,这样我们就可以看到多头和空头的竞争,结果我们可以选择第一个点的分形的最高值(对于阻力线)或者最低值(对于阻力线),第二个点将是后面的最高或者最低分形。用于绘制线形的条件已经准备好了,现在我们只需要在指标代码中实现它们,让我们开始开发指标吧。

构建倾斜线指标的实现实例

首先我们要使用默认设置来创建模板,然后我们为支撑线和阻力线创建两个缓冲区。输入参数 Pips_ (线形突破的大小) 以及 MaxBars (允许的最大线形长度),这些是用于创建指标的自动化过程,随后就是需要更加认真的创造性工作。

在载入指标时,我们要检查我们所处的位置,如果是第一次载入指标,我们要确定起点,因为要避开不能构建出分形的最前面两个柱的计算。根据比尔.威廉姆的意见,分形是一个峰值 (或谷值), 它要高于(低于)左侧和右侧的两个临近的峰值 (谷值)。 

如果不是第一次载入,我们就从最后计算过的柱后开始计算指标。

   int limit=prev_calculated;
   if(limit>3)limit-=3;
   if(limit<2)limit=2;

我们将不会从比尔.威廉姆分形的缓冲区复制数据,而是开发一些函数来检查一个柱是否为分形,不要忘记加上对意外数值的处理来保护防止缓冲区的访问错误。

bool up(const double &h[],int q)
  {
// 检查一个柱后是否有至少两个柱, 
// 如果少于两个柱,这个柱就不可能是分形
// 如果是这样,我们就不做进一步检查而直接返回 false
   if(q>=ArraySize(h)-2)return(false);
// 检查前方是否有至少两个柱, 
// 如果少于两个柱,这个柱就不可能是分形
// 如果是这样,我们就不做进一步检查而直接返回 false
   if(q<2)return(false);
// 检查柱是否为分形,如果是,我们就返回 true
   if(h[q]>=h[q-1])
      if(h[q]>=h[q-2])
         if(h[q]>h[q+1])
            if(h[q]>h[q+2])
               return(true);
// 如果我们已经进行了全部检查而仍然在这个模块中,这个柱就不是分形,返回 false
   return(false);
  }
//+------------------------------------------------------------------+
bool down(const double &h[],int q)
  {
// 本模块与之前的类似
   if(q>=ArraySize(h)-2)return(false);
   if(q<2)return(false);
   if(h[q]<=h[q-1])
      if(h[q]<=h[q-2])
         if(h[q]<h[q+1])
            if(h[q]<h[q+2])
               return(true);
   return(false);
  }


然后,我们需要在 HIGH 数组中找到一个柱来检查是否与我们的参数对应,如果是,我们就记住它,并寻找第二个点来画线,否则,我们就转到下一个柱。

for(int w=limit;w<rates_total;w++)
  {
   if(up(high,w))                  //检查柱上是否有分形
     {
      if(r1==0)r1=w;               //如果它是分形并且我们还没有峰值1, 在此设置峰值1
     }
  }

我们一旦找到第一个分形,就搜索第二个,记住,它应该比第一个柱要低,如果它比第一个柱高,我们应当给分形1设置新值。

if(high[w]>=high[r1])r1=w;                   //与第一个峰值做比较。如果本分形更高,就把该峰值设为第一个
else
   {
    r2=w;                                    //取得第二个峰值数值    
    speedr=(high[r2]-high[r1])/(r2-r1);      //计算线形速度
    w=r1-1;                                  //返回以绘制新线
   }

在找到了符合以上条件的第二个分形后,我们计算线形的速度并继续从第一个分形开始画它(回到第一个分形). 为了避免从前一个点开始画图时出现误差,我们将从开始计算线形,最终,每个点的绘图误差不会超过指标的误差,我们会立即检查,根据我们的条件,线形是否被突破。如果它被突破了,就等到新的构建。需要注意的是,突破检查只在第二个分形之后进行,我们对分形之间的价格行为并不感兴趣。对于支撑线的计算也类似。

ResistanceBuffer[w]=high[r1]+speedr*(w-r1);               //为了最小化误差,我们从最顶端开始计算
if(w>r2)                                                  //检查是否有突破
if(high[w]>ResistanceBuffer[w]+Pips_*_Point){r1=0;r2=0;}

这就是使用不同设置的指标外观。

ind1

ind2

ind3

下面的图片显示了在同一个图表上的多个指标。

ind4

ind5

选择用于绘制水平支撑和阻力水平的点

绘制水平级别,只需要一个点,所以这个任务要更简单。选择点有很多选项,这里只是它们中的一种:

  • 根据前一天(柱)计算的斐波那契水平;
  • 根据平均每日 ATR,在前一天平均价格范围上计算的斐波那契水平;
  • 在一定范围内最大分形数量;
  • 在一定范围内最高价或最低价,开盘价或收盘价的累计;
  • 在某一价格上交易量的累计 (市场设置);
  • 根据选定模式的价格反转;
  • 等等。

您可以在这里加上任何想要的条件,但是本质是一样的: 我们要寻找一个条件, 价格会根据它在某一水平进行反转,条件符合的越多,水平支撑线或者阻力线就越有效。作为实例,我们将首先进行第一个版本的构建,让我们分析价格在一天之内的变化。

每日变动

可以看到,价格在上下波动,每日的极值点就是这样一个水平,价格会到达它,然后就转回到另外的方向,在很少的情况下,每日价格会停在最高价或者最低价上,所以我们可以把每日最高价看作是阻力水平,而最低价视作支撑水平。

在我们的例子中,水平是在交易日的终止时构建的,这就是为什么我们会在下一天把它用作参考水平。但是市场不会站在那里不动,价格的方向和范围是不断变化的,我们将实现功能来看到相对前一日价格的多个计算的水平线。当讨论到前一天时,我们的意思是在比用作交易的时段更高的图表上的前一个柱,所以,在指标中必须实现时段选择选项。另外,让我们加一个系数来转换线相对于前一日的价格,我们为每个水平线提供独立的系数。让我们开始开发我们的指标吧。

实现水平支撑和阻力水平的指标实例

我们首先使用标准方法来创建指标,让我们使用前面的指标名称并在末尾加上H,意思是"Horizontal(水平的)",让我们设置数据要使用的时段,每对线要三个系数,以及7个缓冲区来绘制这些水平。

来自更高时段的数据将记录到三个独立缓冲区: 时间(time), 最高价(highs)和最低价(lows)。另外在我们复制数据的函数中,如有必要应该增加它们的大小。

void array_copy(int b_)
  {
   ArrayResize(time_tf,b_);                         //为我们的数据修改缓冲区大小
   ArrayResize(high_tf,b_);
   ArrayResize(low_tf,b_);

   int total=b_-bars_tf;                            //计算所需复制的数据

   CopyTime(_Symbol,Period_TF,0,total,time_tf)      //把缺失的数据复制到数组中
   CopyHigh(_Symbol,Period_TF,0,total,high_tf);
   CopyLow(_Symbol,Period_TF,0,total,low_tf);

   bars_tf=b_;                                      //记住数组大小和数据的数量
  }


我们已经可以收到数据了,现在我们需要处理它们并加到数组中,所有的计算都将是一样的,所以它们都将在一个函数中进行,我们将会对其中传入数据。

void f1(double k_fibo,int q,int r,const datetime &time_[],double &b1[],double &b2[])
  {
   for(int w=q;w<r;w++)
     {
      int b=f2(time_[w]);         //在更高时段数组中找到当前柱的时间
      double h=high_tf[b];        //取得最高价
      double l=low_tf[b];         //取得最低价
      double hl=h-l;              //取得变化范围
      b1[w]=h-hl*k_fibo;          //把计算数值加到支撑缓冲区
      b2[w]=l+hl*k_fibo;          //把计算数值加到阻力缓冲区
     }
  }


因为时间范围是不同的,我们需要找到在更高时段时间数组中当前的柱的时间,这是通过以下代码来完成的。

int f2(datetime t_)
  {
   int b_=ArrayBsearch(time_tf,t_);      //在排好序的数组中通过标准搜索来找到柱
   if(time_tf[b_]>t_)b_--;               //如果返回了最接近的柱的时间,我们将把它减1
   return(MathMax(0,b_-1));              //不要忘记返回柱时要考虑到最小限制
  }


就是这样,这就是画出相对前一日价格的所需支撑和阻力线的指标。
   int limit=prev_calculated;
   if(limit>0)limit--;

   int bar=Bars(_Symbol,Period_TF);
   if(bars_tf==0 || bar>bars_tf)array_copy(bar);

   f1(0.5,limit,rates_total,time,buffer7,buffer7);           //画出中线
   f1(K_Fibo_1,limit,rates_total,time,buffer1,buffer2);      //根据系数1画出水平线
   f1(K_Fibo_2,limit,rates_total,time,buffer3,buffer4);      //根据系数2画出水平线
   f1(K_Fibo_3,limit,rates_total,time,buffer5,buffer6);      //根据系数3画出水平线

我们已经创建了绘制水平支撑和阻力水平的指标,这就是它在图表上的外观。

您可以在屏幕截图中看到,价格在指标构建的水平线上出现了反转,它们中的一个在很长的时间内都是有效支撑。对于特定的交易系统,可能要优化参数来选择更好的水平。

基于移动平均的支撑和阻力水平

除了水平的支撑和阻力线之外,我们还能讨论什么呢?

注意基于移动平均的指标,在标准终端中,它们之中当然有移动平均,以及布林带和包络线,它们是在图表上显示支撑和阻力水平的很好的指标。打开指标属性 -> "水平" 页面, 并加入两个带有负号的水平和两个带有正号的水平,我们就得到了下面的图片:

从其它指标中也可以得到一样的结果,价格"看到"了这些水平,并像通常的支撑和阻力线一样出现反弹。

结论

在结论中,我想提示一下支撑和阻力水平的重要特性,在价格突破一个水平时,支撑线经常变成阻力线,反之亦然。在交易中使用支撑和阻力线,通常需要额外的进场信号,因为您不能保证说价格达到水平时会发生什么状况,但是在价格接近这一水平时要特别注意。开发基于支撑和阻力水平的策略已经超出了本文的范围。


感谢您的关注。

全部回复

0/140

量化课程

    移动端课程