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

 
Копитикс не может вытащить имеющийся тик
struct MQLTICK
{
  uchar Data[sizeof(MqlTick)];
};

union UNION
{
  MQLTICK Tick1;
  MqlTick Tick2;  
  
  UNION()
  {
    ArrayInitialize(this.Tick1.Data, 1);
  }
};

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

void OnStart()
{  
  const string Name = "A1234";

  if (CustomSymbolCreate(Name) || SymbolInfoInteger(Name, SYMBOL_CUSTOM))
  {    
    UNION Union;
    
    MqlTick Ticks[] = {{0}};
    Ticks[0] = Union.Tick2;
    
    Ticks[0].time = TimeCurrent();
    Ticks[0].time_msc = Ticks[0].time * 1000;
    
    Print(TOSTRING(CustomTicksReplace(Name, Ticks[0].time_msc, Ticks[0].time_msc, Ticks))); // Тик записали без проблем
    
    MqlTick Ticks2[];
    
    SymbolSelect(Name, true);            
    
    // Прочесть тик не можем
    Print(TOSTRING(CopyTicksRange(Name, Ticks2)));
    Print(TOSTRING(CopyTicks(Name, Ticks2)));
    
    SymbolSelect(Name, false);            
    CustomSymbolDelete(Name);    
  }
}

Результат

CustomTicksReplace(Name,Ticks[0].time_msc,Ticks[0].time_msc,Ticks) = 1
CopyTicksRange(Name,Ticks2) = 0
CopyTicks(Name,Ticks2) = 0
 

Копитикс меняет исходные данные

struct MQLTICK
{
  uchar Data[sizeof(MqlTick)];
};

union UNION
{
  MQLTICK Tick1;
  MqlTick Tick2;  
  
  UNION()
  {
    ArrayInitialize(this.Tick1.Data, 1);
  }
};

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

void OnStart()
{  
  const string Name = "A1234";

  if (CustomSymbolCreate(Name) || SymbolInfoInteger(Name, SYMBOL_CUSTOM))
  {    
    UNION Union;
    
    MqlTick Ticks[] = {{0}};
    Ticks[0] = Union.Tick2;
    
    Ticks[0].time = 0;
    Ticks[0].time_msc = 0;

    Print(TOSTRING(Ticks[0].ask));
    
    Print(TOSTRING(CustomTicksReplace(Name, Ticks[0].time_msc, Ticks[0].time_msc, Ticks)));
    
    MqlTick Ticks2[];
    
    SymbolSelect(Name, true);            
    
    // Прочесть тик не можем
    Print(TOSTRING(CopyTicksRange(Name, Ticks2)));

    Print(TOSTRING(Ticks2[0].ask));
    
    SymbolSelect(Name, false);            
    CustomSymbolDelete(Name);    
  }
}


Результат

Ticks[0].ask = 7.748604185489348e-304
CustomTicksReplace(Name,Ticks[0].time_msc,Ticks[0].time_msc,Ticks) = 1
CopyTicksRange(Name,Ticks2) = 1
Ticks2[0].ask = 0.0
 

Почему формируются лишние тики?


Скрипт выводит лишние тики

string GetTickFlag( uint tickflag )
{
  string flag = "";

#define TICKFLAG_MACRO(A) flag += ((bool)(tickflag & TICK_FLAG_##A)) ? " TICK_FLAG_" + #A : "";
  TICKFLAG_MACRO(BID)
  TICKFLAG_MACRO(ASK)
  TICKFLAG_MACRO(LAST)
  TICKFLAG_MACRO(VOLUME)
  TICKFLAG_MACRO(BUY)
  TICKFLAG_MACRO(SELL)
#undef TICKFLAG_MACRO

  if (flag == "")
    flag = " FLAG_UNKNOWN (" + (string)tickflag + ")";
     
  return(flag);
}

#define TOSTRING(A) " " + #A + " = " + (string)Tick.A

string TickToString( const MqlTick &Tick )
{
  return(TOSTRING(time) + "." + (string)IntegerToString(Tick.time_msc %1000, 3, '0') +
         TOSTRING(bid) + TOSTRING(ask) + TOSTRING(last)+ TOSTRING(volume) + GetTickFlag(Tick.flags));
}

struct MQLTICK : public MqlTick
{
  bool operator ==( const MqlTick &Tick ) const
  {
    return((!Tick.ask || (Tick.ask == this.ask)) &&
           (!Tick.bid || (Tick.bid == this.bid)));
  }
  
  void operator =( const MqlTick &Tick )
  {
    this.ask = Tick.ask ? Tick.ask : this.ask;
    this.bid = Tick.bid ? Tick.bid : this.bid;
  }
};

void OnStart()
{
  MqlTick Ticks[];
  const int Amount = CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, 0, 1e4);

  MQLTICK Tick = {0};  
  
  for (int i = 0; i < Amount; i++)
    if (Tick == Ticks[i])
      Print(TickToString(Ticks[i]));
    else
      Tick = Ticks[i];
}


Результат на EURUSD Metaquotes-Demo

 time = 2017.11.14 02:27:14.352 bid = 1.16679 ask = 1.16682 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 02:29:11.325 bid = 1.16685 ask = 1.16687 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 03:04:02.402 bid = 1.16715 ask = 1.16717 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 03:41:09.453 bid = 1.16707 ask = 1.1671 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 03:42:53.101 bid = 1.16718 ask = 1.16721 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 04:51:22.072 bid = 1.16719 ask = 1.16721 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 04:53:55.649 bid = 1.16714 ask = 1.16717 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 04:56:12.254 bid = 1.16713 ask = 1.16716 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 04:57:12.497 bid = 1.16713 ask = 1.16716 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 04:58:28.934 bid = 1.16719 ask = 1.16722 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 05:18:44.717 bid = 1.16728 ask = 1.16731 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 05:25:39.559 bid = 1.16725 ask = 1.16728 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 05:27:54.243 bid = 1.16718 ask = 1.1672 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 05:29:38.909 bid = 1.16718 ask = 1.1672 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 05:31:40.868 bid = 1.16719 ask = 1.1672 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 05:38:29.393 bid = 1.16709 ask = 1.16712 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 05:39:29.429 bid = 1.16709 ask = 1.16712 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 05:47:36.539 bid = 1.16718 ask = 1.1672 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 06:19:44.287 bid = 1.16726 ask = 1.16729 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:21:11.941 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:22:22.686 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:23:11.019 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 06:23:24.926 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:24:22.060 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 06:24:26.871 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:25:26.704 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 06:25:27.401 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:42:16.087 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:44:00.557 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:44:36.362 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 06:45:00.577 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 06:51:36.472 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:52:37.091 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:53:38.025 bid = 1.16734 ask = 1.16737 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 06:56:11.389 bid = 1.16729 ask = 1.16732 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 07:03:22.022 bid = 1.16708 ask = 1.16711 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 07:08:35.305 bid = 1.16718 ask = 1.16721 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 07:24:15.039 bid = 1.16755 ask = 1.16758 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:27:16.339 bid = 1.16751 ask = 1.16754 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:39:26.342 bid = 1.16739 ask = 1.16742 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 07:43:33.909 bid = 1.16744 ask = 1.16747 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:45:25.462 bid = 1.16744 ask = 1.16747 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:47:05.824 bid = 1.16741 ask = 1.16744 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 07:48:19.985 bid = 1.16744 ask = 1.16747 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:49:57.642 bid = 1.16744 ask = 1.16747 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 07:52:39.036 bid = 1.16738 ask = 1.16741 last = 0.0 volume = 0 TICK_FLAG_ASK
 time = 2017.11.14 08:04:47.750 bid = 1.16739 ask = 1.16741 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 08:23:23.778 bid = 1.16705 ask = 1.16707 last = 0.0 volume = 0 TICK_FLAG_BID TICK_FLAG_ASK
 time = 2017.11.14 08:28:22.233 bid = 1.16706 ask = 1.16708 last = 0.0 volume = 0 TICK_FLAG_BID
 time = 2017.11.14 08:28:37.245 bid = 1.16706 ask = 1.16708 last = 0.0 volume = 0 TICK_FLAG_ASK
 

Копитикс в режиме COPY_TICKS_ALL занимается самодеятельностью - заполняет нулевые Bid/Ask-поля.

void OnStart()
{
  MqlTick Ticks[];
  const int Amount = CopyTicks(_Symbol, Ticks);
  
  ArrayPrint(Ticks);
}
[1986] 2017.11.14 10:12:11 1.16873 1.16873 0.0000        0 1510654331879       6
[1987] 2017.11.14 10:12:12 1.16871 1.16873 0.0000        0 1510654332026       2
[1988] 2017.11.14 10:12:12 1.16871 1.16871 0.0000        0 1510654332947       4
[1989] 2017.11.14 10:12:16 1.16869 1.16870 0.0000        0 1510654336930       6
[1990] 2017.11.14 10:12:17 1.16867 1.16868 0.0000        0 1510654337028       6
[1991] 2017.11.14 10:12:20 1.16866 1.16868 0.0000        0 1510654340943       2
[1992] 2017.11.14 10:12:22 1.16868 1.16869 0.0000        0 1510654342728       6
[1993] 2017.11.14 10:12:22 1.16868 1.16870 0.0000        0 1510654342834       4
[1994] 2017.11.14 10:12:22 1.16868 1.16869 0.0000        0 1510654342954       4
[1995] 2017.11.14 10:12:23 1.16867 1.16869 0.0000        0 1510654343339       2
[1996] 2017.11.14 10:12:27 1.16867 1.16868 0.0000        0 1510654347042       4
[1997] 2017.11.14 10:12:31 1.16867 1.16869 0.0000        0 1510654351428       4
[1998] 2017.11.14 10:12:31 1.16868 1.16869 0.0000        0 1510654351832       2
[1999] 2017.11.14 10:12:31 1.16869 1.16871 0.0000        0 1510654351942       6


Для чего это делается? В INFO-режиме такое поведение удобно, а вот в ALL ждешь получения сырых данных, а их показывает только GUI. 



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

В tkc хранятся только (без нулевых цен) флаги, хранятся только (без флагов) цены или же там нерационально присутствуют и флаги и цены?


И зачем введен флаг?

  • TICK_FLAG_VOLUME – тик изменил объем

Изменился объем или нет - не важно совершенно. Или я что-то не понимаю?


ЗЫ Сырые ALL-данные нужны особенно для кастомных символов, т.к. это напрямую касается вопроса канала обмена данным через кастомные символы.

 
fxsaber:

Копитикс в режиме COPY_TICKS_ALL занимается самодеятельностью - заполняет нулевые Bid/Ask-поля.


Для чего это делается? В INFO-режиме такое поведение удобно, а вот в ALL ждешь получения сырых данных, а их показывает только GUI. 



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

В tkc хранятся только (без нулевых цен) флаги, хранятся только (без флагов) цены или же там нерационально присутствуют и флаги и цены?


И зачем введен флаг?

Изменился объем или нет - не важно совершенно. Или я что-то не понимаю?


ЗЫ Сырые ALL-данные нужны особенно для кастомных символов, т.к. это напрямую касается вопроса канала обмена данным через кастомные символы.


Вы пишете в сервисдек о выявленных вами недочетах?

Такое ощущение что всё уходит в пустоту.


И зачем введен флаг?

  • TICK_FLAG_VOLUME – тик изменил объем

По моему это очень важный показатель. Как иначе узнать что совершена сделка, а не просто изменились, передвинулись bid ask?

 
Sergey Chalyshev:

Вы пишете в сервисдек о выявленных вами недочетах?

В СД оперативно реагируют на все заявки. Дальнейшие обсуждения ведутся там.

По моему это очень важный показатель. Как иначе узнать что совершена сделка, а не просто изменились, передвинулись bid ask?

Достаточно только флага

  • TICK_FLAG_LAST – тик изменил цену последней сделки
Переделав его на "прошла сделка". То, что last-цена изменилась - никого не волнует. Может быть несколько подряд сделок с полностью совпадающими ценой и объемом. Поэтому флаг должен быть только один - сделка.
 

TICK_FLAG_VOLUME – тик изменил объем

Как-то раньше не задумывался над написанным в справке.

Объем чего он изменил?

Что вообще означает написанное выше?))

 
fxsaber:

В СД оперативно реагируют на все заявки. Дальнейшие обсуждения ведутся там.

Достаточно только флага

Переделав его на "прошла сделка". То, что last-цена изменилась - никого не волнует. Может быть несколько подряд сделок с полностью совпадающими ценой и объемом. Поэтому флаг должен быть только один - сделка.

Если реагирует это хорошо.

По поводу флагов:

Тоже была такая мысль, в советниках для анализа ситуации,  объединить совпадающие сделки, этого как бы достаточно.

Такая ситуация - время биржи, время сервера, время компьютера не совпадают. Как узнать что MarketClosed, если пришла сделка даже по прошлой цене значит торговля идет.

И если объединить все сделки на одном уровне то непонятно будет за какое время уровень торговался?

P.S. лишние флаги не влияют на объем передаваемых флагов.

 
Sergey Chalyshev:

Если реагирует это хорошо.

По поводу флагов:

Тоже была такая мысль, в советниках для анализа ситуации,  объединить совпадающие сделки, этого как бы достаточно.

Такая ситуация - время биржи, время сервера, время компьютера не совпадают. Как узнать что MarketClosed, если пришла сделка даже по прошлой цене значит торговля идет.

И если объединить все сделки на одном уровне то непонятно будет за какое время уровень торговался?

Зачем объединять на одном уровне? Я бы не объединял, а оставил ленту, как сейчас - что пришло от биржи.

P.S. лишние флаги не влияют на объем передаваемых флагов.
Флаги - вынужденная мера, т.к. сырые данные MQ не возвращают. Они их модифицируют внутри CopyTicks.
 

tkc-файлы разбиты по месяцам. Вопросы из-за этого

  1. Если на терминале еще не закачаны тиковые данные, то при вызове CopyTicks как терминал узнает, какие tkc-файлы тянуть?
  2. CopyTicksRange реализован на основе CopyTicks или же самостоятельно?
  3. Правильно ли понимаю, что получить тики за сентябрь, например, будет всегда быстрее через CopyTicksRange, чем через CopyTicks, т.к. CopyTicks не знает через входные параметры, за какой месяц нужно тянуть данные?
  4. Нужно в индикаторе получить как можно быстрее историю. Есть возможность сделать запрос через CopyTicksRange и получить отлуп в виде -1, пока все не закачается. А если запрашивать по месяцу: текущий, затем предудыщий и т.д. То получится не медленнее же, но при этом индикатор будет готов работать хоть с какой-то историей.  Верно?

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