Обсуждение статьи "LifeHack для трейдера: замешиваем ForEach на дефайнах (#define)" - страница 2

 
Rashid Umarov:

Интересный и неочевидный прием )

Он с изъяном (для структур облом) и не оптимальный.

 
fxsaber:
В копилку

не очень удобно. неочевидно что внешнюю переменную надо объявлять.

 

"На шаблонах" имел ввиду это:

template< typename T >
class SeriesVolume
{
public:
   T operator[]( const int i ) const
   {
      long val[1];
      if( CopyTickVolume( Symbol(), Period(), i, 1, val ) == 1 ){
         return (T)val[0];
      }
      return -1;
   }
};

SeriesVolume< long > Volume;

Если хочется запутать, можно ещё сделать так:

#define CVolume SeriesVolume< long >

CVolume Volume;

Всё остальное просто не нужно.

 
fxsaber:

Меньше писанины - иногда удобно

Вопрос только в целесообразности, удобстве использования и производительности.

Производительность программы не пострадает. А вот спрятать от своих глаз избыточные подробности — это есть положительный эффект. Этот приём с дефайном надо запомнить и использовать.

 
 
fxsaber:

Жутко дорого! Если очень хочется через структуру, то надо было ее хотя бы static делать. И проверки по какой-то причине нет.

SymbolInfoDouble полностью соответствует MT4.

Замер производительности

#define BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double GetAsk()
{
  static MqlTick tick = {0};
  
  return(SymbolInfoTick(Symbol(),tick) ? tick.ask : 0);
}

#define AMOUNT 1e6

void OnStart()
{
  double Sum = 0;
  
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += GetAsk())
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += SymbolInfoDouble(_Symbol, SYMBOL_ASK))
  
  Print(Sum);
}


Результат

Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 78952
Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 162606

Я был абсолютно не прав! SymbolInfoDouble в два раза медленнее SymbolInfoTick.

 
fxsaber:

Замер производительности


Результат


Я был абсолютно не прав! SymbolInfoDouble в два раза медленнее SymbolInfoTick.

Спасибо за замер произвоительности.

Выходит, что документация по SymbolInfoDouble не врёт:

Примечание

Если функция используется для получения информации о последнем тике, то лучше использовать SymbolInfoTick().

 
fxsaber:

Замер производительности

Результат

Я был абсолютно не прав! SymbolInfoDouble в два раза медленнее SymbolInfoTick.

Использование static влияет на скорость? Извиняюсь, что сам не проверил, но думаю, что вы уже сравнивали.

 
Rashid Umarov:

Использование static влияет на скорость? Извиняюсь, что сам не проверил, но думаю, что вы уже сравнивали.

В данном случае не влияет. Думаю, это баг компилятора.

 
fxsaber:

Я был абсолютно не прав! SymbolInfoDouble в два раза медленнее SymbolInfoTick.

Некомпетентен. Результат в Тестере

2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 87424
2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 83410

Там, где нужна производительность (Оптимизатор), лучше использовать SymbolInfoDouble. На реале - без разницы.


ЗЫ Замер скорости функций нужно измерять в среде, где производительность важна - Тестер.

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