Индикатор Moving Average

В данной статье будет подробно рассмотрена работа индикатора Moving Average с точки зрения программирования на языке LCRYP

 

Глобальные переменные

В первой строке объявлены глобальные переменные (Length, Shift, ApplyToPrice, ColorBuySell, LimitBars), в этих переменных будут храниться входные параметры, которые может задавать пользователь. Ими можно будет пользоваться во всех функциях программы. Но нужно помнить, что в каждой функции их нужно инициировать.

int Length,Shift,ApplyToPrice,ColorBuySell,LimitBars;

Рассмотрим функцию OnInit

Первая строка использует команду s_buff. С ее помощью создается буфер с номером 0, для вывода информации. Тип отображения данных буфера - линия и соответствующие цвета (Lime - цвет по умолчанию, Blue - цвет для случая движения вверх, Red - цвет на случай движения вниз). В следующих пяти строках используется команда s_par, которая устанавливает набор входных данных для пользователя. Входные данные индексируются от 0 до 4 (используется 5 входных параметров). Также команда s_par задает тип для каждого поля и название, которое будет отображаться и значение по умолчанию. На этом работа данной части программы завершена. 

int OnInit()
  {
   s_buff(0,1,1,0,"Lime","Blue","Red");
   s_par(0,"int","Length",12);
   s_par(1,"int","Shift",0);
   s_par(2,"int","Apply to Price",6);
   s_par(3,"int","Color Buy/Sell",1);
   s_par(4,"int","LimitBars",1000);
  }

Рассмотрим функцию OnBar

В начале функции нужно узнать входные параметры с помощью команды g_par и сохранить их в соответствующие глобальные переменные согласно индексов, описанных в функции OnInit. В следующих строках происходят некоторые проверки и коррекция входных значений.

   Length=g_par(0);
   Shift=g_par(1);
   ApplyToPrice=g_par(2);
   ColorBuySell=g_par(3);
   LimitBars=g_par(4);
   if(Length<1){Length=1;}
   if(Shift<0){Shift=0;}
   if(Shift>Count-1-Length){Shift=Count-1-Length;}
   if(ApplyToPrice<0){ApplyToPrice=0;}
   if(ApplyToPrice<6){ApplyToPrice=6;}
   ShowName();

После чего используется пользовательская функция ShowName, которая выводит название индикатора с параметрами на окно чарта используя команды prt и prt_a.

int ShowName()
  {
   prt(0,"Moving Average [");
   prt_a(0,Length);prt_a(0,", ");
   prt_a(0,Shift);prt_a(0,", ");
   prt_a(0,ApplyToPrice);prt_a(0,", ");
   prt_a(0,ColorBuySell);
   prt_a(0,"]");
  }

Дальше несколько дополнительных условий:

if(ReCount>LimitBars){ReCount=LimitBars;}

Условие устанавливает ограничение количества входных баров для пересчета, то есть перерасчет будет не более, чем LimitBars баров, заданных пользователем. Встроенная переменная ReCount несет информацию о количестве баров, которое необходимо пересчитать.

if(ReCount<1){return -1;}

Условие завершает работу функции, если нет новых баров для пересчета.

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

for(i=ReCount-1;i>=0;i=i-1)
     {
      p_ma=avg(i,Length,Shift,Count,ApplyToPrice);
      if(ColorBuySell>0)
        {
         p_pred_ma=g_dbuff(0,i+1);
         if(p_ma<p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",-1);
           }
         if(p_ma>p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",1);
           }
         if(p_ma==p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",0);
           }
        }
      else
        {
         s_dbuff(0,i,p_ma,0,0,"",0);
        }
     }

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

Во входных данных присутствует параметр ColorBuySell, который задает возможность отображать различными цветами линию среднего значения цены, реализация этого значения происходит соответственно углу наклона линии. Условие if (ColorBuySell>0) проверяет значение ColorBuySell и переходит или на использование команды s_dbuff, которая отобразит линию цветом по умолчанию, что описано в части условия - блоке else; или же проведет анализ предыдущего значения (значение уже есть, оно записано в буфере 0 на предыдущей итерации), сравнив его с текущим значением. Для этого использована команда g_dbuff, которая позволяет прочитать предыдущее значение. Угол наклона определим сравнением p_ma, p_pred_ma текущего и предыдущего значений. Если текущее значение меньше предыдущего то ассоциируем с сигналом на sell, тогда будет соответствующий цвет (красный), заданный в инициализации данного буфера. Если текущее значение больше предыдущего, то ассоциируем с сигналом на buy (синий). В случае, если значения равны, то ассоциируем с отсутствием сигнала, цвет по умолчанию задан в настройках буфера. Для записи в буфер используется команда команды s_dbuff.

Функция OnTick

Функция не используется, но сама функция должна присутствовать в теле программы.

int OnTick()
  {
  }

Как можно использовать эту функцию в контексте данного индикатора? Если функция OnBar учитывает нулевой бар, то отображаемый результат работы на нем будет не корректен, поскольку цена на нулевом баре не сформирована до конца. Тогда можно при пересчете баров или не учитывать нулевой бар, или на каждом тике делать перерасчет, чтобы постоянно корректировать значением индикатора на нулевом баре по мере формирования нулевого бара. 

Полный листинг программы Moving Average: 

//+------------------------------------------------------------------+
//|                                             Moving Average.lcryp |
//|                                     Copyright 2017, TerminalCoin |
//|                                             www.terminalcoin.com |
//+------------------------------------------------------------------+
int Length,Shift,ApplyToPrice,ColorBuySell,LimitBars;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   s_buff(0,1,1,0,"Lime","Blue","Red");
   s_par(0,"int","Length",12);
   s_par(1,"int","Shift",0);
   s_par(2,"int","Apply to Price",6);
   s_par(3,"int","Color Buy/Sell",1);
   s_par(4,"int","LimitBars",1000);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnBar()
  {
   Length=g_par(0);
   Shift=g_par(1);
   ApplyToPrice=g_par(2);
   ColorBuySell=g_par(3);
   LimitBars=g_par(4);
   if(Length<1){Length=1;}
   if(Shift<0){Shift=0;}
   if(Shift>Count-1-Length){Shift=Count-1-Length;}
   if(ApplyToPrice<0){ApplyToPrice=0;}
   if(ApplyToPrice<6){ApplyToPrice=6;}
   ShowName();
   if(ReCount>LimitBars)
     {
      ReCount=LimitBars;
     }
   if(ReCount<1){return -1;}
   double p_ma,p_pred_ma;
   int i;
   for(i=ReCount-1;i>=0;i=i-1)
     {
      p_ma=avg(i,Length,Shift,Count,ApplyToPrice);
      if(ColorBuySell>0)
        {
         p_pred_ma=g_dbuff(0,i+1);
         if(p_ma<p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",-1);
           }
         if(p_ma>p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",1);
           }
         if(p_ma==p_pred_ma)
           {
            s_dbuff(0,i,p_ma,0,0,"",0);
           }
        }
      else
        {
         s_dbuff(0,i,p_ma,0,0,"",0);
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnTick()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int ShowName()
  {
   prt(0,"Moving Average [");
   prt_a(0,Length);prt_a(0,", ");
   prt_a(0,Shift);prt_a(0,", ");
   prt_a(0,ApplyToPrice);prt_a(0,", ");
   prt_a(0,ColorBuySell);
   prt_a(0,"]");
  }
//+------------------------------------------------------------------+

Назад

TerminalCoin

2018-05-15 19:38:30