Общие вопросы по разработке > Проблема с Types.DoubleList

Общие вопросы по разработке в Альфа-Директ 4. Обсуждение разработки пользовательских индикаторов, стратегий.
nordseven
Сообщения: 39
Зарегистрирован: 05 мар 2016, 19:39
Благодарил (а): 6 раз
Поблагодарили: 1 раз

Проблема с Types.DoubleList

Непрочитанное сообщение nordseven » 04 май 2018, 22:09

Простой индикатор рисующий уровни по High и Low.
Формирую "levelsList" из "High" и "Low". Если значений в "levelsList" больше чем параметр "MaxLevels" то удаляю лишние с КОНЦА "levelsList".
И всё работает. Пример ниже.

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 10); //Грузим историю
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      levelsList.Insert(0, Input.High[0]);
      levelsList.Insert(0, Input.Low[0]);
      LogData(String.Format("{0}; {1}; {2}; {3};", "Первые два уровня добавлены. High: " + Input.High[0], " Low: " + Input.Low[0], " Бар индекс: " + CurrentIndex, " в массиве: " + levelsList.Count), IndicatorName);

      if (levelsList.Count > (int)MaxLevels)
      { 
         var tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(levelsList.Count-1);
         LogData(String.Format("{0}; {1};", "Уровень " + tmp + " удалён", " Бар индекс: " + CurrentIndex), IndicatorName);
         tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(levelsList.Count-1);
         LogData(String.Format("{0}; {1};", "Уровень " + tmp + " удалён", " Бар индекс: " + CurrentIndex), IndicatorName);
      }

      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
          }
   
      A = 0.0;
}


Теперь если начать удалять не с конца "levelsList" а с начала вот так:

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

         var tmp = levelsList[0];
         levelsList.RemoveAt(0);
         LogData(String.Format("{0}; {1};", "Уровень " + tmp + " удалён", " Бар индекс: " + CurrentIndex), IndicatorName);
         tmp = levelsList[0];
         levelsList.RemoveAt(0);
         LogData(String.Format("{0}; {1};", "Уровень " + tmp + " удалён", " Бар индекс: " + CurrentIndex), IndicatorName);

У меня происходит зависание всего Альфа директового хозяйства и уровни не рисуются.
А удалять мне нужно и в конце и в начале и в середине. SOS!

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

Re: Проблема с Types.DoubleList

Непрочитанное сообщение evge » 05 май 2018, 11:25

Не зависает

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 10); //Грузим историю
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      levelsList.Insert(0, Input.High[0]);
      levelsList.Insert(0, Input.Low[0]);

      if (levelsList.Count > (int)MaxLevels)
      { 
         var tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(0);
         //levelsList.RemoveAt(levelsList.Count-1);
         tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(0);
         //levelsList.RemoveAt(levelsList.Count-1);
      }
     
      ShowMessage(levelsList.Count);

      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
       }
 
      A = 0.0;
}


но и не рисует последние уровни т.к. достигнув MaxLevels вы их после добавления через Insert(0...) сразу же и удаляете через RemoveAt(0)

добавлять тогда нужно в конец через Add(...) без индекса.

вот так всё работает, с удалением через RemoveAt(0)

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 10); //Грузим историю
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      levelsList.Add(Input.High[0]);
      levelsList.Add(Input.Low[0]);

      if (levelsList.Count > (int)MaxLevels)
      { 
         var tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(0);
         //levelsList.RemoveAt(levelsList.Count-1);
         tmp = levelsList[levelsList.Count-1];
         levelsList.RemoveAt(0);
         //levelsList.RemoveAt(levelsList.Count-1);
      }
     
      ShowMessage(levelsList.Count);

      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
       }
 
      A = 0.0;
}
никогда такого не было и вот опять

nordseven
Сообщения: 39
Зарегистрирован: 05 мар 2016, 19:39
Благодарил (а): 6 раз
Поблагодарили: 1 раз

Re: Проблема с Types.DoubleList

Непрочитанное сообщение nordseven » 05 май 2018, 12:47

Ну на самом деле я привел здесь упрощенный индикатор чтобы показать проблему... а проблема есть. Индекс в DoubleList должен перестаиваться, а он почему-то не перестраивается. В моем реальном индикаторе мне нужно удалять уровни и в начале листа и в конце и в середине.

Если я удаляю два уровня в начале их должны замещать уровни с индексом 2 и 3.

ensh
Сообщения: 220
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 40 раз

Re: Проблема с Types.DoubleList

Непрочитанное сообщение ensh » 05 май 2018, 14:41

Все должно работать. При декомпиляции индикатора, в коде никакой грязи не обнаружено. Идет работа со стандартным List<double>.

Видимо, что-то еще в программе пошло не так и наложилось на выполнение индикатора.

Кстати, не пользуйтесь такими сложными операторами форматирования, почти весь декомпилированный код индикатора - работа со строками и форматами, это очень сильно тормозит работу индикатора если что.

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

Re: Проблема с Types.DoubleList

Непрочитанное сообщение evge » 05 май 2018, 14:53

nordseven писал(а):Если я удаляю два уровня в начале их должны замещать уровни с индексом 2 и 3.


Второй пример, что привел я, именно это и делает.
в вашем простом примере вы добавляете в начало списка и сразу же эти же элементы удаляете.
Добавляйте в конец списка, как это сделал я во втором листинге через Add() вместо Insert(0...)

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

      levelsList.Add(Input.High[0]);
      levelsList.Add(Input.Low[0]);


если добавлять через Insert(0...) в начало списка, а затем сразу же их и удалять RemoveAt(0...) то конечно ничего в списке не сдвинется.
никогда такого не было и вот опять

nordseven
Сообщения: 39
Зарегистрирован: 05 мар 2016, 19:39
Благодарил (а): 6 раз
Поблагодарили: 1 раз

Re: Проблема с Types.DoubleList

Непрочитанное сообщение nordseven » 07 май 2018, 00:55

Да какая разница. Я добавил значение, индекс пересчитался - всё. Листу времени обработать добавленное значение не хватает?
Почему я о костылях должен думать?

Хорошо, усложняем задачу. Удалять нужно в соответствии с приоритетами.
Добавляю новый лист с приоритетами.

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 10); //Сколько дней истории грузим
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 AddGlobalVariable("priorityList", Types.DoubleList);
 AddGlobalVariable("priority", Types.Int, 0);

 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      if(priority > 4) priority = 0;
      else priority++;

      levelsList.Add(Input.High[0]);
      priorityList.Add(priority);
      
      levelsList.Add(Input.Low[0]);
      priorityList.Add(priority);
             
      if (levelsList.Count > (int)MaxLevels)
      { 
         var delCount = 0;
         for( var i = 0; i < levelsList.Count; i++)
         {
            if(priorityList[i] == 1)
            {
               levelsList.RemoveAt(i);
               priorityList.RemoveAt(i);
               delCount++;
            }
            if(delCount >=2) break;
         }
      }
      
      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
       }


   
      A = 0.0;
}


Висим... а если вместо priorityList.RemoveAt(i); вставить priorityList.RemoveAt(0); - работаем.

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

Re: Проблема с Types.DoubleList

Непрочитанное сообщение evge » 07 май 2018, 08:58

nordseven писал(а):Да какая разница.


Разница существенная.

Возможно, вы не поняли сути того что я изложил.

Конкретно о вашем первом примере:

1. Добавление в начало списка

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

levelsList.Insert(0, Input.High[0]);
levelsList.Insert(0, Input.Low[0]);


2. Проверка на превышение кол-ва

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

if (levelsList.Count > (int)MaxLevels)


при выполнении этого условия вы удаляете эти же элементы через

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

levelsList.RemoveAt(0);


т.е. те же элементы, что пару строк назад добавили через Insert(0, Input.High[0]) и Insert(0, Input.Low[0])

Ничего в итоге не сдвинется в списке, т.к. добавив элементы вы их удаляете с тех же позиции по индексу 0.

Если бы вы добавляли элементы в конец списка через Add(), а удаляли из начала, всё бы сдвигалось и список наполнялся новыми значениями.

По поводу второго примера

1. Скомпилировал ваш код.
2. Добавил индикатор на график и...
3. Терминал не завис.

Висим - это значит не работает индикатор или зависает терминал?

Код отработал, уровни отрисовываются, только не последние (как вы скорее хотите), а те что получилось по условию сформировать ранее.
Нашёл их на графике подвигав ОСЬ цены.

Всё отработало, проблема просто в условиях.

Ваш список заполнился до MaxLevels приоритетами != 1 и далее пошёл заполнятся бесконечно с индексами уже большими чем MaxLevels (может поэтому ваш терминал и зависает).

В цикле вы конечно же ищите приоритеты == 1 и успешно их удаляете по индексу, но учтите, что это индексы уже больше чем MaxLevels.

В конце ваш код отрисует только значения списка от 0 до Maxlevels, но код поиска приоритетов == 1 с этой размерностью ничего не сделает, т.к. там уже сосредоточились элементы приоритеты которых != 1.

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

      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
          }


Проблемы вашего кода:

1. Бесконтрольно добавляются новые элементы в КОНЕЦ списка. Список будет расти бесконечно. Сделайте ShowMessage(levelsList.Count) в любой части кода, если терминал не зависнет, успеете увидеть как список растет без ограничения.
2. Ваш код отрисует уровни очень старые и обновлять их перестанет, т.к. в первых уровнях от 0 до MaxLevels не останется приоритетов == 1. Какие уровни отрисуются, это уже зависит от того с какого момента пошёл обрабатывать историю этот индикатор.

nordseven писал(а):Я добавил значение, индекс пересчитался - всё. Листу времени обработать добавленное значение не хватает?


Списки работают корректно, некорректные условия в вашем коде.

nordseven писал(а):Почему я о костылях должен думать?


Костылей не вижу никаких. О чем речь?
никогда такого не было и вот опять

nordseven
Сообщения: 39
Зарегистрирован: 05 мар 2016, 19:39
Благодарил (а): 6 раз
Поблагодарили: 1 раз

Re: Проблема с Types.DoubleList

Непрочитанное сообщение nordseven » 07 май 2018, 11:32

С первой задачей всё понятно.
Ну да да опять пример не очень удачный
Вот последний пример который я надеюсь прояснит мои затруднения с учетом ваших последних комментариев. Зависает весь терминал. :D

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 1); //Сколько дней истории грузим
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 AddGlobalVariable("priorityList", Types.DoubleList);
 AddGlobalVariable("priority", Types.Int, 0);

 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      //Создаем приоритет
      if(priority > 10) priority = 0;
      else priority++;
      
      //Добавляю уровни в начало просто чтобы первыми отрисовывались последние добавленные, чтобы не бегать по графику и их не искать.
      levelsList.Insert(0, Input.High[0]);
      //Назначаем уровню приоритет
      priorityList.Insert(0, priority);
                           
      //Количество уровней в списке на данный момент (здесь я надеюсь что один бар истории равен одному выполнению функции Evaluate(). Это я так на всякий случай).
      var countLvls = levelsList.Count;          
      //Если количество уровней в списке превышает заданное максимальное количество уровней, начинаем их из списка удалять до тех пор пока их не станет меньше, чем заданное максимальное количество                   
      while ((int)MaxLevels <= countLvls)
      {
         //тригер удаления уровня из списка.
         var lvlDeleted = false;
         //текущий приоритет по которому осуществляется поиск уровня для удаления
         var wrkPriority = 0;
         //до тех пор пока уровень не удален перебираем приоритеты и ищем уровень для удаления.
         while (!lvlDeleted)
         {
            //выставляем текущий приоритет для удаления уровня. Оставляем только уровни с приоритетом 10.
            if(wrkPriority > 9) wrkPriority = 0;
            else wrkPriority++;
            //Ищем
            for (var i = 0; i < countLvls; i++)
            {
               //если нашли
               if(priorityList[i] == wrkPriority)
               {
                  //удаляем уровень с данным индексом из списка уровней
                  levelsList.RemoveAt(i);
                  //удаляем уровень с данным индексом из списка приоритетов
                  priorityList.RemoveAt(i);
                  //говорим что уровень удален
                  lvlDeleted = true;
                  //уменьшаем количество уровней в списке на 1.
                  countLvls--;
                  //прерываем цикл for
                  break;
               }
            }
         }
      }
      
      //рисуем уровни
      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
       }


      A = 0.0;
}




nordseven
Сообщения: 39
Зарегистрирован: 05 мар 2016, 19:39
Благодарил (а): 6 раз
Поблагодарили: 1 раз

Re: Проблема с Types.DoubleList

Непрочитанное сообщение nordseven » 07 май 2018, 12:00

Блин в цикл из-за приоритета уходит. Но всё равно глючная фигня получается

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

function Initialize()
{
// Область определения параметров индикатора

// Обязательные параметры:
 IndicatorName = "GHI";   // Задайте название индикатора и сохраните с данным именем
 PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
 AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи
 AddSeries("A", DrawAs.Line, Color.Red, false);   // Задаем вид линии индикатора A

// Дополнительные параметры:
 AddParameter("History", 600, 1); //Сколько дней истории грузим
 AddParameter("MaxLevels", 10); //Максимальное количество уровней
 AddGlobalVariable("levelsList", Types.DoubleList);
 AddGlobalVariable("priorityList", Types.DoubleList);
 AddGlobalVariable("priority", Types.Int, 0);

 
 AddLevel(0, Color.Red, "A"); 
 AddLevel(1, Color.Red, "A"); 
 AddLevel(2, Color.Red, "A"); 
 AddLevel(3, Color.Red, "A");
 AddLevel(4, Color.Red, "A"); 
 AddLevel(5, Color.Red, "A");
 AddLevel(6, Color.Red, "A"); 
 AddLevel(7, Color.Red, "A");
 AddLevel(8, Color.Red, "A"); 
 AddLevel(9, Color.Red, "A");
}

function Evaluate()
{
      //Создаем приоритет
      if(priority > 10) priority = 0;
      else priority++;
     
      //Добавляю уровни в начало просто чтобы первыми отрисовывались последние добавленные, чтобы не бегать по графику и их не искать.
      levelsList.Insert(0, Input.High[0]);
      //Назначаем уровню приоритет
      priorityList.Insert(0, priority);
                           
      //Количество уровней в списке на данный момент (здесь я надеюсь что один бар истории равен одному выполнению функции Evaluate(). Это я так на всякий случай).
      var countLvls = levelsList.Count;           
      //Если количество уровней в списке превышает заданное максимальное количество уровней, начинаем их из списка удалять до тех пор пока их не станет меньше, чем заданное максимальное количество                   
      while ((int)MaxLevels <= countLvls)
      {
         //тригер удаления уровня из списка.
         var lvlDeleted = false;
         //текущий приоритет по которому осуществляется поиск уровня для удаления
         var wrkPriority = 0;
         //до тех пор пока уровень не удален перебираем приоритеты и ищем уровень для удаления.
         while (!lvlDeleted)
         {
            if(wrkPriority > 10) wrkPriority = 0;
            else wrkPriority++;
            //Ищем
            for (var i = 0; i < countLvls; i++)
            {
               //если нашли
               if(priorityList[i] == wrkPriority)
               {
                  //удаляем уровень с данным индексом из списка уровней
                  levelsList.RemoveAt(i);
                  //удаляем уровень с данным индексом из списка приоритетов
                  priorityList.RemoveAt(i);
                  //говорим что уровень удален
                  lvlDeleted = true;
                  //уменьшаем количество уровней в списке на 1.
                  countLvls--;
                  //прерываем цикл for
                  break;
               }
            }
         }
      }
     
      //рисуем уровни
      for(var z = 0; z < levelsList.Count; z++)
       {
           if((int)MaxLevels > z) Levels[z].Level = levelsList[z];
       }


      A = 0.0;
}
Последний раз редактировалось nordseven 07 май 2018, 12:01, всего редактировалось 1 раз.

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

Re: Проблема с Types.DoubleList

Непрочитанное сообщение evge » 07 май 2018, 12:01

сразу скажу что для последнего ("живого бара") это не так

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

      //Количество уровней в списке на данный момент (здесь я надеюсь что один бар истории равен одному выполнению функции Evaluate(). Это я так на всякий случай).
      var countLvls = levelsList.Count;     


Каждый тик будет вызываться Evaluate() для последнего бара, т.е. пока он рисуется.

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


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

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

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