Могли бы вы рассказать о случае, когда участник форума оказался полезным в вашей работе, и можете ли вы описать это подробно? - страница 11

 

p.s. единственное, мне бы хотелось получить аргументированное пояснение -- почему Артём использует в mql5 -- индексацию буферных массивов как mql4 -- но думаю, что получу ответ в стиле "мне так удобно" -- хотя, Артём говорит, что делал пояснения на этот счёт -- если делал, то полезно бы привести ссылку на его такое пояснение.

 
Andrey F. Zelinsky #:

я отвечаю так, как я понял твой вопрос -- так понимаю, я твой вопрос не понял?


и потом -- для меня эта тема себя исчерпала -- слишком много времени мной потрачено на информационно пустое для меня обсуждение.

я не использую схему Артёма -- как по мне, его схема устаревшая -- я использую схему с индексацией буферных массивов как mql5 (от истории к текущему бару) -- я даже в индикаторах mql4 использую индексацию как в mql5.

Ну так ведь сам решил поучаствовать. Единственно в чём я с тобой согласен, так это не надо никому ничего навязывать. Если ты считаешь оправданным поиск бара на котором оборвалась связь, так и считай его. На мой взгляд это совсем никчёмное занятие. Прибавилось баров больше чем 1, пересчитали весь индикатор и все дела.

А если связь оборвалась на середине бара и close не действительно, объём не соответствует… Его ведь надо пересчитать… А в prev_calculated этот бар уже считался, когда он был последним, текущим.

А вот кстати… Представь ситуацию, что бары прибавились не только в конце истории. Не только самые правые, а есть ещё и в середине. Да, если работать на компе IBM 386 то конечно……………

 
Andrey F. Zelinsky #:

p.s. единственное, мне бы хотелось получить аргументированное пояснение -- почему Артём использует в mql5 -- индексацию буферных массивов как mql4 -- но думаю, что получу ответ в стиле "мне так удобно" -- хотя, Артём говорит, что делал пояснения на этот счёт -- если делал, то полезно бы привести ссылку на его такое пояснение.

Просто не хочет вникать в другие варианты, не хватает времени. И это обсуждение новичкам даст гораздо больше чем все примеры в CodeBase. Так-что твоё время потрачено не зря.

 
Alexey Viktorov #:

А вот кстати… Представь ситуацию, что бары прибавились не только в конце истории. Не только самые правые, а есть ещё и в середине. Да, если работать на компе IBM 386 то конечно……………

этот момент тестировал -- при расширении истории влево (доливка) -- сам движок МТ сбрасывает prev_calculated в ноль -- т.е. если в индикаторе схема движения по барам корректная -- то она корректно отработает такую ситуацию.

 
Andrey F. Zelinsky #:

этот момент тестировал -- при расширении истории влево (доливка) -- сам движок МТ сбрасывает prev_calculated в ноль -- т.е. если в индикаторе схема движения по барам корректная -- то она корректно отработает такую ситуацию.

И это не зависит от направления индексации принятой программистом. Так-что никаких проблем.

 
Alexey Viktorov #:

Просто не хочет вникать в другие варианты, не хватает времени. И это обсуждение новичкам даст гораздо больше чем все примеры в CodeBase. Так-что твоё время потрачено не зря.

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

если не вникать -- то количество никогда не превратится в качество.

"зачем заморачиваться", "зачем вникать, итак работает" -- это когда количество превращается только в бестолковое количество.

 
Alexey Viktorov #:

И это не зависит от направления индексации принятой программистом. Так-что никаких проблем.

да, от направления индексации это не зависит -- зависит от корректной отработки prev_calculated.

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

 
Andrey F. Zelinsky #:
потом исправил своё пояснение -- пояснил, что ситуацию D твой алгоритм вообще не отрабатывает.

Итак. Вот утверждения:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Могли бы вы рассказать о случае, когда участник форума оказался полезным в вашей работе, и можете ли вы описать это подробно?

Andrey F. Zelinsky, 2024.10.05 13:53


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


//--- Проверка и расчёт количества просчитываемых баров
   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-1;
      ArrayInitialize(BufferXXX,EMPTY_VALUE); // инициализация буферов начальными значениями
     }
//--- Цикл
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      // расчёт
     }

рассмотрим четыре примера.

пусть есть 10 баров -- 9 8 7 6 5 4 3 2 1 0


ситуация А -- начало расчёта

rates_total =10

prev_calculated =0

limit =10 -- и надо отнять 1, чтобы не был выход за пределы массива в цикле for(int i=limit; i>=0; i--) -- идёт перерасчёт всей истории от бара 9 до 0


ситуация В -- текущий бар

rates_total =10

prev_calculated =10

limit =0 -- идёт перерасчёт нового бара


ситуация С -- новый бар -- бары:  10 9 8 7 6 5 4 3 2 [1 0]

rates_total =11

prev_calculated =10 -- остановились на баре 1

limit =1 -- идёт перерасчёт только что закрытого бара 1 и нового бара 0


ситуация D -- отсутствовала связь бары:  10 9 8 7 [6 5 4 3 2 1 0]

rates_total =11

prev_calculated =5 -- остановились на баре 6

limit =11-5 =6 -- отнимается 1 по if(limit>1) -- идёт перерасчёт с бара 5, "закрытый" бар 6 не перерасчитывается, а должен был, чтобы отработать его закрытие на манер ситуации С


Вот индикатор:

//+------------------------------------------------------------------+
//|                                                    TestLimit.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Test"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double         Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Buffer,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(close,true);
   string tm=TimeToString(time[0]);
   int limit=rates_total-prev_calculated;
   /*
   if(limit==0)
     {
      Расчёт каждого тика на текущем нулевом баре
     }
   */
//--- Первый запуск, либо изменения в истории
   if(limit>1)
     {
      limit=rates_total-1;
      PrintFormat("%s: Обрабатываем условие if(limit>1) { инициализация буфера и полный перерасчёт индикатора (%d баров) }",tm,limit);
      ArrayInitialize(Buffer,EMPTY_VALUE);
     }
   if(limit>=1)
     {
      string x=(limit==1 ? "Новый бар" : "Первый запуск или изменения в истории");
      PrintFormat("%s: %s. rates_total=%d, prev_calculated=%d, limit=%d. Считаем от %d до 0",tm,x,rates_total,prev_calculated,limit,limit);
     }
//--- Цикл от начала истории до текущего времени
   for(int i=limit;i>=0;i--)
     {
      Buffer[i]=close[i];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


Вот тест:

  1. В 05:07 по серверному времени запустил индикатор (далее все времена по этому же времени),
  2. После открытия нового бара в 05:11 отключил интернет
  3. В 05:19 интернет подключил обратно.

Результаты теста индикатора в журнале:

2024.10.07 05:07: Обрабатываем условие if(limit>1) { инициализация буфера и полный перерасчёт индикатора (250002 баров) }
2024.10.07 05:07: Первый запуск или изменения в истории. rates_total=250003, prev_calculated=0, limit=250002. Считаем от 250002 до 0
2024.10.07 05:08: Новый бар. rates_total=250004, prev_calculated=250003, limit=1. Считаем от 1 до 0
2024.10.07 05:09: Новый бар. rates_total=250005, prev_calculated=250004, limit=1. Считаем от 1 до 0
2024.10.07 05:10: Новый бар. rates_total=250006, prev_calculated=250005, limit=1. Считаем от 1 до 0
2024.10.07 05:11: Новый бар. rates_total=250007, prev_calculated=250006, limit=1. Считаем от 1 до 0
2024.10.07 05:19: Обрабатываем условие if(limit>1) { инициализация буфера и полный перерасчёт индикатора (249999 баров) }
2024.10.07 05:19: Первый запуск или изменения в истории. rates_total=250000, prev_calculated=0, limit=249999. Считаем от 249999 до 0
2024.10.07 05:20: Новый бар. rates_total=250001, prev_calculated=250000, limit=1. Считаем от 1 до 0


Как видим, после обрыва связи prev_calculated сбрасывается в ноль. Поэтому самый быстрый способ - пересчитать всю историю, чем запоминать прошлый prev_calculated, определять именно обрыв связи (ведь бары могут быть пропущены из-за редких тиков), восстанавливать текущее (нулевое после восстановления связи) значение prev_calculated из ранее запомненного и высчитывать количество пропущенных баров.

Алгоритм работает эффективно.

 
Artyom Trishkin #:

Как видим, после обрыва связи prev_calculated сбрасывается в ноль. Поэтому самый быстрый способ - пересчитать всю историю, чем запоминать прошлый prev_calculated, определять именно обрыв связи (ведь бары могут быть пропущены из-за редких тиков), восстанавливать текущее (нулевое после восстановления связи) значение prev_calculated из ранее запомненного и высчитывать количество пропущенных баров.

Алгоритм работает эффективно.

твой тест не полный -- ты пишешь "запоминать прошлый prev_calculated, определять именно обрыв связи" -- такую отработку не позволит сделать сам движок терминала.


prev_calculated сбрасывает в ноль движок терминала -- при отклонении rates_total в больше или меньше хотя больше чем на 1 бар от предыдущего -- движок терминала  prev_calculated сбрасывает в ноль.


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

поведение движка терминала следующее -- он не перескакивает и не доливает бары -- он отрабатывает бар за баром без пропусков.

-- на картинке -- видно, что текущее время :48 -- а отрабатывает движок последовательно бар за баром и пока только :44 бар

т.е. движок терминала не отрабатывает актуальный текущий бар


вывод: корректней делать проверку не на if(limit>1) -- а на if(prev_calculate==0)

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

Файлы:
 
Andrey F. Zelinsky #:
на картинке -- видно

Ладно. Такое пороговое состояние в стиле "индикатор работает, но один бар считает за пять минут и что же при этом делает движок терминала.., а если ещё и отвёрткой ковырнуть..." обсуждать уже не интересно. Кто-то говорил ещё о морганиях для клиентов.

Знаю, сейчас начнёшь о "чистоте экспериментов". Продолжай без меня. Ты никогда не признаёшь ничего за собой. Я, к сожалению, об этом забыл.