Новая версия платформы MetaTrader 5 build 3620: улучшения веб-терминала, поддержка ONNX и ускоренное умножение матриц в MQL5 - страница 3

 

Если бы изначально были запрещены все Copy-функции, кроме CopyRates, то подобных проблем, которые пользователи сами себе создают, не было бы.

А так получилось мнимое расширение/удобство функционала с вводом Copy-функций, вместо низкоуровневого подхода.

С SYMBOL_BID/ASK-свойствами такая же история.

 
fxsaber #:

Если бы изначально были запрещены все Copy-функции, кроме CopyRates, то подобных проблем, которые пользователи сами себе создают, не было бы.

А так получилось мнимое расширение/удобство функционала с вводом Copy-функций, вместо низкоуровневого подхода.

С SYMBOL_BID/ASK-свойствами такая же история.

Не использую CopyRates, чтобы сэономить несколько сот Мб ОЗУ на каждом символе.
Структура весит 60 байт, а мне мне нужно только 24 из них
 
Ilyas #:

Проблемы несинхронизованных данных нет при использовании CopyXXX функций с указанием начального времени бара, надеюсь не нужно объяснять почему.
Именно поэтому, реализацию вариантов CopySeries для запроса данных по времени пока отложили, сосредоточившись на более важных задачах

Так и подумал. Да можно обойтись и CopyXxxx функциями со временными границами.
 
Nikolai Semko #:
Не использую CopyRates, чтобы сэономить несколько сот Мб ОЗУ на каждом символе.
Структура весит 60 байт, а мне мне нужно только 24 из них

Никакой экономии с Copy-функциями нет, т.к. в них идет вызов CopyRates. Первая функция, где иначе:

Экономная она или нет - не знаю.
 
fxsaber #:

Никакой экономии с Copy-функциями нет, т.к. в них идет вызов CopyRates. Первая функция, где иначе:

Экономная она или нет - не знаю.

речь была про пиковую нагрузку на ОЗУ из-за промежуточных внутренних временных MqlRates массивов, которые конечно же быстро очищаются. 
Ну Ок. Соглашусь в том, что если бы была только одна функция CopyRates(), я бы не сильно расстроился. 
Но все равно, в данных момент лично для меня удобнее пользоваться отдельными функциями CopyXxxx с точки зрения произовдительности и задействия ресурсов компьютера(выгода незначительная, но есть).
Если бы была функция  CopySeries() с временными границами, то использовал бы её из-за более лаконичного кода. 

 

Я тут немного 4ку затрону. Но это часть моего вопроса по 5ке.


Из справки по ArrayCopySeries:

"Реального распределения памяти под массив данных и копирования не происходит. При обращении к такому массиву производится перенаправление доступа."

Из справки по ArrayCopyRates:

"При использовании первой формы вызова происходит виртуальное копирование таймсерии в массив структур MqlRates. Это означает, что если данные таймсерии обновились, то повторное копирование не требуется - массив rates_array[] по-прежнему будет ссылаться на актуальную версию таймсерии и данные будут корректными всегда."


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

На сколько я помню, терминал перестает обновлять данные по символу/таймфрейму, когда они какое-то время не запрашиваются из программ и нет открытых графиков по ним.

У меня логика такая. Зачем мне копировать нужное количество данных только при необходимости? Обычно эти данные нужны непосредственно перед отправлением торговых приказов. То есть в самый ответственный момент я рискую вместо котировок получить "подожди, грузятся..."

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

Вот выдрал из эксперта простенький пример для работы с D1 и W1:

const int RATES_WAITING_SEC = 30;
int       RATES_WAITING_TICKS = 10;

MqlRates ratesD1[];
MqlRates ratesW1[];
datetime ratesWaitingTimeTo;
int      ratesWaitingTicksLeft;
bool     rates_IsActual;

int OnInit()
  {
   ratesWaitingTimeTo = 0;
   ratesWaitingTicksLeft = 0;
   return(INIT_SUCCEEDED);
  }

void OnTick()
  {
   rates_IsActual = blockRates(TimeCurrent());
   useRates();
  }

bool blockRates(datetime dtCurrent)
  {
   // Waiting for rates to be loaded
   if(dtCurrent <= ratesWaitingTimeTo || ratesWaitingTicksLeft > 0)
     {
      ArrayCopyRates(ratesD1, _Symbol, PERIOD_D1);
      ArrayCopyRates(ratesW1, _Symbol, PERIOD_W1);
      PrintFormat("Waiting for rates to be loaded. Remaining: %i seconds, %i ticks", ratesWaitingTimeTo - dtCurrent, ratesWaitingTicksLeft);
      if(ratesWaitingTicksLeft > 0)
         ratesWaitingTicksLeft--;
      return(false);
     }
   // Copying
   bool allRatesCopied = true;
   blockRates_CopyTo(ratesD1, PERIOD_D1, allRatesCopied);
   blockRates_CopyTo(ratesW1, PERIOD_W1, allRatesCopied);
   // -------
   if(!allRatesCopied)
     {
      ratesWaitingTimeTo = dtCurrent + RATES_WAITING_SEC;
      ratesWaitingTicksLeft = RATES_WAITING_TICKS;
      return(false);
     }
   return(true);
  }

void blockRates_CopyTo(MqlRates &ratesArray[], ENUM_TIMEFRAMES timeframe, bool &allRatesCopied)
  {
   ResetLastError();
   int copied = ArrayCopyRates(ratesArray, _Symbol, timeframe);
   int error = GetLastError();
   if(copied < 1 || error != ERR_NO_ERROR)
     {
      PrintFormat("CopyRates error %i, rates copied: %i, timeframe %s", error, copied, EnumToString(timeframe));
      allRatesCopied = false;
     }
  }

void useRates()
  {
   if(!rates_IsActual)
      return;
   // Можно использовать ratesD1[] и ratesW1[]
  }

Вопрос по 5ке. Можно ли там сослаться, а не копировать?

Просьба. Обосрите Укажите, пожалуйста, на ошибки в моих рассуждениях и на недостатки этого метода для 4ки.

P.S. Эта штука может и медленная, но надежная - ни разу еще не подводила. Для меня это плата производительностью за спокойный сон. Хотя, я не исследовал, на сколько она медленная.

 
Nikolai Semko #:

речь была про пиковую нагрузку на ОЗУ из-за промежуточных внутренних временных MqlRates массивов, которые конечно же быстро очищаются. 

Эти временные промежуточные массивы во внутренней реализации Copy-функций. Грубо говоря, MQ за пользователей написали эти функции, вместо того, чтобы оформить в виде стандартной библиотеки.

Но все равно, в данных момент лично для меня удобнее пользоваться отдельными функциями CopyXxxx с точки зрения произовдительности

Любая старая Copy-функция не должна работать быстрее CopyRates. Поэтому вызов CopyRates выгоднее нескольких вызовов Copy-функций.

 
fxsaber # :

Эти временные промежуточные массивы во внутренней реализации Copy-функций. Грубо говоря, MQ за пользователей написали эти функции, вместо того, чтобы оформить в виде стандартной библиотеки.

Любая старая Copy-функция не должна работать быстрее CopyRates. Поэтому вызов CopyRates выгоднее нескольких вызовов Copy-функций.

CopyXXX вообще не использует CopyRates(), почему вы так думаете?

В среднем CopyRates() примерно в 2 раза медленнее, чем CopyXXX().

Данные уже кэшированы.

Холодный запуск.


 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Новая версия платформы MetaTrader 5 build 1930: Плавающие окна графиков и .Net библиотеки в MQL5

Renat Fatkhullin, 2018.12.10 19:31

Новые результаты после сегодняшних оптимизаций, которые будут доступны в следующей бета-версии на днях:

  MT4
MT5
Холодный запуск
5 symbols, 100000 max bars:
    EURUSD
    USDCHF
    USDCAD
    GBPUSD
    USDJPY
Iteration 1: took 36085 msc for 5 symbols
Iteration 2: took 155 msc for 5 symbols
...
Iteration 100: took 138 msc for 5 symbols
Total: 51442 msc

5 symbols, 100000 max bars:
    EURUSD
    USDCHF
    USDCAD
    GBPUSD
    USDJPY
Iteration 1: took 552687 msc for 5 symbols
Iteration 2: took 307995 msc for 5 symbols
...
Iteration 100: took 125 msc for 5 symbols
Total: 874137 msc  (было 1434053 msc)

Горячий запуск
Iteration 1: took 235 msc for 5 symbols
Iteration 2: took 138 msc for 5 symbols
...
Iteration 100: took 136 msc for 5 symbols
Total: 15524 msc

Iteration 1: took 273 msc for 5 symbols
Iteration 2: took 128 msc for 5 symbols
...
Iteration 100: took 123 msc for 5 symbols
Total: 13772 msc (было 21456 msc)

По горячему в CopyRates MT5 обогнал MT4 на 2 мс. оптимизация удалась.

Я забыл сразу объяснить важную особенность хранения данных баров в МТ5. В МТ5 бары хранятся в виде отдельных массивов Open, High, Low, Close, Volume. Это означает, что для создания MqlRates бара в функции CopyRates нам нужно собирать структуру ценового бара из множества массивов.

Это заведомо дороже, чем просто выдать готовый бар, как это доступно в MT4. Но и это мы сделали быстрее.


Почему у нас разделены массивы данных в МТ5? Потому что так эффективнее работать и особенно для отдельных функций CopyClose, CopyHigh, High[], Low[] и тд. Очень много мест, где используются конкретные показатели без необходимости обращений ко всему бару.

Давайте сравним скорость доступа CopyHigh в обоих системах. Сразу будем проверять горячие кеши:

  МТ4
МТ5
Горячий запуск CopyHigh
10 230 msc
2 862 msc

Вот тут явно видно преимущество Метатрейдер 5: в 3.5 раза быстрее выдает данные отдельных таймсерий.

Совет: не копируйте бары в пятерке, если нужно иметь только один показатель. Не переводите один в один код из четверки.


 
fxsaber #:

Любая старая Copy-функция не должна работать быстрее CopyRates. Поэтому вызов CopyRates выгоднее нескольких вызовов Copy-функций.

Ну как же не должна, если заполняемый массив MqlRates в несколько раз больше, чем, например массив double того же размера. 


время заполнение более большого массива, естественно будет больше, чем время заполения меньшего. 
Например я, как правило, использую размер массива 131072 (2^17) элементов

Это 131072 *60байт = 7864320 байт (для MqlRates) против 131072*8байт = 1048576 байт (для double). 
Разница времени заполнения будет , думаю, в сотни микросекунд.

ЗЫ Я понимаю, что в ОЗУ уже сидит полный MqlRates массив, но из него как раз происходит копирование (реальное, не по ссылке) или в пользовательский MqlRates массив, или же в double или datetime массивы.