Прошу помощи с MACD на фиксированном кол-ве баров

 

Приветствую!

Взялся написать MACD (из примеров) для фиксированного количества баров, сама гистограмма рисуется нормально, а вот сигнальная линия - полный бред. Всезнающий Гугл предложил пользоваться приведением массива к таймсерии, но это не помогло. Кусок из хелпа - аналогично :(

По-умолчанию для количества баров = Bars все работает.

#property copyright "Copyleft"
#property link      ""

//---- indicator settings
#property  indicator_separate_window
#property  indicator_buffers 2
#property  indicator_color1  Black
#property  indicator_color2  Red
#property  indicator_width1  1
#property  indicator_width2  1
#property  indicator_style1  0
#property  indicator_style2  2
//---- indicator parameters
extern int FastEMA=12;
extern int SlowEMA=26;
extern int SignalSMA=9;
extern int BarsMax=300;
//---- indicator buffers
double     MacdBuffer[];
double     SignalBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- drawing settings
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexDrawBegin(1,SignalSMA);
   IndicatorDigits(Digits+1);
//---- indicator buffers mapping
   SetIndexBuffer(0,MacdBuffer);
   SetIndexBuffer(1,SignalBuffer);
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("MACD("+FastEMA+","+SlowEMA+","+SignalSMA+")");
   SetIndexLabel(0,"MACD");
   SetIndexLabel(1,"Signal");
//---- initialization done
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
int start()
  {
   int limit;
   //int counted_bars=IndicatorCounted();

   //if(counted_bars>0) counted_bars--;
   limit=BarsMax /*Bars*/;
   
   
   for(int i=0; i<limit; i++) {
      MacdBuffer[i]=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i)-iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_CLOSE,i);
   }

   for(i=0; i<limit; i++) {
      SignalBuffer[i]=iMAOnArray(MacdBuffer,0/*Bars*/,SignalSMA,0,MODE_SMA,i);
   }
   return(0);
  }
//+------------------------------------------------------------------+
 

1. Используйте iMACD. 0-й буфер - сама MACD, 1-й - сигнальная.

2. Код не оптимален - на каждом тике будет просчитываться все ваши 300 баров. Зачем?

 

Возможно у вас количество баров на экране более BarsMax из вашего инд., поэтому отображает только линию. Можно добавить в код условие

int limit;   
   if(BarsMax<=WindowBarsPerChart())limit=WindowBarsPerChart()+1;
   else limit=BarsMax;

Тогда думаю будет отображаться правильно.

 

Svinozavr
писал(а)
>>

1. Используйте iMACD. 0-й буфер - сама MACD, 1-й - сигнальная.

2. Код не оптимален - на каждом тике будет просчитываться все ваши 300 баров. Зачем?

1. Спасибо, попробую!

2. Временно убрал из кода тот кусок, что отбрасывал посчитаные бары. Так сказать, минимизируя поверхность для ошибок. Плюс я опасаюсь влияния старых баров на общую картину (см.ниже).

Necron писал(а) >>

Возможно у вас количество баров на экране более BarsMax из вашего инд., поэтому отображается только линию. Можно добавить в код условие

Тогда думаю будет отображаться правильно.

Я хотел чтобы MACD рисовался только по последним N барам вне зависимости от их количества на экране. Если в настройках выставить лимит, то и "штатная" MACD рисуется правильно, но тут возникает пара моментов:

1. В процессе получения новой информации MetaTrader дорисовывает новые бары, не стирая данные о старых. Возможно, я ошибаюсь, но мне кажется это влияет на результаты вычислений.

2. Ограничение на кол-во баров на экране влияет на остальные индикаторы. Опять же, это мое предположение.

 

Учтите, что EMA фильтр с БИХ, и влияние на результат не ограничивается длиной периода, которого у EMA, собственно, и нет (есть пересчет в альфа-коэфф.)

Поэтому, если вы каждый раз будете просчитывать на одной выборке, то результат будет меняться! Т.е. посчитался 1-й бар - в предыстории у него 298 баров. А когда он станет вторым, то предыстория (длина) для него изменится, и изменится, соответственно, и рез-т. // это если каждый раз все 300 баров пересчитывать

Такие дела...)))

 

Вообще, для случаев с ограниченной длиной выборки можно использовать преобразование (сглаживание) Уайлдера - Wilder's smoothing. Это такой симбиоз SMA (КИХ) и EMA (БИХ).

В частности, он применяется в оригинальном (не МТ-шном!) алгоритме ADX. Не знаю, есть ли это преобразование в CodeBase, но оно не сложно для написания самому. Если уж так реально нужно четко по выборке работать. Если здесь алгоритма нет, то в гугле точно найдете. Точно знаю, что описание есть в Метастоковском хэлпе.

 
valerish писал(а) >>

1. Спасибо, попробую!

2. Временно убрал из кода тот кусок, что отбрасывал посчитаные бары. Так сказать, минимизируя поверхность для ошибок. Плюс я опасаюсь влияния старых баров на общую картину (см.ниже).

Я хотел чтобы MACD рисовался только по последним N барам вне зависимости от их количества на экране. Если в настройках выставить лимит, то и "штатная" MACD рисуется правильно, но тут возникает пара моментов:

1. В процессе получения новой информации MetaTrader дорисовывает новые бары, не стирая данные о старых. Возможно, я ошибаюсь, но мне кажется это влияет на результаты вычислений.

2. Ограничение на кол-во баров на экране влияет на остальные индикаторы. Опять же, это мое предположение.

может такой вариант поможкт

Файлы:
macd_sym.mq4  6 kb
Причина обращения: