Общие вопросы по разработке > Опять про вызов индикатора от индикатора

Общие вопросы по разработке в Альфа-Директ 4. Обсуждение разработки пользовательских индикаторов, стратегий.
alex_m
Сообщения: 10
Зарегистрирован: 18 мар 2021, 21:30
Благодарил (а): 6 раз

Опять про вызов индикатора от индикатора

Непрочитанное сообщение alex_m » 18 мар 2021, 21:44

Привет всем,

Помогите начинающему пожалуйста :oops:

Разбираюсь с написанием своего индикатора. Не могу понять, почему перестает отрабатывать вывод серии MACD_Sign на график, когда выбираю MA_fast_type и MA_slow_type 1. Вызоа же MY._my_MA_MA_diff отрабатывает, MACD_Line выводится.
На всякий случай убрал уже все условия, оставил просто две строки кода. Думал может что-то с типами, в явном виде привожу передачу аргументов к (int), хотя опять же, это не причем, MY._my_MA_MA_diff то возвращает серию..

Код: Выделить всё

function Initialize()
{

   IndicatorName = "_my_MA_MA_MACD";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = false;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Price);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
   AddParameter("MA_fast_type", 2, "тип быстр: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_fast_period", 12, "период быстрой MA");
    AddParameter("MA_slow_type", 2, "тип медл: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_slow_period", 26, "период медленной MA");
    AddParameter("MACD_sign_type", 2, "тип сигн MACD: 1-SMA/2-EMA/3-WMA");
    AddParameter("MACD_sign_period", 9, "период сигн MACD");

    AddSeries("MACD_Line", DrawAs.Line, Color.Blue);   // Задаем вид линии индикатора    
    AddSeries("MACD_Sign", DrawAs.Line, Color.Orange);   // Задаем вид линии индикатора
}

function Evaluate()
{

//var sInd = SMA(Input, 10);
//var A = EMA(sInd, 5);   

   var MA_diff = MY._my_MA_MA_diff(Input,(int)MA_fast_type,(int)MA_fast_period,(int)MA_slow_type,(int)MA_slow_period);
   var sign_line = SMA(MA_diff, MACD_sign_period);
   
/*   if (MACD_sign_type == 1)
   {
      sign_line = SMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else if (MACD_sign_type == 2)
   {
      sign_line = EMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else if (MACD_sign_type == 3)
   {
      sign_line = WMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else
   {
      sign_line = SMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }*/
   
   MACD_Line = MA_diff[0];
   MACD_Sign = sign_line[0];
}


вот мой пользовательский индикатор MY._my_MA_MA_diff

Код: Выделить всё

function Initialize()
{
   IndicatorName = "_my_MA_MA_diff";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = false;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Price);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
    AddParameter("MA_fast_type", 2, "тип быстр: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_fast_period", 12, "период быстрой MA");
    AddParameter("MA_slow_type", 2, "тип медл: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_slow_period", 26, "период медленной MA");
    AddSeries("MA_diff", DrawAs.Line, Color.Blue);   // Задаем вид линии индикатора
}

function Evaluate()
{
   var MA_fast = 0.0;
   var MA_slow = 0.0;

   if (MA_fast_type == 1)
   {
      MA_fast = SMA(Input, MA_fast_period)[0];
   }
   else if (MA_fast_type == 2)
   {
      MA_fast = EMA(Input, MA_fast_period)[0];
   }
   else if (MA_fast_type == 3)
   {
      MA_fast = WMA(Input, MA_fast_period)[0];   
   }
   else
   {
      MA_fast = SMA(Input, MA_fast_period)[0];
   }
   
   if (MA_slow_type == 1)
   {
      MA_slow = SMA(Input, MA_slow_period)[0];
   }
   else if (MA_slow_type == 2)
   {
      MA_slow = EMA(Input, MA_slow_period)[0];
   }
   else if (MA_slow_type == 3)
   {
      MA_slow = WMA(Input, MA_slow_period)[0];   
   }
   else
   {
      MA_slow = SMA(Input, MA_slow_period)[0];
   }
   
   MA_diff = MA_fast - MA_slow;
}


Заранее спасибо!

Аватара пользователя
evge
Администратор
Сообщения: 1807
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 361 раз
Контактная информация:

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение evge » 18 мар 2021, 22:30

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

В первом индикаторе название параметров задайте иначе и заработает, поведение конечно странное, но помогает

например так:

Код: Выделить всё

AddParameter("MA_fast_type1", 2, "тип быстр: 1-SMA/2-EMA/3-WMA");
AddParameter("MA_slow_type1", 2, "тип медл: 1-SMA/2-EMA/3-WMA");


и здесь

Код: Выделить всё

var MA_diff = MY._my_MA_MA_diff(Input,(int)MA_fast_type1,(int)MA_fast_period,(int)MA_slow_type1,(int)MA_slow_period);


а лучше все параметры иначе обозвать чем в другом индикаторе.
никогда такого не было и вот опять

alex_m
Сообщения: 10
Зарегистрирован: 18 мар 2021, 21:30
Благодарил (а): 6 раз

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение alex_m » 18 мар 2021, 22:51

evge, огромное спасибо за молниеносный ответ ;) !
но кажется дело где-то в другом..
Чет не нашел как скришоты прикрепить, только через линк можно?

Попробую описать словами: на мой _MA_MA_diff добваил на графике стандартный SMA и он тоже пропадает, когда меняю типы МА. Когда оба МА типа EMA, то их разница получается целочисленная, и SMA от нее работает, а когда разные типы МА, то их разница становится не целая, со знаками после запятой, и SMA перестает работать. Неужели SMA принимает только целочисленный ряд? какая разница что ей усреднять то?

alex_m
Сообщения: 10
Зарегистрирован: 18 мар 2021, 21:30
Благодарил (а): 6 раз

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение alex_m » 18 мар 2021, 23:43

о, научился картинки вставлять!

дело в чем то другом, не в том, что я думал в предыдущем посте.

когда делаю вот такие настройки
screen0.jpg
screen0.jpg (47.59 КБ) 16132 просмотра


то получаю SMA по diff'у
screen.jpg
screen.jpg (33.65 КБ) 16132 просмотра


а вот когда меняю тип на 1, то явно ж видно, что diff есть (синяя линия)
screen1.jpg
screen1.jpg (40.39 КБ) 16132 просмотра


а вот SMA по ней уже NaN
screen2.jpg
screen2.jpg (22.44 КБ) 16132 просмотра


что-то я упускаю, но никак не могу понять что...

Аватара пользователя
evge
Администратор
Сообщения: 1807
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 361 раз
Контактная информация:

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение evge » 19 мар 2021, 05:42

Все что поменял это наименование параметров в _my_MA_MA_MACD и подставил их в MY._my_MA_MA_diff(...). Это всё. В результате MACD_Sign стала отображаться на графике:

MA_fast_type1
MA_slow_type1

MA_MA-01.png
MA_MA-01.png (33.33 КБ) 16108 просмотров


Код: Выделить всё

function Initialize()
{

   IndicatorName = "_my_MA_MA_MACD";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = false;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Price);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
   AddParameter("MA_fast_type1", 2, "тип быстр: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_fast_period", 12, "период быстрой MA");
    AddParameter("MA_slow_type1", 2, "тип медл: 1-SMA/2-EMA/3-WMA");
    AddParameter("MA_slow_period", 26, "период медленной MA");
    AddParameter("MACD_sign_type", 2, "тип сигн MACD: 1-SMA/2-EMA/3-WMA");
    AddParameter("MACD_sign_period", 9, "период сигн MACD");

    AddSeries("MACD_Line", DrawAs.Line, Color.Blue);   // Задаем вид линии индикатора   
    AddSeries("MACD_Sign", DrawAs.Line, Color.Orange);   // Задаем вид линии индикатора
}

function Evaluate()
{

//var sInd = SMA(Input, 10);
//var A = EMA(sInd, 5);   

   var MA_diff = MY._my_MA_MA_diff(Input,(int)MA_fast_type1,(int)MA_fast_period,(int)MA_slow_type1,(int)MA_slow_period);
   var sign_line = SMA(MA_diff, MACD_sign_period);
   
/*   if (MACD_sign_type == 1)
   {
      sign_line = SMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else if (MACD_sign_type == 2)
   {
      sign_line = EMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else if (MACD_sign_type == 3)
   {
      sign_line = WMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }
   else
   {
      sign_line = SMA(MA_diff, MACD_sign_period);
      //MACD_Sign = sign_line[0];
   }*/
   
   MACD_Line = MA_diff[0];
   MACD_Sign = sign_line[0];
}
никогда такого не было и вот опять

Аватара пользователя
evge
Администратор
Сообщения: 1807
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 361 раз
Контактная информация:

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение evge » 19 мар 2021, 06:10

Если брать _my_MA_MA_diff(...) и от него строить SMA, то действительно может выдавать NaN. Есть какая-то проблема в АД4.

даже если его упросить по максимуму и явно брать SMA без параметров type

Код: Выделить всё

function Initialize()
{
   IndicatorName = "_my_MA_MA_diff";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = false;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
    AddParameter("MA_fast_period", 12, "период быстрой MA");
    AddParameter("MA_slow_period", 26, "период медленной MA");
    AddSeries("MA_diff", DrawAs.Line, Color.Blue);   // Задаем вид линии индикатора
}

function Evaluate()
{

   double MA_fast = SMA(Input, MA_fast_period)[0];
   double MA_slow = SMA(Input, MA_slow_period)[0];

   MA_diff = MA_fast - MA_slow;

}


при построении от него SMA выдает NaN.

сам индикатор отображает свои значения, но построенный на графике от него SMA, EMA и т.п. - NaN
никогда такого не было и вот опять

Аватара пользователя
evge
Администратор
Сообщения: 1807
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 361 раз
Контактная информация:

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение evge » 19 мар 2021, 06:18

Заработало так:

Код: Выделить всё

function Initialize()
{
   IndicatorName = "_my_MA_MA_diff";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = false;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
    AddParameter("MA_fast_period", 12, "период быстрой MA");
    AddParameter("MA_slow_period", 26, "период медленной MA");
    AddSeries("MA_diff", DrawAs.Line, Color.Blue);   // Задаем вид линии индикатора
}

function Evaluate()
{

   if (CurrentIndex < Math.Max(MA_fast_period, MA_slow_period)) return;

   double MA_fast = SMA(Input, MA_fast_period)[0];
   double MA_slow = SMA(Input, MA_slow_period)[0];

   MA_diff = MA_fast - MA_slow;

}


попробуйте у себя добавить в скрипт в начале эту строку

Код: Выделить всё

   if (CurrentIndex < Math.Max(MA_fast_period, MA_slow_period)) return;


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

alex_m
Сообщения: 10
Зарегистрирован: 18 мар 2021, 21:30
Благодарил (а): 6 раз

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение alex_m » 19 мар 2021, 14:43

evge писал(а):попробуйте у себя добавить в скрипт в начале эту строку

Код: Выделить всё

   if (CurrentIndex < Math.Max(MA_fast_period, MA_slow_period)) return;

т.е. не будет брать в расчет всё что находится раньше чем максимально заданный период в параметрах.


Так заработало, большое спасибо за совет. Но пока не совсем осознаю почему это помогло.
Читаю про CurrentIndex и MaxIndex в доке
screen4.jpg
screen4.jpg (43.13 КБ) 16017 просмотров


CurrentIndex – возвращает значение текущего индекса бара в момент вызова функции Evaluate(). Мы завершаем выполнение процедуры если СurrentIndex < периодов, а какое значение он имеет? он считается с нуля? Т.е. самый свежий бар на графике имеет currentIndex 0?

А MaxIndex что тогда? Пример из доки сравнения с MaxIndex я вне понимаю.

P.S. вызов скрипта из скрипта с измененными названиями параметров обязательно проверю чуть попозже и отпишусь.

Аватара пользователя
evge
Администратор
Сообщения: 1807
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 361 раз
Контактная информация:

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение evge » 19 мар 2021, 18:55

CurrentIndex == MaxIndex - последний видимый на графике бар.

CurrentIndex == 0 наоборот, самый первый из прочитанной истории.

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

BugsDigger
Сообщения: 533
Зарегистрирован: 11 ноя 2018, 17:11
Благодарил (а): 21 раз
Поблагодарили: 91 раз

Re: Опять про вызов индикатора от индикатора

Непрочитанное сообщение BugsDigger » 19 мар 2021, 19:52

Предположим, что в текущий момент времени нужно рассчитать некоторый индикатор "от начала до конца", где "конец" - текущий момент времени.

По идее для рассчета следовало бы взять все данные от начала времен, начать их обрабатывать и добавлять результат в виде очередной точки к индикатору.

Понятно, что работа с такими объемами данных с практической точки зрения бессмысленна. Поэтому для счета индикатора в буфер данных берется некоторое ограниченное количество точек, а именно MaxIndex+1 (MaxIndex - некоторое предопределенное "разумно-достаточное" число, что-то вроде ~5000). Самый "давний" бар в буфере имеет индекс 0, следующий 1 и т.д. до последнего с индексом MaxIndex. После этого можно начать считать индикатор. Начинаем с самого первого бара в буфере, текущий индекс расчета CurrentIndex=0. Т.к. в любой момент расчета доступны только данные от индекса 0 до CurrentIndex включительно, понятно, что в начальной точке имеем только одну-единственную точку. Рассчитываем нечто по ней, получившийся результат кладем в индикатор; его буфер данных в этот момент также будет содержать 1 точку. Далее смещаемся на 1 точку вперед, CurrentIndex=1, доступны 2 точки входных данных, после расчета индикатора длина его буфера данных станет равной 2 и т.д. до самой последней точки (текущего момента), когда доступны MaxIndex+1 точек входных данных и столько же точек индикатора.

Во многих случаях алгоритм счета таков, что обязательно требуется, скажем, 10 точек входных данных Input и/или, например, 5 уже ранее рассчитанных точек индикатора, а иначе расчет будет некорректен (например, выскочит деление на ноль или обратимся к данным с индексом меньше 0). Если это так, то в процессе счета следует проверять, сколько точек "назад" доступны. Для этого как раз проверяем CurrentIndex. Интересным частным случаем является проверка CurrentIndex==MaxIndex; равенство означает, что достигнут последняя доступная точка буфера (настоящий момент).

В приведенном вами примере из документации видно, что для "регулярного" счета нужна как минимум 1 ранее рассчитанная точка индикатора (EMA[-1]), поэтому в точке CurrentIndex=0 делается нечто другое.

Обратите внимание, что при счете индикатора индексы как бы перевернуты: самая последняя точка буфера (с индексом CurrentIndex) представляется как точка с индексом [0] (EMA=..., что эквивалентно EMA[0]=...), предыдущая (с индексом в буфере CurrentIndex-1) как [-1] (EMA[-1]) и т.д. до последней доступной точки EMA[-CurrentIndex] и Input[-CurrentIndex].

Как-то так, надеюсь, не сильно запудрил мозги. :mrgreen:


Вернуться в «Общие вопросы по разработке»

Кто сейчас на конференции

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