#property copyright "Стандартная оценка. StdScore.mq4 4.0. Copyright © FXcoder, 2009-2014" #property link "http://fxcoder.net" #property strict #property indicator_separate_window #property indicator_buffers 11 // The first buffer is for the value, other 10 are for candle drawing #property indicator_color1 clrRoyalBlue // Value #property indicator_color2 clrLimeGreen // BullBody #property indicator_color3 clrLimeGreen // BullBody2 #property indicator_color4 clrRed // BearBody #property indicator_color5 clrRed // BearBody2 #property indicator_color6 clrNONE // BodyMask #property indicator_color7 clrLimeGreen // BullShadow #property indicator_color8 clrLimeGreen // BullShadow2 #property indicator_color9 clrRed // BearShadow #property indicator_color10 clrRed // BearShadow2 #property indicator_color11 clrNONE // ShadowMask #property indicator_width1 1 #property indicator_levelcolor Gray #property indicator_levelstyle STYLE_DOT #property indicator_level1 2 #property indicator_level2 0 #property indicator_level3 -2 #property indicator_minimum -4 #property indicator_maximum 4 enum ENUM_CHART_TYPE { CHART_TYPE_LINE = 0, // Line CHART_TYPE_BAR = 1, // Bar CHART_TYPE_CANDLESTICK = 2 // Candlestick }; // Период расчета input int N = 20; // Period // Инструмент input string Sym = ""; // Symbol // Реверс input bool Reverse = false; // Reverse // Тип цены для расчета input ENUM_APPLIED_PRICE AppliedPrice = PRICE_MEDIAN; // Applied price // Тип цены значения input ENUM_APPLIED_PRICE ValuePrice = PRICE_CLOSE; // Value and line price // Метод отображения: 0 - линия, 1 - бары, 2 - свечи input ENUM_CHART_TYPE ChartType = CHART_TYPE_CANDLESTICK; // Chart type // Цвет бычьей свечи input color BullColor = clrRoyalBlue; // Bull color // Цвет медвежьей свечи input color BearColor = clrCrimson; // Bear color // Цвет фона, CLR_NONE - автоопределение input color BackColor = clrNONE; // Background color (None=auto) // Толщина тела свечи input int BodyWidth = 0; // Body width (0=auto) // Ограничение количества баров для расчета и отбражения input int MaxBars = 0; // Maximum bars // Сдвиг вправо input int Shift = 0; // Shift input int Smooth = 0; // super smoother period double Value[], BullBody[], BullBody2[], BearBody[], BearBody2[], BodyMask[], BullShadow[], BullShadow2[], BearShadow[], BearShadow2[], ShadowMask[]; datetime _lastTickTime = 0; int _bodyWidth = 2; color _bgColor; string _sym; int _n; int start() { updateBodyWidth(); updateMaskColor(); int countedBars = IndicatorCounted(); if (countedBars > 0) countedBars--; int barsCount = Bars - countedBars; if (MaxBars > 0) { if (Bars - countedBars > 2) { barsCount = MaxBars; clearData(); } else { clearData(MaxBars); barsCount = MathMin(barsCount, MaxBars); } } // в мультивалютном пересчитываем несколько последних баров, а не один if (_lastTickTime != 0 && _sym != Symbol()) barsCount = MathMax(barsCount, iBarShift(Symbol(), Period(), _lastTickTime, false) + 1); double o, h, l, c, value, ma, sd; for (int i = barsCount - 1; i >= 0; i--) { clearData(i); o = EMPTY_VALUE; h = EMPTY_VALUE; l = EMPTY_VALUE; c = EMPTY_VALUE; value = EMPTY_VALUE; ma = EMPTY_VALUE; sd = 0; int si = i; if (_sym == Symbol()) { o = Open[i]; h = High[i]; l = Low[i]; c = Close[i]; } else { // определить бар для другого символа datetime dt = iTime(Symbol(), Period(), i); si = iBarShift(_sym, Period(), dt, true); if (si != -1) { // бар тот же o = iOpen(_sym, Period(), si); h = iHigh(_sym, Period(), si); l = iLow(_sym, Period(), si); c = iClose(_sym, Period(), si); _lastTickTime = dt; // запоминаем время последнего тика } else { // в случае отсутствия данных по символу брать прошлый бар и его цену закрытия si = iBarShift(_sym, Period(), dt, false); if (si != -1) { // защита от подглядывания в будущее datetime sdt = iTime(_sym, Period(), si); if (sdt > dt) si++; o = iClose(_sym, Period(), si); h = o; l = o; c = o; } } } if (c != EMPTY_VALUE) { // Вычитание средней ma = iMA(_sym, Period(), _n, 0, MODE_SMA, AppliedPrice, si); if (ma > 0) { o = o - ma; h = h - ma; l = l - ma; c = c - ma; value = getPrice(ValuePrice, o, h, l, c); // Деление на стандартное отклонение sd = iStdDev(_sym, Period(), _n, 0, MODE_SMA, AppliedPrice, si); if (sd > 0) { o = o / sd; h = h / sd; l = l / sd; c = c / sd; value = getPrice(ValuePrice, o, h, l, c); if (Reverse) { o = -o; h = -h; l = -l; c = -c; // меняем местами верх и низ для корректной отрисовки swap(h, l); value = getPrice(ValuePrice, o, h, l, c); } } // sd > 0 } // ma > 0 } // c != EMPTY_VALUE Value[i] = iSsm(value,Smooth,i); if (ChartType != CHART_TYPE_LINE) drawBar(o, h, l, c, i); } // for: bars loop return(0); } int init() { _n = N >= 2 ? N : 2; _sym = Sym == "" ? Symbol() : UpperString(Sym); _bodyWidth = BodyWidth; if (ChartType == CHART_TYPE_LINE) { SetIndexStyle(0, DRAW_LINE, EMPTY, EMPTY, BullColor); SetIndexStyle(1, DRAW_NONE); SetIndexStyle(2, DRAW_NONE); SetIndexStyle(3, DRAW_NONE); SetIndexStyle(4, DRAW_NONE); SetIndexStyle(5, DRAW_NONE); SetIndexStyle(6, DRAW_NONE); SetIndexStyle(7, DRAW_NONE); SetIndexStyle(8, DRAW_NONE); SetIndexStyle(9, DRAW_NONE); SetIndexStyle(10, DRAW_NONE); } else { SetIndexStyle(0, DRAW_NONE, EMPTY, EMPTY, clrNONE); SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, _bodyWidth, BullColor); SetIndexStyle(2, DRAW_HISTOGRAM, EMPTY, _bodyWidth, BullColor); SetIndexStyle(3, DRAW_HISTOGRAM, EMPTY, _bodyWidth, BearColor); SetIndexStyle(4, DRAW_HISTOGRAM, EMPTY, _bodyWidth, BearColor); SetIndexStyle(5, DRAW_HISTOGRAM, EMPTY, _bodyWidth, _bgColor); SetIndexStyle(6, DRAW_HISTOGRAM, EMPTY, 1, BullColor); SetIndexStyle(7, DRAW_HISTOGRAM, EMPTY, 1, BullColor); SetIndexStyle(8, DRAW_HISTOGRAM, EMPTY, 1, BearColor); SetIndexStyle(9, DRAW_HISTOGRAM, EMPTY, 1, BearColor); SetIndexStyle(10, DRAW_HISTOGRAM, EMPTY, 1, _bgColor); } SetIndexBuffer(0, Value); SetIndexBuffer(1, BullBody); SetIndexBuffer(2, BullBody2); SetIndexBuffer(3, BearBody); SetIndexBuffer(4, BearBody2); SetIndexBuffer(5, BodyMask); SetIndexBuffer(6, BullShadow); SetIndexBuffer(7, BullShadow2); SetIndexBuffer(8, BearShadow); SetIndexBuffer(9, BearShadow2); SetIndexBuffer(10, ShadowMask); for (int i = 0; i <= 10; i++) SetIndexShift(i, Shift); SetIndexLabel(0, "Value"); SetIndexLabel(1, "Bull Body"); SetIndexLabel(2, "Bull Body 2"); SetIndexLabel(3, "Bear Body"); SetIndexLabel(4, "Bear Body 2"); SetIndexLabel(5, "Body Mask"); SetIndexLabel(6, "Bull Shadow"); SetIndexLabel(7, "Bull Shadow 2"); SetIndexLabel(8, "Bear Shadow"); SetIndexLabel(9, "Bear Shadow 2"); SetIndexLabel(10, "Shadow Mask"); string name = "StdScore(" + (Reverse || _sym != Symbol() ? (Reverse ? "1/" : "") + _sym + "," : "") + IntegerToString(_n) + ")"; IndicatorShortName(name); return(0); } void updateMaskColor() { // Определить цвета фона color bgColor = ColorIsNone(BackColor) ? GetBGColor() : BackColor; // Если цвет фона определен, переопределить цвет масок if (ColorIsNone(bgColor)) return; SetIndexStyle(5, DRAW_HISTOGRAM, EMPTY, EMPTY, bgColor); SetIndexStyle(10, DRAW_HISTOGRAM, EMPTY, EMPTY, bgColor); } void updateBodyWidth() { if (BodyWidth > 0) return; // Определить толщину тела бара int newBodyWidth = barStepToBodyWidth(GetBarStep()); if (newBodyWidth == _bodyWidth) return; _bodyWidth = newBodyWidth; if (ChartType == CHART_TYPE_BAR) { for (int i = 6; i <= 10; i++) SetIndexStyle(i, DRAW_HISTOGRAM, EMPTY, _bodyWidth); } else { for (int i = 1; i <= 5; i++) SetIndexStyle(i, DRAW_HISTOGRAM, EMPTY, _bodyWidth); } } void swap(double& a, double& b) { double c = b; b = a; a = c; } void clearData(int bar = -1) { if (bar == -1) { ArrayInitialize(Value, EMPTY_VALUE); ArrayInitialize(BullBody, EMPTY_VALUE); ArrayInitialize(BullBody2, EMPTY_VALUE); ArrayInitialize(BearBody, EMPTY_VALUE); ArrayInitialize(BearBody2, EMPTY_VALUE); ArrayInitialize(BodyMask, EMPTY_VALUE); ArrayInitialize(BullShadow, EMPTY_VALUE); ArrayInitialize(BullShadow2, EMPTY_VALUE); ArrayInitialize(BearShadow, EMPTY_VALUE); ArrayInitialize(BearShadow2, EMPTY_VALUE); ArrayInitialize(ShadowMask, EMPTY_VALUE); } else { Value[bar] = EMPTY_VALUE; BullBody[bar] = EMPTY_VALUE; BullBody2[bar] = EMPTY_VALUE; BearBody[bar] = EMPTY_VALUE; BearBody2[bar] = EMPTY_VALUE; BodyMask[bar] = EMPTY_VALUE; BullShadow[bar] = EMPTY_VALUE; BullShadow2[bar] = EMPTY_VALUE; BearShadow[bar] = EMPTY_VALUE; BearShadow2[bar] = EMPTY_VALUE; ShadowMask[bar] = EMPTY_VALUE; } } double getPrice(int ap, double o, double h, double l, double c) { switch(ap) { case PRICE_CLOSE: return(c); case PRICE_OPEN: return(o); case PRICE_HIGH: return(h); case PRICE_LOW: return(l); case PRICE_MEDIAN: return((h + l) / 2.0); case PRICE_TYPICAL: return((h + l + c) / 3.0); case PRICE_WEIGHTED: return((h + l + 2.0 * c) / 4.0); } return(0); } // Нарисовать бар void drawBar(double open, double high, double low, double close, int bar) { bool isBull = close >= open; bool isBear = !isBull; double bodyMax = open > close ? open : close; double bodyMin = open < close ? open : close; if (ChartType == CHART_TYPE_CANDLESTICK) { BullBody[bar] = isBull && (close >= 0) ? close : EMPTY_VALUE; BullBody2[bar] = isBull && (open < 0) ? open : EMPTY_VALUE; BearBody[bar] = isBear && (open >= 0) ? open : EMPTY_VALUE; BearBody2[bar] = isBear && (close < 0) ? close : EMPTY_VALUE; BodyMask[bar] = (bodyMin > 0) ? bodyMin : (bodyMax < 0 ? bodyMax : EMPTY_VALUE); } BullShadow[bar] = isBull && (high >= 0) ? high : EMPTY_VALUE; BullShadow2[bar] = isBull && (low < 0) ? low : EMPTY_VALUE; BearShadow[bar] = isBear && (high >= 0) ? high : EMPTY_VALUE; BearShadow2[bar] = isBear && (low < 0) ? low : EMPTY_VALUE; ShadowMask[bar] = low >= 0 ? low : (high < 0 ? high : EMPTY_VALUE); } #import "gdi32.dll" uint GetPixel(int hDC, int x, int y); #import #import "user32.dll" int GetWindowDC(int h); int ReleaseDC(int h, int hDC); bool GetWindowRect(int h, int& pos[4]); #import color GetBGColor(int h = 0) { color bgColor = CLR_NONE; if (h == 0) h = WindowHandle(Symbol(), Period()); // Получить цвет фона заданного окна if (h != 0) { int hDC = GetWindowDC(h); // Отрезок из двух точек, пересекающий рамку чарта color c1 = (color)GetPixel(hDC, 3, 10); // фон color c2 = (color)GetPixel(hDC, 4, 10); // рамка // Если рамка есть, то цвет определен верно (окно активно) if (c1 != c2) bgColor = c1; ReleaseDC(h, hDC); } return(bgColor); } bool ColorIsNone(color c) { return((c >> 24) > 0); } string UpperString(string s) { StringToUpper(s); return(s); } bool GetWindowBounds(int &left, int &top, int &right, int &bottom) { int handle = WindowHandle(Symbol(), Period()); if (handle == 0) return(false); int rect[4]; if (GetWindowRect(handle, rect)) { left = rect[0]; top = rect[1]; // "системный" прямоугольник содержит избыточные ряд и столбец, здесь это не нужно, т.к. приведет к путанице right = rect[2] - 1; bottom = rect[3] - 1; return(true); } else { return(false); } } int GetBarStep() { int left, top, right, bottom; int bw = 1; // ширина по умолчанию (не определено) if (GetWindowBounds(left, top, right, bottom)) { int width = right - left - 5 - 42; if (width != 0 && WindowBarsPerChart()!=0) { bw = (int)MathRound(1.0 * width / WindowBarsPerChart()); // коррекция (все ширины бара - степени двойки) bw = (int)MathPow(2, MathRound(MathLog(bw) / MathLog(2))); } } return(bw); } int barStepToBodyWidth(int step) { if (step < 4) return(1); if (step < 8) return(2); if (step < 16) return(3); if (step < 32) return(6); // >=32 return(12); } // 2014-09-17 21:10:11 UTC // MQLMake 1.22. Copyright © FXcoder, 2011-2014. http://fxcoder.net // // // // // #define Pi 3.14159265358979323846264338327950288 double workSsm[][2]; #define _tprice 0 #define _ssm 1 double workSsmCoeffs[][4]; #define _period 0 #define _c1 1 #define _c2 2 #define _c3 3 // // // // // double iSsm(double price, double period, int i, int instanceNo=0) { if (period<=1) return(price); i = Bars-i-1; if (ArrayRange(workSsm,0) !=Bars) ArrayResize(workSsm,Bars); if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1); if (workSsmCoeffs[instanceNo][_period] != period) { workSsmCoeffs[instanceNo][_period] = period; double a1 = MathExp(-1.414*Pi/period); double b1 = 2.0*a1*MathCos(1.414*Pi/period); workSsmCoeffs[instanceNo][_c2] = b1; workSsmCoeffs[instanceNo][_c3] = -a1*a1; workSsmCoeffs[instanceNo][_c1] = 1.0 - workSsmCoeffs[instanceNo][_c2] - workSsmCoeffs[instanceNo][_c3]; } // // // // // int s = instanceNo*2; workSsm[i][s+_tprice] = price; if ((i-2)>=0) workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_c1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + workSsmCoeffs[instanceNo][_c2]*workSsm[i-1][s+_ssm] + workSsmCoeffs[instanceNo][_c3]*workSsm[i-2][s+_ssm]; return(workSsm[i][s+_ssm]); }