Новая версия платформы MetaTrader 5 build 3500: улучшения и исправления - страница 6

 
fxsaber #:

Спасибо за подробности. Тогда точно надо искать слабые места. Просьба все же ускорить историю.

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

 
Renat Fatkhullin #:

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

Речь про работу уже ПОСЛЕ HistorySelect.

 
Renat Fatkhullin #:

Раз уж Вы здесь. Видится ли правильным, что удаление ордера (например, руками) вызывает помещение его не в конец БД исторических ордеров, а в середину?

Например, в Тестере любое помещение в БД ордера происходит дозаписыванием в конец. А в Терминале?

 
fxsaber #:

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

Неужели нужно писать подобие первой функции?! Второй же вариант - полная засада с производительностью.

Уважаемые форумчане, а какой вариант используете Вы?

Тройка вариантов с рекурсией больше ради прикола. ))
Впрочем в большинстве тестов побеждают, но не на много.

/====================================================================
double GetSum4( const STRUCT &Array[], const double Koef1, const double Koef2, const double Koef3, double Sum = 0, int i = 1)
{
  _GetSum(Array[i].Request,Koef1,Koef2,Koef3,Sum);
  if (++i<ArraySize(Array)) return GetSum4(Array,Koef1,Koef2,Koef3,Sum,i);
  return(Sum);
}

double _GetSum( const MqlTradeRequest &Request[], const double Koef1, const double Koef2, const double Koef3, double &Sum, int j = 0 )
{
  Sum += Koef1 * Request[j].price + Koef2 * Request[j].tp +  Koef3 * Request[j].sl;
  if (++j<ArraySize(Request)) return _GetSum(Request,Koef1,Koef2,Koef3,Sum,j);
  return(Sum);
}
//====================================================================
double GetSum5( const STRUCT &Array[], const double Koef1, const double Koef2, const double Koef3, double Sum = 0, int i = 1, int j = 0 )
{
  Sum += Koef1 * Array[i].Request[j].price + Koef2 * Array[i].Request[j].tp + Koef3 * Array[i].Request[j++].sl;
  if (j<ArraySize(Array[i].Request)) return GetSum5(Array,Koef1,Koef2,Koef3,Sum, i,j);
  if (++i<ArraySize(Array)) return GetSum5(Array,Koef1,Koef2,Koef3,Sum, i);
  return(Sum);
}
//====================================================================
double GetSum6( const STRUCT &Array[], const double Koef1, const double Koef2, const double Koef3, double Sum = 0, int i = 1)
{
  __GetSum(Array[i].Request,Koef1,Koef2,Koef3,Sum);
  if (++i<ArraySize(Array)) return GetSum6(Array,Koef1,Koef2,Koef3,Sum,i);
  return(Sum);
}

double __GetSum( const MqlTradeRequest &Request[], const double Koef1, const double Koef2, const double Koef3, double &Sum, int j = 0 )
{
  Sum += GetResult(Request[j],Koef1,Koef2,Koef3);
  if (++j<ArraySize(Request)) return __GetSum(Request,Koef1,Koef2,Koef3,Sum,j);
  return(Sum);
}

double GetResult(const MqlTradeRequest &Request, const double Koef1, const double Koef2, const double Koef3) {
   return Koef1 * Request.price + Koef2 * Request.tp +  Koef3 * Request.sl;
}
//====================================================================

ЗЫ Проблемы рекурсии в том, что на дебаге можно словить переполнение стека.
Да и как говорил Ильяс, оптимизация компилятором рекурсивной функции может быть пересмотрена в будущем.

Файлы:
Test01.mq5  11 kb
 
Nikolai Semko #:

Да и как говорил Ильяс, оптимизация компилятором рекурсивной функции может быть пересмотрена в будущем.

Сильно поменялось с тех пор.

 
Nikolai Semko #:

Тройка вариантов с рекурсией больше ради прикола. ))
Впрочем в большинстве тестов побеждают, но не на много.

Очень сильные расхождения от запуска к запуску. Поэтому сделал такой замер.

#define TOSTR(A) " " + #A + " = " + (string)(A)

#define MACROS(A)                                    \
  {                                                  \
    double Result = 0;                               \
    ulong MinTime = ULONG_MAX;                       \
    ulong MaxTime = 0;                               \
                                                     \
    for (int i = 0; i < 20; i++)                     \
    {                                                \
      ulong StartTime = GetMicrosecondCount();       \
      Result += A;                                   \
      StartTime = GetMicrosecondCount() - StartTime; \
                                                     \
      MinTime = MathMin(StartTime, MinTime);         \
      MaxTime = MathMax(StartTime, MaxTime);         \
    }                                                \
                                                     \
    if ((bool)(Result -= 1) || (Result == 1))        \
      Print(#A + TOSTR(MinTime) + TOSTR(MaxTime));   \
  }

void OnStart()
{
  STRUCT Array[];
  
  // Инициализация.
  for (int i = ArrayResize(Array, 5e3) - 1; i >= 0; i--)
    ArrayResize(Array[i].Request, i);
    
  // Замеряем.
  MACROS(GetSum1(Array, 1, 2, 3))
  MACROS(GetSum2(Array, 1, 2, 3))
  MACROS(GetSum3(Array, 1, 2, 3))
  MACROS(GetSum4(Array, 1, 2, 3))
  MACROS(GetSum5(Array, 1, 2, 3))
  MACROS(GetSum6(Array, 1, 2, 3))
}


GetSum1(Array,1,2,3) MinTime = 138413 MaxTime = 151860
GetSum2(Array,1,2,3) MinTime = 243762 MaxTime = 279650
GetSum3(Array,1,2,3) MinTime = 138158 MaxTime = 156920
GetSum4(Array,1,2,3) MinTime = 134872 MaxTime = 144667
GetSum5(Array,1,2,3) MinTime = 139631 MaxTime = 147597
GetSum6(Array,1,2,3) MinTime = 135350 MaxTime = 145973
 
Renat Fatkhullin #:

Посмотрите примеры использования этого параметра в MQL5\Scripts\Examples\OpenCL\Float\FFT.mq5

Плюс документацию на саму официальную спецификацию OpenCL. Спецификация независима от карт, так что не имеет смысла задавать вопросы про специфичность того или иного устройства.

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

Ещё вопрос, про рейтинг карт

2022.11.14 00:09:04.920 OpenCL  device #0: GPU 'NVIDIA GeForce GTX 1660 SUPER' with OpenCL 3.0 (22 units, 1785 MHz, 6144 Mb, version 473.81, rating 5714)

Как Вы его выставили - по сравнению с HD7950 вышеуказанная карта работает в моей задаче на 30% быстрей, но рейтинг у последней значительно ниже - 869. Если бы я через клауд смог бы в будущем выбирать карты, и платить соответственно по рейтингу (в раз пять меньше), то это было бы хорошим подспорьем.

 
Renat Fatkhullin #:

Доступ в историю - это синхронизированные обращения в базу данных

Вот это бы в документацию.

Поскольку многопоточности нет, то пришлось поделить бота на execution часть и все остальное.

Однако работа с историей как-то выпала, потому что вот не очевидно с первого взгляда, что обращения синхронизированы.

 
Azat #:

Однако работа с историей как-то выпала, потому что вот не очевидно с первого взгляда, что обращения синхронизированы.

Уверен, что Ренат ошибся. HistorySelect-функции - синхронные. HistoryGet - нет.

 
На MarketWatch две стрелочки назад вперед для быстрой смены сетов инструментов не хватает
Причина обращения: