VP-Range-v6_v1

Author: VP-Range: Volume Profile (on time range) v6.0. © FXcoder
Price Data Components
0 Views
0 Downloads
0 Favorites
VP-Range-v6_v1
ÿþ//+------------------------------------------------------------------+

//|                                                      ProjectName |

//|                                      Copyright 2012, CompanyName |

//|                                       http://www.companyname.net |

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

#property copyright "VP-Range: Volume Profile (on time range) v6.0. © FXcoder"

#property link      "http://fxcoder.blogspot.com"

#property strict

#property indicator_chart_window

#property indicator_plots 0



#define PUT_IN_RANGE(A, L, H) ((H) < (L) ? (A) : ((A) < (L) ? (L) : ((A) > (H) ? (H) : (A))))

#define COLOR_IS_NONE(C) (((C) >> 24) != 0)

#define RGB_TO_COLOR(R, G, B) ((color)((((B) & 0x0000FF) << 16) + (((G) & 0x0000FF) << 8) + ((R) & 0x0000FF)))

#define ROUND_PRICE(A, P) ((int)((A) / P + 0.5))

#define NORM_PRICE(A, P) (((int)((A) / P + 0.5)) * P)

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

//|                                                                  |

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

enum ENUM_POINT_SCALE

  {

   POINT_SCALE_1 = 1,      // *1

   POINT_SCALE_10 = 10,    // *10

   POINT_SCALE_100 = 100,  // *100

  };

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

//|                                                                  |

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

enum ENUM_VP_BAR_STYLE

  {

   VP_BAR_STYLE_LINE,        // Line

   VP_BAR_STYLE_BAR,         // Empty bar

   VP_BAR_STYLE_FILLED,      // Filled bar

   VP_BAR_STYLE_OUTLINE,     // Outline

   VP_BAR_STYLE_COLOR        // Color

  };

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

//|                                                                  |

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

enum ENUM_VP_SOURCE

  {

   VP_SOURCE_TICKS=0,// Ticks



   VP_SOURCE_M1 = 1,      // M1 bars

   VP_SOURCE_M5 = 5,      // M5 bars

   VP_SOURCE_M15 = 15,    // M15 bars

   VP_SOURCE_M30 = 30,    // M30 bars

  };

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

//|                                                                  |

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

enum ENUM_VP_RANGE_MODE

  {

   VP_RANGE_MODE_BETWEEN_LINES = 0,   // Between lines

   VP_RANGE_MODE_LAST_MINUTES = 1,    // Last minutes

   VP_RANGE_MODE_MINUTES_TO_LINE = 2  // Minitues to line

  };

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

//|                                                                  |

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

enum ENUM_VP_HG_POSITION

  {

   VP_HG_POSITION_WINDOW_LEFT = 0,    // Window left

   VP_HG_POSITION_WINDOW_RIGHT = 1,   // Window right

   VP_HG_POSITION_LEFT_OUTSIDE = 2,   // Left outside

   VP_HG_POSITION_RIGHT_OUTSIDE = 3,  // Right outside

   VP_HG_POSITION_LEFT_INSIDE = 4,    // Left inside

   VP_HG_POSITION_RIGHT_INSIDE = 5    // Right inside

  };



/* Calculation */

input ENUM_VP_RANGE_MODE RangeMode = VP_RANGE_MODE_BETWEEN_LINES;    // Range mode

input int RangeMinutes = 1440;                                       // Range minutes

input int ModeStep = 100;                                            // Mode step (points)

input ENUM_POINT_SCALE HgPointScale = POINT_SCALE_10;                // Point scale

input ENUM_APPLIED_VOLUME VolumeType = VOLUME_TICK;                  // Volume type

input ENUM_VP_SOURCE DataSource = VP_SOURCE_M1;                      // Data source



/* Histogram */

input ENUM_VP_BAR_STYLE HgBarStyle = VP_BAR_STYLE_LINE;              // Bar style

input ENUM_VP_HG_POSITION HgPosition = VP_HG_POSITION_WINDOW_RIGHT;  // Histogram position

input color HgColor = C'128,160,128';                                // Color 1

input color HgColor2 = C'128,160,128';                               // Color 2

input int HgLineWidth = 1;                                           // Line width



/* Levels */

input color ModeColor = clrBlue;                                     // Mode color

input color MaxColor = clrNONE;                                      // Maximum color

input color MedianColor = clrNONE;                                   // Median color

input color VwapColor = clrNONE;                                     // VWAP color

input int ModeLineWidth = 1;                                         // Mode line width

input ENUM_LINE_STYLE StatLineStyle = STYLE_DOT;                     // Median & VWAP line style



input color ModeLevelColor=Green;                                  // Mode level line color (None=disable)

int ModeLevelWidth=1;                                   // Mode level line width

input ENUM_LINE_STYLE ModeLevelStyle=STYLE_SOLID;                  // Mode level line style



/* Service */

input string Id="+vpr";                                            // Identifier

bool ShowHorizon = true;                                  // Show data horizon

double Zoom = 0;                                          // Zoom (0=auto)

int WaitMilliseconds = 500;                               // Wait milliseconds

color TimeFromColor = Blue;                               // Left border line color

ENUM_LINE_STYLE TimeFromStyle = STYLE_DASH;               // Left border line style

color TimeToColor = Red;                                  // Right border line color

ENUM_LINE_STYLE TimeToStyle = STYLE_DASH;                 // Right border line style

double HgWidthPercent = 15;                               // Histogram width, % of chart

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

//|                                                                  |

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

void OnInit()

  {

   _prefix=Id+" m"+IntegerToString(RangeMode)+" ";

   _tfn = Id + "-from";

   _ttn = Id + "-to";

   _hgPoint=_Point*HgPointScale;

   _modeStep=ModeStep/HgPointScale;



// íàñòîéêè îòîáàæåíèÿ

   _hgBarStyle=HgBarStyle;

   _hgPointDigits=GetPointDigits(_hgPoint);



   _defaultHgColor1 = HgColor;

   _defaultHgColor2 = HgColor2;



   _hgLineWidth=HgLineWidth;



   _modeColor= ModeColor;

   _maxColor = MaxColor;

   _medianColor=MedianColor;

   _vwapColor=VwapColor;

   _modeLineWidth=ModeLineWidth;



   _statLineStyle=StatLineStyle;



   _modeLevelColor = ModeLevelColor;

   _modeLevelWidth = ModeLevelWidth;

   _modeLevelStyle = ModeLevelStyle;



   _showHg=!(ColorIsNone(_hgColor1) && ColorIsNone(_hgColor2));

   _showModes=!ColorIsNone(_modeColor);

   _showMax=!ColorIsNone(_maxColor);

   _showMedian=!ColorIsNone(_medianColor);

   _showVwap=!ColorIsNone(_vwapColor);

   _showModeLevel=!ColorIsNone(_modeLevelColor);



   _zoom=MathAbs(Zoom);



   _updateTimer=new MillisecondTimer(WaitMilliseconds,false);



// òàéìôåéì èñòî÷íèêà äàííûõ

   _dataPeriod=GetDataPeriod(DataSource);

  }

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

//|                                                                  |

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

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)

  {



// Åñëè ñäâèíóëè ãàíèöû âûäåëåíèå, îáíîâèòü èíäèêàòî

   if(id==CHARTEVENT_OBJECT_DRAG)

     {

      if((sparam==_tfn) || (sparam==_ttn))

         CheckTimer();

     }



// èçìåíåíèå ãàôèêà (ìàñøòàá, ïîëîæåíèå, öâåò ôîíà).

   if(id==CHARTEVENT_CHART_CHANGE)

     {

      int firstVisibleBar= WindowFirstVisibleBar();

      int lastVisibleBar = firstVisibleBar-WindowBarsPerChart();



      bool update =

                   (_firstVisibleBar == _lastVisibleBar) ||

                   (

                   ((firstVisibleBar!=_firstVisibleBar) || (lastVisibleBar!=_lastVisibleBar)) && 

                   ((HgPosition==VP_HG_POSITION_WINDOW_LEFT) || (HgPosition==VP_HG_POSITION_WINDOW_RIGHT))

                   );



                   _firstVisibleBar= firstVisibleBar;

      _lastVisibleBar = lastVisibleBar;



      if(UpdateAutoColors())

        {

         _lastOK=false;

         CheckTimer();

        }

      else if(update)

        {

         CheckTimer();

        }

     }

  }

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

//|                                                                  |

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

int OnCalculate(const int ratesTotal,const int prevCalculated,const datetime &time[],const double &open[],const double &high[],const double &low[],const double &close[],const long &tickVolume[],const long &volume[],const int &spread[])

  {



   if(UpdateAutoColors())

     {

      // ïè îáíîâëåíèè öâåòà ôîíà îáíîâëÿòü ñàçó, ñáîñèâ ïèçíàê ïîñëåäíåãî óñïåøíîãî âûïîëíåíèÿ

      _lastOK=false;

      CheckTimer();

     }

   else if(_updateOnTick)

     {

      // îáíîâëÿòü íà êàæäîì òèêå, åñëè âûñòàâëåí òàêîé ïèçíàê ïè àíàëèçå ïàâîé ãàíèöû

      CheckTimer();

     }



   return(0);

  }

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

//|                                                                  |

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

void OnTimer()

  {



   CheckTimer();

  }

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

//|                                                                  |

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

void OnDeinit(const int reason)

  {

// óäàëÿåì âñå ãèñòîãàììû è èõ ïîèçâîäíûå

   ObjectsDeleteAll(0,_prefix);



// óäàëèòü ëèíèè òîëüêî ïè ÿâíîì óäàëåíèè èíäèêàòîà ñ ãàôèêà

   if(UninitializeReason()==REASON_REMOVE)

     {

      ObjectDelete(0,_tfn);

      ObjectDelete(0,_ttn);

     }



   delete(_updateTimer);

  }

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

//|                                                                  |

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

void CheckTimer()

  {

// Âûêë_÷èòü åçåâíûé òàéìå

   EventKillTimer();



// Åñëè òàéìå ñàáîòàë, íàèñîâàòü êàòèíêó. Ëèáî ñàçó, åñëè â ïîøëûé àç áûëà ïîáëåìà.

   if(_updateTimer.Check() || !_lastOK)

     {

      // Îáíîâèòü.  ñëó÷àå íåóäà÷è ïîñòàâèòü òàéìå íà 3 ñåêóíäû, ÷òîáû ïîïîáîâàòü ñíîâà åù¸ àç.

      // 3 ñåêóíäû äîëæíî áûòü äîñòàòî÷íî äëÿ ïîäãóçêè ïîñëåäíåé èñòîèè. Èíà÷å âñ¸ ïîñòî ïîâòîèòñÿ åù¸ ÷ååç 3.

      _lastOK=Update();



      if(!_lastOK)

         EventSetTimer(3);



      ChartRedraw();



      // àñ÷¸ò è èñîâàíèå ìîãóò áûòü äëèòåëüíûìè, ëó÷øå ïååçàïóñòèòü òàéìå

      _updateTimer.Reset();

     }

   else

     {

      // Íà ñëó÷àé, åñëè ñâîé òàéìå áîëüøå íå áóäåò ïîâåÿòüñÿ, äîáàâèòü ïèíóäèòåëüíó_ ïîâåêó ÷ååç ñåêóíäó (ìåíüøå MQL íå óìååò)

      EventSetTimer(1);

     }

  }

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

//|                                                                  |

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

bool Update()

  {

// óäàëÿåì ñòàûå îáúåêòû

   ObjectsDeleteAll(0,_prefix);



// Îïåäåëèòü àáî÷èé äèàïàçîí



   datetime timeFrom,timeTo;



   if(RangeMode==VP_RANGE_MODE_BETWEEN_LINES) // ìåæäó äâóõ ëèíèé

     {

      // íàéòè ëèíèè ãàíèö

      timeFrom=GetObjectTime1(_tfn);

      timeTo=GetObjectTime1(_ttn);



      if((timeFrom==0) || (timeTo==0))

        {

         // åñëè ãàíèöû äèàïàçîíà íå çàäàíû, óñòàíîâèòü èõ çàíîâî â âèäèìó_ ÷àñòü 1êàíà

         datetime timeLeft=GetBarTime(WindowFirstVisibleBar());

         datetime timeRight=GetBarTime(WindowFirstVisibleBar()-WindowBarsPerChart());

         ulong timeRange=timeRight-timeLeft;



         timeFrom=(datetime)(timeLeft+timeRange/3);

         timeTo=(datetime)(timeLeft+timeRange*2/3);



         // íàèñîâàòü ëèíèè

         DrawVLine(_tfn,timeFrom,TimeFromColor,1,TimeFromStyle,false);

         DrawVLine(_ttn,timeTo,Crimson,1,TimeToStyle,false);

        }



      ObjectEnable(0,_tfn);

      ObjectEnable(0,_ttn);



      // åñëè ëèíèè ïååïóòàíû ìåñòàìè, ïîìåíÿòü ìåñòàìè âåìåíà íà÷àëà è êîíöà

      if(timeFrom>timeTo)

         Swap(timeFrom,timeTo);

     }

   else if(RangeMode==VP_RANGE_MODE_MINUTES_TO_LINE) // îò ïàâîé ëèíèè RangeMinutes ìèíóò

     {

      // íàéòè ïàâó_ ëèíè_

      timeTo=GetObjectTime1(_ttn);

      int bar;



      if(timeTo==0)

        {

         // åñëè ëèíèè íåò, óñòàíîâèòü åãî â âèäèìó_ ÷àñòü 1êàíà

         int leftBar=WindowFirstVisibleBar();

         int rightBar = WindowFirstVisibleBar() - WindowBarsPerChart();

         int barRange = leftBar - rightBar;



         bar=MathMax(0,leftBar-barRange/3);

         timeTo=GetBarTime(bar);

        }

      else

        {

         bar=miBarShift(_Symbol,_Period,timeTo);

        }



      bar+=RangeMinutes/(PeriodSeconds(_Period)/60);

      timeFrom=GetBarTime(bar);



      DrawVLine(_tfn,timeFrom,TimeFromColor,1,TimeFromStyle,false);



      // íàèñîâàòü ëåâó_ ãàíèöó è îòêë_÷èòü âîçìîæíîñòü å¸ âûäåëåíèÿ

      if(ObjectFind(0,_ttn)==-1)

        {

         DrawVLine(_ttn,timeTo,TimeToColor,1,TimeToStyle,false);

        }



      ObjectDisable(0,_tfn);

      ObjectEnable(0,_ttn);

     }

   else if(RangeMode==VP_RANGE_MODE_LAST_MINUTES)

     {

      timeFrom=GetBarTime(RangeMinutes-1,PERIOD_M1);

      timeTo=GetBarTime(-1,PERIOD_M1);



      // óäàëèòü ëèíèè ãàíèö

      ObjectDelete(0,_tfn);

      ObjectDelete(0,_ttn);

     }

   else

     {

      return(false);

     }



   if(ShowHorizon)

     {

      datetime horizon=GetHorizon(DataSource,_dataPeriod);

      DrawHorizon(_prefix+"hz",horizon);

     }



   int barFrom,barTo;



   if(!GetRangeBars(timeFrom,timeTo,barFrom,barTo))

      return(false);



// åñëè ïàâàÿ ãàíèöà ïàâåå íóëåâîãî áàà, òî ãèñòîãàììó îáíîâëÿòü íà êàæäîì òèêå

   _updateOnTick=barTo<0;



// ïîëó÷àåì ãèñòîãàììó

   int modes[];

   double volumes[];

   double lowPrice;



   int count;



   if(DataSource==VP_SOURCE_TICKS)

      count=GetHgByTicks(timeFrom,timeTo-1,_hgPoint,_dataPeriod,VolumeType,lowPrice,volumes);

   else

      count=GetHg(timeFrom,timeTo-1,_hgPoint,_dataPeriod,VolumeType,lowPrice,volumes);



   if(count<=0)

      return(false);



// Óîâíè

   int modeCount=_showModes ? HgModes(volumes,_modeStep,modes) : -1;

   int maxPos=_showMax ? ArrayMax(volumes) : -1;

   int medianPos=_showMedian ? ArrayMedian(volumes) : -1;

   int vwapPos=_showVwap ? HgVwap(volumes,lowPrice,_hgPoint) : -1;



   string prefix=_prefix+(string)((int)RangeMode)+" ";

   double hgWidthBars=((HgPosition==VP_HG_POSITION_LEFT_INSIDE) || (HgPosition==VP_HG_POSITION_RIGHT_INSIDE))

                      ?(barFrom-barTo)

                      : WindowBarsPerChart() *(HgWidthPercent/100.0);



   double maxVolume=volumes[ArrayMaximum(volumes)];



// Ó÷åñòü íóëåâûå îáú¸ìàìû âñåõ áàîâ èñòî÷íèêà

   if(maxVolume == 0)

      maxVolume = 1;



// Îïåäåëèòü ìàñøòàá

   double zoom=_zoom>0 ? _zoom : hgWidthBars/maxVolume;



// Êàéíèå áàû îòîáàæåíèÿ ãèñòîãàììû

   int drawBarFrom,drawBarTo;



   if(HgPosition==VP_HG_POSITION_WINDOW_LEFT)

     {

      // ëåâàÿ ãàíèöà îêíà [> |  |  ]

      drawBarFrom=WindowFirstVisibleBar();

      drawBarTo=(int)(drawBarFrom-zoom*maxVolume);

     }

   else if(HgPosition==VP_HG_POSITION_WINDOW_RIGHT)

     {

      // ïàâàÿ ãàíèöà îêíà [  |  | <]

      drawBarFrom=WindowFirstVisibleBar()-WindowBarsPerChart();

      drawBarTo=(int)(drawBarFrom+zoom*maxVolume);

     }

   else if(HgPosition==VP_HG_POSITION_LEFT_OUTSIDE)

     {

      // ëåâàÿ ãàíèöà äèàïàçîíà âëåâî íàóæó [  <|  |  ]

      drawBarFrom=barFrom;

      drawBarTo=(int)(drawBarFrom+zoom*maxVolume);

     }

   else if(HgPosition==VP_HG_POSITION_RIGHT_OUTSIDE)

     {

      // ïàâàÿ ãàíèöà äèàïàçîíà íàóæó [   |  |>  ]

      drawBarFrom=barTo;

      drawBarTo=(int)(drawBarFrom-zoom*maxVolume);

     }

   else if(HgPosition==VP_HG_POSITION_LEFT_INSIDE)

     {

      // ëåâàÿ ãàíèöà äèàïàçîíà âëåâî âíóòü [   |>  |  ]

      drawBarFrom=barFrom;

      drawBarTo=barTo;

     }

   else //if (HgPosition == VP_HG_POSITION_RIGHT_INSIDE)

     {

      // ïàâàÿ ãàíèöà äèàïàçîíà [   | <|  ]

      drawBarFrom=barTo;

      drawBarTo=barFrom;

     }



// Îòîáàçèòü ãèñòîãàììó

   DrawHg(prefix,lowPrice,volumes,drawBarFrom,drawBarTo,zoom,modes,maxPos,medianPos,vwapPos);



   return(true);

  }

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

//|                                                                  |

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

datetime GetObjectTime1(const string name)

  {

   datetime time;



   if(!ObjectGetInteger(0,name,OBJPROP_TIME,0,time))

      return(0);



   return(time);

  }

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

//|                                                                  |

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

template<typename T>

int ArrayIndexOf(const T &arr[],const T value,const int startingFrom=0)

  {

   int size=ArraySize(arr);



   for(int i=startingFrom; i<size; i++)

     {

      if(arr[i]==value)

         return(i);

     }



   return(-1);

  }

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

//|                                                                  |

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

template<typename T>

bool ArrayCheckRange(const T &arr[],int &start,int &count)

  {

   int size=ArraySize(arr);



// â ñëó÷àå ïóñòîãî ìàññèâà åçóëüòàò íåîïåäåë¸í, íî âåíóòü êàê îøèáî÷íûé

   if(size<=0)

      return(false);



// â ñëó÷àå íóëåâîãî äèàïàçîíà åçóëüòàò íåîïåäåë¸í, íî âåíóòü êàê îøèáî÷íûé

   if(count==0)

      return(false);



// ñòàò âûõîäèò çà ãàíèöû ìàññèâà

   if((start>size-1) || (start<0))

      return(false);



   if(count<0)

     {

      // åñëè êîëè÷åñòâî íå óêàçàíî, âåíóòü âñ¸ îò start

      count=size-start;

     }

   else if(count>size-start)

     {

      // åñëè 1ëåìåíòîâ íåäîñòàòî÷íî äëÿ óêàçàííîãî êîëè÷åñòâà, âåíóòü ìàêñèìàëüíî âîçìîæíîå

      count=size-start;

     }



   return(true);

  }

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

//|                                                                  |

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

int ArrayMedian(const double &values[])

  {

   int size=ArraySize(values);

   double halfVolume=Sum(values)/2.0;



   double v=0;



// ïîéòè ïî ãèñòîãàììå è îñòàíîâèòüñÿ íà ñååäèíå ïî îáú¸ìó

   for(int i=0; i<size; i++)

     {

      v+=values[i];



      if(v>=halfVolume)

         return(i);

     }



   return(-1);

  }

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

//|                                                                  |

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

string TrimRight(string s,const ushort ch)

  {

   int len=StringLen(s);



// Íàéòè íà÷àëî âûåçàåìîãî äî êîíöà ó÷àñòêà

   int cut=len;



   for(int i=len-1; i>=0; i--)

     {

      if(StringGetCharacter(s,i)==ch)

         cut--;

      else

         break;

     }



   if(cut!=len)

     {

      if(cut==0)

         s="";

      else

         s=StringSubstr(s,0,cut);

     }



   return(s);

  }

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

//|                                                                  |

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

string DoubleToString(const double d,const uint digits,const uchar separator)

  {

   string s=DoubleToString(d,digits)+""; //HACK: áåç +"" ôóíêöèÿ ìîæåò âåíóòü ïóñòîå çíà÷åíèå (áèëä 697)



   if(separator!='.')

     {

      int p=StringFind(s,".");



      if(p!=-1)

         StringSetCharacter(s,p,separator);

     }



   return(s);

  }

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

//|                                                                  |

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

string DoubleToCompactString(const double d,const uint digits=8,const uchar separator='.')

  {

   string s=DoubleToString(d,digits,separator);



// óáàòü íóëè â êîíöå äîáíîé ÷àñòè

   if(StringFind(s,CharToString(separator))!=-1)

     {

      s = TrimRight(s, '0');

      s = TrimRight(s, '.');

     }



   return(s);

  }

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

//|                                                                  |

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

double MathRound(const double value,const double error)

  {

   return(error == 0 ? value : MathRound(value / error) * error);

  }

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

//|                                                                  |

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

template<typename T>

void Swap(T &value1,T &value2)

  {

   T tmp=value1;

   value1 = value2;

   value2 = tmp;

  }

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

//|                                                                  |

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

template<typename T>

T Sum(const T &arr[],int start=0,int count=-1)

  {

   if(!ArrayCheckRange(arr,start,count))

      return((T)NULL);



   T sum=(T)NULL;



   for(int i=start,end=start+count; i<end; i++)

      sum+=arr[i];



   return(sum);

  }

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

//|                                                                  |

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

int GetPointDigits(const double point)

  {

   if(point==0)

      return(_Digits);



   return(GetPointDigits(point, _Digits));

  }

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

//|                                                                  |

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

int GetPointDigits(const double point,const int maxDigits)

  {

   if(point==0)

      return(maxDigits);



   string pointString = DoubleToCompactString(point, maxDigits);

   int pointStringLen = StringLen(pointString);

   int dotPos=StringFind(pointString,".");



// pointString => result:

//   1230   => -1

//   123    =>  0

//   12.3   =>  1

//   1.23   =>  2

//   0.123  =>  3

//   .123   =>  3



   return(dotPos < 0

          ? StringLen(TrimRight(pointString,'0'))-pointStringLen

          : pointStringLen-dotPos-1);

  }

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

//|                                                                  |

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

template<typename T>

int ArrayMax(const T &array[],const int start=0,const int count=WHOLE_ARRAY)

  {

   return(ArrayMaximum(array, start, count));

  }

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

//|                                                                  |

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

int HgModes(const double &values[],const int modeStep,int &modes[])

  {

   int modeCount=0;

   ArrayFree(modes);



// èùåì ìàêñèìóìû ïî ó÷àñòêàì

   for(int i=modeStep,count=ArraySize(values)-modeStep; i<count; i++)

     {

      int maxFrom=i-modeStep;

      int maxRange=2*modeStep+1;

      int maxTo=maxFrom+maxRange-1;



      int k=ArrayMax(values,maxFrom,maxRange);



      if(k!=i)

         continue;



      for(int j=i-modeStep; j<=i+modeStep; j++)

        {

         if(values[j]!=values[k])

            continue;



         modeCount++;

         ArrayResize(modes,modeCount,count);

         modes[modeCount-1]=j;

        }

     }



   return(modeCount);

  }

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

//|                                                                  |

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

int HgVwap(const double &volumes[],const double low,const double step)

  {

   if(step==0)

      return(-1);



   double vwap=0;

   double totalVolume=0;

   int size=ArraySize(volumes);



   for(int i=0; i<size; i++)

     {

      double price=low+i*step;

      double volume=volumes[i];



      vwap+=price*volume;

      totalVolume+=volume;

     }



   if(totalVolume==0)

      return(-1);



   vwap/=totalVolume;

   return((int)((vwap - low) / step + 0.5));

  }

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

//|                                                                  |

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

int miBarShift(string symbol,ENUM_TIMEFRAMES timeframe,datetime time,bool exact=false)

  {

   if(time<0)

      return(-1);



   datetime arr[];

   datetime time1;

   CopyTime(symbol,timeframe,0,1,arr);

   time1=arr[0];



   if(CopyTime(symbol,timeframe,time,time1,arr)<=0)

      return(-1);



   if(ArraySize(arr)>2)

      return(ArraySize(arr) - 1);



   return(time < time1 ? 1 : 0);

  }

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

//|                                                                  |

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

datetime miTime(string symbol,ENUM_TIMEFRAMES timeframe,int index)

  {

   if(index<0)

      return(-1);



   datetime arr[];



   if(CopyTime(symbol,timeframe,index,1,arr)<=0)

      return(-1);



   return(arr[0]);

  }

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

//|                                                                  |

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

int WindowBarsPerChart()

  {

   return((int)ChartGetInteger(0, CHART_WIDTH_IN_BARS));

  }

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

//|                                                                  |

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

int WindowFirstVisibleBar()

  {

   return((int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR));

  }

// ïîëó÷èòü (âû÷èñëèòü) ãèñòîãàììó ïî òèêàì

int GetHgByTicks(const datetime timeFrom,const datetime timeTo,const double point,const ENUM_TIMEFRAMES dataPeriod,const ENUM_APPLIED_VOLUME appliedVolume,double &low,double &volumes[])

  {

// Îïåäåëèòü êîëè÷åñòâî òèêîâ ïî ñóììàíîìó òèêîâîìó îáú¸ìó áàîâ äèàïàçîíà

   long tickVolumes[];

   int tickVolumeCount=CopyTickVolume(_Symbol,dataPeriod,timeFrom,timeTo,tickVolumes);



   if(tickVolumeCount<=0)

      return(0);



   long tickVolumesTotal=Sum(tickVolumes);



// Ñêîïèîâàòü òèêè, íóæíû òîëüêî ñîâåø¸ííûå ñäåëêè, íóæíà èíôîìàöè òîëüêî ïî Last + îáú¸ì + âåìÿ òèêà

   MqlTick ticks[];

   int tickCount=CopyTicks(_Symbol,ticks,COPY_TICKS_TRADE,timeFrom*1000,(uint)tickVolumesTotal);



// Íåò òèêîâ - íåò ãèñòîãàììû

   if(tickCount<=0)

     {

      return(0);

     }



// Îïåäåëèòü ìèíèìóì è ìàêñèìóì, àçìå ìàññèâà ãèñòîãàììû

   MqlTick tick=ticks[0];

   low=NORM_PRICE(tick.last,point);

   double high=low;

   long timeToMs=timeTo*1000;



   for(int i=1; i<tickCount; i++)

     {

      tick=ticks[i];



      // Èíîãäà ïîëó÷åííûå òèêè âûõîäÿò çà óêàçàííûé äèàïàçîí (îøèáêà â äàííûõ íà ñåâåå, íàïèìå).

      //  òàêîì ñëó÷àå îáåçàòü ëèøíåå. Ñàì ìàññèâ ìîæíî íå èçìåíÿòü, äîñòàòî÷íî óòî÷íèòü êîëè÷åñòâî ïàâèëüíûõ òèêîâ.

      // Ïåäïîëîæèòåëüíî ïîáëåìû âûõîäà çà ëåâó_ ãàíèöó íåò.

      if(tick.time_msc>timeToMs)

        {

         tickCount=i;

         break;

        }



      double tickLast=NORM_PRICE(tick.last,point);



      if(tickLast<low)

         low=tickLast;



      if(tickLast>high)

         high=tickLast;

     }



   int lowIndex=ROUND_PRICE(low,point);

   int highIndex=ROUND_PRICE(high,point);

   int hgSize=highIndex-lowIndex+1; // êîëè÷åñòâî öåí â ãèñòîãàììå

   ArrayResize(volumes,hgSize);

   ArrayInitialize(volumes,0);



// Ñëîæèòü âñå òèêè â îäíó ãèñòîãàììó



   int pri;



   for(int j=0; j<tickCount; j++)

     {

      tick= ticks[j];

      pri = ROUND_PRICE(tick.last,point)-lowIndex;



      // Åñëè íóæåí åàëüíûé îáú¸ì, áå¸ì åãî èç èíôîìàöèè ïî òèêó.

      // Åñëè íóæåí òèêîâûé îáú¸ì, òî äîñòàòî÷íî ó÷åñòü êàæäûé òèê îâíî îäèí àç.

      volumes[pri]+=(appliedVolume==VOLUME_REAL) ?(double)tick.volume : 1;

     }



   return(hgSize);

  }

// ïîëó÷èòü (âû÷èñëèòü) ãèñòîãàììó ïî áààì, èìèòèóÿ òèêè

int GetHg(const datetime timeFrom,const datetime timeTo,const double point,const ENUM_TIMEFRAMES dataPeriod,const ENUM_APPLIED_VOLUME appliedVolume,double &low,double &volumes[])

  {

// Ïîëó÷èòü áàû òàéìôåéìà àñ÷¸òà (îáû÷íî M1)

   MqlRates rates[];

   int rateCount=CopyRates(_Symbol,dataPeriod,timeFrom,timeTo,rates);



   if(rateCount<=0)

      return(0);



// Îïåäåëèòü ìèíèìóì è ìàêñèìóì, àçìå ìàññèâà ãèñòîãàììû

   MqlRates rate=rates[0];

   low=NORM_PRICE(rate.low,point);

   double high=NORM_PRICE(rate.high,point);



   for(int i=1; i<rateCount; i++)

     {

      rate=rates[i];



      double rateHigh=  NORM_PRICE(rate.high,point);

      double rateLow = NORM_PRICE(rate.low,point);



      if(rateLow<low)

         low=rateLow;



      if(rateHigh>high)

         high=rateHigh;

     }



   int lowIndex=ROUND_PRICE(low,point);

   int highIndex=ROUND_PRICE(high,point);

   int hgSize=highIndex-lowIndex+1; // êîëè÷åñòâî öåí â ãèñòîãàììå

   ArrayResize(volumes,hgSize);

   ArrayInitialize(volumes,0);



// Ñëîæèòü âñå òèêè âñåõ áàîâ â îäíó ãèñòîãàììó



   int pri,oi,hi,li,ci;

   double dv,v;



   for(int j=0; j<rateCount; j++)

     {

      rate=rates[j];



      oi = ROUND_PRICE(rate.open, point) - lowIndex;

      hi = ROUND_PRICE(rate.high, point) - lowIndex;

      li = ROUND_PRICE(rate.low, point) - lowIndex;

      ci = ROUND_PRICE(rate.close, point) - lowIndex;



      v=(appliedVolume==VOLUME_REAL) ?(double)rate.real_volume :(double)rate.tick_volume;



      // èìèòàöèÿ òèêîâ âíóòè áàà

      if(ci>=oi)

        {

/* áû÷üÿ ñâå÷à */



         // ñåäíèé îáú¸ì êàæäîãî òèêà

         dv=v/(oi-li+hi-li+hi-ci+1.0);



         // open --> low

         for(pri=oi; pri>=li; pri--)

            volumes[pri]+=dv;



         // low+1 ++> high

         for(pri=li+1; pri<=hi; pri++)

            volumes[pri]+=dv;



         // high-1 --> close

         for(pri=hi-1; pri>=ci; pri--)

            volumes[pri]+=dv;

        }

      else

        {

/* ìåäâåæüÿ ñâå÷à */



         // ñåäíèé îáú¸ì êàæäîãî òèêà

         dv=v/(hi-oi+hi-li+ci-li+1.0);



         // open ++> high

         for(pri=oi; pri<=hi; pri++)

            volumes[pri]+=dv;



         // high-1 --> low

         for(pri=hi-1; pri>=li; pri--)

            volumes[pri]+=dv;



         // low+1 ++> close

         for(pri=li+1; pri<=ci; pri++)

            volumes[pri]+=dv;

        }

     }



   return(hgSize);

  }

// Ïîëó÷èòü âåìÿ ïåâûõ äîñòóïíûõ äàííûõ

datetime GetHorizon(ENUM_VP_SOURCE dataSource,ENUM_TIMEFRAMES dataPeriod)

  {

   if(dataSource==VP_SOURCE_TICKS)

     {

      MqlTick ticks[];

      int tickCount=CopyTicks(_Symbol,ticks,COPY_TICKS_INFO,1,1);



      if(tickCount<=0)

         return ((datetime)(SymbolInfoInteger(_Symbol, SYMBOL_TIME) + 1));



      return(ticks[0].time);

     }



   return((datetime)(miTime(_Symbol, dataPeriod, Bars(_Symbol, dataPeriod) - 1)));

  }

// Ïîëó÷èòü òàéìôåéì èñòî÷íèêà äàííûõ

ENUM_TIMEFRAMES GetDataPeriod(ENUM_VP_SOURCE dataSource)

  {

   switch(dataSource)

     {

      case VP_SOURCE_TICKS: return(PERIOD_M1); // äëÿ ïîëó÷åíèÿ ÷èñëà íåîáõîäèìûõ äëÿ çàãóçêè òèêîâ



      case VP_SOURCE_M1:    return(PERIOD_M1);

      case VP_SOURCE_M5:    return(PERIOD_M5);

      case VP_SOURCE_M15:   return(PERIOD_M15);

      case VP_SOURCE_M30:   return(PERIOD_M30);

      default:              return(PERIOD_M1);

     }

  }

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

//|                                                                  |

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

bool ColorToRGB(const color c,int &r,int &g,int &b)

  {

// Åñëè öâåò çàäàí íåâåíûé, ëèáî çàäàí êàê îòñóòñòâó_ùèé, âåíóòü false

   if(COLOR_IS_NONE(c))

      return(false);



   b = (c & 0xFF0000) >> 16;

   g = (c & 0x00FF00) >> 8;

   r = (c & 0x0000FF);



   return(true);

  }

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

//|                                                                  |

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

color MixColors(const color color1,const color color2,double mix,double step=16)

  {

// Êîåêöèÿ íåâåíûõ ïààìåòîâ

   step= PUT_IN_RANGE(step,1.0,255.0);

   mix = PUT_IN_RANGE(mix,0.0,1.0);



   int r1,g1,b1;

   int r2,g2,b2;



// àçáèòü íà êîìïîíåíòû

   ColorToRGB(color1,r1,g1,b1);

   ColorToRGB(color2,r2,g2,b2);



// âû÷èñëèòü

   int r = PUT_IN_RANGE((int)MathRound(r1 + mix * (r2 - r1), step), 0, 255);

   int g = PUT_IN_RANGE((int)MathRound(g1 + mix * (g2 - g1), step), 0, 255);

   int b = PUT_IN_RANGE((int)MathRound(b1 + mix * (b2 - b1), step), 0, 255);



   return(RGB_TO_COLOR(r, g, b));

  }

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

//|                                                                  |

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

bool ColorIsNone(const color c)

  {

   return(COLOR_IS_NONE(c));

  }

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

//|                                                                  |

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

class MillisecondTimer

  {

private: int      _milliseconds;

private: uint     _lastTick;



public: void MillisecondTimer(const int milliseconds,const bool reset=true)

     {

      _milliseconds=milliseconds;



      if(reset)

         Reset();

      else

         _lastTick=0;

     }



public: bool Check()

     {

      // ïîâåèòü îæèäàíèå

      uint now=getCurrentTick();

      bool stop=now>=_lastTick+_milliseconds;



      // ñáàñûâàåì òàéìå

      if(stop)

         _lastTick=now;



      return(stop);

     }



public: void Reset()

     {

      _lastTick=getCurrentTick();

     }



private: uint getCurrentTick() const

     {

      return(GetTickCount());

     }



  };

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

//|                                                                  |

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

void ObjectEnable(const long chartId,const string name)

  {

   ObjectSetInteger(chartId,name,OBJPROP_HIDDEN,false);

   ObjectSetInteger(chartId,name,OBJPROP_SELECTABLE,true);

  }

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

//|                                                                  |

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

void ObjectDisable(const long chartId,const string name)

  {

   ObjectSetInteger(chartId,name,OBJPROP_HIDDEN,true);

   ObjectSetInteger(chartId,name,OBJPROP_SELECTABLE,false);

  }

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

//|                                                                  |

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

int GetTimeBarRight(datetime time,ENUM_TIMEFRAMES period=PERIOD_CURRENT)

  {

   int bar=miBarShift(_Symbol,period,time);

   datetime t=miTime(_Symbol,period,bar);



   if((t!=time) && (bar==0))

     {

      // âåìÿ çà ïåäåëàìè äèàïàçîíà

      bar=(int)((miTime(_Symbol,period,0)-time)/PeriodSeconds(period));

     }

   else

     {

      // ïîâåèòü, ÷òîáû áà áûë íå ñëåâà ïî âåìåíè

      if(t<time)

         bar--;

     }



   return(bar);

  }

// ïîëó÷èòü âåìÿ ïî íîìåó áàà ñ ó÷åòîì âîçìîæíîãî âûõîäà çà äèàïàçîí áàîâ (íîìå áàà ìåíüøå 0)

datetime GetBarTime(const int shift,ENUM_TIMEFRAMES period=PERIOD_CURRENT)

  {

   if(shift>=0)

      return(miTime(_Symbol, period, shift));

   else

      return(miTime(_Symbol, period, 0) - shift * PeriodSeconds(period));

  }

// íàèñîâàòü ëèíè_ ãîèçîíòà äàííûõ

void DrawHorizon(const string lineName,const datetime time)

  {

   DrawVLine(lineName,time,Red,1,STYLE_DOT,false);

   ObjectDisable(0,lineName);

  }

// íàèñîâàòü âåòèêàëüíó_ ëèíè_

void DrawVLine(const string name,const datetime time1,const color lineColor,const int width,const int style,const bool back)

  {

   if(ObjectFind(0,name)>=0)

      ObjectDelete(0,name);



   ObjectCreate(0,name,OBJ_VLINE,0,time1,0);

   ObjectSetInteger(0,name,OBJPROP_COLOR,lineColor);

   ObjectSetInteger(0,name,OBJPROP_BACK,back);

   ObjectSetInteger(0,name,OBJPROP_STYLE,style);

   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);

  }

// íàèñîâàòü áà ãèñòîãàììû

void DrawBar(const string name,const datetime time1,const datetime time2,const double price,

             const color lineColor,const int width,const ENUM_VP_BAR_STYLE barStyle,const ENUM_LINE_STYLE lineStyle,bool back)

  {

   ObjectDelete(0,name);



   if(barStyle==VP_BAR_STYLE_BAR)

     {

      ObjectCreate(0,name,OBJ_RECTANGLE,0,time1,price-_hgPoint/2.0,time2,price+_hgPoint/2.0);



     }

   else if((barStyle==VP_BAR_STYLE_FILLED) || (barStyle==VP_BAR_STYLE_COLOR))

     {

      ObjectCreate(0,name,OBJ_RECTANGLE,0,time1,price-_hgPoint/2.0,time2,price+_hgPoint/2.0);

     }

   else if(barStyle==VP_BAR_STYLE_OUTLINE)

     {

      ObjectCreate(0,name,OBJ_TREND,0,time1,price,time2,price+_hgPoint);

     }

   else

     {

      ObjectCreate(0,name,OBJ_TREND,0,time1,price,time2,price);

     }



   SetBarStyle(name,lineColor,width,barStyle,lineStyle,back);

  }

// óñòàíîâèòü ñòèëü áàà

void SetBarStyle(const string name,const color lineColor,const int width,const ENUM_VP_BAR_STYLE barStyle,const ENUM_LINE_STYLE lineStyle,bool back)

  {

   ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);

   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);

   ObjectSetInteger(0,name,OBJPROP_COLOR,lineColor);

   ObjectSetInteger(0,name,OBJPROP_STYLE,lineStyle);

   ObjectSetInteger(0,name,OBJPROP_WIDTH,lineStyle==STYLE_SOLID ? width : 1);



   ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,false);

   ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false);



   ObjectSetInteger(0,name,OBJPROP_BACK,back);

   ObjectSetInteger(0,name,OBJPROP_FILL,(barStyle==VP_BAR_STYLE_FILLED) || (barStyle==VP_BAR_STYLE_COLOR));

  }

// íàèñîâàòü óîâåíü

void DrawLevel(const string name,const double price)

  {

   ObjectDelete(0,name);

   ObjectCreate(0,name,OBJ_HLINE,0,0,price);



   ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);

   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);

   ObjectSetInteger(0,name,OBJPROP_COLOR,_modeLevelColor);

   ObjectSetInteger(0,name,OBJPROP_STYLE,_modeLevelStyle);

   ObjectSetInteger(0,name,OBJPROP_WIDTH,_modeLevelStyle==STYLE_SOLID ? _modeLevelWidth : 1);



// íå äîëæåí áûòü ôîíîì, èíà÷å íå áóäåò îòîáàæåíà öåíà ñïàâà

   ObjectSetInteger(0,name,OBJPROP_BACK,false);

  }

// íàèñîâàòü ãèñòîãàììó

void DrawHg(const string prefix,const double lowPrice,const double &volumes[],const int barFrom,const int barTo,

            double zoom,const int &modes[],const int max=-1,const int median=-1,const int vwap=-1)

  {

   if(ArraySize(volumes)==0)

      return;



   if(barFrom>barTo)

      zoom=-zoom;



   color cl=_hgColor1;

   double maxValue=volumes[ArrayMaximum(volumes)];



// Ó÷åñòü âîçìîæíîñòü íóëåâûõ çíà÷åíèé âñåõ áàîâ

   if(maxValue == 0)

      maxValue = 1;



   double volume;

   double nextVolume=0;

   bool isOutline=_hgBarStyle==VP_BAR_STYLE_OUTLINE;



   int bar1 = barFrom;

   int bar2 = barTo;

   int modeBar2=barTo;



   for(int i=0,size=ArraySize(volumes); i<size; i++)

     {

      double price=NormalizeDouble(lowPrice+i*_hgPoint,_hgPointDigits);

      string priceString=DoubleToString(price,_hgPointDigits);

      string name=prefix+priceString;

      volume=volumes[i];



      if(isOutline)

        {

         if(i<size-1)

           {

            nextVolume=volumes[i+1];

            bar1 = (int)(barFrom + volume * zoom);

            bar2 = (int)(barFrom + nextVolume * zoom);

            modeBar2=bar1;

           }

        }

      else if(_hgBarStyle!=VP_BAR_STYLE_COLOR)

        {

         bar2=(int)(barFrom+volume*zoom);

         modeBar2=bar2;

        }



      datetime timeFrom=GetBarTime(barFrom);

      datetime timeTo=GetBarTime(barTo);

      datetime t1 = GetBarTime(bar1);

      datetime t2 = GetBarTime(bar2);

      datetime mt2= GetBarTime(modeBar2);



      // Ïè ñîâïàäåíèè íåñêîëüêèõ óîâíåé èñîâàòü òîëüêî îäèí â ïèîèòåòå: max, median, vwap, mode.

      // Åñëè íè÷åãî íå ñîâïàäàåò, íàèñîâàòü îáû÷íûé áà.



      if(_showModeLevel && (ArrayIndexOf(modes,i)!=-1))

         DrawLevel(name+" level",price);



      // Â åæèìå êîíòóà ïîñëåäíèé áà íå èñóåòñÿ

      if(_showHg && !(isOutline && (i==size-1)))

        {

         if(_hgColor1!=_hgColor2)

            cl=MixColors(_hgColor1,_hgColor2,(isOutline ? MathMax(volume,nextVolume) : volume)/maxValue,8);



         DrawBar(name,t1,t2,price,cl,_hgLineWidth,_hgBarStyle,STYLE_SOLID,true);

        }



      if(_showMedian && (i==median))

        {

         DrawBar(name+" median",timeFrom,timeTo,price,_medianColor,_modeLineWidth,VP_BAR_STYLE_LINE,_statLineStyle,false);

        }

      else if(_showVwap && (i==vwap))

        {

         DrawBar(name+" vwap",timeFrom,timeTo,price,_vwapColor,_modeLineWidth,VP_BAR_STYLE_LINE,_statLineStyle,false);

        }

      else if((_showMax && (i==max)) || (_showModes && (ArrayIndexOf(modes,i)!=-1)))

        {

         color modeColor=(_showMax && (i==max)) ? _maxColor : _modeColor;



         if(_hgBarStyle==VP_BAR_STYLE_LINE)

            DrawBar(name,timeFrom,mt2,price,modeColor,_modeLineWidth,VP_BAR_STYLE_LINE,STYLE_SOLID,false);

         else if(_hgBarStyle==VP_BAR_STYLE_BAR)

            DrawBar(name,timeFrom,mt2,price,modeColor,_modeLineWidth,VP_BAR_STYLE_BAR,STYLE_SOLID,false);

         else if(_hgBarStyle==VP_BAR_STYLE_FILLED)

            DrawBar(name,timeFrom,mt2,price,modeColor,_modeLineWidth,VP_BAR_STYLE_FILLED,STYLE_SOLID,false);

         else if(_hgBarStyle==VP_BAR_STYLE_OUTLINE)

            DrawBar(name+"+",timeFrom,mt2,price,modeColor,_modeLineWidth,VP_BAR_STYLE_LINE,STYLE_SOLID,false);

         else if(_hgBarStyle==VP_BAR_STYLE_COLOR)

            DrawBar(name,timeFrom,mt2,price,modeColor,_modeLineWidth,VP_BAR_STYLE_FILLED,STYLE_SOLID,false);

        }

     }

  }

// ïîëó÷èòü äèàïàçîí áàîâ â òåêóùåì ÒÔ (äëÿ èñîâàíèÿ)

bool GetRangeBars(const datetime timeFrom,const datetime timeTo,int &barFrom,int &barTo)

  {

   barFrom=GetTimeBarRight(timeFrom);

   barTo=GetTimeBarRight(timeTo);

   return(true);

  }

// Îáíîâèòü öâåòà, âû÷èñëÿåìûå àâòîìàòè÷åñêè. Åñëè îáíîâëåíèå ïîèçîøëî, âåíóòü true, èíà÷å false

bool UpdateAutoColors()

  {

   if(!_showHg)

      return(false);



   bool isNone1 = ColorIsNone(_defaultHgColor1);

   bool isNone2 = ColorIsNone(_defaultHgColor2);



   if(isNone1 && isNone2)

      return(false);



   color newBgColor=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND);



   if(newBgColor==_prevBackgroundColor)

      return(false);



   _hgColor1 = isNone1 ? newBgColor : _defaultHgColor1;

   _hgColor2 = isNone2 ? newBgColor : _defaultHgColor2;



   _prevBackgroundColor=newBgColor;

   return(true);

  }



string _prefix;

string _tfn;

string _ttn;



// èñòîèÿ èñîâàíèÿ

datetime _drawHistory[];

// ïîñëåäíèé çàïóñê óñïåøíûé

bool _lastOK=false;



// ìèíèìàëüíîå èçìåíåíèå öåíû äëÿ îòîáàæåíèÿ ãã

int _modeStep=0;



color _prevBackgroundColor=clrNONE;



int _rangeCount;



ENUM_VP_BAR_STYLE _hgBarStyle;

double _hgPoint;

int _hgPointDigits;



color _defaultHgColor1;

color _defaultHgColor2;

color _hgColor1;

color _hgColor2;

int _hgLineWidth;



color _modeColor;

color _maxColor;

color _medianColor;

color _vwapColor;

int _modeLineWidth;



ENUM_LINE_STYLE _statLineStyle;



color _modeLevelColor;

ENUM_LINE_STYLE _modeLevelStyle;

int _modeLevelWidth;



bool _showHg;

bool _showModes;

bool _showMax;

bool _showMedian;

bool _showVwap;

bool _showModeLevel;



double _zoom;



int _firstVisibleBar= 0;

int _lastVisibleBar = 0;



MillisecondTimer *_updateTimer;



bool _isTimeframeEnabled=false;



bool _updateOnTick=true;

ENUM_TIMEFRAMES _dataPeriod;



/*



Ñïèñîê èçìíåíåíèé



6.0

	* äîáàâëåíî: íîâûé ïààìåò "Data source" äëÿ óêàçàíèÿ èñòî÷íèêà äàííûõ - òàéìôåéìû M1, M5, M15 èëè (òîëüêî â MT5) òèêè.

	* èçìåíåíî: ïààìåò "Point scale" ïååíåñ¸í âûøå â ñïèñêå ïààìåòîâ

	* èçìåíåíî: ïààìåò "Bar style" ïååíåñ¸í âûøå â ñïèñêå ïààìåòîâ



5.8

	* èñïàâëåíî: ãèñòîãàììà íå îòîáàæàåòñÿ, åñëè åñòü õîòÿ áû îäèí áà ñ íóëåâûì îáú¸ìîì íà òàéìôåéìå èñòî÷íèêà äàííûõ



5.7

	* VP:

		* èñïàâëåíî: ïè "Range period" = "1 Week" ãèñòîãàììû ñìåùàëèñü íà äåíü âëåâî



5.6

	* VP-Range:

		* èñïàâëåíî: íå îáíîâëÿåòñÿ ãèñòîãàììà â åæèìå "Last minutes"

		* èñïàâëåíî: íå ó÷èòûâàåòñÿ ïîñëåäíÿÿ ìèíóòà â åæèìå "Last minutes"



5.5

	* èçìåíåíû ññûëêè íà ñàéò

	* ñïèñîê èçìåíåíèé â êîäå



5.4

	* èñïàâëåíà ìåäèàíà â MT4



5.3

	* èñïàâëåíî: â MT4 ïè èñîâàíèè ïóñòûìè ïÿìîóãîëüíèêàìè ïëîõî áûëî âèäíî ìîäû èç-çà íàëîæåíèÿ áàîâ

	* ñòèëü áàîâ ïî óìîë÷àíè_ èçìåí¸í íà ëèíèè



5.2

	* VP-Range:

		* èñïàâëåíî: â åæèìå "Minutes to line" íå âûäåëÿåòñÿ ïàâàÿ ãàíèöà, íî âûäåëÿåòñÿ ëåâàÿ, äîëæíî áûòü íàîáîîò

		* èñïàâëåíî: ïîñëå ïååêë_÷åíèÿ åæèìà ñ "Minutes to line" íà "Between lines" íå âûäåëÿåòñÿ îäíà èç ãàíèö



5.1

	* èñïàâëåíî èãíîèîâàíèå îòîáàæåíèÿ íà îïåäåë¸ííûõ òàéìôåìàõ â MT4 (îáõîä áàãà â MT4)



5.0

	* óâåëè÷åíû òàéìàóòû ïååèñîâêè äëÿ ñíèæåíèÿ íàãóçêè

	* òîëüêî VP:

		* âåìåííîé ñäâèã îò -12 äî +12 ÷àñîâ ñ øàãîì 1 ÷àñ äëÿ êîìïåíñàöèè ñäâèãà ÷àñîâîãî ïîÿñà ó áîêåà

		* ïî óìîë÷àíè_ ìåäèàíà è VWAP âûêë_÷åíû



4.0

	* èíäèêàòî ïååèìåíîâàí íà VP (ñîêàùåíèå îò Volume Profile)

	* äîáàâëåíà âåñèÿ äëÿ MetaTrader 5 ñ ìèíèìàëüíûìè îòëè÷èÿìè â êîäå îò âåñèè äëÿ MetaTrader 4

	* äîáàâëåíî: âòîîé öâåò ãèñòîãàììû äëÿ èñîâàíèÿ ãàäèåíòîì

	* äîáàâëåíî: òèïû ãèñòîãàìì Outline (êîíòó) è Color (öâåò)

	* äîáàâëåíî: óîâíè VWAP (ñåäíåâçâåøåííàÿ ïî îáú¸ìó öåíà) è Median (ìåäèàíà)

	* äîáàâëåíî: ó÷íîå óêàçàíèå ìàñøòàáà ïóíêòà

	* äîáàâëåíî: VP-Range: àñïîëîæåíèå ãèñòîãàììû âíóòè äèàïàçîíà

	* äîáàâëåíî: VP: îòîáàæåíèå ãèñòîãàìì ñïàâà íàëåâî

	* èçìåíåíî: Mode step òåïåü ñëåäóåò óêàçûâàòü â 10 àç áîëüøå äëÿ òîãî æå åçóëüòàòà, 1òî ñäåëàíî äëÿ áîëüøåé òî÷íîñòè íà íåáîëüøèõ äèàïàçîíàõ

	* èçìåíåíî: VP: äàííûå ïîñëåäíåãî áàà òåïåü ó÷èòûâà_òñÿ

	* èçìåíåíî: VP-Range: â åæèìàõ îòîáàæåíèÿ îò ãàíèö îêíà è ãàíèö äèàïàçîíà íàóæó øèèíà ãèñòîãàììû óâåëè÷åíà ñ 10% äî 15% îò àçìåîâ ãàôèêà, â îñòàëüíûõ ñëó÷àÿõ (âíóòè ãàíèö äèàïàçîíà) øèèíà àâíà øèèíå äèàïàçîíà



3.2

	* èñïàâëåíî: ïè îòêûòèè íà ãàôèêå áåç èñòîèè ïîÿâëÿåòñÿ îøèáêà "...array out of range in..."

	* èçìåíåíî: ëèíèÿ ãîèçîíòà ñïÿòàíà èç ñïèñêà îáúåêòîâ è îòêë_÷åíà äëÿ âûáîà



3.1

	* èñïàâëåíî: ïè îáíîâëåíèè ïî ïîñëåäíèì äàííûì ìîãóò îñòàâàòüñÿ ñòàûå ìîäû è ìàêñèìóìû

	* äîáàâëåíî: TPO-Range òåïåü îáíîâëÿåòñÿ ñàçó ïîñëå ïååìåùåíèÿ ãàíèö â ñîîòâåòñòâóùèõ åæèìàõ



3.0

	* ñêûòû íåäîêóìåíòèîâàííûå ïààìåòû DataPeriod è PriceStep (áûëè ïîêàçàíû ïî îøèáêå)

	* èñïîëüçîâàíèå íîâûõ âîçìîæíîñòåé MetaTrader 4 è îïòèìèçàöèÿ ïîä íåãî:

		* óëó÷øåíû îòîáàæàåìûå íàçâàíèÿ ïààìåòîâ

		* ïåå÷èñëÿåìûå ïààìåòû (åæèìû, ñòèëè, ïåèîäû) åàëèçîâàíû â âèäå ñïèñêîâ âûáîà, èõ ÷èñëîâûå çíà÷åíèÿ îñòàëèñü ïåæíèìè

		* ëèíèè ãèñòîãàìì íåëüçÿ âûáàòü ìûøêîé (íå ìåøà_òñÿ ñåäè äóãèõ èíäèêàòîîâ è àçìåòêè)

		* îïòèìèçàöèÿ ïîñëå èçìåíåíèé â àáîòå ôóíêöèè ArrayCopyRates()

		* ïîääåæêà åàëüíûõ îáúåìîâ, åñëè îíè äîñòóïíû

	* èñïàâëåí ïààìåò ModeStep, òåïåü îí ëó÷øå åàãèóåò íà èçìåíåíèÿ

	* óäàëåíèå çà ñîáîé ëèíèé äèàïàçîíà â TPO-Range, â îäíîì èç ïåäûäóùèõ îáíîâëåíèé MetaTrader èñïàâëåíà îøèáêà, ìåøà_ùàÿ äåëàòü 1òî

	* óäàëåíà ñêûòàÿ ïîääåæêà íåñêîëüêèõ ìåòîäîâ èìèòàöèè òèêîâ, îñòàâëåí òîëüêî íàèáîëåå òî÷íûé

	* â åæèìå 1 (Last minutes) TPO-Range ëèíèè âûáîà/îòîáàæåíèÿ äèàïàçîíà áîëüøå íå ïîêàçûâà_òñÿ



2.6

	* ñîâìåñòèìîñòü ñ MetaTrader âåñèè 4.00 Build 600 è íîâåå



2.5.7491

	* â íåêîòîûõ åæèìàõ â ñòèëå ïî óìîë÷àíè_ (HGStyle=1) ïè ñæàòèè ãàôèêà ïî âåòèêàëè èñ÷åçàåò èçîáàæåíèå ëîêàëüíûõ ìàêñèìóìîâ

	* óäàëåíî èç-çà îøèáêè â ÌÒ: TPO-Range - ïè óäàëåíèè èíäèêàòîà óäàëÿ_òñÿ è ëèíèè ãàíèö (áûëî äîáàâëåíî â 2.4.7290)



2.5.7484

	* â ñòèëå ïî óìîë÷àíè_ (HGStyle=1) ïè ñæàòèè ãàôèêà ïî âåòèêàëè èñ÷åçàåò èçîáàæåíèå ëîêàëüíûõ ìàêñèìóìîâ



2.5.7473

	* íàçâàíèÿ èíäèêàòîîâ èçìåíåíû â ñîîòâåòñòâèè ñ àñïîñòàí¸ííûì íàçâàíèåì ìåòîäèêè àñ÷¸òà, ñõîæåé ñ äàííîé

	* äîáàâëåí ïààìåò HGStyle: 0 - èñîâàòü ëèíèÿìè, 1 - èñîâàòü ïóñòûìè ïÿìîóãîëüíèêàìè (çíà÷åíèå ïî óìîë÷àíè_), 2 - îáû÷íûå ïÿìîóãîëüíèêè (åæèì ïîëåçåí ïè íàëîæåíèè íåñêîëüêèõ èíäèêàòîîâ TPO äóã íà äóãà)



2.4.7290

	* èñïàâëåíî: íå óäàëÿ_òñÿ ñòàûå ìîäû ïè èñïîëüçîâàíèè íà ìåíÿ_ùèõñÿ äàííûõ

	* èç íàáîà èñêë_÷¸í ñêèïò +FindVL

	* èñïàâëåíî: ïè âêë_÷åííîé ìàêñèìàëüíîé ìîäå è îòêë_÷åííûõ îñòàëüíûõ ïîêàçûâà_òñÿ âñå

	* +VL - ïè óäàëåíèè èíäèêàòîà óäàëÿ_òñÿ è ëèíèè ãàíèö



2.3.6704

	* ïîëíîñòü_ óáàí åæèì àáîòû ÷ååç vlib2.dll

	* èñïàâëåíî: ïè îòêë_÷åííûõ ìîäàõ, íî âêë_÷åííîé ìàêñèìàëüíîé, ìàêñèìàëüíàÿ íå èñîâàëàñü

	* +MP - ïîêàç ìàêñèìàëüíîé ìîäû ïî óìîë÷àíè_ îòêë_÷åí

	* èñïàâëåíî: +VL - ïè îòêë_÷åííûõ ìîäàõ, íî âêë_÷åííûõ óîâíÿõ, óîâíè íå èñîâàëèñü



2.2.6294

	* åæèì àáîòû áåç vlib2.dll

	* óáàíû ëèøíèå ìåòîäû ïîèñêà ìîä

	* ïààìåò Smooth ïååèìåíîâàí â ModeStep

	* êîä èç +mpvl.mqh ïååíåñåí â îñíîâíûå ôàéëû (óïîùåíèå óñòàíîâêè è àñïîñòàíåíèÿ)



2.1

	* èñïàâëåíî: îøèáêà â àñ÷åòàõ

	* óáàíû ëèøíèå ìåòîäû àñ÷åòà (ñêûòûé ïààìåò TickMethod)

	* èñïàâëåíî: àâòîîïåäåëåíèå ìàñøòàáà Smooth ïè àáîòå íà ïÿòèçíàêå

	* äîáàâëåíû îïöèè â ñêèïòå +FindVL



2.0

	* ñóùåñòâåííî óâåëè÷åíà ñêîîñòü àáîòû

	* îïòèìèçèîâàí íàáî ïààìåòîâ



1-18 (1.1-1.18)

	* òåñòîâûå âåñèè, àçëè÷à_ùèåñÿ ïî ôóíêöèîíàëó è ïààìåòàì



*/



/*



Copyright (c) FXcoder. All rights reserved.



àçåøàåòñÿ ïîâòîíîå àñïîñòàíåíèå è èñïîëüçîâàíèå êàê â âèäå èñõîäíîãî êîäà, òàê è â äâîè÷íîé ôîìå, ñ èçìåíåíèÿìè

èëè áåç, ïè ñîáë_äåíèè ñëåäó_ùèõ óñëîâèé:



    * Ïè ïîâòîíîì àñïîñòàíåíèè èñõîäíîãî êîäà äîëæíî îñòàâàòüñÿ óêàçàííîå âûøå óâåäîìëåíèå îá àâòîñêîì ïàâå,

      1òîò ñïèñîê óñëîâèé è ïîñëåäó_ùèé îòêàç îò ãààíòèé.



    * Ïè ïîâòîíîì àñïîñòàíåíèè äâîè÷íîãî êîäà äîëæíà ñîõàíÿòüñÿ óêàçàííàÿ âûøå èíôîìàöèÿ îá àâòîñêîì ïàâå, 1òîò

      ñïèñîê óñëîâèé è ïîñëåäó_ùèé îòêàç îò ãààíòèé â äîêóìåíòàöèè è/èëè â äóãèõ ìàòåèàëàõ, ïîñòàâëÿåìûõ ïè

      àñïîñòàíåíèè.



    * Íè íàçâàíèå FXcoder, íè èìåíà åå ñîòóäíèêîâ íå ìîãóò áûòü èñïîëüçîâàíû â êà÷åñòâå ïîääåæêè èëè ïîäâèæåíèÿ

      ïîäóêòîâ, îñíîâàííûõ íà 1òîì ÏÎ áåç ïåäâàèòåëüíîãî ïèñüìåííîãî àçåøåíèÿ.



0òà ïîãàììà ïåäîñòàâëåíà âëàäåëüöàìè àâòîñêèõ ïàâ è/èëè äóãèìè ñòîîíàìè «êàê îíà åñòü» áåç êàêîãî-ëèáî âèäà

ãààíòèé, âûàæåííûõ ÿâíî èëè ïîäàçóìåâàåìûõ, âêë_÷àÿ, íî íå îãàíè÷èâàÿñü èìè, ïîäàçóìåâàåìûå ãààíòèè êîììå÷åñêîé

öåííîñòè è ïèãîäíîñòè äëÿ êîíêåòíîé öåëè. Íè â êîåì ñëó÷àå íè îäèí âëàäåëåö àâòîñêèõ ïàâ è íè îäíî äóãîå ëèöî,

êîòîîå ìîæåò èçìåíÿòü è/èëè ïîâòîíî àñïîñòàíÿòü ïîãàììó, êàê áûëî ñêàçàíî âûøå, íå íåñ¸ò îòâåòñòâåííîñòè, âêë_÷àÿ

ë_áûå îáùèå, ñëó÷àéíûå, ñïåöèàëüíûå èëè ïîñëåäîâàâøèå óáûòêè, âñëåäñòâèå èñïîëüçîâàíèÿ èëè íåâîçìîæíîñòè èñïîëüçîâàíèÿ

ïîãàììû (âêë_÷àÿ, íî íå îãàíè÷èâàÿñü ïîòååé äàííûõ, èëè äàííûìè, ñòàâøèìè íåïàâèëüíûìè, èëè ïîòåÿìè ïèíåñåííûìè

èç-çà âàñ èëè òåòüèõ ëèö, èëè îòêàçîì ïîãàììû àáîòàòü ñîâìåñòíî ñ äóãèìè ïîãàììàìè), äàæå åñëè òàêîé âëàäåëåö èëè

äóãîå ëèöî áûëè èçâåùåíû î âîçìîæíîñòè òàêèõ óáûòêîâ.



Redistribution and use in source and binary forms, with or without modification, are permitted provided that the

following conditions are met:



    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following

      disclaimer.



    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the

      following disclaimer in the documentation and/or other materials provided with the distribution.



    * Neither the name of the FXcoder nor the names of its contributors may be used to endorse or promote products

      derived from this software without specific prior written permission.



This software is provided by the copyright holders and contributors "as is" and any express or implied warranties,

including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are

disclaimed. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental,

special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or

services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability,

whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of

this software, even if advised of the possibility of such damage.



*/



// 2016-04-18 18:51:26 UTC. MQLMake 1.42. © FXcoder

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 ---