Скрипты: EMA и SMMA идентичны

 

EMA и SMMA идентичны:

Этот крошечный скрипт наглядно демонстрирует идентичность двух распространенных мувингов

Author: Sceptic Philozoff

 

позабавило... и улыбнуло...

 
А ещё сравните WPR(14) и Stoch(14,1,1).
 
Sadhu:
А ещё сравните WPR(14) и Stoch(14,1,1).
Да, было такое дело.
 
"Скрипт абсолютно бесполезен для торговли"
Ты на правильном пути, Mathemat, большие ученые не опускались до всякой прикладухи. :-)
А, вообще, красиво.
 
granit77:
"Скрипт абсолютно бесполезен для торговли" ...большие ученые не опускались до всякой прикладухи. :-)
Ну что тут сказать, granit77... Во-первых, спасибо за комплимент! Ну а скрипт... ну да, бесполезен (в смысле что его незачем вставлять в советнег), но само знание о том, что он демонстрирует, не бессмысленно: какой-нибудь стратег, долго и обстоятельно обосновывающий преимущества SMMA перед EMA в его стратегии, оказывается, ничего не стоит. И вообще - не ты ли отстаивал право на неопосредованное деньгами удовольствие в ветке о граале?!
 
Mathemat:
granit77:
"Скрипт абсолютно бесполезен для торговли" ...большие ученые не опускались до всякой прикладухи. :-)
Ну что тут сказать, granit77... Во-первых, спасибо за комплимент! Ну а скрипт... ну да, бесполезен (в смысле что его незачем вставлять в советнег), но само знание о том, что он демонстрирует, не бессмысленно: какой-нибудь стратег, долго и обстоятельно обосновывающий преимущества SMMA перед EMA в его стратегии, оказывается, ничего не стоит. И вообще - не ты ли отстаивал право на неопосредованное деньгами удовольствие в ветке о граале?!
Отстаивал и буду отстаивать, единомышленникам привет!
 
Все бы хорошо, но смею заметить, что алгоритм расчета SMMA неверный. Описание алгоритма в документации приведено верное, а расчет сам в индикаторе проделан неверно. SMMA в теории больше напоминает слегка сглаженную SMA, поскольку в расчетах отталкивается от себя самой на предыдущем баре.
Так что ваш вывод о схожести EMA и SMMA можно считать ошибочным.
Кстати, путаница с описанием и реализацией еще имеет место быть в индикаторе ADX, поскольку упущен очень важный момент в том, что все сглаживания в этом индикаторе проводятся с помощью средней Вайлдера (Wilder), т.е. при помощи ЕМА с периодом 2*N-1. Именно по этой причине значения индикатора в МТ не совпадают со значениями в других торговых платформах при одинаковых периодах.
Ниже привожу индикатор с правильной реализацией алгоритма SMMA.
//+------------------------------------------------------------------+
//|                                     Custom Moving Average_v1.mq4 |
//|                      Copyright © 2004, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//|                Revised by Igorad, E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
 
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int Price=0;
extern int MA_Period=14;
extern int MA_Shift=0;
extern int MA_Method=2;
//---- indicator buffers
double ExtMapBuffer[];
//----
int ExtCountedBars=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   int    draw_begin;
   string short_name;
//---- drawing settings
   SetIndexStyle(0,DRAW_LINE);
   SetIndexShift(0,MA_Shift);
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   if(MA_Period<2) MA_Period=13;
   draw_begin=MA_Period-1;
//---- indicator short name
   switch(MA_Method)
     {
      case 1 : short_name="EMA(";  draw_begin=0; break;
      case 2 : short_name="SMMA("; break;
      case 3 : short_name="LWMA("; break;
      default :
         MA_Method=0;
         short_name="SMA(";
     }
   IndicatorShortName(short_name+MA_Period+")");
   SetIndexDrawBegin(0,draw_begin);
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer);
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   if(Bars<=MA_Period) return(0);
   ExtCountedBars=IndicatorCounted();
//---- check for possible errors
   if (ExtCountedBars<0) return(-1);
//---- last counted bar will be recounted
   if (ExtCountedBars>0) ExtCountedBars--;
//----
   switch(MA_Method)
     {
      case 0 : sma();  break;
      case 1 : ema();  break;
      case 2 : smma(); break;
      case 3 : lwma();
     }
//---- done
   return(0);
  }
//+------------------------------------------------------------------+
//| Simple Moving Average                                            |
//+------------------------------------------------------------------+
void sma()
  {
   double sum=0;
   int    i,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
   if(pos<MA_Period) pos=MA_Period;
   for(i=1;i<MA_Period;i++,pos--)
      sum+=iMA(NULL,0,1,0,0,Price,pos);
//---- main calculation loop
   while(pos>=0)
     {
      sum+=iMA(NULL,0,1,0,0,Price,pos);
      ExtMapBuffer[pos]=sum/MA_Period;
       sum-=iMA(NULL,0,1,0,0,Price,pos+MA_Period-1);
        pos--;
     }
//---- zero initial bars
   if(ExtCountedBars<1)
      for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
  }
//+------------------------------------------------------------------+
//| Exponential Moving Average                                       |
//+------------------------------------------------------------------+
void ema()
  {
   double pr=2.0/(MA_Period+1);
   int    pos=Bars-2;
   if(ExtCountedBars>2) pos=Bars-ExtCountedBars-1;
//---- main calculation loop
   while(pos>=0)
     {
      if(pos==Bars-2) ExtMapBuffer[pos+1]=iMA(NULL,0,1,0,0,Price,pos+1);
      ExtMapBuffer[pos]=iMA(NULL,0,1,0,0,Price,pos)*pr+ExtMapBuffer[pos+1]*(1-pr);
        pos--;
     }
  }
//+------------------------------------------------------------------+
//| Smoothed Moving Average                                          |
//+------------------------------------------------------------------+
void smma()
  {
   double sum=0;
   int    i,k,pos=Bars-ExtCountedBars+1;
//---- main calculation loop
   pos=Bars-MA_Period;
   if(pos>Bars-ExtCountedBars) pos=Bars-ExtCountedBars;
   while(pos>=0)
     {
      if(pos==Bars-MA_Period)
        {
         //---- initial accumulation
         sum=0;
         for(i=0;i<MA_Period;i++)
         sum+=iMA(NULL,0,1,0,0,Price,pos+i);
         ExtMapBuffer[pos]=sum/MA_Period;
        }
      else 
        {
        sum=0;
        for(i=0;i<MA_Period;i++) sum+=iMA(NULL,0,1,0,0,Price,pos+i+1);
           
        ExtMapBuffer[pos]=(sum - ExtMapBuffer[pos+1] + iMA(NULL,0,1,0,0,Price,pos))/MA_Period;
          }  
        pos--;
     }
  }
//+------------------------------------------------------------------+
//| Linear Weighted Moving Average                                   |
//+------------------------------------------------------------------+
void lwma()
  {
   double sum=0.0,lsum=0.0;
   double price;
   int    i,weight=0,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
   if(pos<MA_Period) pos=MA_Period;
   for(i=1;i<=MA_Period;i++,pos--)
     {
      price=iMA(NULL,0,1,0,0,Price,pos);
      sum+=price*i;
      lsum+=price;
      weight+=i;
     }
//---- main calculation loop
   pos++;
   i=pos+MA_Period;
   while(pos>=0)
     {
      ExtMapBuffer[pos]=sum/weight;
      if(pos==0) break;
      pos--;
      i--;
      price=iMA(NULL,0,1,0,0,Price,pos);
      sum=sum-lsum+price*MA_Period;
      lsum-=iMA(NULL,0,1,0,0,Price,i);
      lsum+=price;
     }
//---- zero initial bars
   if(ExtCountedBars<1)
      for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
  }
//+------------------------------------------------------------------+
При этом RSI, в теории использующее такое же сглаживание Вайлдера, в МТ реализовано правильно.
 
igorad:
Все бы хорошо, но смею заметить, что алгоритм расчета SMMA неверный. Описание алгоритма в документации приведено верное, а расчет сам в индикаторе проделан неверно. SMMA в теории больше напоминает слегка сглаженную SMA, поскольку в расчетах отталкивается от себя самой на предыдущем баре.
Так что ваш вывод о схожести EMA и SMMA можно считать ошибочным.

igorad, говоря откровенно, я не особенно внимательно смотрел на реализацию алгоритма SMMA в кастомном индюкаторе Moving Average. Я ориентировался только на его описание на сайте, вот здесь: https://www.metatrader5.com/ru/terminal/help/indicators/trend_indicators/ma , и полагался на его верность.

Свой вывод могу строго аргументировать с помощью простой арифметики и не считаю ошибочным. Особо хочу подчеркнуть, что это не схожесть, а полная идентичность. Разница обусловлена только разными инициализациями, и, как и полагается для фильтров этого вида, стремится к нулю при стремлении начального индекса скользящего окна к бесконечности.

P.S. Математическое доказательство готов привести, как только ты его потребуешь. Оно совсем простое. Можешь убедиться в этом самостоятельно, расписав формулы, приведенные по ссылке выше.

 
Свой вывод могу строго аргументировать с помощью простой арифметики и не считаю ошибочным. Смею заметить, что это не схожесть, а полная идентичность.
Тут и доказывать особо нечего. Представленная SMMA в МТ на самом деле является средней Вайлдера.

формула средней Вайлдера: MA = MA[1] + 1/N*(P - MA[1])
после преобразований получаем MA = (MA[1]*(N-1) +P)/N

А вот строки из кода, которые отвечают за это:
else 
sum=ExtMapBuffer[pos+1]*(MA_Period-1)+Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
Поэтому вы и получили полное совпадение ЕМА с периодом 2*N-1 и так называемой SMMA, поскольку
коэффициент 1/N можно преобразовать к виду 2/((2*N-1)+1).
 
ОК, igorad, давай теперь посмотрим на то, что у нас получается.

1. Ты сам же говоришь, что описание алгоритма в документации - верное. А я говорю, что именно из этого алгоритма (по формулам, а не по коду, реализованному в МТ) я вывел тождество рекуррентных формул для EMA(2N-1) и SMMA(N). Только вот в формуле
SMMA (i) = (SUM1 - SMMA (i - 1) + CLOSE (i)) / N 
есть неточность: надо в общем виде заменить SUM1 на SUM(i - 1), что косвенно подтверждается нижеприведенными пояснениями. Тогда дальше все очевидно:
SMMA (i) = (SUM (i - 1) - SMMA (i - 1) + CLOSE (i)) / N = 
	 = ( (N - 1) * SMMA (i - 1)    + CLOSE (i)) / N = 
	 = (1 - 1/N) * SMMA (i - 1)    + 1/N * CLOSE (i)
Теперь ясно, что при правильном подборе N наша формула идентична рекуррентной для EMA с некоторым периодом.

2. Только что ты доказал то же самое, но уже теперь исходя из метаквотовского кода.

3. Тем не менее ты настаиваешь на том, что твоя ревизия SMMA - единственно верная. Я наложил на чарт твой индюкатор с теми же значениями периодов, т.е. SMMA(80) и EMA(159), и они очень сильно отличаются друг от друга.

4. Вот еще: https://www.mql5.com/en/forum/46462 . Ты согласен с такой формулой?

Так где же истина? Где ты брал единственно верное определение SMMA?