見出し画像

(MT4)インジケータ:QQE(無料DL)

ども、じゅにこです。

久しぶりのMQL関連の記事となります。

MT4にてQQEを利用したEAを作成したいなと思い立ったところから始まるのですが、そもそも既製品利用ではなくMQL4コードから書きたかったので、QQEのMQL4用のコードを無料で公開しているところを探していたのですが見つからず。

MT5用にQQEのプログラミングコードを公開している方が居たので、そのコードを拝借し、MQL4に書き換えることにしました。

元々のMQL5用のコードは上記リンク先よりDLできます。
それをMQL4用に書き換えたものをページ下部に貼り付けてます。

学習材料向けの記事じゃないので、内容については特に解説しません。
MT4で使いたい方はコピペ&コンパイルして使ってください。

アラート機能付きのダウンロードファイルは有料で別記事にて紹介しております。

//+------------------------------------------------------------------+
//|                                                          QQE.mq4 |
//|                                         Copyright 2022, じゅにこ. |
//|                https://note.com/junico02_se_blog/n/nefebbb791433 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, じゅにこ."
#property link      "https://note.com/junico02_se_blog/n/nefebbb791433"
#property version   "1.00"
#property strict
#property indicator_separate_window


#property indicator_buffers 5
#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_LINE
#property indicator_color3  clrDarkGray
#property indicator_width3  1

#property indicator_label4  "QQE_LINE"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrDodgerBlue
#property indicator_width4  2

#property indicator_label5  "QQE_LINE"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrIndianRed
#property indicator_width5  2



#property indicator_level1     30.0
#property indicator_level2     70.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT


//--- 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_u[];
double val_d[];
double val[];
double levs[];
double levf[];

//+------------------------------------------------------------------+
//| 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,val_u,INDICATOR_DATA);
   SetIndexBuffer(4,val_d,INDICATOR_DATA);

//--- indicator short name assignment
   IndicatorSetString(INDICATOR_SHORTNAME,"QQE ("+(string)inpRsiPeriod+","+(string)inpRsiSmoothingFactor+")");
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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(Bars(_Symbol,_Period) < rates_total) return(prev_calculated);
   
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(val_u,false);
   ArraySetAsSeries(val_d,false);
   ArraySetAsSeries(val,false);
   ArraySetAsSeries(levs,false);
   ArraySetAsSeries(levf,false);
   
   int i=(int)MathMax(prev_calculated-1,0);
   for(; i<rates_total && !_StopFlag; i++)
     {
      val[i]=iEma(iRsi(getPrice(inpPrice,open,close,high,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;
        }
        
      if(val[i]>levf[i] && val[i]>levs[i]){val_u[i]=val[i];}
      if((val[i]<levf[i] && val[i]<levs[i])){val_d[i]=val[i];}      
     }
   return (i);
   
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

#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);
  }
//+------------------------------------------------------------------+


この記事が気に入ったらサポートをしてみませんか?