Использование адаптивной скользящей средней Кауфмана

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 06 авг 2017, 17:08

Адаптивная скользящая средняя (АМА) разработана Перри Кауфманом в 1995 г. Он подробно описал её в своей работе Smarter Trading: Improving Performance in Changing Markets. Считается, что АМА существенно лучше работает чем другие скользящие средние. Оставим подробное ознакомление с АМА для других тем, а здесь же займемся вопросами использования АМА в коде.
На просторах интернета есть несколько разработанных кодов, имеющих отношение к АМА.
Прежде всего это код индикатора АМА:
Код: выделить все
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Sienna

input int     intAMAPe  = 9; // Период скользящей средней Кауфмана
input int     nfast     = 2;
input int     nslow    = 30;
input double  G      = 2.0; // Показатель степени

//---- buffers
double AMABuffer[];

int    cbars = 0, prevbars = 0;
double slowSC, fastSC;

//*********************************************************************************************

int init()
{
   SetIndexStyle(0, DRAW_LINE, 0, 2);
   SetIndexBuffer(0, AMABuffer);
   
   IndicatorDigits(4);
   
return(0);
}

//*********************************************************************************************

int start()
{
   int    pos = 0;
   double noise = 0.000000001, AMA, AMA0, signal, ER;
   double dSC, ERSC, SSC;
   
   if(prevbars == Bars) return(0);
   
//---- TODO: add your code here
   slowSC = (2.0 / (nslow + 1));
   fastSC = (2.0 / (nfast + 1));
   cbars = IndicatorCounted();
   if(Bars <= (intAMAPe + 2)) return(0);
//---- check for possible errors
   if(cbars < 0) return(-1);
//---- last counted bar will be recounted
   if(cbars > 0) cbars--;
   pos = Bars - intAMAPe - 2;
   AMA0 = Close[pos + 1];
   while(pos >= 0)
   {
      if(pos == Bars - intAMAPe - 2) AMA0 = Close[pos + 1];
      signal = MathAbs(Close[pos] - Close[pos + intAMAPe]);
      noise = 0.000000001;
      for(int i = 0; i < intAMAPe; i++)
      {
         noise = noise + MathAbs(Close[pos + i] - Close[pos + i + 1]);
      }
      ER = signal / noise; // коэффициент эффективности
      dSC = (fastSC - slowSC);
      ERSC = ER * dSC;
      SSC = ERSC + slowSC;
      AMA = AMA0 + (MathPow(SSC, G) * (Close[pos] - AMA0));
      AMABuffer[pos] = AMA;
      AMA0 = AMA;
      pos--;
   }
   prevbars = Bars;

return(0);
}

Данный индикатор рисует на графике собственно АМА. Однако, для применения в коде советника далеко не всегда удобно обращаться отдельно к файлам индикаторов и т.п., а желательно иметь реализацию в виде функции.
Есть функция разработанная Кимом (см. код далее).
Код: выделить все
//+------------------------------------------------------------------+
//| Индикатор AМА (средняя Кауфмана)                                                 |
//| Параметры:                                                       |
//|   sym - наименование инструмента                                 |
//|   tf  - таймфрейм (количество минут)                             |
//|   nbi - номер буфера индикатора                                  |
//|   nb  - номер бара           
//                                    |
//+------------------------------------------------------------------+
double iAMA(string sym, int tf, int nbi, int nb)
{
  double noise = 0.000000001, AMA, AMA0, signal, ER;
  double dSC, ERSC, SSC, ddK;
  double slowSC, fastSC, vbi[3];
  int    nfast = 2;
  int    nslow = 30;
  double G = 2.0;
  double dK = 2.0;
  int    i;

  slowSC = (2.0 / (nslow + 1));
  fastSC = (2.0/ (nfast + 1));
  AMA0 = iClose(sym, tf, nb + 1);
 
  signal = MathAbs(iClose(sym, tf, nb) - iClose(sym, tf, nb + AMA_Period));
  for(i = 0; i < AMA_Period; i++)
  {
    noise = noise + MathAbs(iClose(sym, tf, nb + i) - iClose(sym, tf, nb + i + 1));
  }
  ER = signal / noise;
 
  dSC = (fastSC - slowSC);
  ERSC = ER * dSC;
  SSC = ERSC + slowSC;
  AMA = AMA0 + (MathPow(SSC, G) * (iClose(sym, tf, nb) - AMA0));
  vbi[0] = AMA;

  ddK = AMA - AMA0;
  if(MathAbs(ddK) > dK * Point && ddK > 0) vbi[1] = AMA; else vbi[1] = 0;
  if(MathAbs(ddK) > dK * Point && ddK < 0) vbi[2] = AMA; else vbi[2] = 0;

return(vbi[nbi]);
}

Однако, в данной реализации есть как неудобства так и неправильный расчет АМА. Это и не удивительно - автор берет предыдущее значение необходимому при расчете АМА в качестве начального, а это очень неточная реализация, т.к. расчет АМА рекурсивный и для того, чтобы вычислить очередное значение АМА необходимо провести значительно больше предыдущих расчетов АМА. Также, автор использует переменную период АМА как внешний параметр и если мы запустим данную функцию в своем коде, то нам придется формировать эту переменную как внешнюю с уже указанным именем, а это не всякому новичку при изучении MQL может быть понятно. Зато другие переменные, которые обязательно должны быть параметрами, передающимися в функцию, сделаны внутренними переменными функции, что неправильно в принципе. Также присутствует фильтр по значения АМА, который совершенно не нужен, т.к. фильтрация делается отдельно (если необходимо), а сама функция АМА должна выводить фактические значения АМА. Поэтому данная реализация никак не может быть приемлемой.
Таким образом, за основу создания прототипа функции для расчета АМА можно взять код из реализации индикатора АМА, рассмотренный в начале статьи:
Код: выделить все
double f_AMA(int per, int efp, int esp, int shi)
{
/*
   Автор: Haos (http://www.investforum.ru)
   Описание:
   Функция осуществляет расчет адаптированной скользящей средней Кауфмана (АМА)
   Параметры:
   per - период скользящей средней Кауфмана
   efp - период быстрой экспоненциальной скользящей средней
   esp - период медленной экспоненциальной скользящей средней
   shi - номер бара на котором рассчитывается АМА
*/
   double dbl_Noise = 0, dbl_Signal, dbl_ER, dbl_SSC;
   double dbl_AMA[];
   ArrayResize(dbl_AMA, Bars - per - 1);
   double dbl_SlowSC = (2.0 / (esp + 1));
   double dbl_FastSC = (2.0 / (efp + 1));
   if(Bars <= (per + 2)) return(0);
   int pos = Bars - per - 2;
   
   double dbl_AMA0 = Close[pos + 1];
   while(pos >= 0)
   {
      if(pos == Bars - per - 2) dbl_AMA0 = Close[pos + 1];
      dbl_Signal = MathAbs(Close[pos] - Close[pos + per]);
      dbl_Noise = 0;
      for(int i = 0; i < per; i++)
      {
         dbl_Noise = dbl_Noise + MathAbs(Close[pos + i] - Close[pos + i + 1]);
      }
      dbl_ER = dbl_Signal / dbl_Noise; // коэффициент эффективности
      dbl_SSC = dbl_ER * (dbl_FastSC - dbl_SlowSC) + dbl_SlowSC;
      dbl_AMA[pos] = dbl_AMA0 + (MathPow(dbl_SSC, 2) * (Close[pos] - dbl_AMA0));
      dbl_AMA0 = dbl_AMA[pos];
      pos--;
   }

return(dbl_AMA[shi]);
}

Данная функция вычисляет значения АМА, фактически, начиная от начала графика (с учетом длины периода АМА), т.е. с избытком на все случаи "программистских задач". Обычно для получения сигнала на пересечение средних и т.п. достаточно данных от последних 3 баров. Функция возвращает значение АМА на заданном номере бара.
В качестве тестируемого примера можно написать скрипт (см. ниже), установить на график индикатор АМА и запустить скрипт. Далее сравнить значения последних 3 значений АМА с данными индикатора и убедиться в правильности расчетов:
Код: выделить все
//|                                                  SC-Test-AMA.mq4 |
//|                                                             Haos |
//|                                        http://www.investforum.ru |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link      "http://www.investforum.ru"
#property version   "1.00"
#property strict
#property show_inputs

input int intAMAPe = 9;    // Период скользящей средней Кауфмана
input int intMAFPe = 2;    // Период быстрой экспоненциальной скользящей средней
input int intMASPe = 30;   // Период медленной экспоненциальной скользящей средней



//*********************************************************************************************

void OnStart()
{
  double dblAMA0 = f_AMA(intAMAPe, intMAFPe, intMASPe, 0);
  double dblAMA1 = f_AMA(intAMAPe, intMAFPe, intMASPe, 1);
  double dblAMA2 = f_AMA(intAMAPe, intMAFPe, intMASPe, 2);
  Comment( "\n", "AMA[0]: ", DoubleToStr(dblAMA0, 4),
           "\n", "AMA[1]: ", DoubleToStr(dblAMA1, 4),
           "\n", "AMA[2]: ", DoubleToStr(dblAMA2, 4));
   
}

//*********************************************************************************************

double f_AMA(int per, int efp, int esp, int shi)
{
/*
   Описание:
   Функция осуществляет расчет адаптированной скользящей средней Кауфмана (АМА)
   Параметры:
   per - период скользящей средней Кауфмана
   efp - период быстрой экспоненциальной скользящей средней
   esp - период медленной экспоненциальной скользящей средней
   shi - номер бара на котором рассчитывается АМА
*/
   double dbl_Noise = 0, dbl_Signal, dbl_ER, dbl_SSC;
   double dbl_AMA[];
   ArrayResize(dbl_AMA, Bars - per - 1);
   double dbl_SlowSC = (2.0 / (esp + 1));
   double dbl_FastSC = (2.0 / (efp + 1));
   if(Bars <= (per + 2)) return(0);
   int pos = Bars - per - 2;
   
   double dbl_AMA0 = Close[pos + 1];
   while(pos >= 0)
   {
      if(pos == Bars - per - 2) dbl_AMA0 = Close[pos + 1];
      dbl_Signal = MathAbs(Close[pos] - Close[pos + per]);
      dbl_Noise = 0;
      for(int i = 0; i < per; i++)
      {
         dbl_Noise = dbl_Noise + MathAbs(Close[pos + i] - Close[pos + i + 1]);
      }
      dbl_ER = dbl_Signal / dbl_Noise; // коэффициент эффективности
      dbl_SSC = dbl_ER * (dbl_FastSC - dbl_SlowSC) + dbl_SlowSC;
      dbl_AMA[pos] = dbl_AMA0 + (MathPow(dbl_SSC, 2) * (Close[pos] - dbl_AMA0));
      dbl_AMA0 = dbl_AMA[pos];
      pos--;
   }

return(dbl_AMA[shi]);
}
Вложения
01.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 14 авг 2017, 14:40

Поскольку АМА является самодостаточной для построении торговой системы, т.к. сигналом на вход в рынок (согласно автору) служит изменение направления АМА. Однако, автор отмечает, что для избежания многих ложных входов, когда рынок находится во флете лучше применять фильтр, который рассмотрим далее.
В основе этого фильтра лежит стандартное отклонение ежедневных приращений индикатора АМА за определенный период времени (обычно тот же период, на котором вычисляется ER).
Выборочное стандартное отклонение, как мы уже разбирали здесь, рассчитывается по формуле:

STD.jpg

Таким образом, формула фильтра будет выглядеть так:

Filter = K * S,

где
К - процентный коэффициент;
S - стандартное отклонение,
n - период на котором вычисляется стандартное отклонение;
По умолчанию, n = 10.
Для различных рынков Кауфман предлагает применять различные значения процентного коэф-та К. Так, для торговли фьючерсами или на на рынке Форекс, подходя небольшие значения фильтра, порядка 10% (К = 0,1). Для рынка акций необходим более широкий фильтр - до 100% (К = 1,0).

Сигнал к покупке: АМА - АМАmin > Filter;

Сигнал к продаже: АМАmax - AMA > Filter;
где,
АМА - текущее значение АМА;
АМАmin - минимальное значение АМА за рассматриваемый период n;
АМАmax - максимальное значение АМА за рассматриваемый период n;
Несмотря на свою простоту, такой фильтр очень эффективно отсеивает незначительные колебания индикатора на ненаправленных рынках, заметно уменьшая количество ложных торговых сигналов на "пиле".
На рисунке (см. рис. ниже) представлен фрагмент дневных данных РАО ЕЭС. В верхней части рисунка показаны сигналы торговой системы на основе АМА без фильтра, а в нижней части рисунка - с фильтром. Хорошо видно, что на флетовом участке были отсеяны 4 ложных сигнала.
Вложения
08.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 16 авг 2017, 12:18

Посчитаем что дает сей алгоритм для фильтра сигналов по АМА сначала в Excel на основе последних данных на часовом ТФ по EURUSD.
Расчет АМА на последних 10 барах:

09-1.png

Расчет значений:

09-2.png

Таким образом, на прошлом баре имеет место сигнал на продажу.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 16 авг 2017, 12:33

Теперь неплохо бы написать индикатор, который помимо АМА чертит на графике и стрелочки при входе в рынок. Так можно будет визуально оценить качество сигналов, а также проверить правильность расчетов при использовании фильтра.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Использование адаптивной скользящей средней Кауфмана

Сообщение Denver » 19 мар 2019, 17:44

Haos писал(а):Теперь неплохо бы написать индикатор, который помимо АМА чертит на графике и стрелочки при входе в рынок. Так можно будет визуально оценить качество сигналов, а также проверить правильность расчетов при использовании фильтра.

Да как скачать тут эту адаптивную скользящую среднюю Кауфмана простому ... трейдеру ничего не смыслящему в языке программирования Mql? :du_ma_et:
Последний раз редактировалось Haos 19 мар 2019, 18:32, всего редактировалось 2 раз(а).
Причина: удалено лишнее
Аватар пользователя
Denver
 
Сообщений: 3226
Зарегистрирован: 16 янв 2014, 07:01
Средств на руках: 384.35 Доллар
Награды: 1
Ветеран II (1)
Группа: Базовая
Благодарил (а): 835 раз.
Поблагодарили: 603 раз.

Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 19 мар 2019, 18:33

Сам заметил, что индикатор не выложил. Сейчас выложу.
Вложения
IN-AMA-v1.mq4
(4.21 KB) Скачиваний: 104
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Использование адаптивной скользящей средней Кауфмана

Сообщение Denver » 20 мар 2019, 07:09

Haos писал(а):Сейчас выложу.

Интересный инструмент. Если бы мне его предложили в начале знакомства с форексом (или даже не пол пути), то я был бы весьма рад воспользоваться таким индикатором.

Личный вывод: очень рекомендую данный индикатор для тех, кто только начинает знакомство с форексом. Сэкономите время на поиски правильных индикаторов. Естественно - не пользоваться только одним этим индикатором как полноценной ТС).
Аватар пользователя
Denver
 
Сообщений: 3226
Зарегистрирован: 16 янв 2014, 07:01
Средств на руках: 384.35 Доллар
Награды: 1
Ветеран II (1)
Группа: Базовая
Благодарил (а): 835 раз.
Поблагодарили: 603 раз.

Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 20 мар 2019, 07:41

Denver писал(а):Интересный инструмент. Если бы мне его предложили в начале знакомства с форексом (или даже не пол пути), то я был бы весьма рад воспользоваться таким индикатором.

Личный вывод: очень рекомендую данный индикатор для тех, кто только начинает знакомство с форексом. Сэкономите время на поиски правильных индикаторов. Естественно - не пользоваться только одним этим индикатором как полноценной ТС).

Я уже давно закончил знакомство с трейдингом, а МАшки применяю и всегда применял (к примеру, эта ТС), АМА же самая лучшая из них, видимо. Поэтому на любом этапе знакомства с трейдингом можно и нужно использовать МАшки. Не зря есть выражение, что на рынке больше всего денег зарабатывается с помощью скользящих средних (что бы там не казалось или не думалось относительно них).
Но это уже мы отвлеклись от темы. Все обсуждения индикаторов давайте в соотв. разделах и темах проводить.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Использование адаптивной скользящей средней Кауфмана

Сообщение Haos » 01 апр 2019, 12:30

Рассмотрим как в коде применять две АМА для идентификации тренда, что, по сути, аналог торговли на двух средних.
В модуле эксперта в месте для определения глобальных переменных модуля (выше функции OnInit()) нужно объявить два массива для получения значений АМА быстрой линии и АМА медленной.

Код: выделить все
double dblMAMA1[3]; // 1 - быстрая  АМА
double dblMAMA2[3]; // 2 - медленная АМА

Объявленные глобальными, этим массивы будут доступны во всех функциях модуля эксперта.
Напишем две функции. Первая будет заполнять указанные два массива тремя последними значениями АМА (что достаточно для определения тренда и сигнала на пересечения АМА).

Код: выделить все
void f_GetAMA()
{
   for(int i = 0; i < 3; i++)
   {
      dblMAMA1[i] = f_AMA(intAPe1, intFPe1, intSPe1, i);
      dblMAMA2[i] = f_AMA(intAPe2, intFPe2, intSPe2, i);
   }
}

В качестве параметров f_AMA() указаны необходимые имена переменных. Таким образом, после выполнения данной функции массивы dblMAMA1[], dblMAMA2[] будут заполнены.
Предлагаю улучшить данную функцию самостоятельно и/или задавать вопросы по этому поводу.

Вторая функция будет возвращать значения типа string соответствующее имеющемуся тренду, определенному на основе двух АМА:

Код: выделить все
string f_2AMATre()                 
/*
   Используются массивы: dblMAMA1[], dblMAMA2[]
   Ф-ия определяет тренд по комбинации 2 МАшек (на последнем закрытом баре)
   возвращает "UP" если быстрая AМА выше медленной AМА
   возвращает "DN" если быстрая AМА ниже медленной AМА
   возвращает "NO" если тренд не определен
*/
{
   
   if(dblMAMA1[1] > dblMAMA2[1]) return("UP");
   if(dblMAMA1[1] < dblMAMA2[1]) return("DN");
   
return("NO");
}


Таким образом, для определения тренда по двум АМА достаточно в теле модуля эксперта последовательно вызвать две рассмотренные функции:

Код: выделить все
void OnTick()
{
    ...   
   f_GetAMA(); // получим новые значения АМА
   string  strTre = f_2AMATre();
   // Обработка тренда:
   if(strTre == "UP")
   {
   // то-то и то-то для бычьего тренда
   }
...
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 52

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

cron