9003b29674
Indicator Collection
201 lines
14 KiB
Plaintext
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);
|
|
} |