Volume custom

Price Data Components
0 Views
0 Downloads
0 Favorites
Volume custom
ÿþ//+------------------------------------------------------------------+

//|                                                Volume custom.mq5 |

//|                        Copyright 2020, MetaQuotes Software Corp. |

//|                                             https://www.mql5.com |

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

#property copyright "https://www.mql5.com/ru/users/forexmen2013"

//---- indicator settings

#property strict

#property indicator_separate_window

#property indicator_buffers 8

#property indicator_plots   5

#property indicator_type1   DRAW_COLOR_HISTOGRAM

#property indicator_color1  clrGreen,clrRed

#property indicator_style1  0

#property indicator_width1  2

#property indicator_label2  "UP"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrGreen

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

#property indicator_label3  "DW"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrRed

#property indicator_style3  STYLE_SOLID

#property indicator_width3  1

#property indicator_label4  "SignalUP"

#property indicator_type4   DRAW_ARROW

#property indicator_color4  clrBlue

#property indicator_width4  2

#property indicator_label5  "SignalDW"

#property indicator_type5   DRAW_ARROW

#property indicator_color5  clrYellow

#property indicator_width5  2

#property indicator_minimum 0.0

enum Creation

  {

   volume_and_candle=1,

   only_volume

  };

//--- input data

input Creation            type=volume_and_candle; // Creation mode

input double              MA_display_ratio=2.0;   // The ratio of MA display to histograms

//---- indicator buffers

double                    ExtVolumesBuffer[];

double                    ExtColorsBuffer[];

double                    ExtCurrVolumeUP[];

double                    ExtCurrVolumeDW[];

double                    MA_ExtCurrVolumeUP[];

double                    MA_ExtCurrVolumeDW[];

double                    ExtSignalUP[];

double                    ExtSignalDW[];

string                    symbolName;

MqlRates                  sRatesM1[];

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

//| Custom indicator initialization function                         |

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

void OnInit()

  {

   symbolName=Symbol();

   ArraySetAsSeries(sRatesM1,true);

//---- buffers

   SetIndexBuffer(0,ExtVolumesBuffer,INDICATOR_DATA);

   SetIndexBuffer(1,ExtColorsBuffer,INDICATOR_COLOR_INDEX);

   SetIndexBuffer(2,MA_ExtCurrVolumeUP,INDICATOR_DATA);

   SetIndexBuffer(3,MA_ExtCurrVolumeDW,INDICATOR_DATA);

   SetIndexBuffer(4,ExtSignalUP,INDICATOR_DATA);

   SetIndexBuffer(5,ExtSignalDW,INDICATOR_DATA);

   SetIndexBuffer(6,ExtCurrVolumeUP,INDICATOR_CALCULATIONS);

   SetIndexBuffer(7,ExtCurrVolumeDW,INDICATOR_CALCULATIONS);



   PlotIndexSetDouble(6,PLOT_EMPTY_VALUE,0.0);

   PlotIndexSetDouble(7,PLOT_EMPTY_VALUE,0.0);

//---- name for DataWindow and indicator subwindow label

   IndicatorSetString(INDICATOR_SHORTNAME,"Volumes custom");

//---- indicator digits

   IndicatorSetInteger(INDICATOR_DIGITS,0);

  }

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

//|  Volumes custom                                                   |

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

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[])

  {

//---check for sRatesM1 total

   if(rates_total<2)

      return(0);

//--- starting work

   int start=prev_calculated-1;

//--- correct position

   if(start<1)

      start=1;

//--- main cycle

   if(!CalculateVolume(start,rates_total,prev_calculated,tick_volume,high,low,open,close,time))

      return(0);

//--- exponential MA

   ExponentialMAOnBuffer(rates_total,prev_calculated,0,9,ExtCurrVolumeUP,MA_ExtCurrVolumeUP);

   ExponentialMAOnBuffer(rates_total,prev_calculated,0,9,ExtCurrVolumeDW,MA_ExtCurrVolumeDW);

//--- OnCalculate done. Return new prev_calculated.

   return(rates_total);

  }

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

//|  Calculate volume                                                |

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

bool CalculateVolume(const int nPosition,

                     const int nRatesCount,

                     const int nCalculatedCount,

                     const long &SrcBuffer[],

                     const double &nHigh[],

                     const double &nLow[],

                     const double &nOpen[],

                     const double &nClose[],

                     const datetime &nTime[])

  {

   double aCurrVolume[];

   double aCurrVolumeUP[];

   double aCurrVolumeDW[];

   int ratesCountM1=nRatesCount-1>nPosition?Bars(symbolName,PERIOD_M1):PeriodSeconds()/60;

   int copiedM1=CopyRates(symbolName,PERIOD_M1,0,ratesCountM1,sRatesM1);

   if(copiedM1<=0)

     {

      Comment("Failed to get history data for the symbol ",symbolName);

      return(false);

     }

   ArrayResize(aCurrVolume,nRatesCount);

   ArrayResize(aCurrVolumeUP,nRatesCount);

   ArrayResize(aCurrVolumeDW,nRatesCount);

   ArrayInitialize(aCurrVolume,0);

   ArrayInitialize(aCurrVolumeUP,0);

   ArrayInitialize(aCurrVolumeDW,0);

//---

   ArraySetAsSeries(nTime,true);

   int positionM1=nRatesCount-1>nPosition?copiedM1-1:(int)(sRatesM1[0].time-nTime[0])/60;

   for(int n=positionM1; n>=0 && !IsStopped(); n--)

     {

      int barShift=iBarShift(symbolName,PERIOD_CURRENT,sRatesM1[n].time,false);

      if(barShift==-1)

        {

         Comment("Failed to get iBarShift data for the symbol ",symbolName);

         return(false);

        }

      //---

      double volumeM1=(double)sRatesM1[n].tick_volume;

      double calcVolumeM1=volumeM1*0.5;

      aCurrVolume[barShift]+=volumeM1;

      double openM1=sRatesM1[n].open/_Point;

      double closeM1=sRatesM1[n].close/_Point;

      double highM1=MathMax(sRatesM1[n].high/_Point,closeM1);

      double lowM1=MathMin(sRatesM1[n].low/_Point,closeM1);

      double spreadM1=sRatesM1[n].spread;

      //spreadM1=spreadM1<=45?spreadM1:0;

      double resultCO=closeM1-openM1;

      double resultHL=highM1-lowM1;

      double resultHO=highM1-openM1;

      double resultOL=openM1-lowM1;

      if(type==1)

        {

         if(resultHL>=2)

           {

            if(resultCO>0.0)

               aCurrVolumeUP[barShift]+=spreadM1+resultHL+resultCO+calcVolumeM1;

            if(resultCO<0.0)

               aCurrVolumeDW[barShift]+=spreadM1+resultHL-resultCO+calcVolumeM1;

            if(resultCO==0.0)

              {

               aCurrVolumeUP[barShift]+=(spreadM1+resultHL+calcVolumeM1)*0.5;

               aCurrVolumeDW[barShift]+=(spreadM1+resultHL+calcVolumeM1)*0.5;

              }

            if(resultCO>0.0&&resultHO<=resultOL)

               aCurrVolumeUP[barShift]+=resultOL+resultCO;

            if(resultCO<0.0&&resultHO>resultOL)

               aCurrVolumeDW[barShift]+=resultHO-resultCO;

           }

         else

           {

            aCurrVolumeUP[barShift]+=(spreadM1+calcVolumeM1)*0.5;

            aCurrVolumeDW[barShift]+=(spreadM1+calcVolumeM1)*0.5;

           }

        }

      else

        {

         if(resultHL>=2)

           {

            if(resultCO>0.0)

               aCurrVolumeUP[barShift]+=volumeM1;

            if(resultCO<0.0)

               aCurrVolumeDW[barShift]+=volumeM1;

            if(resultCO==0.0)

              {

               aCurrVolumeUP[barShift]+=calcVolumeM1;

               aCurrVolumeDW[barShift]+=calcVolumeM1;

              }

            if(resultCO>0.0&&resultHO<=resultOL)

               aCurrVolumeUP[barShift]+=calcVolumeM1*0.5;

            if(resultCO<0.0&&resultHO>resultOL)

               aCurrVolumeDW[barShift]+=calcVolumeM1*0.5;

           }

         else

           {

            aCurrVolumeUP[barShift]+=calcVolumeM1;

            aCurrVolumeDW[barShift]+=calcVolumeM1;

           }

        }

     }

//---

   ArraySetAsSeries(aCurrVolume,true);

   ArraySetAsSeries(aCurrVolumeUP,true);

   ArraySetAsSeries(aCurrVolumeDW,true);

   ExtVolumesBuffer[0]=(double)aCurrVolume[0];

   ExtCurrVolumeUP[0]=(double)aCurrVolumeUP[0];

   ExtCurrVolumeDW[0]=(double)aCurrVolumeDW[0];

   ExtColorsBuffer[0]=0.0;

//---

   for(int i=nPosition; i<nRatesCount && !IsStopped(); i++)

     {

      double dCurrVolume=(double)aCurrVolume[i];

      double dCurrVolumeUP=(double)aCurrVolumeUP[i];

      double dCurrVolumeDW=(double)aCurrVolumeDW[i];

      double candleHL=nHigh[i]-nLow[i];

      double candleOC=nClose[i]-nOpen[i];

      //--- calculate indicator

      ExtVolumesBuffer[i]=dCurrVolume;

      ExtCurrVolumeUP[i]=dCurrVolumeUP*MA_display_ratio;

      ExtCurrVolumeDW[i]=dCurrVolumeDW*MA_display_ratio;

      ExtSignalUP[i]=EMPTY_VALUE;

      ExtSignalDW[i]=EMPTY_VALUE;

      if(dCurrVolumeUP-dCurrVolumeDW>=0.0)

        {

         ExtColorsBuffer[i]=0.0;

         if(ExtColorsBuffer[i-1]!=0.0&&candleOC<0.0)

            ExtSignalUP[i]=dCurrVolume;

        }

      else

        {

         ExtColorsBuffer[i]=1.0;

         if(ExtColorsBuffer[i-1]!=1.0&&candleOC>=0.0)

            ExtSignalDW[i]=dCurrVolume;

        }

     }

//---

   return(true);

  }

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

//|  Exponential moving average on price array                       |

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

int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,

                          const int period,const double& price[],double& buffer[])

  {

   int    i,limit;

//--- check for data

   if(period<=1 || rates_total-begin<period)

      return(0);

   double dSmoothFactor=2.0/(1.0+period);

//--- save as_series flags

   bool as_series_price=ArrayGetAsSeries(price);

   bool as_series_buffer=ArrayGetAsSeries(buffer);

   if(as_series_price)

      ArraySetAsSeries(price,false);

   if(as_series_buffer)

      ArraySetAsSeries(buffer,false);

//--- first calculation or number of bars was changed

   if(prev_calculated==0)

     {

      limit=period+begin;

      //--- set empty value for first bars

      for(i=0; i<begin; i++)

         buffer[i]=0.0;

      //--- calculate first visible value

      buffer[begin]=price[begin];

      for(i=begin+1; i<limit; i++)

         buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);

     }

   else

      limit=prev_calculated-1;

//--- main loop

   for(i=limit; i<rates_total; i++)

      buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);

//--- restore as_series flags

   if(as_series_price)

      ArraySetAsSeries(price,true);

   if(as_series_buffer)

      ArraySetAsSeries(buffer,true);

//---

   return(rates_total);

  }



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

Comments