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

Общие вопросы по разработке в Альфа-Директ 4. Обсуждение разработки пользовательских индикаторов, стратегий.
Владимир
Сообщения: 84
Зарегистрирован: 14 ноя 2016, 02:17
Благодарил (а): 3 раза
Поблагодарили: 5 раз

Как нарисовать в индикаторе

Непрочитанное сообщение Владимир » 09 янв 2017, 12:06

Доброе время суток! Подскажите как правильно пользоваться функциями рисования. Написал индикатор который должен помечать нужные свечки треугольниками (соединять линиями) но столкнулся с тем как в других языках программирования есть режим наладки где можно по шагам пройти нужные участки программы и найти свою ошибку. Упростил индикатор до минимума. Решил попробовать выделить (пометить) 3 свечку вот, что получается!!! В чём мая ошибка на графике помечены все свечки.
Как можно построить линию по координатам например соединить хай свечи[8] и лою свечи[2]? если данные сохранили в массиве?

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

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

// Обязательные параметры:
IndicatorName = "test"; // Задайте название индикатора и сохраните с данным именем
PriceStudy = true; // Рисовать в области цены (true – да, false – нет)
AddInput("Input", Inputs.Candle); // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
AddSeries("LineHigh", DrawAs.Line, Color.Green); // Задаем вид линии индикатора с именем LineHigh
AddSeries("LineLow", DrawAs.Line, Color.Red); // Задаем вид линии индикатора с именем LineLow
AddSeries("MarkerUp", DrawAs.Custom, Color.Red); // Метим экстремум
AddSeries("MarkerLow", DrawAs.Custom, Color.Yellow); // Метим экстремум

// Дополнительные параметры:
AddParameter("Scan", 163, 1); // сканируемый период
}

function Evaluate()
{
if ((MaxIndex - CurrentIndex) > Scan) return;
{
for (var x=0; x<Scan; x++)
{
/////при нормальных свечах
if (x==2) //
{
MarkerLow=Input.High[x];
MarkerLow.DrawArrowDown();
}
} //закрытие цикла for

}

}
Вложения
пример.jpg
пример.jpg (137.79 КБ) 18342 просмотра

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

Re: Как нарисовать в индикаторе

Непрочитанное сообщение evge » 12 янв 2017, 07:43

Владимир писал(а):но столкнулся с тем как в других языках программирования есть режим наладки где можно по шагам пройти нужные участки программы и найти свою ошибку


Режима отладки в скриптах АД4 нет, но можно для поиска ошибок использовать сохранение данных в лог файл, как пример:

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

LogData(String.Format("Время бара: {0} {1}, Максимальная цена:{2}, Минимальная цена:{3}", BarDate(0), BarTime(0), Input.High[0], Input.Low[0]), IndicatorName);


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

значения будут сохранятся в

X:\Users\ВАШ ПОЛЬЗОВАТЕЛЬ\AppData\Local\Alfa-Direct\Logs\test.log (по имени индикатора в данном случае)

содержание будет примерно таким

2017.01.12 07:58:44.297 Время бара: 14.12.2016 0:00:00 18:30:00, Максимальная цена:17425, Минимальная цена:17382
2017.01.12 07:58:44.297 Время бара: 14.12.2016 0:00:00 18:35:00, Максимальная цена:17425, Минимальная цена:17383
2017.01.12 07:58:44.297 Время бара: 14.12.2016 0:00:00 18:40:00, Максимальная цена:17400, Минимальная цена:17382
2017.01.12 07:58:44.297 Время бара: 14.12.2016 0:00:00 19:05:00, Максимальная цена:17417, Минимальная цена:17333
2017.01.12 07:58:44.297 Время бара: 14.12.2016 0:00:00 19:10:00, Максимальная цена:17365, Минимальная цена:17341

Далее про индикатор - пример

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

MarkerLow=Input.High[x];


означает

присвоить значение High бара со смещением "x" для текущего бара серии MarkerLow.
Т.е. на текущем баре будет отрисовано значение High (3 бара назад)
поэтому и рисует на всех барах, т.к. вы указали, что надо обходить на каждом баре циклом назад на расстояние Scan и брать со смещения 2 значение для текущего бара.

исправленный код, если я правильно понял задачу:

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

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

// Обязательные параметры:
IndicatorName = "testx"; // Задайте название индикатора и сохраните с данным именем
PriceStudy = true; // Рисовать в области цены (true – да, false – нет)
AddInput("Input", Inputs.Candle); // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
AddSeries("LineHigh", DrawAs.Line, Color.Green); // Задаем вид линии индикатора с именем LineHigh
AddSeries("LineLow", DrawAs.Line, Color.Red); // Задаем вид линии индикатора с именем LineLow
AddSeries("MarkerUp", DrawAs.Custom, Color.Red); // Метим экстремум
AddSeries("MarkerLow", DrawAs.Custom, Color.Yellow); // Метим экстремум

// Дополнительные параметры:
AddParameter("Scan", 163, 1); // сканируемый период
}

function Evaluate()
{
if ((MaxIndex - CurrentIndex) > Scan) return;

if (CurrentIndex == MaxIndex)

for (var x=0; x<Scan; x++)
{
   if (x==2)
   {
      MarkerLow[x]=Input.High[x];
   }
} //закрытие цикла for

MarkerLow.DrawArrowDown();

}


Хотя здесь можно обойтись вообще без цикла, если явно известно что надо именно 3ый :) бар, но будем думать что внутри цикла какой-то алгоритм и я его не убрал из примера этого.

Здесь

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

if (CurrentIndex == MaxIndex)


означает, что выполнять цикл мы будем только на последнем баре истории, т.е. сканировать будем от последнего бара и только на нем, а не на каждом баре. Уберите это условие (строку) и увидите, что отрисовка будет на всех барах начиная с 3-го и далее в историю.

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

MarkerLow[x]=Input.High[x];


MarkerLow[x] - [x] означает что мы подставляем (задним числом) значение в MarketLow, т.к. мы не хотим рисовать на текущем баре.
А чтобы это значение нарисовалось надо на кажлом баре вызывать DrawArrowDown, т.к. заранее мы не знаем надо ли рисовать или нет. Поэтому

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

MarkerLow.DrawArrowDown();


Вынесен за пределы цикла и условия CurrentIndex == MaxIndex, и выполняется для всех баров. Но отрисовывать будет только на барах где задано значение, даже задним числом, как в нашем примере MarkerLow[x].

Владимир писал(а):Как можно построить линию по координатам например соединить хай свечи[8] и лою свечи[2]? если данные сохранили в массиве?


пример

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

function Initialize()
{
IndicatorName = "testz";
PriceStudy = true;
AddInput("Input", Inputs.Candle);
AddSeries("Line", DrawAs.Line, Color.Green);

}

function Evaluate()
{

if (CurrentIndex == MaxIndex)
{
   Line[2]=Input.Low[2];
   Line[7]=Input.High[7];
}

Line.DrawLine();

}
никогда такого не было и вот опять

Владимир
Сообщения: 84
Зарегистрирован: 14 ноя 2016, 02:17
Благодарил (а): 3 раза
Поблагодарили: 5 раз

Re: Как нарисовать в индикаторе

Непрочитанное сообщение Владимир » 12 янв 2017, 17:58

Спасибо большое evge ! Буду пробывать. Плохо конечно, что в документации по индикаторам нет примеров с картинками и более подробных комментариев для новичков. Поэтому многие и путаются как и я.

Владимир
Сообщения: 84
Зарегистрирован: 14 ноя 2016, 02:17
Благодарил (а): 3 раза
Поблагодарили: 5 раз

Re: Как нарисовать в индикаторе

Непрочитанное сообщение Владимир » 16 янв 2017, 14:56

Добрый день! Подскажите не совсем понятно:
1 как задать толщину и тип линии?
2 как нарисовать восходящий тренд зеленым, нисходящий красным (используя массив) ?
3 как можно нарисовать луч и можно ли получать числовые значения этого луча на нулевой свече?
Эта попытка написать индикатор "Волны Вульфа" описание его полно в интернете если кому интересно.


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

function Initialize()
{
// Область определения параметров индикатора
// Обязательные параметры:
   IndicatorName = "WolfeWave";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
   AddSeries("LineHigh", DrawAs.Line, Color.Green);   // Задаем вид линии индикатора с именем LineHigh
   AddSeries("LineLow", DrawAs.Line, Color.Red);   // Задаем вид линии индикатора с именем LineLow 
   AddSeries("MarkerUp", DrawAs.Custom, Color.Red);   // Метим экстремум
   AddSeries("MarkerLow", DrawAs.Custom, Color.Yellow);   // Метим экстремум

// Дополнительные параметры:
 AddParameter("ExsN1", 80, 1);
 AddParameter("Scan", 163, 1); // сканируемый период
 //AddParameter("имя переменной", период, множитель),  требующий размер истории 163 баров ( т.е. 163*1)
 AddGlobalVariable("Kbuy", Types.Double, 0.0);  //выводим значение предпологаемой переменной цены покупки
 //AddGlobalVariable("ExstremaNumber", Types.Int, 80); // Задаем число экстремумов
 AddGlobalVariable("NaprHelp", Types.Int,1); // Задаем число экстремумов
 AddGlobalVariable("XHighN", Types.Int);   //переменная хранения номера свечи хая для сравнения
 AddGlobalVariable("XLowN", Types.Int);     //переменная хранения номера свечи лоу для сравнения
//AddGlobalVariable("ExstremaNumber", Types.Int);

}

function Evaluate()
{ var ExstremaNumber=ExsN1/1;
double [] Buf_High = new double[ExstremaNumber];   // Объявление массивов цен (под буферы индикатора)
double [] Buf_Low = new double[ExstremaNumber];   // Объявление массивов цен (под буферы индикатора)
int [] Buf_time_High = new int[ExstremaNumber];   // Объявление массивов время цены (под буферы индикатора)
int [] Buf_time_Low = new int[ExstremaNumber];   // Объявление массивов время цены (под буферы индикатора)

   if ((MaxIndex - CurrentIndex) > Scan) return;
   {
    if (CurrentIndex == MaxIndex)
{
   var Napr=0; //направление движения цены 0- нет; 1-лонг; 2-шорт;
  //  var NaprHelp=1; //изменение направления ;
   var IzNapr=0; //изменение направления  0- нет; 1-лонг; 2-шорт;
    var HighX= Input.High[Scan];   //переменная хранения значения хая для сравнения
    var LowX=Input.Low[Scan];     //переменная хранения значения лоу для сравнения
    var High = Input.High[Scan];  //переменная сравнения хая
   var Low = Input.Low[Scan];    //переменная сравнения лоу
    XHighN=Scan-1; XLowN=Scan-1;
  for (var x= Scan-1; x>0; x--) 
   {
 /////при нормальных свечах
     if (Input.Open[x]<Input.Close[x]) //проверяем закрытие свечи лонг шорт
        {//лонг
          if (High<Input.Close[x])
          {   // считаем, что произошло обновление High. Поэтому переписываея значения хая и лоу
          Napr=1;   //лонг
          High=Input.High[x];
          Low=Input.Low[x];
          HighX=High; //сохраняем значение хая в памяти
          XHighN=x;   //сохраняем значение в памяти
          }
      }
      else
          {//шорт
           if (Low>Input.Close[x])
            { // считаем, что произошло обновление low. Поэтому переписываея значения хая и лоу
             Napr=2;  //шорт
             High=Input.High[x];
             Low=Input.Low[x];
             LowX=Low; //сохраняем значение лоу в памяти
             XLowN=x; //сохраняем значение в памяти
            }
           }
 /////при формировании свечей с гепами
     if (Input.Open[x]>Input.Close[x]) //проверяем закрытие свечи лонг шорт
        {//лонг
          if (High<Input.Open[x])
          {   // считаем, что произошло обновление High. Поэтому переписываея значения хая и лоу
          Napr=1;   //лонг
          High=Input.High[x];
          Low=Input.Low[x];
          HighX=High; //сохраняем значение хая в памяти
          XHighN=x;   //сохраняем значение в памяти
          }
      }
      else
          {//шорт
           if (Low>Input.Open[x])
            { // считаем, что произошло обновление low. Поэтому переписываея значения хая и лоу
             Napr=2;  //шорт
             High=Input.High[x];
             Low=Input.Low[x];
             LowX=Low; //сохраняем значение лоу в памяти
              XLowN=x; //сохраняем значение в памяти
           }
           }

    //заполняем буфер хаёв
            if (Napr==NaprHelp && Napr==2)    //смена направления с лонга в шорт
            {
              for (var ch=ExstremaNumber-1; ch>0; ch--) //ExstremaNumber-1
              {
               Buf_High[ch]=Buf_High[ch-1];
               Buf_time_High[ch]=Buf_time_High[ch-1];
               }
              Buf_High[0]=HighX;
              Buf_time_High[0]=XHighN;
              NaprHelp=1;
             }
   //заполняем буфер лоёв
            if (Napr==NaprHelp && Napr==1)    //смена направления с шорта в лонг
            {
              for (var Lo=ExstremaNumber-1; Lo>0; Lo--)  //ExstremaNumber-1
              {
               Buf_Low[Lo]=Buf_Low[Lo-1];
                Buf_time_Low[Lo]=Buf_time_Low[Lo-1];
               }
              Buf_Low[0]=LowX;
              Buf_time_Low[0]=XLowN;
              NaprHelp=2;
             }
   /////////////////////////////////////
   } //закрытие цикла for
 
  ///пробуем строить  график
        for(var i=0; i<ExstremaNumber-1; i++)
           {
            if (MarkerLow[Buf_time_Low[i]]>0 || Buf_Low[i]>0)// нулевые данные игнорируем для построения
            MarkerLow[Buf_time_Low[i]]=Buf_Low[i]; //данные для построения меток хаёв
              if (MarkerUp[Buf_time_High[i]]>0 || Buf_High[i]>0) // нулевые данные игнорируем для построения
              MarkerUp[Buf_time_High[i]]=Buf_High[i];  //данные для построения меток лоёв
          if ((MarkerLow[Buf_time_Low[i]]>0 || Buf_Low[i]>0) && (MarkerUp[Buf_time_High[i]]>0 || Buf_High[i]>0))
              {
               LineHigh[Buf_time_Low[i]]=Buf_Low[i];
               LineHigh[Buf_time_High[i]]=Buf_High[i];
              }
            }//построение графика закончено
  }
}
MarkerUp.DrawArrowDown();
MarkerLow.DrawArrowUp();
LineHigh.DrawLine();
LineLow.DrawLine();
}


Вложения
Пример индикатора.jpg

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

Re: Как нарисовать в индикаторе

Непрочитанное сообщение evge » 16 янв 2017, 20:35

Владимир писал(а):1 как задать толщину и тип линии?


В документации по скриптам индикаторов и стратегий это есть:

DrawLine – рисовать линию на данном баре от предыдущего бара

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

// отрисует по заданным параметрам индикатора
Series.DrawLine();
// отрисует линию как нам хочется
Series.DrawLine(Color color, LineStyles style, int width);

Стили (style):
Line.Solid;
Line.DashBig;
Line.DashSmall;
Line.Dot;

Владимир писал(а):2 как нарисовать восходящий тренд зеленым, нисходящий красным (используя массив) ?


пример индикатора EMA с отрисовкой восходящей и нисходящей линии разными цветами. см. второе сообщение.

Владимир писал(а):3 как можно нарисовать луч и можно ли получать числовые значения этого луча на нулевой свече?


Вот пример, один из первых индикаторов, который я выложил здесь TrendLines, рисует луч между 2 точками на графике в истории до 0 точки. Берем уравнение прямой и рисуем между 2 точками до третьей точки линию
Т.е. если имеем 2 точки на графике, можно нарисовать прямую (луч) между этими точками до 0-ой точки.
В коде можно подглядеть как делал это я.
никогда такого не было и вот опять

Владимир
Сообщения: 84
Зарегистрирован: 14 ноя 2016, 02:17
Благодарил (а): 3 раза
Поблагодарили: 5 раз

Re: Как нарисовать в индикаторе

Непрочитанное сообщение Владимир » 18 янв 2017, 15:59

Добрый день! Дело в том "evge" , что документация в альфа ( "Terminal 4.0 скрипты пользовательскич индикаторов и стратегий") написана как справочник, поэтому новичку при написании пользовательских индикаторов не совсем понятно как его применять. Поэтому многие и ищут более понятные примеры, а задать вопрос не каждый решается!
Для тех кто не понял приведу простой пример

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

function Initialize()
{
// Область определения параметров индикатора
// Обязательные параметры:
   IndicatorName = "Test";   // Задайте название индикатора и сохраните с данным именем
   PriceStudy = true;   // Рисовать в области цены (true – да, false – нет)
   AddInput("Input", Inputs.Candle);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
   AddSeries("LineHigh", DrawAs.Custom, Color.Green);   // Задаем вид линии индикатора с именем LineHigh
   AddSeries("LineLow", DrawAs.Custom, Color.Red);   // Задаем вид линии индикатора с именем LineLow
   AddSeries("MarkerUp", DrawAs.Custom, Color.Red);   // Метим экстремум
   AddSeries("MarkerLow", DrawAs.Custom, Color.Yellow);   // Метим экстремум
// Дополнительные параметры:
 AddParameter("Scan", 163, 1); // сканируемый период

}

function Evaluate()
{
   if ((MaxIndex - CurrentIndex) > Scan) return;
   {
    if (CurrentIndex == MaxIndex)
{
  ///пробуем строить  график
               
            MarkerLow[20]=Input.Low[20]; //данные для построения меток хаёв
                           
         MarkerUp[10]=Input.High[10];  //данные для построения меток лоёв
       
               LineHigh[21]=Input.Low[21]; //данные для построения зеленой линии
               LineHigh[9]=Input.High[9];

       LineLow[9]=Input.High[9];    //данные для построения красной линии
       LineLow[1]=Input.Low[1];
   //построение графика закончено
  }
}
MarkerUp.DrawArrowDown();
MarkerLow.DrawArrowUp();
LineHigh.DrawLine(Color.Green, Line.Solid, 2); //Series.DrawLine(Color color, LineStyles style, int width);
LineLow.DrawLine(Color.Red, Line.Solid, 2);  //название линии.DrawLine(цвет линии, стиль линии, толщина);
}


рисунок пример2

но при построении с использованием массива почему то линии строится непрерывной, точки экстремума строятся без проблем:
Buf_time_Low - массив координат свечки по времени
Buf_Low - массив координат свечки цена
Buf_time_High - массив координат свечки по времени
Buf_High - массив координат свечки цена

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

  ///пробуем строить  график
        for(var i=0; i<ExstremaNumber-1; i++)
           {
            if (MarkerLow[Buf_time_Low[i]]>0 || Buf_Low[i]>0)// нулевые данные игнорируем для построения
            MarkerLow[Buf_time_Low[i]]=Buf_Low[i]; //данные для построения меток хаёв
              if (MarkerUp[Buf_time_High[i]]>0 || Buf_High[i]>0) // нулевые данные игнорируем для построения
              MarkerUp[Buf_time_High[i]]=Buf_High[i];  //данные для построения меток лоёв
          if ( Buf_Low[i]>0 &&  Buf_High[i]>0)
              {
               LineHigh[Buf_time_Low[i]]=Buf_Low[i];  //Строим линию зелёную
               LineHigh[Buf_time_High[i]]=Buf_High[i];
              }
            }//построение графика закончено
  }
}
MarkerUp.DrawArrowDown();
MarkerLow.DrawArrowUp();
LineHigh.DrawLine(Color.Green, Line.Solid, 2);
LineLow.DrawLine(Color.Red, Line.Solid, 2);
}

Пример3
Вложения
пример3.jpg
пример2.jpg
пример2.jpg (67.98 КБ) 18183 просмотра


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

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

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