Скачать MetaTrader 5

Изменение входных параметров индикатора на ходу

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
kbw74614
228
kbw74614  
Хочу написать универсальный модуль, который бы можно было в несколько нажатий подключить к любому индикатору.

Модуль бы позволял менять входные целочисленные (int) параметры индикатора на ходу. По нажатию на TAB происходил бы соответствующий выбор входного параметра. Колесико мыши (что-то события такого в MQL не нашел) - его изменние на ±1.

Подскажите, как архитектурно лучше всего реализовать. Прочел статью MQL5, обработка событий: Изменяем период мувинга «на лету», которой уже более четырех лет. Наверняка, появились более гибкие и красивые решения.

По какой-то причине в прошлый раз с универсальным ООП-шаблоном написания индикатора не помогли. Надеюсь, на этот раз не пройдете мимо.
Vitalie Postolache
12445
Vitalie Postolache  
Сомневаюсь, что с помощью сторонней программы можно вытащить список пользовательских параметров из индикатора и как-то к ним подключаться. Через iCustom как-то всё по-другому, там сразу задаются все параметры до вызова этого самого iCustom.
Alexey Navoykov
4910
Alexey Navoykov  

Вытащить значения входных параметров можно через парсинг файлов с настройками чартов.  Но это будут лишь значения. А узнать тип параметров невозможно. Да и переинциализировать индикатор изменёнными значениями тоже вряд ли удастся.

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

kbw74614
228
kbw74614  
Meat:

Вытащить значения входных параметров можно через парсинг файлов с настройками чартов.  Но это будут лишь значения. А узнать тип параметров невозможно. Да и переинциализировать индикатор изменёнными значениями тоже вряд ли удастся.

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

Ну совсем уж универсальный подход не обязателен. Имел в виду, что берем исходник большинства индикаторов и минимальным количеством копи-пасты и правок добавляем обозначенный функционал. Давайте сделаем. Если понять, что и как можно сделать, так можно вообще конвертер написать, который обычный индикатор превращает в такой нестандартный (для текущего времени) тип.
Alexey Navoykov
4910
Alexey Navoykov  
kbw74614:
Ну совсем уж универсальный подход не обязателен. Имел в виду, что берем исходник большинства индикаторов и минимальным количеством копи-пасты и правок добавляем обозначенный функционал. Давайте сделаем. Если понять, что и как можно сделать, так можно вообще конвертер написать, который обычный индикатор превращает в такой нестандартный (для текущего времени) тип.

Изначально вы писали про "несколько нажатий" (да и про исходник вроде речь не шла), теперь уже готовы на минимальное количество правок, но всё-равно вряд ли получится обойтись малой кровью. Ведь изменять значения input-переменных программно нельзя. Придётся создать для каждой переменной дубликат...

Комбинатор
16530
Комбинатор  
kbw74614:
Ну совсем уж универсальный подход не обязателен. Имел в виду, что берем исходник большинства индикаторов и минимальным количеством копи-пасты и правок добавляем обозначенный функционал. Давайте сделаем. Если понять, что и как можно сделать, так можно вообще конвертер написать, который обычный индикатор превращает в такой нестандартный (для текущего времени) тип.
У меня было, если найду выложу.
kbw74614
228
kbw74614  
Meat:

Изначально вы писали про "несколько нажатий" (да и про исходник вроде речь не шла), теперь уже готовы на минимальное количество правок, но всё-равно вряд ли получится обойтись малой кровью. Ведь изменять значения input-переменных программно нельзя. Придётся создать для каждой переменной дубликат...

Для конвертера это не проблема: запустил - готов правильный индикатор.

TheXpert:
У меня было, если найду выложу.
Ждем тогда конвертер. 
Комбинатор
16530
Комбинатор  
kbw74614:
Ждем тогда конвертер. 

Нету конвертера. Есть простенькая панель к которой легко подключить изменение настроек добавлением небольшого количества кода.

Писано оно все оооочень давно, еще во время становления MQL5, но вроде пашет ) правда минорные косяки с отображением и т.п. возможны. Если надо скину.

Вот весь исходник советника чтобы было видно само подключение

#include <TheXpert/SettingsBar/SettingsBar.mqh>

SettingsBar Bar;

string GetSettingNameByID(int id)
{
   switch (id)
   {
      case 0: return "Bool Setting";
      case 1: return "Double Setting";
      case 2: return "Int Setting";
      case 3: return "Selection Setting";
      case 4: return "String Setting";
   }
   return "N\A";
}

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
   Bar.OnChartEvent(id, lparam, dparam, sparam);
   
   if (id == CHARTEVENT_CUSTOM + EVENT_SETTING_CHANGED)
   {
      Print("Setting < ", GetSettingNameByID(lparam), " > has been changed to ", sparam);
   }

   ChartRedraw();
}

int OnInit()
{
   Bar.AddBoolSetting("Bool Setting", 0, true);
   Bar.AddDoubleSetting("Double Setting", 1, 2.35, 0.1, -20, 20);
   Bar.AddIntSetting("Int Setting", 2, 10, 2, 0, 100);
   
   SelectionTable TF;

   TF.AddSelection(PERIOD_M1, "1 Minute");
   TF.AddSelection(PERIOD_M5, "5 Minutes");
   TF.AddSelection(PERIOD_M15, "15 Minutes");
   TF.AddSelection(PERIOD_M30, "30 Minutes");
   TF.AddSelection(PERIOD_H1, "1 Hour");
   TF.AddSelection(PERIOD_H4, "4 Hours");
   TF.AddSelection(PERIOD_D1, "1 Day");

   Bar.AddSelectionSetting("Selection Setting", 3, PERIOD_M1, TF);
   
   Bar.AddStringSetting("String Setting", 4, "string value");

   Bar.SetTitle("Settings Example");

   return(0);
}

void OnDeinit(const int reason)
{}

void OnTick()
{}
kbw74614
228
kbw74614  
TheXpert:

Вот весь исходник советника чтобы было видно само подключение

Спасибо, теперь стало ясно. Конвертер, действительно, элементарно написать под это дело. И все индикаторы станут с динамическими входными параметрами!

Остались две проблемы:

  • Колесико мыши как задействовать?
  • В индикаторах при изменении входного параметра нужно OnCalculate запустить с нуля (все пересчитать). У меня не выходит сформировать входные параметры для OnCalculate. Делаю так:
    void FullOnCalculate( void )
    {
      long volume[];
      int spread[];
    
      ArraySetAsSeries(volume, TRUE);
      ArraySetAsSeries(spread, TRUE);
    
      const int Size = MathMin(CopyTickVolume(Symbol(), Period(), 0, Bars, volume),
                               CopySpread(Symbol(), Period(), 0, Bars, spread));
    
      OnCalculate(Size, 0, Time, Open, High, Low, Close, Volume, volume, spread);
    
      return;  
    }
Dmitry Fedoseev
46938
Dmitry Fedoseev  
kbw74614:

Спасибо, теперь стало ясно. Конвертер, действительно, элементарно написать под это дело. И все индикаторы станут с динамическими входными параметрами!

Остались две проблемы:

  • Колесико мыши как задействовать?
  • В индикаторах при изменении входного параметра нужно OnCalculate запустить с нуля (все пересчитать). У меня не выходит сформировать входные параметры для OnCalculate. Делаю так:
Переименовать OnCalculate в OnCalculate2, сделать новую пустую OnCalculate и вызывать из нее OnCalculate2
kbw74614
228
kbw74614  
Integer:
Переименовать OnCalculate в OnCalculate2, сделать новую пустую OnCalculate и вызывать из нее OnCalculate2

Фактически так и делаю здесь:

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[])
{
  return(Relation.Calculate(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, spread));
}

Но такой вызов происходит, когда OnCalculate запускается сам - например, по приходу нового тика. А как вызвать OnCalculate напрямую? Например, OnStart вызвать получается без проблем. А с OnCalculate вызов  делается без проблем (как написал в FullOnCalculate), но вот что-то странное затем творится с входными массивами - выход за пределы. Пробовал все входные массивы переопределить через CopyRates в MqlRates. Но все равно происходит выход за пределы массива при выполнении вызванного OnCalculate.

 

А при самостоятельном выполнении OnCalculate никаких проблем не возникает. Либо это баг, либо что-то делаю неправильно. Прошу помочь. 

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий