//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+
|