Скачать MetaTrader 5

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

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

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

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

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

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

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

kbw74614
228
kbw74614 2014.10.10 16:21  
Meat:

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

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

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

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

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

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

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

TheXpert:
У меня было, если найду выложу.
Ждем тогда конвертер. 
Комбинатор
16019
Комбинатор 2014.10.10 19:53  
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 2014.10.10 21:21  
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
43482
Dmitry Fedoseev 2014.10.11 00:49  
kbw74614:

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

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

  • Колесико мыши как задействовать?
  • В индикаторах при изменении входного параметра нужно OnCalculate запустить с нуля (все пересчитать). У меня не выходит сформировать входные параметры для OnCalculate. Делаю так:
Переименовать OnCalculate в OnCalculate2, сделать новую пустую OnCalculate и вызывать из нее OnCalculate2
kbw74614
228
kbw74614 2014.10.11 06:16  
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 никаких проблем не возникает. Либо это баг, либо что-то делаю неправильно. Прошу помочь. 

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