Как можно передать индикатор с параметрами в класс?

 

Пишу класс для работы с зиг-загом. По сути, вот код:

//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                                                                                        ZZHandling.mqh |
//|                                                                                                                                       |
//|                                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------+
#ifndef ZZHandling_H
#define ZZHandling_H

#property copyright ""
#property link      ""
#property version   "1.00"
#property strict

//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                Структура свойств экстремумов Zig-Zag'a                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------+
struct ZZProperty {
  int    indexInZZSequence;    // Индекс бара из таймсерии iBars, на котором образован экстремум
  double price;                // Цена Zig-Zag'a на индексе из таймсерии iBars, на котором образован экстремум
};
//+=======================================================================================================================================+
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//|                                            КЛАСС, ХРАНЯЩИЙ И ОБРАБАТЫВАЮЩИЙ ДАННЫЕ Zig-Zag'a                                          |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+=======================================================================================================================================+
class ZZHandling {
  private:
//  ZZProperty m_ZZProperty;
//  ZZProperty m_ZZProperties[4];
  //---- Конструктор и деструктор
  public:
    ZZHandling(void);
   ~ZZHandling(void);
    //------------------------------------   Функции для выполнения операций с данными Zig-Zag'a   ----------------------------------------
    void setZZProperties(ZZProperty& stZZProperty, int pZZIndex, double pPrice);
    void getZZSequenceProperties(ZZProperty& ZZProperties[], int extremumCountToCollect);
};

ZZHandling *ZZHandle;
//=========================================================================================================================================
// Конструктор класса. ====================================================================================================================
ZZHandling :: ZZHandling(void) {
}
//=========================================================================================================================================
// Деструктор класса. =====================================================================================================================
ZZHandling :: ~ZZHandling(void) {
}
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                           Присвоение значений свойствам экстремума Zig-Zag'a                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------+
void ZZHandling :: setZZProperties(ZZProperty& stZZProperty, int pZZIndex, double pPrice) {
//    Print(__FUNCTION__, ": pZZIndex = ", pZZIndex);
  //  Print(__FUNCTION__, ": pPrice = ", pPrice);
  stZZProperty.indexInZZSequence = pZZIndex;
  stZZProperty.price = pPrice;
}
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                    Сбор экстремумов Zig-Zag'a                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------+
void ZZHandling :: getZZSequenceProperties(ZZProperty& ZZProperties[], int extremumCountToCollect) {
  int cnt = 0;    // Индекс буфера последних N-эффективных значений Zig-Zag'a
  for (int i = 0; i <= Bars; i++) {
    if (cnt == extremumCountToCollect + 1) break;
    double ZZPrice = iCustom(NULL, i_ZZTF, "ZZ_mtf", i_ZZTF, 0, i);
    if (ZZPrice == EMPTY_VALUE) continue;
    setZZProperties(ZZProperties[cnt], i, ZZPrice);
    cnt++;
  }
}

#endif

Есть вещи которые будут оптимизированы. Имею ввиду, некоорые параметры из методов вообще уберу. Они будут инициализироваться при создании экземпляра класса.

Но, на данный, возник вопрос. В строке:

    double ZZPrice = iCustom(NULL, i_ZZTF, "ZZ_mtf", i_ZZTF, 0, i);

Имеется получение данных из зиг-зага с именем ZZ_mtf и параметром i_ZZTF. А что если имя индикатора будет другими и параметров будет больше одного? А тогда будет грабля. По сему, возник вопрос. Как можно это реализовать так, что бы здесь был не фиксированный индикатор с его параметрами, а можно было бы передать любой индикатор с любым количеством параметров?

 
hoz:

Пишу класс для работы с зиг-загом. По сути, вот код:

Есть вещи которые будут оптимизированы. Имею ввиду, некоорые параметры из методов вообще уберу. Они будут инициализироваться при создании экземпляра класса.

Но, на данный, возник вопрос. В строке:

Имеется получение данных из зиг-зага с именем ZZ_mtf и параметром i_ZZTF. А что если имя индикатора будет другими и параметров будет больше одного? А тогда будет грабля. По сему, возник вопрос. Как можно это реализовать так, что бы здесь был не фиксированный индикатор с его параметрами, а можно было бы передать любой индикатор с любым количеством параметров?

https://www.mql5.com/ru/docs/series/indicatorcreate
 
hoz:

Пишу класс для работы с зиг-загом. По сути, вот код:

Есть вещи которые будут оптимизированы. Имею ввиду, некоорые параметры из методов вообще уберу. Они будут инициализироваться при создании экземпляра класса.

Но, на данный, возник вопрос. В строке:

Имеется получение данных из зиг-зага с именем ZZ_mtf и параметром i_ZZTF. А что если имя индикатора будет другими и параметров будет больше одного? А тогда будет грабля. По сему, возник вопрос. Как можно это реализовать так, что бы здесь был не фиксированный индикатор с его параметрами, а можно было бы передать любой индикатор с любым количеством параметров?

Судя по строке вызова индикатора Вы пишите класс для mql4, в mql5 немного другой подход к работе с индикаторами. Попробуйте воспользоваться перегрузкой функций https://www.mql5.com/ru/docs/basis/function/functionoverload, передавая название индикатора в одном из строковых параметров. 

Документация по MQL5: Основы языка / Функции / Перегрузка функций
Документация по MQL5: Основы языка / Функции / Перегрузка функций
  • www.mql5.com
Обычно в названии функции стремятся отобразить ее основное назначение. Читабельные программы, как правило, содержат разнообразные и грамотно подобранные идентификаторы. Иногда различные функции используются для одних и тех же целей. Например, рассмотрим функцию, которая вычисляет среднее значение массива чисел двойной точности, и такую же...
 
Artyom Trishkin:
https://www.mql5.com/ru/docs/series/indicatorcreate

Всё-то оно хорошо, но, как я понял, этот вариант подходит лшь для работы с стандартными индикаторами, что не есть вариант. У функции IndicatorCreate() параметр indicator_type (Тип индикатора, может принимать одно из значений перечисления ENUM_INDICATOR). Т.е. передавать нужно лишь типы индикатора из перечисления стандартных индикаторов. А с пользовательским такой вариант не прокатит как-нить?

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

 
hoz:

Всё-то оно хорошо, но, как я понял, этот вариант подходит лшь для работы с стандартными индикаторами, что не есть вариант. У функции IndicatorCreate() параметр indicator_type (Тип индикатора, может принимать одно из значений перечисления ENUM_INDICATOR). Т.е. передавать нужно лишь типы индикатора из перечисления стандартных индикаторов. А с пользовательским такой вариант не прокатит как-нить?

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

Можно и пользовательские передавать точно так же - читайте справку внимательно.
 
Artyom Trishkin:
Можно и пользовательские передавать точно так же - читайте справку внимательно.

Пока я копировал в документации, ты ответил. Но не зря-же я там был:))))

Дополнение:

IND_CUSTOM

Custom indicator

 
Dmitriy Gizlyk:

Судя по строке вызова индикатора Вы пишите класс для mql4, в mql5 немного другой подход к работе с индикаторами. Попробуйте воспользоваться перегрузкой функций https://www.mql5.com/ru/docs/basis/function/functionoverload, передавая название индикатора в одном из строковых параметров. 

Это понятно, но если даже применить перегрузку, что сразу же приходить в голову, то всё-равно как-бы не очень гибко выходит. Придётся писать ровно столько перегрузок, сколько вариаций сигнатур будет у этой функции, в зависимости от потенциальных параметров индикаторов. Оно, конечно, но я думал, есть ещё какие-то варианты..

 
hoz:

... Есть вещи которые будут оптимизированы. Имею ввиду, некоорые параметры из методов вообще уберу ...

Вообще-то не это нуждается в оптимизации в первую очередь. Ваш код в цикле вызывает внешний индикатор. Если будут нужны 5 последних точек зигзага (напр для волн Вульфа), будете циклом заставлять этот внешний обсчитываться где-то тысячу раз пока не найдёте 5? Не пробовали замерить сколько ресурсов это пожирает?

Оптимизацию стоит начать с переноса расчёта зигзага в тело класса. Если нет - во внешний индикатор добавить буфер и код, который этот буфер будет заполнять последними точками. Тогда для 5 точек хватит 5 вызовов iCustom

 
Alexander Puzanov:

Вообще-то не это нуждается в оптимизации в первую очередь. Ваш код в цикле вызывает внешний индикатор. Если будут нужны 5 последних точек зигзага (напр для волн Вульфа), будете циклом заставлять этот внешний обсчитываться где-то тысячу раз пока не найдёте 5? Не пробовали замерить сколько ресурсов это пожирает?

Оптимизацию стоит начать с переноса расчёта зигзага в тело класса. Если нет - во внешний индикатор добавить буфер и код, который этот буфер будет заполнять последними точками. Тогда для 5 точек хватит 5 вызовов iCustom

Я с этим вопросом не особо спешил (о хэндле) т.к. пришлось переписывать всё что было с мкл4, на мкл5. Так вот по поводу оптимизации:

void ZZHandling :: getZZSequenceProperties(ZZProperty& ZZProperties[], int extremumCountToCollect) {
  int cnt = 0;    // Индекс буфера последних N-эффективных значений Zig-Zag'a
  for (int i = 0; i <= Bars; i++) {
    if (cnt == extremumCountToCollect + 1) break;
    double ZZPrice = iCustom(NULL, i_ZZTF, "ZZ_mtf", i_ZZTF, 0, i);
    if (ZZPrice == EMPTY_VALUE) continue;
    setZZProperties(ZZProperties[cnt], i, ZZPrice);
    cnt++;
  }
}

Не будет ничего обсчитываться. У меня же условие:

if (cnt == extremumCountToCollect + 1) break;

На данный момент, extremumCountToCollect = 5. Поэтому, как только мы собрали последние 5 неэффективных значений, дальше индикатор уже ничего не будет просчитывать. Кроме того, индикатор же сам просчитывает то, что нужно не зависимо от эксперта, заполняя буер экстремумов. С чего бы это вдруг эксперт заставить пересчитывать индикатор? Мы так всего навсего получаем данные из индикаторного буфера, в моём случае на индексе 0 и не более того. Вы со мной не согласны?

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