Обсуждение статьи "Готовим мультисимвольные мультипериодные индикаторы"

 

Опубликована статья Готовим мультисимвольные мультипериодные индикаторы:

В статье рассмотрим принципы создания мультисимвольных мультипериодных индикаторов и получение от них данных в советниках и индикаторах. Рассмотрим основные нюансы использования мульти-индикаторов в советниках и индикаторах, и их отрисовку через буферы пользовательского индикатора.

После компиляции тестового индикатора запустим его на графике с периодом М1, в настройках выберем текущий символ и период расчёта индикатора М5. В этом случае будут созданы два выбранных в настройках индикатора скользящих средних. Один будет рассчитан на данных текущего графика, а второй — на данных пятиминутного периода графика. Переключая таймфрейм графика можно будет видеть как на М1 рисуются две линии: одна будет соответствовать скользящей средней, рассичтанной на М1, а вторая — скользящей средней, рассчитанной на М5. Если переключить график на М5, то будет создан только один индикатор, так как второй будет идентичен первому, и он создан не будет. Если переключить график на М15, то один индикатор будет рассчитан на М15, а второй — на М5, и он тоже будет отображён на графике.


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

Автор: Artyom Trishkin

 

Автору спасибо. Есть над чем подумать...

Имхо, если класс базовый, то и название ему примерно такое CBaseIndMSTF. Или даже CBaseIndMSMTF. MSMTF - multi-symbol multi-timeframe.

По именам.

ENUM_IND_CATEGORY - годится.

Следующие не очень.

ENUM_COMPARE_MODE --> ENUM_IND_COMPARE_MODE

ENUM_LINE_STATE --> ENUM_IND_LINE_STATE

ENUM_ERR_TYPE --> ENUM_IND_CALC_ERR_TYPE


enum ENUM_ERR_TYPE            // Тип ошибки при расчётах индикаторов
  {
   ERR_TYPE_NO_ERROR,         // Нет ошибки
   ERR_TYPE_NO_CYNC,          // Данные не синхронизированы
   ERR_TYPE_NO_DATA,          // Данные не загружены
   ERR_TYPE_NO_CALC,          // Расчёт не завершён
  };

ERR_TYPE_NO_CYNC --> ERR_TYPE_NO_SYNC

 
Denis Kirichenko #:

Автору спасибо. Есть над чем подумать...

Имхо, если класс базовый, то и название ему примерно такое CBaseIndMSTF. Или даже CBaseIndMSMTF. MSMTF - multi-symbol multi-timeframe.

По именам.

ENUM_IND_CATEGORY - годится.

Следующие не очень.

ENUM_COMPARE_MODE --> ENUM_IND_COMPARE_MODE

ENUM_LINE_STATE --> ENUM_IND_LINE_STATE

ENUM_ERR_TYPE --> ENUM_IND_CALC_ERR_TYPE


ERR_TYPE_NO_CYNC --> ERR_TYPE_NO_SYNC

С этим соглашусь. Остальные - частности

 
to sync/to synchronize - синхронизировать
 
Denis Kirichenko #:
to sync/to synchronize - синхронизировать

Не могу понять смысла. Выделены два символа "s", и что?

"No Sync" - не синхронизировано. Что не так? "Error: No Synchronized"

аааа

В последний момент увидел C вместо S... Ясно. Спасибо. Поправлю.

 

Артём, запустил индикатор TestMSTFMovingAverages на график EURUSD. Выходной день. Тф1 = M15, Тф2 = H1.

Входные параметры:

InpIndicator=26
InpSymbol=
InpTimeframe=16385
InpPrice=1
InpMethod=0
InpShift=0
InpAsSeries=true

Вот что вышло:

Логи:

HD      0       20:22:12.149    TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::AddNewMA: MA(10) indicator (handle 10) added to the collection
PJ      0       20:22:12.150    TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::AddNewMA: MA(EURUSD,H1:10) indicator (handle 11) added to the collection
CG      0       20:22:12.179    TestMSTFMovingAverages (EURUSD,M15)     CIndMSTF::Calculate::MA(EURUSD,H1:10): Start downloading data by EURUSD/H1. Waiting for the next tick...
OG      0       20:22:12.179    TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::Calculate::MA(EURUSD,H1:10): Error in indicator calculation: Data not loaded
HQ      0       20:22:12.179    TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::Calculate: Not all indicators have been calculated successfully. It is necessary to recalculate the buffers of all indicators
QH      0       20:22:12.224    TestMSTFMovingAverages (EURUSD,M15)     CIndMSTF::DataToBuffer::MA(EURUSD,H1:10) First start, or historical data has been changed. Initialize Buffer(0)


Выделил свечу в 23:00 перекрестием. Видно, что красная линия SMA10 меняет своё значение только на следующей свече после 23:00. Т.е. переход значений имеем в 23:00 и 23:15.

В моём понимании переход с текущего на следующее значение на Тф2 должен иметь место  в 22:45 и 23:00.


Затем вот что у меня получилось. Запустил на отдельном графике EURUSD-H1 индикатор SMA10 со смещением = 1.

Открываю новый график и запускаю TestMSTFMovingAverages. И чудо, вижу, что кажется картина исправилась.


Логи:

2023.10.29 20:38:42.583 TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::AddNewMA: MA(10) indicator (handle 10) added to the collection
2023.10.29 20:38:42.584 TestMSTFMovingAverages (EURUSD,M15)     CMSTFIndicators::AddNewMA: MA(EURUSD,H1:10) indicator (handle 11) added to the collection
2023.10.29 20:38:42.622 TestMSTFMovingAverages (EURUSD,M15)     CIndMSTF::DataToBuffer::MA(10) First start, or historical data has been changed. Initialize Buffer(0)
2023.10.29 20:38:42.654 TestMSTFMovingAverages (EURUSD,M15)     CIndMSTF::DataToBuffer::MA(EURUSD,H1:10) First start, or historical data has been changed. Initialize Buffer(0)


Причём, как в первом случае, так и во втором на панели в 23:00 значение МА(EURUSD,H1:10) = 1.056959. Что, имхо, правильно. Видимо в первом случае что-то не так с заполнением буфера для МА(EURUSD,H1:10).

 
Denis Kirichenko #:

Артём, запустил индикатор TestMSTFMovingAverages на график EURUSD. Выходной день. Тф1 = M15, Тф2 = H1.

Входные параметры:

Вот что вышло:

Логи:


Выделил свечу в 23:00 перекрестием. Видно, что красная линия SMA10 меняет своё значение только на следующей свече после 23:00. Т.е. переход значений имеем в 23:00 и 23:15.

В моём понимании переход с текущего на следующее значение на Тф2 должен иметь место  в 22:45 и 23:00.


Затем вот что у меня получилось. Запустил на отдельном графике EURUSD-H1 индикатор SMA10 со смещением = 1.

Открываю новый график и запускаю TestMSTFMovingAverages. И чудо, вижу, что кажется картина исправилась.


Логи:


Причём, как в первом случае, так и во втором на панели в 23:00 значение МА(EURUSD,H1:10) = 1.056959. Что, имхо, правильно. Видимо в первом случае что-то не так с заполнением буфера для МА(EURUSD,H1:10).

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

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

А откуда такое значение частоты? Опытным путём удалось определить?

 
Denis Kirichenko #:

А откуда такое значение частоты? Опытным путём удалось определить?

Сообщение от разработчиков на форуме.

 

Есть такая структура:

//--- struct
struct SBuffer                // Структура индикаторного буфера
  {
   double            array[];    // Массив-буфер индикатора
   double            init_value; // Инициализирующее значение
   int               shift;      // Сдвиг буфера по горизонтали
   string            descript;   // Описание буфера
   //--- (1) Устанавливает, (2) возвращает инициализирующее значение,
   void              SetInitValue(const double value) { init_value=value;                             }
   double            InitValue(void)                  { return init_value;                            }
   //--- (1) Устанавливает, (2) возвращает сдвиг буфера
   void              SetShift(const int value)        { shift=value;                                  }
   int               Shift(void)                      { return shift;                                 }
//--- (1) Изменяет размер массива буфера, (2) возвращает размер массива буфера,
//--- (3) инициализирует массив установленным "пустым" значением
   bool              BuffResize(const int new_size)   { return(ArrayResize(array,new_size)==new_size);}
   uint              BufferSize(void)                 { return array.Size();                          }
   int               InitBuffer(void)                 { return ArrayInitialize(array,init_value);     }
  };

Раз есть set\get-методы, то имхо не хватает спецификатора доступа private:

//--- struct
struct SBuffer                // Структура индикаторного буфера
   {
   private:
      double            array[];    // Массив-буфер индикатора
      double            init_value; // Инициализирующее значение
      int               shift;      // Сдвиг буфера по горизонтали
      string            descript;   // Описание буфера
   public:
      //--- (1) Устанавливает, (2) возвращает инициализирующее значение,
      void              SetInitValue(const double value)
         {
         init_value = value;
         }
      double            InitValue(void)
         {
         return init_value;
         }
      //--- (1) Устанавливает, (2) возвращает сдвиг буфера
      void              SetShift(const int value)
         {
         shift = value;
         }
      int               Shift(void)
         {
         return shift;
         }
//--- (1) Изменяет размер массива буфера, (2) возвращает размер массива буфера,
//--- (3) инициализирует массив установленным "пустым" значением
      bool              BuffResize(const int new_size)
         {
         return(ArrayResize(array, new_size) == new_size);
         }
      uint              BufferSize(void)
         {
         return array.Size();
         }
      int               InitBuffer(void)
         {
         return ArrayInitialize(array, init_value);
         }
   };


И ещё нужны тогда методы для работы с буфером...

 
Denis Kirichenko #:

Есть такая структура:

Раз есть set\get-методы, то имхо не хватает спецификатора доступа private:


И ещё нужны тогда методы для работы с буфером...

Изначально старался не усложнять

Причина обращения: