10评论

0收藏

布林线指标详解

avatar Pieces | 2035 人阅读 | 10 人评论 | 2018-03-08

//+------------------------------------------------------------------+
//|                                                        Bands.mq4 |
//|                      Copyright ?2005, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright ?2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 LightSeaGreen
#property indicator_color2 LightSeaGreen
#property indicator_color3 LightSeaGreen
//---- indicator parameters
extern int    BandsPeriod=20;
extern int    BandsShift=0;
extern double BandsDeviations=2.0;
//---- buffers
double MovingBuffer[];
double UpperBuffer[];
double LowerBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,MovingBuffer);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,UpperBuffer);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,LowerBuffer);
//----
   SetIndexDrawBegin(0,BandsPeriod+BandsShift);
   SetIndexDrawBegin(1,BandsPeriod+BandsShift);
   SetIndexDrawBegin(2,BandsPeriod+BandsShift);
//----
   return(0);
}
//+------------------------------------------------------------------+
//| Bollinger Bands                                                  |
//+------------------------------------------------------------------+
int start()
{
   int    i,k,counted_bars=IndicatorCounted();
   double deviation;
   double sum,oldval,newres;
//----
   if(Bars<=BandsPeriod) return(0);    //Bars代表图中所有的k的数量,如果图中的k只读出来20或者20以下的个数,不足以计算布林线,则退出程序
//---- initial zero

//counted_bars=IndicatorCounted()
//IndicatorCounted()代表已经被计算过的bars,即刚运行程序,最初为0,运行过一次,就把几乎所有的bars已经计算过一次了。
//官方的文档说的是:IndicatorCounted()的返回值是那些 从上一次运行指标后一直没有改变的柱的数量。
//IndicatorCounted()得到的值,不包含当前的k,也就是说,假设图中有10000个Bars,指标运行前,IndicatorCounted()=0,指标运行过一次后,经过计算的Bars数量为IndicatorCounted()=9999
//当第一次计算指标时,IndicatorCounted()=0,所以下面的counted_bars=0<1,即当程序第一次运行时,执行清零任务

   if(counted_bars<1)
      for(i=1;i<=BandsPeriod;i++)
      {
         //BandsPeriod=20,那么Bars-i在i=1到20的过程中,假设有10000个K,则Bars-i=9999到9980,9999为最久远的一个k的索引(索引从0开始)
         //最久远的20个K因为数据不够20个K,无法计算出指标值,所以给他们清零
         MovingBuffer[Bars-i]=EMPTY_VALUE;
         UpperBuffer[Bars-i]=EMPTY_VALUE;
         LowerBuffer[Bars-i]=EMPTY_VALUE;
      }
//----
   int limit=Bars-counted_bars;  //未经计算的柱数量,一般指标只要运行了一下,这个值总是等于1
   if(counted_bars>0) limit++;   //counted_bars>0,代表指标已经运行过了,即不是最开始加载指标的首次运行了。limit++使limit经过这一步运算,总是等于2
   for(i=0; i<limit; i++)
      MovingBuffer=iMA(NULL,0,BandsPeriod,BandsShift,MODE_SMA,PRICE_CLOSE,i);
   //上面的limit=2,这样第一次循环,i=0,第二次循环i=1,第三次i=2不满足2<2了,就不执行了,循环只进行两次,计算了MovingBuffer[0]和MovingBuffer[1]
   //为什么需要添加"if(counted_bars>0) limit++;"这么一行,导致计算了MovingBuffer[0]和MovingBuffer[1],而不是只计算MovingBuffer[0]?? 理由暂时不明。。。

//----

   i=Bars-BandsPeriod+1;   //假设10000个Bars,则i=9980+1=9981

   //下面:依然假设Bars有10000个,在第一次运行程序的时候counted_bars=0,if不成立,本行不执行,i保留上一行的值9981,下面的循环可以运行9982次
   if(counted_bars>BandsPeriod-1) i=Bars-counted_bars-1; //只要不是刚加载指标运行,if都会成立,则i的值永恒为0,下面的循环,也只会运行1次。
   //上面一行为何不是counted_bars>BandsPeriod-1而不是counted_bars>BandsPeriod,也不是counted_bars>BandsPeriod+1??  还没搞明白。。。
   while(i>=0)//第一次运行的时候,假设有10000个Bars(索引从9999->0),i=9981,则指标在下面会填充UpperBuffer[9981]-->UpperBuffer[0]这些索引的值,留下9999-9982这些索引的18个k无法填充。为啥不是19或者20?没想明白呢。。不影响使用
   {
      sum=0.0;
      k=i+BandsPeriod-1;   //假设程序第一次运行的时候,正在进行第一次循环,i=9981,k=9981+20-1=10000,第二次大循环运行时,i=9980,则k=9999
      oldval=MovingBuffer;

      /*
      下面的while说明:假设第一次运行,k=10000,子循环会一直计算到k=9981。当k=9980时就不计算了。
      i=9981时,大循环运行9982次
      在这9982次里,i在一次一次减少(大循环)
      当第一次进入大循环,i=9981,k=10000,则子循环运行20次
      当第二次进入大循环,i=9980,k=9999,则子循环运行20次
      以此类推,小循环在i的每个值时,都运行20遍
      */
      while(k>=i)
      {
         newres=Close[k]-oldval;    //在20个范围内,每个k偏离均线的距离
         sum+=newres*newres;        //这两行配合下面的一句话就是布林的公式了
         k--;
      }
      //均方差公式在布林的意义不太确定,经查阅均方差的意义,好像是。。。假设布林参数为1.0,会有一些"有点异常"的价格排除在布林之外,
      //假设参数为2.0,则会把一些"特别异常"的价格排除在外)
      //自己的理解是,假设在当前K,Close[0]这个位置,则当前中轨到上轨或下轨的距离是:20个K平均偏移均线的程度---至此终于看懂"能看懂的布林代码"啥意思了。是把均方差替换成平均值了

      //S = ((x1-x的平均值)^2 + (x2-x的平均值)^2+(x3-x的平均值)^2+...+(xn-x的平均值)^2)/n)的平方根
      //得到S后,再*BandsDeviations就是deviation了。默认BandsDeviations=2.0,就是两倍的均方差

      /*
         布林上下线的公式
         TL = ML + (D*StdDev)
         BL = ML — (D*StdDev)
         D就是BandsDeviations
         StdDev就是上面注释中的S
      */

      deviation=BandsDeviations*MathSqrt(sum/BandsPeriod);
      UpperBuffer=oldval+deviation;
      LowerBuffer=oldval-deviation;
      i--;
   }
//----
   return(0);
}
//+------------------------------------------------------------------+

""
还没有人打赏,支持一下

评论|共 10 个

依依

发表于 2020-6-17 10:06:02 | 显示全部楼层

我是个凑数的。。。

point

发表于 2020-7-11 15:34:24 | 显示全部楼层

学习了,不错

ogoiqsjkv56

发表于 2020-7-24 12:15:12 | 显示全部楼层

学习了,不错

music

发表于 2020-8-14 22:58:52 | 显示全部楼层

学习了,不错

CCCUK

发表于 2020-8-27 18:35:12 | 显示全部楼层

帮你顶下哈!!

bestuser

发表于 2021-7-13 17:56:20 | 显示全部楼层

支持下

逍遥风云

发表于 2021-7-27 20:44:57 | 显示全部楼层

谢谢

张爱

发表于 2021-8-3 12:29:17 | 显示全部楼层

hhubio

发表于 2024-3-24 09:29:53 | 显示全部楼层


学习了,不错

12下一页
您需要登录后才可以回帖 登录 | 注册 微信登录

EA之家评论守则