//+------------------------------------------------------------------+ //| Linear Momentum.mq4 | //| Copyright 2015, Totom Sukopratomo | //| https://www.mqlmonster.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Totom Sukopratomo" #property link "https://www.mqlmonster.com" #property version "1.00" #property strict #property indicator_separate_window #property indicator_buffers 3 #property indicator_levelcolor clrDimGray #property indicator_levelstyle STYLE_DOT //--- plot MoLin #property indicator_label1 "Linear Momentum" #property indicator_type1 DRAW_LINE //#property indicator_color1 clrRed #property indicator_color1 White #property indicator_color2 Green #property indicator_color3 Lime #property indicator_style1 STYLE_SOLID #property indicator_width1 2 enum enMaTypes { ma_sma, // Simple moving average ma_ema, // Exponential moving average ma_smma, // Smoothed MA ma_lwma, // Linear weighted MA }; input int SmoothingPeriod = 14; // Smoothing Period input enMaTypes SmoothingMethod = ma_ema; // Smoothing Method input bool alertsOn = false; // Alerts on true/false? input bool alertsOnCurrent = true; // Alerts open bar true/false? input bool alertsMessage = true; // Alerts pop-up message true/false? input bool alertsSound = false; // Alerts sound true/false? input bool alertsNotify = false; // Alerts push notification true/false? input bool alertsEmail = false; // Alerts email true/false? input string soundFile = "alert2.wav"; // Sound file //--- indicator buffers double linm[],temp[],valt[],bolllo[],bollhi[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { IndicatorBuffers(5); SetIndexBuffer(0,linm,INDICATOR_DATA); SetIndexBuffer(1,bolllo,INDICATOR_DATA); SetIndexBuffer(2,bollhi,INDICATOR_DATA); SetIndexBuffer(3,temp,INDICATOR_CALCULATIONS); SetIndexBuffer(4,valt,INDICATOR_CALCULATIONS); IndicatorSetString(INDICATOR_SHORTNAME,"LM ("+(string)SmoothingPeriod+")"); 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[]) { int i=rates_total-prev_calculated+1; if (i>=rates_total) i=rates_total-1; for (; i>=0 && !_StopFlag; i--) { temp[i] = tick_volume[i]*(close[i]-open[i]); linm[i] = iCustomMa(SmoothingMethod,temp[i],SmoothingPeriod,i,rates_total); valt[i] = (i0) ? 1 : (linm[i]<0) ? -1 : valt[i+1] : 0; bolllo[i]=iBandsOnArray(linm,0,20,2,0,MODE_LOWER,i); bollhi[i]=iBandsOnArray(linm,0,20,2,0,MODE_UPPER,i); } if (alertsOn) { int whichBar = (alertsOnCurrent) ? 0 : 1; if (valt[whichBar] != valt[whichBar+1]) { if (valt[whichBar] == 1) doAlert(" crossing zero up"); if (valt[whichBar] ==-1) doAlert(" crossing zero down"); } } return(rates_total); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // string getAverageName(int method) { switch(method) { case ma_ema: return("EMA"); case ma_lwma: return("LWMA"); case ma_sma: return("SMA"); case ma_smma: return("SMMA"); } return(""); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // #define _maInstances 6 #define _maWorkBufferx1 1*_maInstances #define _maWorkBufferx2 2*_maInstances #define _maWorkBufferx3 3*_maInstances double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0) { r = bars-r-1; switch (mode) { case ma_sma : return(iSma(price,(int)ceil(length),r,bars,instanceNo)); case ma_ema : return(iEma(price,length,r,bars,instanceNo)); case ma_smma : return(iSmma(price,(int)ceil(length),r,bars,instanceNo)); case ma_lwma : return(iLwma(price,(int)ceil(length),r,bars,instanceNo)); default : return(price); } } // // // // // double workSma[][_maWorkBufferx1]; double iSma(double price, int period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars); workSma[r][instanceNo+0] = price; double avg = price; int k=1; for(; k=0; k++) avg += workSma[r-k][instanceNo+0]; return(avg/(double)k); } // // // // // double workEma[][_maWorkBufferx1]; 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 workSmma[][_maWorkBufferx1]; double iSmma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars); workSmma[r][instanceNo] = price; if (r>1 && period>1) workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period; return(workSmma[r][instanceNo]); } // // // // // double workLwma[][_maWorkBufferx1]; double iLwma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars); workLwma[r][instanceNo] = price; if (period<=1) return(price); double sumw = period; double sum = period*price; for(int k=1; k=0; k++) { double weight = period-k; sumw += weight; sum += weight*workLwma[r-k][instanceNo]; } return(sum/sumw); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // void doAlert(string doWhat) { static string previousAlert="nothing"; static datetime previousTime; string message; if (previousAlert != doWhat || previousTime != Time[0]) { previousAlert = doWhat; previousTime = Time[0]; // // // // // message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Linear-Momentum "+doWhat; if (alertsMessage) Alert(message); if (alertsNotify) SendNotification(message); if (alertsEmail) SendMail(_Symbol+" Linear-Momentum ",message); if (alertsSound) PlaySound(soundFile); } } //------------------------------------------------------------------- // //------------------------------------------------------------------- // // // // // string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"}; int iTfTable[] = {1,5,15,30,60,240,1440,10080,43200}; string timeFrameToString(int tf) { for (int i=ArraySize(iTfTable)-1; i>=0; i--) if (tf==iTfTable[i]) return(sTfTable[i]); return(""); }