Files
MT5-indicator-collection/Weighted deviation bands.mq5
Coding for Dummies 9003b29674 Indicator Collection
Indicator Collection
2024-08-27 23:35:50 +07:00

201 lines
14 KiB
Plaintext

//------------------------------------------------------------------------------------------------------------------------
#property copyright "© mladen, 2023"
#property link "mladenfx@gmail.com"
#property description "Momentum deviation bands"
#property version "1.00"
//------------------------------------------------------------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 3
#property indicator_label1 "Upper band"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrLimeGreen
#property indicator_style1 STYLE_DASHDOTDOT
#property indicator_label2 "Average"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrDarkGray
#property indicator_label3 "Lower band"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrCoral
#property indicator_style3 STYLE_DASHDOTDOT
//
//
//
input int inpPeriod = 30; // Period
input double inpMultiplier = 2.0; // Deviations
input ENUM_APPLIED_PRICE inpPrice = PRICE_CLOSE; // Price
//
//
//
double val[],bandup[],banddn[];
struct sGlobalStruct
{
int period;
};
sGlobalStruct global;
//------------------------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------------------------
//
//
//
int OnInit()
{
SetIndexBuffer(0,bandup,INDICATOR_DATA);
SetIndexBuffer(1,val ,INDICATOR_DATA);
SetIndexBuffer(2,banddn,INDICATOR_DATA);
//
//
//
global.period = MathMax(inpPeriod,1);
IndicatorSetString(INDICATOR_SHORTNAME,StringFormat("Weighted deviation bands (%i,%.2f)",inpPeriod,inpMultiplier));
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) { return; }
//------------------------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------------------------
//
//
//
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[])
{
int limit = (prev_calculated>0) ? prev_calculated-1 : 0;
//
//
//
for (int i=limit; i<rates_total && !_StopFlag; i++)
{
double _deviation = iDeviationWeighted(iGetPrice(inpPrice,open,high,low,close,i),global.period,val[i],i,rates_total);
bandup[i] = val[i] + _deviation*inpMultiplier;
banddn[i] = val[i] - _deviation*inpMultiplier;
}
return(rates_total);
}
//------------------------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------------------------
//
//
//
double iDeviationWeighted(double value, int period, double& average, int i, int bars)
{
struct sCalcStruct
{
struct sWorkStruct
{
double value;
double valueSum;
double valueWeightSum;
};
sWorkStruct data[];
int dataSize;
double weightSum;
//
//
//
sCalcStruct() : dataSize(-1) {}
};
static sCalcStruct m_work;
if (m_work.dataSize<=bars) m_work.dataSize = ArrayResize(m_work.data,bars+500,5000);
if (period<1) period = 1;
//
//
//
m_work.data[i].value = value;
if (i >= period)
{
m_work.data[i].valueSum = m_work.data[i-1].valueSum + m_work.data[i].value - m_work.data[i-period].value;
m_work.data[i].valueWeightSum = m_work.data[i-1].valueWeightSum - m_work.data[i-1].valueSum + m_work.data[i].value*(double)period;
}
else
{
period = i+1;
m_work.weightSum = (double)period;
m_work.data[i].valueWeightSum = (double)period*m_work.data[i].value;
m_work.data[i].valueSum = m_work.data[i].value;
//
//
//
for(int k=1; k<period && i>=k; k++)
{
double weight = period-k;
m_work.weightSum += weight;
m_work.data[i].valueWeightSum += m_work.data[i-k].value*weight;
m_work.data[i].valueSum += m_work.data[i-k].value;
}
}
//
//
//
double mean = average = m_work.data[i].valueWeightSum/m_work.weightSum;
double sums = 0;
for (int k=0, weight=period; k<period && i>=k; k++,weight--)
{
sums += (double)weight*(m_work.data[i-k].value-mean)*(m_work.data[i-k].value-mean);
}
//
//
//
return(sqrt(sums/m_work.weightSum));
}
//------------------------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------------------------
//
//
//
template <typename type>
double iGetPrice(ENUM_APPLIED_PRICE tprice, type& open[], type& high[], type& low[], type& close[], int i)
{
switch(tprice)
{
case PRICE_CLOSE: return(close[i]);
case PRICE_OPEN: return(open[i]);
case PRICE_HIGH: return(high[i]);
case PRICE_LOW: return(low[i]);
case PRICE_MEDIAN: return((high[i]+low[i])/2.0);
case PRICE_TYPICAL: return((high[i]+low[i]+close[i])/3.0);
case PRICE_WEIGHTED: return((high[i]+low[i]+close[i]+close[i])/4.0);
}
return(0);
}