#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 #property indicator_buffers 1 #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 int minVariation = 2; // Min Variation Vol 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 double volPrices[]; double volumes[]; double lowPrice; int _ratesTotal; void OnInit() { SetIndexBuffer(0, volPrices, INDICATOR_DATA); _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[]) { _ratesTotal = ratesTotal; if (UpdateAutoColors()) { // ïðè îáíîâëåíèè öâåòà ôîíà îáíîâëÿòü ñðà çó, ñáðîñèâ ïðèçíà ê ïîñëåäíåãî óñïåøíîãî âûïîëíåíèÿ _lastOK = false; CheckTimer(); } else if (_updateOnTick) { // îáíîâëÿòü íà êà æäîì òèêå, åñëè âûñòà âëåí òà êîé ïðèçíà ê ïðè à íà ëèçå ïðà âîé ãðà íèöû CheckTimer(); } fill_data(); return(ratesTotal); } 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)) { // åñëè ãðà íèöû äèà ïà çîíà íå çà äà íû, óñòà íîâèòü èõ çà íîâî â âèäèìóþ ÷à ñòü ýêðà íà 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) { // åñëè ëèíèè íåò, óñòà íîâèòü åãî â âèäèìóþ ÷à ñòü ýêðà íà int leftBar = WindowFirstVisibleBar(); int rightBar = WindowFirstVisibleBar() - WindowBarsPerChart(); int barRange = leftBar - rightBar; bar = MathMax(0, leftBar - barRange / 3); timeTo = GetBarTime(bar); } else { bar = _iBarShift(_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[]; 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); } void fill_data() { for(int i=0;i<_ratesTotal;i++) volPrices[i] = 0; volPrices[_ratesTotal-1] = lowPrice; volPrices[_ratesTotal-2] = lowPrice + ArraySize(volumes) * _hgPoint; // bot from top (bot volume) for(int i=0;i minVariation) { //ObjectSetDouble(0,"botVol",OBJPROP_PRICE,lowPrice + i * _hgPoint); volPrices[_ratesTotal-3] = lowPrice + i * _hgPoint; // low price break; } } // top from bop (top volume) for(int i=ArraySize(volumes)-1;i>=0;i--) { if(volumes[i] > minVariation) { //ObjectSetDouble(0,"topVol",OBJPROP_PRICE,lowPrice + i * _hgPoint); volPrices[_ratesTotal-4] = lowPrice + i * _hgPoint; // high price break; } } if(volPrices[_ratesTotal-3] > volPrices[_ratesTotal-4]) { double aux = volPrices[_ratesTotal-3]; volPrices[_ratesTotal-3] = volPrices[_ratesTotal-4]; volPrices[_ratesTotal-4] = aux; } } datetime GetObjectTime1(const string name) { datetime time; if (!ObjectGetInteger(0, name, OBJPROP_TIME, 0, time)) return(0); return(time); } template 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 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) { // åñëè ýëåìåíòîâ íåäîñòà òî÷íî äëÿ óêà çà ííîãî êîëè÷åñòâà , âåðíóòü ìà êñèìà ëüíî âîçìîæíîå 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 void Swap(T &value1, T &value2) { T tmp = value1; value1 = value2; value2 = tmp; } template 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 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 _iBarShift(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 _iTime(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)(_iTime(_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 = _iBarShift(_Symbol, period, time); datetime t = _iTime(_Symbol, period, bar); if ((t != time) && (bar == 0)) { // âðåìÿ çà ïðåäåëà ìè äèà ïà çîíà bar = (int)((_iTime(_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(_iTime(_Symbol, period, shift)); else return(_iTime(_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 ðà ç áîëüøå äëÿ òîãî æå ðåçóëüòà òà , ýòî ñäåëà íî äëÿ áîëüøåé òî÷íîñòè íà íåáîëüøèõ äèà ïà çîíà õ * èçìåíåíî: 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 (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. Ðà çðåøà åòñÿ ïîâòîðíîå ðà ñïðîñòðà íåíèå è èñïîëüçîâà íèå êà ê â âèäå èñõîäíîãî êîäà , òà ê è â äâîè÷íîé ôîðìå, ñ èçìåíåíèÿìè èëè áåç, ïðè ñîáëþäåíèè ñëåäóþùèõ óñëîâèé: * Ïðè ïîâòîðíîì ðà ñïðîñòðà íåíèè èñõîäíîãî êîäà äîëæíî îñòà âà òüñÿ óêà çà ííîå âûøå óâåäîìëåíèå îá à âòîðñêîì ïðà âå, ýòîò ñïèñîê óñëîâèé è ïîñëåäóþùèé îòêà ç îò ãà ðà íòèé. * Ïðè ïîâòîðíîì ðà ñïðîñòðà íåíèè äâîè÷íîãî êîäà äîëæíà ñîõðà íÿòüñÿ óêà çà ííà ÿ âûøå èíôîðìà öèÿ îá à âòîðñêîì ïðà âå, ýòîò ñïèñîê óñëîâèé è ïîñëåäóþùèé îòêà ç îò ãà ðà íòèé â äîêóìåíòà öèè è/èëè â äðóãèõ ìà òåðèà ëà õ, ïîñòà âëÿåìûõ ïðè ðà ñïðîñòðà íåíèè. * Íè íà çâà íèå FXcoder, íè èìåíà åå ñîòðóäíèêîâ íå ìîãóò áûòü èñïîëüçîâà íû â êà ÷åñòâå ïîääåðæêè èëè ïðîäâèæåíèÿ ïðîäóêòîâ, îñíîâà ííûõ íà ýòîì ÏÎ áåç ïðåäâà ðèòåëüíîãî ïèñüìåííîãî ðà çðåøåíèÿ. Ýòà ïðîãðà ììà ïðåäîñòà âëåíà âëà äåëüöà ìè à âòîðñêèõ ïðà â è/èëè äðóãèìè ñòîðîíà ìè «êà ê îíà åñòü» áåç êà êîãî-ëèáî âèäà ãà ðà íòèé, âûðà æåííûõ ÿâíî èëè ïîäðà çóìåâà åìûõ, âêëþ÷à ÿ, íî íå îãðà íè÷èâà ÿñü èìè, ïîäðà çóìåâà åìûå ãà ðà íòèè êîììåð÷åñêîé öåííîñòè è ïðèãîäíîñòè äëÿ êîíêðåòíîé öåëè. Íè â êîåì ñëó÷à å íè îäèí âëà äåëåö à âòîðñêèõ ïðà â è íè îäíî äðóãîå ëèöî, êîòîðîå ìîæåò èçìåíÿòü è/èëè ïîâòîðíî ðà ñïðîñòðà íÿòü ïðîãðà ììó, êà ê áûëî ñêà çà íî âûøå, íå íåñ¸ò îòâåòñòâåííîñòè, âêëþ÷à ÿ ëþáûå îáùèå, ñëó÷à éíûå, ñïåöèà ëüíûå èëè ïîñëåäîâà âøèå óáûòêè, âñëåäñòâèå èñïîëüçîâà íèÿ èëè íåâîçìîæíîñòè èñïîëüçîâà íèÿ ïðîãðà ììû (âêëþ÷à ÿ, íî íå îãðà íè÷èâà ÿñü ïîòåðåé äà ííûõ, èëè äà ííûìè, ñòà âøèìè íåïðà âèëüíûìè, èëè ïîòåðÿìè ïðèíåñåííûìè èç-çà âà ñ èëè òðåòüèõ ëèö, èëè îòêà çîì ïðîãðà ììû ðà áîòà òü ñîâìåñòíî ñ äðóãèìè ïðîãðà ììà ìè), äà æå åñëè òà êîé âëà äåëåö èëè äðóãîå ëèöî áûëè èçâåùåíû î âîçìîæíîñòè òà êèõ óáûòêîâ. 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