191 lines
6.4 KiB
MQL5
191 lines
6.4 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Bollinger Bands with Pre Smoothing |
|
||
|
|
//| phade |
|
||
|
|
//| fxcalculator.io |
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "phade"
|
||
|
|
#property link "fxcalculator.io"
|
||
|
|
#property description "Bollinger Bands with optional outer band smoothing"
|
||
|
|
#property version "1.00"
|
||
|
|
|
||
|
|
#property indicator_chart_window
|
||
|
|
#property indicator_buffers 6
|
||
|
|
#property indicator_plots 3
|
||
|
|
|
||
|
|
// Plot properties for the Bollinger Bands
|
||
|
|
#property indicator_label1 "Bands upper"
|
||
|
|
#property indicator_type1 DRAW_LINE
|
||
|
|
#property indicator_color1 clrSilver
|
||
|
|
#property indicator_width1 2
|
||
|
|
|
||
|
|
#property indicator_label2 "Bands lower"
|
||
|
|
#property indicator_type2 DRAW_LINE
|
||
|
|
#property indicator_color2 clrSilver
|
||
|
|
#property indicator_width2 2
|
||
|
|
|
||
|
|
#property indicator_label3 "Bands middle"
|
||
|
|
#property indicator_type3 DRAW_LINE
|
||
|
|
#property indicator_color3 clrBisque
|
||
|
|
|
||
|
|
// Input parameters
|
||
|
|
input int BB_Period = 20; // BB Period
|
||
|
|
input double BB_Deviation = 2.0; // Standard deviation multiplier
|
||
|
|
input ENUM_MA_METHOD ma_method = MODE_SMA; // MA type
|
||
|
|
input bool additive_smoothing = true; // Additive outer band smoothing
|
||
|
|
input int MA_Period_1 = 14; // Upper band MA smoothing period
|
||
|
|
input int MA_Period_2 = 14; // Lower band MA smoothing period
|
||
|
|
|
||
|
|
// Indicator buffers
|
||
|
|
double BBUpperBuffer[];
|
||
|
|
double BBLowerBuffer[];
|
||
|
|
double BBMainBuffer[];
|
||
|
|
double BBCalcBuffer[];
|
||
|
|
double ma_buf_a[];
|
||
|
|
double ma_buf_b[];
|
||
|
|
|
||
|
|
// Moving Average handles
|
||
|
|
int handle;
|
||
|
|
int handle_2;
|
||
|
|
int upper;
|
||
|
|
int lower;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator initialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
SetIndexBuffer(0, BBUpperBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(1, BBLowerBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(2, BBMainBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(3, BBCalcBuffer, INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(4, ma_buf_a, INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(5, ma_buf_b, INDICATOR_CALCULATIONS);
|
||
|
|
|
||
|
|
handle = iMA(NULL, 0, BB_Period, 0, ma_method, PRICE_CLOSE);
|
||
|
|
handle_2 = iMA(NULL, 0, BB_Period, 0, ma_method, PRICE_CLOSE);
|
||
|
|
upper = iMA(NULL, 0, additive_smoothing ? BB_Period + MA_Period_1 : MA_Period_1, 0, ma_method, PRICE_CLOSE);
|
||
|
|
lower = iMA(NULL, 0, additive_smoothing ? BB_Period + MA_Period_2 : MA_Period_2, 0, ma_method, PRICE_CLOSE);
|
||
|
|
|
||
|
|
IndicatorSetString(INDICATOR_SHORTNAME, "Bollinger Bands with outer band smoothing");
|
||
|
|
|
||
|
|
return(INIT_SUCCEEDED);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator deinitialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnDeinit(const int reason)
|
||
|
|
{
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
IndicatorRelease(handle_2);
|
||
|
|
IndicatorRelease(upper);
|
||
|
|
IndicatorRelease(lower);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator iteration function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnCalculate(const int rates_total,
|
||
|
|
const int prev_calculated,
|
||
|
|
const datetime &time[],
|
||
|
|
const double &open[],
|
||
|
|
const double &high[],
|
||
|
|
const double &low[],
|
||
|
|
const double &close[],
|
||
|
|
const long &tick_volume[],
|
||
|
|
const long &volume[],
|
||
|
|
const int &spread[])
|
||
|
|
{
|
||
|
|
if(rates_total < BB_Period)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
int calculated = BarsCalculated(handle);
|
||
|
|
if(calculated < rates_total)
|
||
|
|
{
|
||
|
|
Print("Not all data of handle is calculated (", calculated, " bars). Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
calculated = BarsCalculated(handle_2);
|
||
|
|
if(calculated < rates_total)
|
||
|
|
{
|
||
|
|
Print("Not all data of handle_2 is calculated (", calculated, " bars). Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
calculated = BarsCalculated(upper);
|
||
|
|
if(calculated < rates_total)
|
||
|
|
{
|
||
|
|
Print("Not all data of upper is calculated (", calculated, " bars). Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
calculated = BarsCalculated(lower);
|
||
|
|
if(calculated < rates_total)
|
||
|
|
{
|
||
|
|
Print("Not all data of lower is calculated (", calculated, " bars). Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
int to_copy = (prev_calculated > rates_total || prev_calculated < 0) ? rates_total : rates_total - prev_calculated;
|
||
|
|
if(prev_calculated > 0)
|
||
|
|
to_copy++;
|
||
|
|
|
||
|
|
if(IsStopped()) return 0;
|
||
|
|
if(CopyBuffer(handle, 0, 0, to_copy, BBMainBuffer) <= 0)
|
||
|
|
{
|
||
|
|
Print("Getting main MA failed! Error ", GetLastError());
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(IsStopped()) return 0;
|
||
|
|
if(CopyBuffer(handle_2, 0, 0, to_copy, BBCalcBuffer) <= 0)
|
||
|
|
{
|
||
|
|
Print("Getting calculation MA failed! Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(IsStopped()) return 0;
|
||
|
|
if(CopyBuffer(upper, 0, 0, to_copy, ma_buf_a) <= 0)
|
||
|
|
{
|
||
|
|
Print("Getting upper smoothing MA failed! Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(IsStopped()) return 0;
|
||
|
|
if(CopyBuffer(lower, 0, 0, to_copy, ma_buf_b) <= 0)
|
||
|
|
{
|
||
|
|
Print("Getting lower smoothing MA failed! Error ", GetLastError());
|
||
|
|
return prev_calculated;
|
||
|
|
}
|
||
|
|
|
||
|
|
int limit = (prev_calculated == 0) ? 0 : prev_calculated - 1;
|
||
|
|
|
||
|
|
for(int i = limit; i < rates_total && !IsStopped(); i++)
|
||
|
|
{
|
||
|
|
double stdDev = iDeviation(close, BBCalcBuffer, BB_Period, i);
|
||
|
|
BBUpperBuffer[i] = ma_buf_a[i] + BB_Deviation * stdDev;
|
||
|
|
BBLowerBuffer[i] = ma_buf_b[i] - BB_Deviation * stdDev;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rates_total;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Function to calculate standard deviation |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double iDeviation(const double &price[], const double &ma_price[], int period, int pos)
|
||
|
|
{
|
||
|
|
double dSum = 0;
|
||
|
|
|
||
|
|
for(int i = 0; i < period && pos >= 0; i++)
|
||
|
|
{
|
||
|
|
int index = pos - i;
|
||
|
|
|
||
|
|
if(index >= 0 && index < ArraySize(price) && index < ArraySize(ma_price))
|
||
|
|
dSum += MathPow(price[index] - ma_price[pos], 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
return MathSqrt(dSum / period);
|
||
|
|
}
|