Рациональные приемы (предложения) ускорения оптимизатора - страница 3

 
Можно голову включить... сперва оптимизировать параметры входа, потом мм.... на три-четыре порядка меньше вариантов оптимизации
 
Yuri_Evseenkov:

1.  В справке написано  "Рекомендуется вызывать функцию EventSetTimer() однократно в функции OnInit(), а функцию EventKillм Timer() вызывать однократно в OnDeinit()."

2. Если Вы имеете ввиду конкретный  код то пожалуйста. Торговая стратегия поиска разворотов на основе кода Popular_Prices.https://www.mql5.com/ru/code/12310 В код вставил торговые функции и подсчет объёмов. На каждом баре происходит переборка пяти массивов-таймсерий, переборка,сортировка пользовательских массивов. Ввел несколько параметров оптимизация которых идет долго. Если найдете на меня время- подробности напишу в личку.

1. Ну, для обычных задач так и надо делать, а для нестандартных можно и отойти от рекомендаций.
Я же говорю, надо проверить.

2. Не вижу конкретного кода ) Но уже вижу, что задачу можно оптимизировать алгоритмически.
Например, абсолютно незачем на каждом баре прочесывать историю для расчетов, можно хранить кол-во касаний цены каждого уровня в индикаторных буферах. А отсортировать последние значения для принятия решения - не ресурсоемкая задача.
И не очень понятно, что там оптимизировать. Давайте больше конкретики.

 
komposter:

 Не вижу конкретного кода ) Но уже вижу, что задачу можно оптимизировать алгоритмически.
Например, абсолютно незачем на каждом баре прочесывать историю для расчетов, можно хранить кол-во касаний цены каждого уровня в индикаторных буферах. А отсортировать последние значения для принятия решения - не ресурсоемкая задача.
И не очень понятно, что там оптимизировать. Давайте больше конкретики.

Ну если автор ветки не против обсудить эту стратегию то пожалуйста.

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

Оптимизировать нужно прежде всего число баров  и расстояние от лучшей зоны(красная горизонтальная линия) при котором дается  торговый  приказ  по логике разворота. Ордера закрываются не по фиксированным стопам, а по ситуации.Текущий бар помог своей зоне выйти на первое место - алгоритм ТС не может теперь работать  - закрывай ордер. ПОЭТОМУ НЕОБХОДИМО ДЛЯ КАЖДОГО БАРА ЗНАТЬ ЕГО ВЛИЯНИЕ НА ИСТОРИЮ.

Чего не надо делать так это торговать на важных новостях и в пору высокой волатильности - данная ТС не для этого. Вот здесь бы мне и пригодилась функция bool TesterToDate( datetime NextDate ); которую предлагает ввести автор ветки в своём первом посте. Определил код что " начала плясать губерния  " - пропускай время  пока не устаканится.  Это функция помогла бы не только ускорить оптимизацию но и повысить адекватность кода - торговой стратегии.


                                                                 

 
Yuri_Evseenkov:

Ну если автор ветки не против обсудить эту стратегию то пожалуйста.

У вас есть код советника, который долго оптимизируется? Реальный советник и реальный (адекватный) набор перебираемых параметров? Или вы только ожидаете, что это будет долго?
Пропуск новостей (важных), имхо, даст ускорение процентов на 5. Это если в ОнТик постоянно проверять, не прошло ли запрещенное время. 
 
komposter:
У вас есть код советника, который долго оптимизируется? Реальный советник и реальный (адекватный) набор перебираемых параметров? Или вы только ожидаете, что это будет долго?
Пропуск новостей (важных), имхо, даст ускорение процентов на 5. Это если в ОнТик постоянно проверять, не прошло ли запрещенное время. 

Ссылку на код взятый за основу приводил на предыдущей странице. В файле результаты  тестирования на ноуте НР Windows 8.1 Intel Celeron. Железо конечно слабовато но новое и ПО все родное кроме МТ4.

2015.04.13 16:33:38.624 XAUUSD,M1: 30024 tick events (31024 bars, 60823 bar states) processed within 1316735 ms (total time 1320156 ms)

Один прогон тестера длится 22 минуты. И это на минимально нужных мне параметрах: быстрый метод на открытиях бара , месяц прогона, глубина проникновения в историю 1440 баров. А прогонов таких нужно сделать что бы оптимизировать хотя бы по месяцу минимум 100. А по году на порядок выше.  Код постоянно модернизирую а это опять переоптимизация.

Файлы:
1304.PNG  45 kb
1304_1.PNG  45 kb
 
Yuri_Evseenkov:

Ссылку на код взятый за основу приводил на предыдущей странице. В файле результаты  тестирования на ноуте НР Windows 8.1 Intel Celeron. Железо конечно слабовато но новое и ПО все родное кроме МТ4.

2015.04.13 16:33:38.624 XAUUSD,M1: 30024 tick events (31024 bars, 60823 bar states) processed within 1316735 ms (total time 1320156 ms)

Один прогон тестера длится 22 минуты. И это на минимально нужных мне параметрах: быстрый метод на открытиях бара , месяц прогона, глубина проникновения в историю 1440 баров. А прогонов таких нужно сделать что бы оптимизировать хотя бы по месяцу минимум 100. А по году на порядок выше.  Код постоянно модернизирую а это опять переоптимизация.

Ну, тут очевидно, что выбранный подход не оптимален.

Но вы опять хотите играть в угадайку, а это не конструктивно и не интересно.

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

 
komposter:

Ну, тут очевидно, что выбранный подход не оптимален.

Но вы опять хотите играть в угадайку, а это не конструктивно и не интересно.

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

Спасибо за советы , учту на будущее. Но для моего случая...

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

 P.S Принцип работы оптимизируемого кода мало чем отличается от опубликованного мною в Code Base. Окончательный вариант сейчас мне не хотелось бы выкладывать. В основном из-за шкурных интересов.

 
Yuri_Evseenkov:

Спасибо за советы , учту на будущее. Но для моего случая...

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

 P.S Принцип работы оптимизируемого кода мало чем отличается от опубликованного мною в Code Base. Окончательный вариант сейчас мне не хотелось бы выкладывать. В основном из-за шкурных интересов.

Что-то не получается у меня донести свои мысли )

1. Зачем пересчитывать историю?
Каждый бар нужно посчитать один раз, а рассчитанные значения нужно сохранить в индикаторные буферы, массивы или файл. Потом нужно только читать эти значения и, например, находить максимальное из них за последние Х баров.

2. Чего привязались к функции пропуска куска истории?
Пятый раз прошу - замерьте скорость пропуска с помощью:

  • булевского флага и его проверки в начале ОнТик;
  • установки таймера, рассчитанного на запуск в конкретное время.
Это займет 10 минут и снимет кучу вопросов.
Поверьте, если ваш советник тестируется 20 минут, то, ограничив вызовы расчетной части только на определенные дни недели (например), вы получите пропорциональное ускорение.
Например, если разрешите работу только в Пн и Ср, то получите ускорение в 2.5 раза (2 дня вместо 5).

3. Индикатор, безусловно, написан не оптимально. Надо в первую очередь подумать над его оптимизацией.

 

ps: я не против добавления предложенной функции, я просто так и не увидел, где ее применить ;)

 

Советник для демонстрации идеи из первого поста:

#property strict

extern int Size = 100; // Для перебора (без ГА): 10 - 110, шаг 1
extern ENUM_DAY_OF_WEEK TradeDay = WEDNESDAY;

// https://www.mql5.com/ru/forum/42642
// Переводит по возможности следующими в тестере тики, начиная с даты NextDate
// Возвращает TRUE - будет перевод. FALSE - невозможно (висят ордера или iCustom-индикаторы).
bool TesterToDate( datetime NextDate );

#define DAY_SECONDS (PERIOD_D1 * PERIOD_H1)
#define WEEK_DAYS 7

datetime GetNextWeekDayTime( datetime time, const ENUM_DAY_OF_WEEK WeekDay )
{
  int Step = WeekDay - TimeDayOfWeek(time);

  if (Step <= 0)
    Step += WEEK_DAYS;

  time += Step * DAY_SECONDS - time % DAY_SECONDS;

  return(time);
}

bool NotSkipOnTick( void )
{
//  static bool Flag = TRUE; // для минимального количества вызовов GetNextWeekDayTime
  static datetime NextDay = 0;
  static datetime NewNextDay = 0;
  const datetime time = TimeCurrent();
  const bool Res = (time >= NextDay);

  if (Res)
  {
//    if (Flag)
      NewNextDay = GetNextWeekDayTime(time, TradeDay);

//    Flag = (TesterToDate(NewNextDay) || (time >= NewNextDay));  // за счет этого мы перескочим ~ 90% "бессмысленных" тиков в тестере/оптимизаторе

//    if (Flag)
      NextDay = NewNextDay;
  }

  return(Res);
}

// Данная примитивная ТС может быть реализована без OnTick - только OnTimer. Но намеренно не стал этого делать.
void System( void )
{
  if ((OrdersTotal() == 0) && (TimeDayOfWeek(TimeCurrent()) == TradeDay))
  {
    bool Flag = (OrdersHistoryTotal() == 0);

    if (!Flag && OrderSelect(OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY))
      Flag =  (TimeCurrent() - OrderOpenTime() >= DAY_SECONDS);

    if (Flag)
      OrderSend(Symbol(), OP_BUY, 0.1, Ask, 0, Ask - Size * Point, Ask + Size * Point);
  }

  return;
}

void OnTick( void )
{
  if (NotSkipOnTick())
    System();

  return;
}
Желающие могут прогнать в оптимизаторе. У меня получается 20 секунд ("по ценам открытия" 1 135 000 M1-баров EURUSD) при полном переборе в оптимизаторе. Если бы была реализована TesterToDate - заняло бы ~2 секунд (10-кратное ускорение). Целесообразно?
 
zaskok:

Желающие могут прогнать в оптимизаторе. У меня получается 20 секунд ("по ценам открытия" 1 135 000 M1-баров EURUSD) при полном переборе в оптимизаторе. Если бы была реализована TesterToDate - заняло бы ~2 секунд (10-кратное ускорение). Целесообразно?

Нет, 2 вместо 20 нецелесообразно. А 200 вместо 2000 не получится.

Имхо, конечно. 

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