4kk4.MQL5/Indicators/KG Bands.mq5

355 lines
24 KiB
MQL5
Raw Permalink Normal View History

2026-04-27 07:00:02 +07:00
<EFBFBD><EFBFBD>#property copyright "4kk4"
#property link "https://www.mql5.com/en/users/4kk4"
#property description "KG Bollinger Bands"
//#include <MovingAverages.mqh>
//---
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 5
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_width1 2
#property indicator_type2 DRAW_LINE
#property indicator_color2 Red
#property indicator_type3 DRAW_LINE
#property indicator_color3 Red
#property indicator_type4 DRAW_LINE
#property indicator_color4 Red
#property indicator_style4 STYLE_DOT
#property indicator_type5 DRAW_LINE
#property indicator_color5 Red
#property indicator_style5 STYLE_DOT
#property indicator_label1 "Bands middle"
#property indicator_label2 "Bands upper 1"
#property indicator_label3 "Bands lower 1"
#property indicator_label4 "Bands upper 2"
#property indicator_label5 "Bands lower 2"
//--- input parametrs
input ENUM_MA_METHOD InpMaMethod = MODE_EMA; // Mode
input int InpBandsPeriod=60; // Periode MA (Total Menit)
input int InpBandsShift=0; // Shift
input double InpBandsDeviations=1.0; // Deviation 1
input double InpBandsDeviation2=2.0; // Deviation 2
//--- global variables
int ExtBandsPeriod,ExtBandsShift;
double ExtBandsDeviations;
double ExtBandsDeviation2;
int ExtPlotBegin=0;
//--- indicator buffer
double ExtMLBuffer[];
double ExtTLBuffer[];
double ExtBLBuffer[];
double ExtTL2Buffer[];
double ExtBL2Buffer[];
double ExtStdDevBuffer[];
string short_name = "Bands ";
//+------------------------------------------------------------------+
//| simple moving average |
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])
{
int i,limit;
//--- first calculation or number of bars was changed
if(prev_calculated==0)// first calculation
{
limit=ExtBandsPeriod+begin;
//--- set empty value for first limit bars
for(i=0;i<limit-1;i++)
ExtMLBuffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
firstValue+=price[i];
firstValue/=ExtBandsPeriod;
ExtMLBuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total && !IsStopped();i++)
ExtMLBuffer[i]=ExtMLBuffer[i-1]+(price[i]-price[i-ExtBandsPeriod])/ExtBandsPeriod;
//---
}
//+------------------------------------------------------------------+
//| exponential moving average |
//+------------------------------------------------------------------+
void CalculateEMA(int rates_total,int prev_calculated,int begin,const double &price[])
{
int i,limit;
double SmoothFactor=2.0/(1.0+ExtBandsPeriod);
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
limit=ExtBandsPeriod+begin;
ExtMLBuffer[begin]=price[begin];
for(i=begin+1;i<limit;i++)
ExtMLBuffer[i]=price[i]*SmoothFactor+ExtMLBuffer[i-1]*(1.0-SmoothFactor);
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total && !IsStopped();i++)
ExtMLBuffer[i]=price[i]*SmoothFactor+ExtMLBuffer[i-1]*(1.0-SmoothFactor);
//---
}
//+------------------------------------------------------------------+
//| linear weighted moving average |
//+------------------------------------------------------------------+
void CalculateLWMA(int rates_total,int prev_calculated,int begin,const double &price[])
{
int i,limit;
static int weightsum;
double sum;
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
weightsum=0;
limit=ExtBandsPeriod+begin;
//--- set empty value for first limit bars
for(i=0;i<limit;i++)
ExtMLBuffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
{
int k=i-begin+1;
weightsum+=k;
firstValue+=k*price[i];
}
firstValue/=(double)weightsum;
ExtMLBuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total && !IsStopped();i++)
{
sum=0;
for(int j=0;j<ExtBandsPeriod;j++)
sum+=(ExtBandsPeriod-j)*price[i-j];
ExtMLBuffer[i]=sum/weightsum;
}
//---
}
//+------------------------------------------------------------------+
//| smoothed moving average |
//+------------------------------------------------------------------+
void CalculateSmoothedMA(int rates_total,int prev_calculated,int begin,const double &price[])
{
int i,limit;
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
limit=ExtBandsPeriod+begin;
//--- set empty value for first limit bars
for(i=0;i<limit-1;i++)
ExtMLBuffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
firstValue+=price[i];
firstValue/=ExtBandsPeriod;
ExtMLBuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total && !IsStopped();i++)
ExtMLBuffer[i]=(ExtMLBuffer[i-1]*(ExtBandsPeriod-1)+price[i])/ExtBandsPeriod;
}
//+------------------------------------------------------------------+
//| Calculate Standard Deviation |
//+------------------------------------------------------------------+
double StdDev_Func(const int position,const double &price[],const double &ma_price[],const int period)
{
double std_dev=0.0;
//--- calcualte StdDev
if(position>=period)
{
for(int i=0; i<period; i++)
std_dev+=MathPow(price[position-i]-ma_price[position],2.0);
std_dev=MathSqrt(std_dev/period);
}
//--- return calculated value
return(std_dev);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input values
if(InpBandsPeriod<2)
{
ExtBandsPeriod=60;
PrintFormat("Incorrect value for input variable InpBandsPeriod=%d. Indicator will use value=%d for calculations.",InpBandsPeriod,ExtBandsPeriod);
}
else
{
switch(InpMaMethod)
{
case MODE_EMA :
short_name +="EMA";
break;
case MODE_LWMA :
short_name +="LWMA";
break;
case MODE_SMA :
short_name +="SMA";
break;
case MODE_SMMA :
short_name +="SMMA";
break;
}
int period = PeriodSeconds()/60;
//daily 1440 minutes
if(period == 10080)
period = 7200; //mingguan
if(period == 40320)
period = 28800; //bulanan
if(period == 161280)
period = 115200;//4 bulanan
if(period == 483840)
period = 345600;//tahunan
ExtBandsPeriod = (InpBandsPeriod) / period; // Period
//--- indicator name
IndicatorSetString(INDICATOR_SHORTNAME,short_name+"("+string(ExtBandsPeriod)+")");
}
if(InpBandsShift<0)
{
ExtBandsShift=0;
PrintFormat("Incorrect value for input variable InpBandsShift=%d. Indicator will use value=%d for calculations.",InpBandsShift,ExtBandsShift);
}
else
ExtBandsShift=InpBandsShift;
ExtBandsDeviations=InpBandsDeviations;
ExtBandsDeviation2=InpBandsDeviation2;
//--- define buffers
SetIndexBuffer(0,ExtMLBuffer);
SetIndexBuffer(1,ExtTLBuffer);
SetIndexBuffer(2,ExtBLBuffer);
SetIndexBuffer(3,ExtTL2Buffer);
SetIndexBuffer(4,ExtBL2Buffer);
SetIndexBuffer(5,ExtStdDevBuffer,INDICATOR_CALCULATIONS);
//--- set index labels
PlotIndexSetString(0,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Middle");
PlotIndexSetString(1,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper");
PlotIndexSetString(2,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower");
PlotIndexSetString(3,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper2");
PlotIndexSetString(4,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower2");
//--- indexes draw begin settings
ExtPlotBegin=ExtBandsPeriod-1;
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(3,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(4,PLOT_DRAW_BEGIN,ExtBandsPeriod);
//--- indexes shift settings
PlotIndexSetInteger(0,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(1,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(2,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(3,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(4,PLOT_SHIFT,ExtBandsShift);
//--- number of digits of indicator value
IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
}
//+------------------------------------------------------------------+
//| Bollinger Bands |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
if(rates_total<ExtPlotBegin)
return(0);
//--- indexes draw begin settings, when we've recieved previous begin
if(ExtPlotBegin!=ExtBandsPeriod+begin)
{
ExtPlotBegin=ExtBandsPeriod+begin;
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(3,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(4,PLOT_DRAW_BEGIN,ExtPlotBegin);
}
//--- starting calculation
int pos;
if(prev_calculated>1)
pos=prev_calculated-1;
else
pos=0;
//--- main cycle
switch(InpMaMethod)
{
case MODE_EMA:
CalculateEMA(rates_total,prev_calculated,begin,price);
break;
case MODE_LWMA:
CalculateLWMA(rates_total,prev_calculated,begin,price);
break;
case MODE_SMMA:
CalculateSmoothedMA(rates_total,prev_calculated,begin,price);
break;
case MODE_SMA:
CalculateSimpleMA(rates_total,prev_calculated,begin,price);
break;
}
for(int i=pos; i<rates_total && !IsStopped(); i++)
{
//--- middle line
//ExtMLBuffer[i]=CalculateMovingAverage(i, ExtBandsPeriod,prev_calculated, price);
//--- calculate and write down StdDev
ExtStdDevBuffer[i]=StdDev_Func(i,price,ExtMLBuffer,ExtBandsPeriod);
if(ExtBandsDeviations > 0)
{
//--- upper line
ExtTLBuffer[i]=ExtMLBuffer[i]+ExtBandsDeviations*ExtStdDevBuffer[i];
//--- lower line
ExtBLBuffer[i]=ExtMLBuffer[i]-ExtBandsDeviations*ExtStdDevBuffer[i];
}
else
{
//--- upper line
ExtTLBuffer[i]=0;
//--- lower line
ExtBLBuffer[i]=0;
}
if(ExtBandsDeviation2>0)
{
//--- upper line
ExtTL2Buffer[i]=ExtMLBuffer[i]+ExtBandsDeviation2*ExtStdDevBuffer[i];
//--- lower line
ExtBL2Buffer[i]=ExtMLBuffer[i]-ExtBandsDeviation2*ExtStdDevBuffer[i];
}
else
{
//--- upper line
ExtTL2Buffer[i]=0;
//--- lower line
ExtBL2Buffer[i]=0;
}
}
//--- OnCalculate done. Return new prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+