Testing 'CopyTicks' - page 41

 
Ran into a bug where CopyTicksRange returns all requested ticks correctly, but LastError == ERR_HISTORY_TIMEOUT(4403).


 
fxsaber:

The tkc files are broken down by month. Questions because of this

  1. If the terminal doesn't have the tick data uploaded yet, when you call CopyTicks, how does the terminal know which tkc files to pull?
Pulls every month, starting from the current month.
  1. Is CopyTicksRange implemented based on CopyTicks or independently?
Based on CopyTicks, i.e. not optimised at all.
  1. Am I right to understand that getting ticks for September, for example, will always be faster through CopyTicksRange, than through CopyTicks, because CopyTicks doesn't know through the input parameters, for which month data should be pulled?

No, CopyTicksRange will be just as slow because of the point above. Here is a script showing some absurdity of the current implementation of CopyTicksRange

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

void OnStart()
{  
  
  MqlTick Ticks[];
  
  ResetLastError();
  
  Print(__FUNCTION__);
  Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_ALL, 1, 2)));
  Print(TOSTRING(_LastError));
}

It seems to be clearly given information what tkc-files must be pulled. But no, it will pull the same way as CopyTicks - all tkc-files. And it will stop working by timeout. But actually it should work almost instantly.

  1. You need to get the history in the indicator as quickly as possible. It is possible to request it via CopyTicksRange and get a -1 until everything is downloaded. And if you request by month: current month, then previous month, etc. It will not be slower, but the indicator will be ready to work with at least some history. Right?

No difference, as it turns out (see points above).

 

CopyTicks does not work in OnDeinit ifUninitializeReason !=REASON_CHARTCHANGE

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

void TickTest()
{
  MqlTick Ticks[];

  ResetLastError();
  Print(TOSTRING(CopyTicks(_Symbol, Ticks)));
  Print(TOSTRING(_LastError));
}

void OnInit()
{
  Print("\n" + __FUNCTION__);
  
  TickTest();
}

void OnDeinit( const int )
{
  Print("\n" + __FUNCTION__);
  Print(TOSTRING(UninitializeReason()));
  
  TickTest();
}


Result (after Expert Advisor removal)

OnInit
CopyTicks(_Symbol,Ticks) = 2000
_LastError = 0

OnDeinit
UninitializeReason() = 1
CopyTicks(_Symbol,Ticks) = -1
_LastError = 4401


This happens in Expert Advisors. In indicators, CopyTicks works normally in OnDeinit.

 
When you change the account(to another trade server) we need to write into the file the last 2000 ticks of the old account. How to do it?


This will not work.

void OnDeinit( const int )
{
  MqlTick Ticks[];

  CopyTicks(_Symbol, Ticks); // Если была смена торгового сервера, то БД-тиков поменялась

  FileSave(__FILE__, Ticks);
}


Please generate CHARTEVENT_ACCOUNTCLOSING event before account change, when processing it (in OnChartEvent) all trading environment has not yet switched to the new one.

 
fxsaber:
When changing the account(another trade server) it is necessary to write into the file the last 2000 ticks of the old account. How do I do that?


This will not work.


Before changing the account, please generate CHARTEVENT_ACCOUNTCLOSING event, when processing it (in OnChartEvent) the whole trading environment has not yet switched to the new one.

Intelligently, we should add a feedback, as it is done in Windows.

In the form of a flag in chart (or not chart) event, when setting it, the event itself (in this case, account switch) is canceled.

 

Let it be abrupt, but it's annoying that dozens of bug reports, they get fixed, and new ones keep popping up with this CopyTicks.

It tires me out such tricks.

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

void OnStart()
{
  MqlTick Ticks[];

  if (CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, 0, 131072 + 1) > 0) // Если прибавлять не единицу, а ноль, то все будет работать
  {
    const ulong BeginTime = Ticks[0].time_msc;
    
    Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, BeginTime, LONG_MAX)));
    Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, BeginTime, (TimeCurrent() + 1) * 1000)));
  }
}


Result

CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,LONG_MAX) = 0
CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,(TimeCurrent()+1)*1000) = 131073


Remove one from the source code

CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,LONG_MAX) = 131072
CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,(TimeCurrent()+1)*1000) = 131072


Reproduced on different characters and trade servers. Checked on day off - kotirs are standing.


When will the bugs be defeated in this thread?

 

Indeed, such an interesting feature in the language, and it works out of the box...

Here's a question. I downloaded the ticks manually (685,007 ticks) through the Symbols menu. I need for EURUSD from 2016.11.01 00:00 to 2016.11.08 00:00. Here is a screenshot.



I am requesting programmatically like this:

void OnStart()
  {
   string symbol="EURUSD";
   MqlTick ticks_array[];
   uint flags=COPY_TICKS_INFO;
   ulong from_msc,to_msc;
   from_msc=(ulong)D'01.11.2016 00:00';
   to_msc=(ulong)D'08.11.2016 00:00';
//--- получить тики - 20 попыток
   for(int att=0;att<20;att++)
     {
      int copied=CopyTicksRange(symbol,ticks_array,flags,from_msc,to_msc);
      if(copied>0)
         break;
      Sleep(100);
     }
//--- остановка
   DebugBreak();
  }


The output is 0. What is wrong?

 
Dennis Kirichenko:

The output is 0. What's wrong?

Multiply by 1000 from and to.

 
fxsaber:

Multiply by 1,000 from and to.


Shame on me, I've got it wrong. Thanks, man.

 
Lost a lot of time to localize this bug CopyTicksRange


template <typename T>
T MyPrint( const T Value, const string Str )
{
  static const bool IsDebug = MQLInfoInteger(MQL_DEBUG);

//  if (IsDebug)
  {
//    DebugBreak(); // если хочется посмотреть средствами дебага

    Print(Str + " = " + (string)Value);
  }
  
  return(Value);
}

#define _P(A) MyPrint(A, __FUNCSIG__ ", Line = " + (string)__LINE__ + ": " + #A)

int GetSymbolTicks( const string Symb, MqlTick &Ticks[] )
{
  const bool Selected = SymbolInfoInteger(Symb, SYMBOL_SELECT);

  const int Amount = SymbolInfoInteger(Symb, SYMBOL_CUSTOM) && (Selected || SymbolSelect(Symb, true)) ? _P(CopyTicksRange(Symb, Ticks, COPY_TICKS_INFO)) : -1; // здесь баг!
  
  if (!Selected)
    SymbolSelect(Symb, false);

  return(Amount);
}

bool TicksToSymbol( const string Symb, const MqlTick &Ticks[] )
{
  const int Size = ArraySize(Ticks);
  
  CustomTicksDelete(Symb, Ticks[0].time_msc, Ticks[Size - 1].time_msc);
  
  return(Size ? (_P(CustomTicksReplace(Symb, Ticks[0].time_msc, Ticks[Size - 1].time_msc, Ticks)) > 0) : false);
}

void OnStart()
{
  MqlTick Ticks[];
    
  if (CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, D'2017.12.01' * 1000, (TimeCurrent() + 1) * 1000) > 100) // Если поставить сегодня - D'2017.12.05', то баг не проявится
  {
    ArrayResize(Ticks, 100);
    
    static const string Name = _Symbol + "_Custom";
    
    CustomSymbolDelete(Name);
    
    if (CustomSymbolCreate(Name) && CustomSymbolSetInteger(Name, SYMBOL_DIGITS, _Digits))
    {    
      TicksToSymbol(Name, Ticks);
    
      MqlTick Ticks2[];
      
      GetSymbolTicks(Name, Ticks2);
    }

    CustomSymbolDelete(Name);
  }
}

After the first run on EURUSD M1 MetaQuotes-Demo we have a correct result

bool TicksToSymbol(const string,const MqlTick&[]), Line = 36: CustomTicksReplace(Symb,Ticks[0].time_msc,Ticks[Size-1].time_msc,Ticks) = 100
int GetSymbolTicks(const string,MqlTick&[]), Line = 22: CopyTicksRange(Symb,Ticks,COPY_TICKS_INFO) = 100


All next runs will show a bug

bool TicksToSymbol(const string,const MqlTick&[]), Line = 36: CustomTicksReplace(Symb,Ticks[0].time_msc,Ticks[Size-1].time_msc,Ticks) = 100
int GetSymbolTicks(const string,MqlTick&[]), Line = 22: CopyTicksRange(Symb,Ticks,COPY_TICKS_INFO) = 0


The situation will be repeated after reloading the terminal: first run - fine, next runs - bug.


SZY Note the highlighted comment in the source!