Testando 'CopyTicks'. - página 41

 
Encontrei um bug em que CopyTicksRange devolve todos os ticks solicitados corretamente, mas LastError == ERR_HISTORY_TIMEOUT(4403).


 
fxsaber:

Os arquivos tkc são discriminados por mês. Perguntas por causa disso

  1. Se o terminal ainda não tem os dados do tkc carregados, quando você liga para o CopyTicks, como o terminal sabe quais arquivos tkc devem ser puxados?
Puxa todos os meses, a partir do mês atual.
  1. O CopyTicksRange é implementado com base no CopyTicks ou de forma independente?
Baseado em CopyTicks, ou seja, não otimizado de forma alguma.
  1. Estou certo em entender que fazer ticks para setembro, por exemplo, será sempre mais rápido através do CopyTicksRange, do que através do CopyTicks, porque o CopyTicks não sabe através dos parâmetros de entrada, para qual mês os dados devem ser puxados?

Não, o CopyTicksRange será igualmente lento por causa do ponto acima. Aqui está um roteiro mostrando algum absurdo da implementação atual do 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));
}

Parece ser claramente informado o que os arquivos de tkc devem ser puxados. Mas não, ele puxará da mesma forma que o CopyTicks - todos os arquivos tkc. E deixará de funcionar por tempo limite. Mas na verdade, deve funcionar quase que instantaneamente.

  1. Você precisa obter o histórico no indicador o mais rápido possível. É possível solicitá-lo via CopyTicksRange e obter um -1 até que tudo seja baixado. E se você solicitar por mês: mês atual, depois mês anterior, etc. Não será mais lento, mas o indicador estará pronto para trabalhar com pelo menos algum histórico. Certo?

Não há diferença, como se vê (ver pontos acima).

 

CopyTicks não funciona no OnDeinit seUninitializeRazão !=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();
}


Resultado (após a remoção do Expert Advisor)

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

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


Isto acontece em Expert Advisors. Nos indicadores, CopyTicks funciona normalmente no OnDeinit.

 
Quando você muda a conta(para outro servidor comercial), precisamos escrever no arquivo os últimos 2000 ticks da conta antiga. Como fazer isso?


Isto não vai funcionar.

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

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

  FileSave(__FILE__, Ticks);
}


Favor gerar CHARTEVENT_ACCOUNTCLOSING evento antes da mudança de conta, ao processá-la (em OnChartEvent) todo o ambiente comercial ainda não mudou para o novo.

 
fxsaber:
Ao alterar a conta(outro servidor comercial) é necessário escrever no arquivo os últimos 2000 ticks da conta antiga. Como posso fazer isso?


Isto não vai funcionar.


Antes de mudar a conta, favor gerar CHARTEVENT_ACCOUNTCLOSING evento, ao processá-la (em OnChartEvent) todo o ambiente comercial ainda não mudou para o novo.

Inteligentemente, devemos acrescentar um feedback, como é feito no Windows.

Como uma bandeira em um evento gráfico (ou não), ao defini-la, o evento em si (neste caso, a troca de conta) é cancelado.

 

Que seja abrupto, mas é irritante que dezenas de relatórios de erros sejam corrigidos, e novos relatórios continuem aparecendo com este CopyTicks.

Isso me cansa de tais truques.

#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)));
  }
}


Resultado

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


Remover um do código fonte

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


Reproduzido em diferentes personagens e servidores comerciais. Checado no dia de folga - as cotações estão de pé.


Quando os insetos serão derrotados nesta linha?

 

Na verdade, uma característica tão interessante no idioma, e funciona fora da caixa.

Aqui vai uma pergunta. Eu baixei os ticks manualmente (685.007 ticks) através do menu Symbols. Eu preciso de EURUSD de 2016.11.01 00:00 até 2016.11.08 00:00. Aqui está uma captura de tela.



Estou solicitando programmaticamente assim:

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();
  }


A saída é 0. O que está errado?

 
Dennis Kirichenko:

A saída é 0. O que está errado?

Multiplicar por 1000 de e para.

 
fxsaber:

Multiplicar por 1.000 de e para.


Que vergonha para mim, eu me enganei. Obrigado, cara.

 
Perdeu muito tempo para localizar este 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);
  }
}

Após a primeira execução no EURUSD M1 MetaQuotes-Demo, temos um resultado correto

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


Todas as próximas execuções mostrarão um 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


A situação se repetirá após o recarregamento do terminal: primeira corrida - multa, próxima corrida - bug.


SZY Note o comentário em destaque na fonte!