Author: Maxim Kuznetsov
Indicators Used
Moving average indicator
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
AdvMA
ÿþ//+------------------------------------------------------------------+

//|                                                        AdvMA.mq4 |

//|                                                  Maxim Kuznetsov |

//|                                          https://www.luxtrade.tk |

//+------------------------------------------------------------------+

#property copyright "Maxim Kuznetsov"

#property link      "https://www.luxtrade.tk"

#property description "Advanced MA"

#property version   "1.00"

#property strict

#property indicator_buffers 1

#property indicator_type1 DRAW_LINE

#property indicator_style1 STYLE_SOLID

#property indicator_color1 clrRed

#property indicator_width1 1

 

#property indicator_chart_window

//--- input parameters

enum ENUM_MA_TYPE {

   MA_TYPE_SMA=MODE_SMA,     // SMA

   MA_TYPE_SMMA=MODE_SMMA,   // SMMA

   MA_TYPE_EMA=MODE_EMA,     // EMA

   MA_TYPE_LWMA=MODE_LWMA,   // LWMA

   MA_TYPE_PARABOLIC=1000,   // Parabolic Weighted

   MA_TYPE_SINUS,            // Sinus Weighted

   MA_TYPE_EXPONENT,         // Exponent Weighted

   MA_TYPE_DEVIANCE,         // Price Deviance Weighted

   MA_TYPE_VOLDEV,           // Volume Deviance Weighted

   MA_TYPE_VOLUME,           // Volume Weighted

   MA_TYPE_NONE              // none

};

enum ENUM_MA_PRICE {

   MA_PRICE_OPEN=PRICE_OPEN,  // Open

   MA_PRICE_HIGH=PRICE_HIGH,  // High

   MA_PRICE_LOW=PRICE_LOW,    // Low

   MA_PRICE_CLOSE=PRICE_CLOSE,   // Close

   MA_PRICE_MEDIAN=PRICE_MEDIAN, // Median (High+Low)/2.0

   MA_PRICE_TYPICAL=PRICE_TYPICAL, // Typical (High+Low+Close)/3.0

   MA_PRICE_WEIGHTED=PRICE_WEIGHTED, // Weighted (High+Low+Close+Close)/4.0

   MA_PRICE_AVERAGE=1000,      // Average (Open+Close)/2.0

   MA_PRICE_AVERCLOSE,       // Mosted (Open+Close+Close/3.0)

   MA_PRICE_MAXOC,            // Max(Open,Close)

   MA_PRICE_MINOC             // Min(Open,Close)

};

enum ENUM_MA_FILTER {

   MA_FILTER_NONE,            // no filters

   MA_FILTER_MEDIAN,          // Median 

   MA_FILTER_MEDIAN_WEIGHT    // (Median+past)/2.0

};

input ENUM_MA_PRICE     MA_PRICE=MA_PRICE_CLOSE;   // Price

input ENUM_MA_FILTER    MA_FILTER=MA_FILTER_NONE;  // Filter

input ENUM_MA_TYPE      MA_TYPE=MA_TYPE_SMA;       // Type

input int      MA_PERIOD=13;  // Period

input int      MA_SHIFT=0;    // Shift

input double   MA_K=1.0;      // Scale (for Parabolic,Sinus,Deviance,Volume)

input ENUM_MA_FILTER    POST_FILTER=MA_FILTER_NONE;  // Post filtering



double WEIGHT[];  // Weight for weighted MA



double MA[];      // final medium average

double RAW[];     // source price

double PRICE[];   // price after pre-filtering

double AVERAGED[]; // after averaging



int OnInit()

{

   IndicatorBuffers(4);

   SetIndexBuffer(0,MA);   SetIndexShift(0,MA_SHIFT);

   SetIndexBuffer(1,RAW);

   SetIndexBuffer(2,PRICE);

   SetIndexBuffer(3,AVERAGED);

   if (MA_TYPE==MA_TYPE_SMA || MA_TYPE==MA_TYPE_LWMA || MA_TYPE==MA_TYPE_PARABOLIC || MA_TYPE==MA_TYPE_SINUS || MA_TYPE==MA_TYPE_EXPONENT) {

      if (!MakePositionalWeight(MA_TYPE,MA_PERIOD,MA_K,WEIGHT)) return INIT_FAILED;

   }

   return(INIT_SUCCEEDED);

}

void OnDeinit(const int reason) 

{

}

bool MakePositionalWeight(ENUM_MA_TYPE type,int period,double k,double &weight[]) 

{

   if (ArrayResize(weight,period)!=period) {

      Alert("ArrayResize failed");

      return false;

   }

   ArraySetAsSeries(weight,false);

   int i;

   double sum=0;

   double a = 0;

   if (type==MA_TYPE_EXPONENT) a=2.0/((double)period+1.0);

   switch(type) {

      case MA_TYPE_SMA:

      for(i=0;i<period;i++) {

         weight[i]=1.0/(double)period;

         sum+=weight[i];

      }

      break;         

      case MA_TYPE_LWMA:

      for(i=0;i<period;i++) {

         weight[i]=((double)i+1.0)/((double)period+1.0);

         sum+=weight[i];

      }

      break;      

      case MA_TYPE_PARABOLIC:

      for(i=0;i<period;i++) {

         weight[i]=MathPow(((double)i+1.0)/((double)period+1.0),k);

         sum+=weight[i];

      }

      break;

      case MA_TYPE_SINUS:

      for(i=0;i<period;i++) {

         weight[i]=MathPow(1.0+MathSin(M_PI*(i+1)/period-M_PI/2),k);

         sum+=weight[i];

      }

      break;

      case MA_TYPE_EXPONENT:

      for(i=0;i<period;i++) {

         weight[i]=a*MathPow(1.0-a,period-i-1);

         sum+=weight[i];

      }

      break;         

   }

   if (sum==0) {

      Alert("sum weighgt eq 0");

      return false;

   }

   for(i=0;i<period;i++) {

      weight[i]=weight[i]/sum;

   }

   ArraySetAsSeries(weight,true);

   return true;

}

bool MakeVolumeWeight(int period,double arg,int i,const long &volume[])

{

   if (ArrayResize(WEIGHT,period)!=period) return false;

   double sum=0;

   // 0?>;=O5< D8;LB@>20==K<8 >1JQ<0<8

   for(int k=0;k<period;k++) {

      WEIGHT[k]=FilterVolume(MA_FILTER,volume[i+k],volume[i+k+1],volume[i+k+2]);

      sum=sum+WEIGHT[k];

   }

   if (sum==0) return false;

   // >@<8@C5<

   for(int k=0;k<period;k++) {

      WEIGHT[k]=WEIGHT[k]/sum;

   }

   if (MA_K!=0.0 && MA_K!=1.0) {

      // B@51C5BAO <0AHB018@>20=85

      sum=0.0;

      for(int k=0;k<period;k++) {

         WEIGHT[k]=MathPow(WEIGHT[k],MA_K);

         sum=sum+WEIGHT[k];

      }

      if (sum==0) return false;

      // 8 5IQ @07 =>@<8@C5<

      for(int k=0;k<period;k++) {

         WEIGHT[k]=WEIGHT[k]/sum;

      }

   }

   return true;

}

bool MakeVolumeDevianceWeight(int period,double arg,int i,const long &volume[])

{

   if (ArrayResize(WEIGHT,period)!=period) return false;

   double sum=0;

   // 0?>;=O5< D8;LB@>20==K<8 >1JQ<0<8, 2KG8A;O5< A@54=89 >1JQ<

   for(int k=0;k<period;k++) {

      WEIGHT[k]=FilterVolume(MA_FILTER,volume[i+k],volume[i+k+1],volume[i+k+2]);

      sum=sum+WEIGHT[k];

   }

   if (sum==0) return false;

   double avg=sum/period;

   // 70?>;=O5< >B:;>=5=8O<8 >B A@54=59

   sum=0.0;

   for(int k=0;k<period;k++) {

      WEIGHT[k]=MathAbs(WEIGHT[k]-avg);

      sum=sum+WEIGHT[k];

   }   

   // >@<8@C5<

   for(int k=0;k<period;k++) {

      WEIGHT[k]=WEIGHT[k]/sum;

   }

   if (MA_K!=0.0 && MA_K!=1.0) {

      // B@51C5BAO <0AHB018@>20=85

      sum=0.0;

      for(int k=0;k<period;k++) {

         WEIGHT[k]=MathPow(WEIGHT[k],MA_K);

         sum=sum+WEIGHT[k];

      }

      if (sum==0) return false;

      // 8 5IQ @07 =>@<8@C5<

      for(int k=0;k<period;k++) {

         WEIGHT[k]=WEIGHT[k]/sum;

      }

   }

   return true;

}

bool MakeDevianceWeight(int period,double arg,int i)

{

  if (ArrayResize(WEIGHT,period)!=period) return false;

  // 2KGA8;O5< A@54=NN F5=C

   double sum=0;

   for(int k=0;k<period;k++) {

      sum=sum+PRICE[i+k];

   }

   double avg=sum/period;

  // 70?>;=O5< >B:;>=5=8O<8

   sum=0.0;

   for(int k=0;k<period;k++) {

      WEIGHT[k]=MathAbs(PRICE[i+k]-avg);

      sum=sum+WEIGHT[k];

   }

   if (sum==0) return false;

   // >@<8@C5<

   for(int k=0;k<period;k++) {

      WEIGHT[k]=WEIGHT[k]/sum;

   }

   if (MA_K!=0.0 && MA_K!=1.0) {

      // B@51C5BAO <0AHB018@>20=85

      sum=0.0;

      for(int k=0;k<period;k++) {

         WEIGHT[k]=MathPow(WEIGHT[k],MA_K);

         sum=sum+WEIGHT[k];

      }

      if (sum==0) return false;

      // 8 5IQ @07 =>@<8@C5<

      for(int k=0;k<period;k++) {

         WEIGHT[k]=WEIGHT[k]/sum;

      }

   }

   return true;   

}



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;

   if (limit<=0) limit=0;

   else limit--;

   ArraySetAsSeries(open,true);ArraySetAsSeries(high,true);ArraySetAsSeries(low,true);ArraySetAsSeries(close,true);ArraySetAsSeries(tick_volume,true);

   ArraySetAsSeries(RAW,true);ArraySetAsSeries(PRICE,true);ArraySetAsSeries(MA,true);

   for(int bar=limit;bar<rates_total;bar++) {

      int i = rates_total - bar - 1;

      if (i<0 || i>=rates_total) {

         Alert("WTF");

         return rates_total;

      }

      //MA[i]=EMPTY_VALUE;

      //RAW[i]=EMPTY_VALUE;

      //PRICE[i]=EMPTY_VALUE;

      RAW[i]=AppliedPrice(MA_PRICE,i,open,high,low,close);

      if (bar>3) PRICE[i]=FilterPrice(MA_FILTER,i,RAW);

      else PRICE[i]=RAW[i];

      if (bar>MA_PERIOD+3) {

         if (MA_TYPE==MA_TYPE_VOLUME) {

            MakeVolumeWeight(MA_PERIOD,MA_K,i,tick_volume);

         } else if (MA_TYPE==MA_TYPE_DEVIANCE) {

            MakeDevianceWeight(MA_PERIOD,MA_K,i);

         } else if (MA_TYPE==MA_TYPE_VOLDEV) {

            MakeVolumeDevianceWeight(MA_PERIOD,MA_K,i,tick_volume);

         }

         AVERAGED[i]=CalcMa(MA_TYPE,MA_PERIOD,MA_K,i); 

      }

      else AVERAGED[i]=EMPTY_VALUE;

      if (bar>3) MA[i]=FilterPrice(POST_FILTER,i,AVERAGED);

      else MA[i]=AVERAGED[i];

   }

   return(rates_total);

}

double CalcMa(ENUM_MA_TYPE type,int period,double arg,int i) {

   switch(type) {

      case MA_TYPE_NONE:

         return PRICE[i];

      //case MA_TYPE_SMA:

      case MA_TYPE_SMMA:

      //case MA_TYPE_LWMA:

      case MA_TYPE_EMA: 

         return iMAOnArray(PRICE,0,period,0,(ENUM_MA_METHOD)type,i);

   }

   double value=0;

   for(int k=0;k<ArraySize(WEIGHT) && k<period && (i+k)<ArraySize(PRICE);k++) {

      value+=PRICE[i+k]*WEIGHT[k];

   }

   return value;   

}



double AppliedPrice(ENUM_MA_PRICE apply,int i,const double &open[],const double &high[],const double &low[],const double &close[])

{

   if (i<0 || i>=ArraySize(open) || i>=ArraySize(high)|| i>=ArraySize(low)|| i>=ArraySize(close)) return EMPTY_VALUE;

   switch(apply) {

      case MA_PRICE_OPEN: return open[i];

      case MA_PRICE_HIGH: return high[i];

      case MA_PRICE_LOW: return low[i];

      case MA_PRICE_CLOSE: return close[i];

      case MA_PRICE_MEDIAN: return (high[i]+low[i])/2.0;

      case MA_PRICE_TYPICAL: return (high[i]+low[i]+close[i])/3.0;

      case MA_PRICE_WEIGHTED: return (high[i]+low[i]+close[i]+close[i])/4.0;

      case MA_PRICE_AVERAGE: return (open[i]+close[i])/2.0;

      case MA_PRICE_AVERCLOSE: return (open[i]+close[i]+close[i])/3.0;

      case MA_PRICE_MAXOC: return Maximum(open[i],close[i]);

      case MA_PRICE_MINOC: return Minimum(open[i],close[i]);

   }

   return close[i];

}

double FilterPrice(ENUM_MA_FILTER filter,int i,double &price[])

{

   if (i<0 || i>=ArraySize(price)) return EMPTY_VALUE;

   if (i>=ArraySize(price)-3) return price[i];

   switch(filter) {

      case MA_FILTER_NONE: return price[i];break;

      case MA_FILTER_MEDIAN: return Median(price[i+2],price[i+1],price[i]);

      case MA_FILTER_MEDIAN_WEIGHT: return Average(Median(price[i+2],price[i+1],price[i]),price[i]);

   } 

   return price[i];

}

double FilterPrice(ENUM_MA_FILTER filter,double p1,double p2,double p3)

{

   switch(filter) {

      case MA_FILTER_NONE: return p1;break;

      case MA_FILTER_MEDIAN: return Median(p1,p2,p3);

      case MA_FILTER_MEDIAN_WEIGHT: return Average(Median(p1,p2,p3),p1);

   } 

   return p1;

}

double FilterVolume(ENUM_MA_FILTER filter,long p1,long p2,long p3)

{

   if (p1<=1.0) p1=1.0;

   if (p2<=1.0) p2=1.0;

   if (p3<=1.0) p3=1.0;

   switch(filter) {

      case MA_FILTER_NONE: return (double)p1;break;

      case MA_FILTER_MEDIAN: return Median((double)p1,(double)p2,(double)p3);

      case MA_FILTER_MEDIAN_WEIGHT: return Average(Median((double)p1,(double)p2,(double)p3),(double)p1);

   } 

   return (double)p1;

}



double Average(double a,double b)

{

   if (!MathIsValidNumber(a) || a==EMPTY_VALUE) {

      if (!MathIsValidNumber(b) || b == EMPTY_VALUE) return EMPTY_VALUE;

      return b;

   }

   return (a+b)/2.0;   

}

double Median(double a,double b,double c) 

{

   if (!MathIsValidNumber(a) || a==EMPTY_VALUE) return Minimum(b,c);   

   if (!MathIsValidNumber(b) || b==EMPTY_VALUE) return Minimum(a,c);   

   if (!MathIsValidNumber(c) || c==EMPTY_VALUE) return Minimum(a,b);   

   if (a<=b && b<=c) return b;

   if (b<=a && a<=c) return a;

   return c;

}

double Minimum(double a,double b)

{

   if (!MathIsValidNumber(a) || a==EMPTY_VALUE) return b;

   if (!MathIsValidNumber(b) || b==EMPTY_VALUE) return a;

   if (a<b) return a;

   return b;

}

double Maximum(double a,double b)

{

   if (!MathIsValidNumber(a) || a==EMPTY_VALUE) return b;

   if (!MathIsValidNumber(b) || b==EMPTY_VALUE) return a;

   if (a>b) return a;

   return b;

}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---