Тестируем 'CopyTicks' - страница 24

 
Alexey Kozitsyn:

Почему?

int  CopyTicks(
   string           symbol_name,           // имя символа
   MqlTick&         ticks_array[],         // массив для приёма тиков
   uint             flags=COPY_TICKS_ALL,  // флаг, определяющий тип получаемых тиков
   ulong            from=0,                // дата, начиная с которой запрашиваются тики
   uint             count=0                // количество тиков, которые необходимо получить
   );
Жирным выделил. Массив в конец - отказ от дефолтных значений.
 
fxsaber:
int  CopyTicks(
   string           symbol_name,           // имя символа
   MqlTick&         ticks_array[],         // массив для приёма тиков
   uint             flags=COPY_TICKS_ALL,  // флаг, определяющий тип получаемых тиков
   ulong            from=0,                // дата, начиная с которой запрашиваются тики
   uint             count=0                // количество тиков, которые необходимо получить
   );
Жирным выделил.
Не выделилось, но, скорее всего, ответил выше...
 
fxsaber:
int  CopyTicks(
   string           symbol_name,           // имя символа
   MqlTick&         ticks_array[],         // массив для приёма тиков
   uint             flags=COPY_TICKS_ALL,  // флаг, определяющий тип получаемых тиков
   ulong            from=0,                // дата, начиная с которой запрашиваются тики
   uint             count=0                // количество тиков, которые необходимо получить
   );
Жирным выделил. Массив в конец - отказ от дефолтных значений.

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

int  CopyBuffer(
   int       indicator_handle,     // handle индикатора
   int       buffer_num,           // номер буфера индикатора
   int       start_pos,            // откуда начнем 
   int       count,                // сколько копируем
   double    buffer[]              // массив, куда будут скопированы данные
   );

 Ведь все же уже придумали, зачем изобретать что-то новое?

 
Alexey Kozitsyn:

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

Так с даты по дату и будет. CopyTicks пытаться подогнать по синтаксису к Copy-функциям только из-за присутствия Copy в названии - удобства не принесет. Удобно и оправдано, это когда можно делать препроцессорные штуки, как эта

// Позволяет, как в MT4, работать с таймсериями: Open[Pos], High[Pos], Low[Pos], Close[Pos], Time[Pos], Volume[Pos].
// А так же задает привычные MT4-функции: iOpen, iHigh, iLow, iClose, iTime, iVolume.
#define DEFINE_TIMESERIE(NAME,FUNC,T)                                                                         \
  class CLASS##NAME                                                                                           \
  {                                                                                                           \
  public:                                                                                                     \
    static T Get( const string Symb, const int TimeFrame, const int iShift )                                  \
    {                                                                                                         \
      T tValue[];                                                                                             \
                                                                                                              \
      return((Copy##FUNC((Symb == NULL) ? _Symbol : Symb, _Period, iShift, 1, tValue) > 0) ? tValue[0] : -1); \
    }                                                                                                         \
                                                                                                              \
    T operator []( const int iPos ) const                                                                     \
    {                                                                                                         \
      return(CLASS##NAME::Get(_Symbol, _Period, iPos));                                                       \
    }                                                                                                         \
  };                                                                                                          \
                                                                                                              \
  CLASS##NAME NAME;                                                                                           \
                                                                                                              \
  T i##NAME( const string Symb, const int TimeFrame, const int iShift )                                       \
  {                                                                                                           \
    return(CLASS##NAME::Get(Symb, TimeFrame, iShift));                                                        \
  }

DEFINE_TIMESERIE(Volume, TickVolume, long)
DEFINE_TIMESERIE(Time, Time, datetime)
DEFINE_TIMESERIE(Open, Open, double)
DEFINE_TIMESERIE(High, High, double)
DEFINE_TIMESERIE(Low, Low, double)
DEFINE_TIMESERIE(Close, Close, double)
А для CopyTicks подобное не сделать, т.к. есть два разных физических потока (TRADE и INFO) и один синтетический (ALL) - flags.
 
fxsaber:

Так с даты по дату и будет. CopyTicks пытаться подогнать по синтаксису к Copy-функциям только из-за присутствия Copy в названии - удобства не принесет. Удобно и оправдано, это когда можно делать препроцессорные штуки, как это

#define DEFINE_TIMESERIE(NAME,FUNC,T)                                                                         \
  class CLASS##NAME                                                                                           \
  {                                                                                                           \
  public:                                                                                                     \
    static T Get( const string Symb, const int TimeFrame, const int iShift )                                  \
    {                                                                                                         \
      T tValue[];                                                                                             \
                                                                                                              \
      return((Copy##FUNC((Symb == NULL) ? _Symbol : Symb, _Period, iShift, 1, tValue) > 0) ? tValue[0] : -1); \
    }                                                                                                         \
                                                                                                              \
    T operator []( const int iPos ) const                                                                     \
    {                                                                                                         \
      return(CLASS##NAME::Get(_Symbol, _Period, iPos));                                                       \
    }                                                                                                         \
  };                                                                                                          \
                                                                                                              \
  CLASS##NAME NAME;                                                                                           \
                                                                                                              \
  T i##NAME( const string Symb, const int TimeFrame, const int iShift )                                       \
  {                                                                                                           \
    return(CLASS##NAME::Get(Symb, TimeFrame, iShift));                                                        \
  }

DEFINE_TIMESERIE(Volume, TickVolume, long)
DEFINE_TIMESERIE(Time, Time, datetime)
DEFINE_TIMESERIE(Open, Open, double)
DEFINE_TIMESERIE(High, High, double)
DEFINE_TIMESERIE(Low, Low, double)
DEFINE_TIMESERIE(Close, Close, double)
А для CopyTicks подобное не сделать, т.к. есть два разных физических потока (TRADE и INFO) и один синтетический (ALL) - flags.

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

 
fxsaber:

На вашем демо, действительно, так. На БКС - нет

Network 'xxx': authorized on BCS-MetaTrader5 through Access Server #2 (ping: 46.66 ms)


2016.10.18 15:12:32.949 Test14 (Si-12.16,M1)    Time: 29089 msc for 1503 records
2016.10.18 15:12:32.822 Test14 (Si-12.16,M1)    Time: 33207 msc for 1501 records
2016.10.18 15:12:32.639 Test14 (Si-12.16,M1)    Time: 21389 msc for 1500 records
2016.10.18 15:12:31.959 Test14 (Si-12.16,M1)    Time: 21926 msc for 1500 records

 А на Альпари совсем плохо

Network 'xxx': authorized on Alpari-MT5 through mt5.nl.3 (ping: 61.87 ms)

2016.10.18 15:14:47.159 Test14 (GBPUSD,M1)      Time: 31086 msc for 1836 records
2016.10.18 15:14:46.999 Test14 (GBPUSD,M1)      Time: 30698 msc for 1836 records
2016.10.18 15:14:46.779 Test14 (GBPUSD,M1)      Time: 46306 msc for 1836 records
2016.10.18 15:14:46.612 Test14 (GBPUSD,M1)      Time: 30440 msc for 1836 records
2016.10.18 15:14:46.532 Test14 (GBPUSD,M1)      Time: 36227 msc for 1836 records

Высказался выше о неудобстве копитикс. Представленный индикатор тормозит по причине того, что вынужден несколько раз вызывать копитикс. И все тормоза именно из-за него. А дело вот в чем

Было предложено решение

Сейчас же, чтобы закачать тики между датами, надо делать запросы по НЕИЗВЕСТНО сколько тиков, начиная с начальной даты. И затем смотреть каждый раз, а достиг ли конечной даты. А с учетом того, что каждый запрос копитикс дается очень дорого, и получаются такие тормоза. 

Данные с реала открытия, подгрузка только свежих тиков:

2016.10.20 18:47:06.499 GetTickHistory: Получено 4 тиков за 46 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.499 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.499 GetTickHistory: Получено 3 тиков за 20 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.499 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.499 GetTickHistory: Получено 3 тиков за 19 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.499 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.540 GetTickHistory: Получено 8 тиков за 107 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.540 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.540 GetTickHistory: Получено 5 тиков за 19 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.540 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.540 GetTickHistory: Получено 5 тиков за 19 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.540 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
2016.10.20 18:47:06.540 GetTickHistory: Получено 5 тиков за 18 мкс (пинг = 62214 мкс)
2016.10.20 18:47:06.540 GetTickHistory: Получены все доступные тики. Время [0]: 2016.10.20 16:47
COPY_TICKS_TRADE!
 
CopyTicks(), похоже, асинхронная функция? Часто прилетают тики за свечи, которые еще не открылись...
 
Alexey Kozitsyn:
CopyTicks(), похоже, асинхронная функция?
Да.
 
Хотелось бы услышать от разработчиков как обстоят дела с CopyTicks() в тестере... что-то у меня плохие подозрения на этот счет. Интересует, опять таки, работа с COPY_TICKS_TRADE!
 

Замучил терминал. Скрипт

void OnStart()
{
  MqlTick Ticks[];
  
  Print(CopyTicks(_Symbol, Ticks));
  Print(GetLastError());
}

зависает. Ручное его удаление выводит в журнал

2016.10.28 16:48:57.737 Test (GBPUSD,M1)        4401
2016.10.28 16:48:57.737 Test (GBPUSD,M1)        -1

Смена ТФ и символа - аналогично. После перезагрузки заработал.
 

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