188 lines
6.7 KiB
Plaintext
188 lines
6.7 KiB
Plaintext
|
|
|
|
//+------------------------------------------------------------------
|
|
#property copyright "mladen"
|
|
#property link "mladenfx@gmail.com"
|
|
#property description "QQE"
|
|
//+------------------------------------------------------------------
|
|
#property indicator_separate_window
|
|
#property indicator_buffers 4
|
|
#property indicator_plots 3
|
|
#property indicator_label1 "QQE fast"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_color1 clrDarkGray
|
|
#property indicator_style1 STYLE_DOT
|
|
#property indicator_label2 "QQE slow"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_color2 clrDarkGray
|
|
#property indicator_label3 "QQE"
|
|
#property indicator_type3 DRAW_COLOR_LINE
|
|
#property indicator_color3 clrDarkGray,clrDeepSkyBlue,clrLightSalmon
|
|
#property indicator_width3 2
|
|
//--- input parameters
|
|
input int inpRsiPeriod = 14; // RSI period
|
|
input int inpRsiSmoothingFactor = 5; // RSI smoothing factor
|
|
input double inpWPFast = 2.618; // Fast period
|
|
input double inpWPSlow = 4.236; // Slow period
|
|
input ENUM_APPLIED_PRICE inpPrice=PRICE_CLOSE; // Price
|
|
//--- buffers declarations
|
|
double val[],valc[],levs[],levf[];
|
|
|
|
//
|
|
|
|
#include <AZ-INVEST/CustomBarConfig.mqh>
|
|
|
|
//
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//--- indicator buffers mapping
|
|
SetIndexBuffer(0,levf,INDICATOR_DATA);
|
|
SetIndexBuffer(1,levs,INDICATOR_DATA);
|
|
SetIndexBuffer(2,val,INDICATOR_DATA);
|
|
SetIndexBuffer(3,valc,INDICATOR_COLOR_INDEX);
|
|
//--- indicator short name assignment
|
|
IndicatorSetString(INDICATOR_SHORTNAME,"QQE ("+(string)inpRsiPeriod+","+(string)inpRsiSmoothingFactor+")");
|
|
//---
|
|
return (INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator de-initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 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(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
|
|
return(0);
|
|
|
|
if(!customChartIndicator.BufferSynchronizationCheck(close))
|
|
return(0);
|
|
|
|
int _prev_calculated = customChartIndicator.GetPrevCalculated();
|
|
|
|
///
|
|
|
|
if(Bars(_Symbol,_Period)<rates_total) return(_prev_calculated);
|
|
|
|
int i=(int)MathMax(_prev_calculated-1,0); for(; i<rates_total && !_StopFlag; i++)
|
|
{
|
|
val[i]=iEma(iRsi(getPrice(inpPrice,customChartIndicator.Open,customChartIndicator.Close,customChartIndicator.High,customChartIndicator.Low,i,rates_total),inpRsiPeriod,i,rates_total),inpRsiSmoothingFactor,i,rates_total,0);
|
|
double _iEma = iEma((i>0 ? MathAbs(val[i-1]-val[i]) : 0),inpRsiPeriod,i,rates_total,1);
|
|
double _iEmm = iEma( _iEma,inpRsiPeriod,i,rates_total,2);
|
|
double _iEmf = _iEmm*inpWPFast;
|
|
double _iEms = _iEmm*inpWPSlow;
|
|
//
|
|
//---
|
|
//
|
|
{
|
|
double tr = (i>0) ? levs[i-1] : 0;
|
|
double dv = tr;
|
|
if(val[i] < tr) { tr = val[i] + _iEms; if((i>0 && val[i-1] < dv) && (tr > dv)) tr = dv; }
|
|
if(val[i] > tr) { tr = val[i] - _iEms; if((i>0 && val[i-1] > dv) && (tr < dv)) tr = dv; }
|
|
levs[i]=tr;
|
|
}
|
|
{
|
|
double tr = (i>0) ? levf[i-1] : 0;
|
|
double dv = tr;
|
|
if(val[i] < tr) { tr = val[i] + _iEmf; if((i>0 && val[i-1] < dv) && (tr > dv)) tr = dv; }
|
|
if(val[i] > tr) { tr = val[i] - _iEmf; if((i>0 && val[i-1] > dv) && (tr < dv)) tr = dv; }
|
|
levf[i]=tr;
|
|
}
|
|
valc[i]=(val[i]>levf[i] && val[i]>levs[i]) ? 1 :(val[i]<levf[i] && val[i]<levs[i]) ? 2 :(i>0) ? valc[i-1]: 0;
|
|
}
|
|
return (i);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom functions |
|
|
//+------------------------------------------------------------------+
|
|
#define rsiInstances 1
|
|
#define rsiInstancesSize 3
|
|
double workRsi[][rsiInstances*rsiInstancesSize];
|
|
#define _price 0
|
|
#define _change 1
|
|
#define _changa 2
|
|
//
|
|
//---
|
|
//
|
|
double iRsi(double price,double period,int r,int bars,int instanceNo=0)
|
|
{
|
|
if(ArrayRange(workRsi,0)!=bars) ArrayResize(workRsi,bars);
|
|
int z=instanceNo*rsiInstancesSize;
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
workRsi[r][z+_price]=price;
|
|
if(r<period)
|
|
{
|
|
int k; double sum=0; for(k=0; k<period && (r-k-1)>=0; k++) sum+=MathAbs(workRsi[r-k][z+_price]-workRsi[r-k-1][z+_price]);
|
|
workRsi[r][z+_change] = (workRsi[r][z+_price]-workRsi[0][z+_price])/MathMax(k,1);
|
|
workRsi[r][z+_changa] = sum/MathMax(k,1);
|
|
}
|
|
else
|
|
{
|
|
double alpha=1.0/MathMax(period,1);
|
|
double change=workRsi[r][z+_price]-workRsi[r-1][z+_price];
|
|
workRsi[r][z+_change] = workRsi[r-1][z+_change] + alpha*( change - workRsi[r-1][z+_change]);
|
|
workRsi[r][z+_changa] = workRsi[r-1][z+_changa] + alpha*(MathAbs(change) - workRsi[r-1][z+_changa]);
|
|
}
|
|
return(50.0*(workRsi[r][z+_change]/MathMax(workRsi[r][z+_changa],DBL_MIN)+1));
|
|
}
|
|
//
|
|
//---
|
|
//
|
|
double workEma[][3];
|
|
//
|
|
//---
|
|
//
|
|
double iEma(double price,double period,int r,int bars,int instanceNo=0)
|
|
{
|
|
if(ArrayRange(workEma,0)!=bars) ArrayResize(workEma,bars);
|
|
|
|
//
|
|
//---
|
|
//
|
|
|
|
workEma[r][instanceNo]=price;
|
|
if(r>0 && period>1)
|
|
workEma[r][instanceNo]=workEma[r-1][instanceNo]+2.0/(1.0+period)*(price-workEma[r-1][instanceNo]);
|
|
return(workEma[r][instanceNo]);
|
|
}
|
|
//
|
|
//---
|
|
//
|
|
double getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars)
|
|
{
|
|
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|