Общие вопросы по разработке > StrategyRay() формат даты точек

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

StrategyRay() формат даты точек

Непрочитанное сообщение evge » 12 фев 2022, 09:05

Для информации сохраню здесь ответ на вопрос в ЛС.

Ещё в бета релизе от 6 мая 2019 и по текущие версии АД4 появилась возможность торговли по линиям граф инструментов с графика.

StrategyRay-01.png
StrategyRay-01.png (9.44 КБ) 8723 просмотра


Появился вопрос в ЛС по поводу какой же формат даты передавать в StrategyRay() для роботов по линии, если это луч?

Замечу, что StrategyRay() можно использовать и в индикаторах.

подсмотрел ответ в TA.dll

используется DataPoint и методы:

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

public static long SecondsFromDateTime(DateTime value)
   {
      return (long)value.Subtract(Standard1990).TotalSeconds;
   }

public static DateTime DateTimeFromSeconds(long value)
   {
      return Standard1990.AddSeconds(value);
   }


т.е. это long кол-ва секунд с начала 1990 года, т.к. Standard1990 это:

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

public static DateTime Standard1990 = new DateTime(1990, 1, 1, 0, 0, 0);


в общем можно получить эти значения с любого бара графика по их индексам смещения (например) или от CurrentIndex запомнить и искать смещение через разницу CurrentIndex текущего бара и гл. переменной CurrentIndex сохраненного бара в истории. Это уже кому как нравится и зависит от задачи.

как получить?

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

DataPoint.SecondsFromDateTime(ДатаВремяБара)


как получить дату время бара?

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

DateTime dt = BarDate(0).Add(BarTime(0));

здесь 0 - это смещение бара назад в историю от текущего. (0 - текущий)

в итоге чтобы задать время двух точек на графике от известных баров можно сделать будет так:

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


//200 баров назад
DateTime dt1 = BarDate(200).Add(BarTime(200));
long bt1 = DataPoint.SecondsFromDateTime(dt1);

//100 баров назад
DateTime dt2 = BarDate(100).Add(BarTime(100));
long bt2 = DataPoint.SecondsFromDateTime(dt2);

//строим луч от даты и времени bt1 до bt2 по ценам 5000 и 5500
var TrendLine = StrategyRay(Input, bt1, 5000, bt2, 5500);



Получаем луч построенный по двум точкам на графике.
Можно использовать для своих нужд и цену или знач. индикаторов сравнивать с значением из TrendLine

Ещё выяснил, что ряд полученный по StrategyRay() не строится непосредственно от точки 1 до точки 2 и далее, строится начиная только с точки 2 и далее.
Думаю, что это сделано для оптимизации, т.к. нет необходимости в стратегии знать какие были значения непосредственно между этими двумя точками, т.к. эта информация никак стратегии не поможет, а вот что содержится для текущего бара уже интересно.

Хотя по оптимизации тут же вопрос возникает.
Зачем тогда вообще получать ряд?
Может быть только одна точка для текущего бара была бы ещё более производительным вариантом.
Какой смысл несет информация от второй точки до текущего бара?!
Получилось как-то неполноценно.
Оптимизация неполная, а с другой стороны и данные неполные, т.е. отсутствует расчет между заданными точками.
Меня бы конечно вариант с полными данными от точки 1 по текущий бар больше устроил.
Но для работы стратегий вообще тут ряд не нужен, а нужен только результат луча на текущем баре.

Это показали тесты отрисовки индикатором данных по ряду TrendLine между двумя точками.
Данные имелись только от второй точки и далее.
Хотел сделать индикатор использующий данные StrategyRay() полученный по экстремумам.

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

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

Re: StrategyRay() формат даты точек

Непрочитанное сообщение BugsDigger » 12 фев 2022, 10:05

Спасибо за информацию.

> как получить дату время бара?

Есть недокументированная ф-ция GetTime(int bar=0), которая сразу возвращает DateTime нужного бара. BarDate и BarTime вызывают ее и выделяют из нее соответствующие части. Трудно сказать, почему ф-ция не документирована.

См. Пара (полезных) недокументашек
https://www.alfadirect4.ru/viewtopic.php?t=600

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

Re: StrategyRay() формат даты точек

Непрочитанное сообщение evge » 12 фев 2022, 11:28

Набросок примера использования StrategyRay()

StrategyRay-02.png
StrategyRay-02.png (39.41 КБ) 8679 просмотров


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

function Initialize()
{
IndicatorName = "StrategyRayDemo";
PriceStudy = true;
AddInput("Input", Inputs.Candle, 1, true, "");
AddSeries("ExtH", DrawAs.Custom, Color.Green);
AddSeries("ExtL", DrawAs.Custom, Color.Red);
AddSeries("HH", DrawAs.Custom, Color.Red);
AddSeries("LL", DrawAs.Custom, Color.Green);
AddParameter("Period", 10, 1);
AddParameter("History", 4, 1);

AddGlobalVariable("H", Types.IntList);
AddGlobalVariable("L", Types.IntList);
}

function Evaluate()
{

// evge 12.02.2022 https://alfadirect4.ru

var I = Input;

// проверяем экстремум ли это
bool isH = true, isL = true;
for (int x = 1; x <= Period; x++)
{
   if (I.High[Period + x] > I.High[Period] || I.High[Period - x] > I.High[Period]) isH = false;
   if (I.Low[Period + x] < I.Low[Period] || I.Low[Period - x] < I.Low[Period]) isL = false;
}

// Сохраним индекс экстремума в List
if (isH)
   {   
   H.Add(CurrentIndex - Period);
   ExtH[Period] = I.High[Period];   
   }
if (isL)
   {
   L.Add(CurrentIndex - Period);
   ExtL[Period] = I.Low[Period];   
   }

// Храним только кол-во не более History последних экстремумов
if (H.Count() > History) H.RemoveAt(0);
if (L.Count() > History) L.RemoveAt(0);

///////////////////
// строим RAYs

//по нисходящим High экстремумам
if (H.Count() >= 2)
{
   // смещение баров экстремумов
   int I0 = 0;
   int I1 = 0;
   for (int x = H.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - H[x];
      I1 = CurrentIndex - H[x-1];
      if (I.High[I0] < I.High[I1]) break;
   }
   
   // экстремумы High нисходящие   
   if (I.High[I0] < I.High[I1])
   {
      DateTime dt1 = BarDate(I0).Add(BarTime(I0));
      long bt1 = DataPoint.SecondsFromDateTime(dt1);
   
      DateTime dt2 = BarDate(I1).Add(BarTime(I1));
      long bt2 = DataPoint.SecondsFromDateTime(dt2);
   
      var TrendLine = StrategyRay(I, bt1, I.High[I0], bt2, I.High[I1]);
      
      //HH[0] = TrendLine[0];
      
      //Дорисовываем (перерисовываем) по экстремумам
      for (int x = 0; x <= I0; x++)
      HH[x] = TrendLine[x];
   }
}

//по восходящим Low экстремумам
if (L.Count() >= 2)
{
   // смещение баров экстремумов
   int I0 = 0;
   int I1 = 0;
   for (int x = L.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - L[x];
      I1 = CurrentIndex - L[x-1];
      if (I.Low[I0] > I.Low[I1]) break;
   }

   // экстремумы Low восходящие   
   if (I.Low[I0] > I.Low[I1])
   {
      DateTime dt1 = BarDate(I0).Add(BarTime(I0));
      long bt1 = DataPoint.SecondsFromDateTime(dt1);
   
      DateTime dt2 = BarDate(I1).Add(BarTime(I1));
      long bt2 = DataPoint.SecondsFromDateTime(dt2);
   
      var TrendLine = StrategyRay(I, bt1, I.Low[I0], bt2, I.Low[I1]);
      
      //LL[0] = TrendLine[0];
      
      //Дорисовываем (перерисовываем) по экстремумам
      for (int x = 0; x <= I0; x++)
      LL[x] = TrendLine[x];
   }
}


// Отрисовка лучей
HH.DrawCircle();
LL.DrawCircle();

// Отрисовка заданных экстремумов
ExtH.DrawArrowDown();
ExtL.DrawArrowUp();

}



если убрать циклическую отрисовку, а оставить только на текущем баре

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

      //HH[0] = TrendLine[0];
      
      //Дорисовываем (перерисовываем) по экстремумам
      for (int x = 0; x <= I0; x++)
      HH[x] = TrendLine[x];


заменив на

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

      HH[0] = TrendLine[0];
      
      //Дорисовываем (перерисовываем) по экстремумам
      //for (int x = 0; x <= I0; x++)
      //HH[x] = TrendLine[x];


и аналогично проделав с Low экстремумами, то отрисовка будет от момента обнаружения экстремума (точнее, отрисовка будет одинаково начата, но не будет дорисовки до значений до второй точки от бара обнаружения) и далее
на скрине ниже оба варианта, но второй с увеличенным размером кружков (Circle) в настройках индикатора

StrategyRay-03.png
StrategyRay-03.png (39.98 КБ) 8676 просмотров
никогда такого не было и вот опять

Jude_Masson
Сообщения: 30
Зарегистрирован: 03 окт 2020, 22:38
Благодарил (а): 12 раз
Поблагодарили: 7 раз

Re: StrategyRay() формат даты точек

Непрочитанное сообщение Jude_Masson » 16 фев 2022, 00:38

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

Я вроде понял код ваш, но вот отредактировать получилось только так. Если я хоть где то убирал if то сразу переставало работать )))

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

     
      I0 = CurrentIndex - H[x];
      I1 = CurrentIndex - H[x-1];
      if (I.High[I0] < I.High[I1]) break;
   }
   
   // экстремумы High нисходящие   
   if (I.High[I0] < I.High[I1])


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

   
      I0 = CurrentIndex - H[x];
      I1 = CurrentIndex - H[x-1];
      if (I.High[I0] < I.High[I1] || I.High[I0] >= I.High[I1]) break;
   }
   
   // экстремумы High нисходящие   
   if (I.High[I0] < I.High[I1] || I.High[I0] >= I.High[I1])

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

Re: StrategyRay() формат даты точек

Непрочитанное сообщение evge » 16 фев 2022, 01:18

Я специально делал рисовать пока не появится новая пара экстремумов

минимумов восходящих и максимумов нисходящих,

как раз изначально прекращало рисовать при появлении нового экстремума

т.е. поиск идёт по всем экстремумам в list и если находится такая пара, то она помещается от неё и рисуется.

если нужно код

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

   int I0 = 0;
   int I1 = 0;
   for (int x = H.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - H[x];
      I1 = CurrentIndex - H[x-1];
      if (I.High[I0] < I.High[I1]) break;
   }


заменить на

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

   int I0 = CurrentIndex - H[H.Count - 1];
   int I1 = CurrentIndex - H[H.Count - 2];


и аналогично

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

   int I0 = 0;
   int I1 = 0;
   for (int x = L.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - L[x];
      I1 = CurrentIndex - L[x-1];
      if (I.Low[I0] > I.Low[I1]) break;
   }


на

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

   int I0 = CurrentIndex - L[L.Count - 1];
   int I1 = CurrentIndex - L[L.Count - 2];


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

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

Re: StrategyRay() формат даты точек

Непрочитанное сообщение evge » 16 фев 2022, 01:44

Ниже пример рисования лучей расчетным путем, без вызова StategyRay.

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

Код стал меньше т.к. ушла часть с поиском времени бара в нужном формате и сам вызов StrategyRay.

Это пример, по необходимости, его можно будет довести до нужного вам состояния или использовать из него алгоритм.

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

function Initialize()
{
IndicatorName = "SoftRayDemo";
PriceStudy = true;
AddInput("Input", Inputs.Candle, 1, true, "");
AddSeries("ExtH", DrawAs.Custom, Color.Green);
AddSeries("ExtL", DrawAs.Custom, Color.Red);
AddSeries("HH", DrawAs.Custom, Color.Red);
AddSeries("LL", DrawAs.Custom, Color.Green);
AddParameter("Period", 10, 1);
AddParameter("History", 4, 1);

// если 0 то перерисовка до первой точки.
// любое иное значение, то рисуем только до найденного нового экстремума
AddParameter("RayToFirst", 0, 0);

AddGlobalVariable("H", Types.IntList);
AddGlobalVariable("L", Types.IntList);
}

function Evaluate()
{

// evge 16.02.2022 https://alfadirect4.ru

var I = Input;

// проверяем экстремум ли это
bool isH = true, isL = true;
for (int x = 1; x <= Period; x++)
{
   if (I.High[Period + x] > I.High[Period] || I.High[Period - x] > I.High[Period]) isH = false;
   if (I.Low[Period + x] < I.Low[Period] || I.Low[Period - x] < I.Low[Period]) isL = false;
}

// Сохраним индекс экстремума в List
if (isH)
   {   
   H.Add(CurrentIndex - Period);
   ExtH[Period] = I.High[Period];   
   }
if (isL)
   {
   L.Add(CurrentIndex - Period);
   ExtL[Period] = I.Low[Period];   
   }

// Храним только кол-во не более History последних экстремумов
if (H.Count() > History) H.RemoveAt(0);
if (L.Count() > History) L.RemoveAt(0);

///////////////////
// строим RAYs

//по нисходящим High экстремумам
if (H.Count() >= 2)
{
   // смещение баров экстремумов
   int I0 = 0;
   int I1 = 0;
   for (int x = H.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - H[x];
      I1 = CurrentIndex - H[x-1];
      if (I.High[I0] < I.High[I1]) break;
   }
   
   // экстремумы High нисходящие   
   if (I.High[I0] < I.High[I1])
   {     
      //Дорисовываем (перерисовываем) по экстремумам
      for (int x = 0; x <= (RayToFirst == 0 ? I0 : I1); x++)
      HH[x] = (double)(x - I0) / (I1 - I0) * (I.High[I1] - I.High[I0]) + I.High[I0];
   }
}

//по восходящим Low экстремумам
if (L.Count() >= 2)
{
   // смещение баров экстремумов
   int I0 = 0;
   int I1 = 0;
   for (int x = L.Count() - 1; x >= 1; x--)
   {
      I0 = CurrentIndex - L[x];
      I1 = CurrentIndex - L[x-1];
      if (I.Low[I0] > I.Low[I1]) break;
   }

   // экстремумы Low восходящие   
   if (I.Low[I0] > I.Low[I1])
   {
      //Дорисовываем (перерисовываем) по экстремумам
      for (int x = 0; x <= (RayToFirst == 0 ? I0 : I1); x++)
      {
      LL[x] = (double)(x - I0) / (I1 - I0) * (I.Low[I1] - I.Low[I0]) + I.Low[I0];
      }
   }
}

// Отрисовка лучей
HH.DrawCircle();
LL.DrawCircle();

// Отрисовка заданных экстремумов
ExtH.DrawArrowDown();
ExtL.DrawArrowUp();

}


Вся логика изменилась на расчет точек прямой. В этом примере убран весь код через StrategyRay.

осталась отрисовка с поиском точек

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

     for (int x = 0; x <= I1; x++)
      HH[x] = (double)(x - I0) / (I1 - I0) * (I.High[I1] - I.High[I0]) + I.High[I0];


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


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

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

Сейчас этот форум просматривают: Bing [Bot] и 14 гостей