//+------------------------------------------------------------------+ //| AMkA.mq4 | //| Copyright © 2006, D&S kiriyenko. | //| http://groups.google.com/group/expert-developing | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, D&S Kiriyenko." #property link "http://groups.google.com/group/expert-developing" //---- #property indicator_chart_window #property indicator_buffers 3 #property indicator_color1 Green #property indicator_width1 1 #property indicator_color2 Red #property indicator_width2 2 #property indicator_color3 Blue #property indicator_width3 2 //+------------------------------------------------------------------+ //| макроопределения | //+------------------------------------------------------------------+ //---- строковые константы #define INDICATOR_SHORT_NAME "AMkA" #define MAIN "AMkA line" #define UP "UpTrend point" #define DOWN "DownTrend point" //+------------------------------------------------------------------+ //| внешние переменные | //+------------------------------------------------------------------+ //---- периоды extern int periodAMA = 9; //период расчёта к-та эффективности extern double nfast = 2; //период EMA для эффективного рынка extern double nslow = 30; //период EMA для неэффективного рынка //---- расчёт сглаживающей константы extern double Pow = 2.0; //степень эффективности //---- фильтр сигналов extern double dK = 1.0; //коэффициент для фильтра extern bool use_stdev = true; //использовать стандартное отклонение //---- применять к цене extern int app_price = 5; //по умолчанию - к типической //+------------------------------------------------------------------+ //| глобальные переменные | //+------------------------------------------------------------------+ //---- буферы double kAMAbuffer[]; double kAMAupsig[]; double kAMAdownsig[]; //---- сглаживающие коэффициенты double slowSC, fastSC; //---- приращения индикатора double ddAMA[]; //+------------------------------------------------------------------+ //| Вставка значения в массив приращений | //+------------------------------------------------------------------+ bool InsertDif(double a) { //---- проверка, заполнен ли массив for(int i = 0; i < periodAMA; i++) //для всех элементов массива if(ddAMA[i] == 0) //если элемент равен нулю { ddAMA[i] = a; //сохраняем значение в этот элемент return (true); //и удачно завершаемся } //---- массив уже заполнен, нужно вставлять элемент с конца for(i = 0; i < periodAMA-1; i++) //все элементы массива, кроме последнего ddAMA[i] = ddAMA[i+1]; //сдвигаем влево на одну позицию ddAMA[periodAMA-1] = a; //и записываем значение в самую правую позицию return (true); //после чего удачно завершаемся } //+------------------------------------------------------------------+ //| Запрос цены бара | //+------------------------------------------------------------------+ double Price(int i, int app = PRICE_TYPICAL) { switch(app) { case PRICE_CLOSE: return(Close[i]); break; case PRICE_OPEN: return(Open[i]); break; case PRICE_HIGH: return(High[i]); break; case PRICE_LOW: return(Low[i]); break; case PRICE_MEDIAN: return((High[i] + Low[i])/2); break; case PRICE_TYPICAL: return((High[i] + Low[i] + Close[i])/3); break; case PRICE_WEIGHTED: return((High[i] + Low[i] + Close[i]*2)/4); break; } } //+------------------------------------------------------------------+ //| Инициализация | //+------------------------------------------------------------------+ int init() { //---- главная линия SetIndexBuffer(0, kAMAbuffer); SetIndexStyle(0, DRAW_LINE, 0, 2); SetIndexLabel(0, MAIN); SetIndexEmptyValue(0, 0.0); //---- подтверждение восходящего тренда SetIndexBuffer(1, kAMAupsig); SetIndexStyle(1, DRAW_ARROW); SetIndexArrow(1, 159); SetIndexLabel(1, UP); SetIndexEmptyValue(1, 0.0); //---- подтверждение нисходящего тренда SetIndexBuffer(2, kAMAdownsig); SetIndexStyle(2, DRAW_ARROW); SetIndexArrow(2, 159); SetIndexLabel(2, DOWN); SetIndexEmptyValue(2, 0.0); //---- настройки индикатора IndicatorDigits(4); string name = StringConcatenate(INDICATOR_SHORT_NAME, " (", periodAMA, "/", nfast, "/", nslow, ")"); IndicatorShortName(name); //---- расчёт к-тов slowSC = (2.0 / (nslow + 1)); //медленный к-т сглаживания fastSC = (2.0 / (nfast + 1)); //быстрый к-т сглаживания //---- подготовка массива ArrayResize(ddAMA, periodAMA); ArrayInitialize(ddAMA, 0.); //---- готово return(0); } //+------------------------------------------------------------------+ //| Деинициализация | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| Итерационная функция | //+------------------------------------------------------------------+ int start() { //---- оптимизация производительности if(Bars <= periodAMA + 2) return (0); //если баров на графике слишком мало, выходим //---- оптимизация кода индикатора int counted_bars = IndicatorCounted(); //число баров, не изменённых с последнего вызова if(counted_bars < 0) return (0); //защищаемся от ошибок else if(counted_bars > 0) counted_bars--; //последний посчитанный бар будет пересчитан int pos = Bars - periodAMA - 2; //позицию в начало отсчёта if(counted_bars > 0) pos = Bars - counted_bars; //или определяем позицию //---- подготовка переменных double AMA0 = Price(pos+1, app_price); //предыдущее АМА не расчитывалось if(kAMAbuffer[pos+1] > 0) AMA0 = kAMAbuffer[pos+1]; //или расчитывалось if(AMA0 == 0) Print(Bars - pos); //---- расчёт индикатора while(pos >= 0) { //---- расчёт сигнала double signal = MathAbs(Price(pos, app_price) - Price(pos + periodAMA, app_price)); //---- расчёт шума double noise = 0.000000001; for(int i = 0; i < periodAMA; i++) { noise = noise + MathAbs(Price(pos+i, app_price) - Price(pos + i + 1, app_price)); } //---- расчёт коэффициента сглаживания double ER = signal / noise; //коэффициент эффективности double SSC = ER*(fastSC - slowSC) + slowSC; //коэффициент сглаживания //---- расчёт главной линии double AMA = AMA0 + (MathPow(SSC, Pow)*(Price(pos, app_price) - AMA0)); //расчёт AMA = NormalizeDouble(AMA, Digits); kAMAbuffer[pos] = AMA; //вывод //---- расчёт фильтрации тренда double ddK = (AMA - AMA0) / Point; //разность if(use_stdev) { InsertDif(ddK); //накапливаем приращение if(pos < Bars - 2*(periodAMA + 2)) //если баров накопилось достаточно { //---- расчёт среднего арифметического double SMAdif = 0; //вначале равно нулю for(i = 0; i < periodAMA; i++) { SMAdif += ddAMA[i]; //последовательно суммируем } SMAdif /= periodAMA; //и делим на количество //---- расчёт стандартного отклонения double StDev = 0; //вначале равно нулю for(i = 0; i < periodAMA; i++) { StDev += MathPow(ddAMA[i] - SMAdif, 2); //суммируем квадраты отклонений } StDev = MathSqrt(StDev)/periodAMA; //извлекаем корень и делим на количество //---- расчёт фильтра double Filter = dK*StDev; } else Filter = 100000; } else Filter = dK; //---- обработка значений double var1 = 0, var2 = 0; if(ddK > Filter) var1 = AMA; //есть восходящий тренд if(ddK < -Filter) var2 = AMA; //есть нисходящий тренд kAMAupsig[pos] = var1; //нет восходящего тренда kAMAdownsig[pos] = var2; // нет нисходящего тренда //---- переход к концу цикла AMA0 = AMA; //сохраняем предыдущее значение AMA pos--; //переходим к сдедующему бару } //---- завершение работы return(0); //готово } //+------------------------------------------------------------------+