Tiki em tempo real - página 22

 
Andrey Khatimlianskii:

Veja o cronograma do registro. Tudo isso aconteceu em um ms, e ao lado dele (no mesmo ms) um monte de OnBooks.

Você pode contar todos os eventos por balcões, mas mesmo visualmente você pode ver que há mais OnBooks.

Andrew, os números lá são fixos em microssegundos, quando o OnFunctions é acionado, e tudo é impresso junto, então, a partir da matriz. Talvez haja mais OnBooks no total - eu os contarei, mas não está claro porque eles saltam à frente dos OnTicks na fila. Ou nem todo OnTick corresponde a um OnBook?
 
prostotrader:


Você não escreveu que usa encomendas da Async?
Eu estava me perguntando, que algoritmo você usa para controlar a execução dos negócios?

 
Aleksey Mavrin:
Andrew, os números lá são fixos em microssegundos quando o OnFunctions é acionado, e tudo é impresso junto, então, a partir da matriz. OnBooks no total pode ser mais - eu vou contar, mas não está claro porque eles saltam à frente dos OnTicks na fila ou o quê. Ou nem todo OnTick corresponde a um OnBook?

bem-vindo ao mundo do trabalho em rede ))))

A coisa mais fácil a fazer é administrar oNetstat - a -b sob o administrador.

Você verá portas e software, eu não quero incomodar, mas acho que o servidor MT5 passa de forma assíncrona pacotes com informações diferentes que o terminal coloca nas "prateleiras" necessárias.

SZZY: sobre a impressão() e a omissão de impressões se você imprimir muitas de cada vez, você sabe? - Basta escrever suas informações no arquivo - assim você salvará tudo e em ordem, mas não se esqueça de fechar o arquivo antes de fechá-lo. Em teoria e impressão() nos logs do arquivo devem estar completos, mas não verificaram e, em geral, não confio se muitos dados saem. Discutido aquihttps://www.mql5.com/ru/forum/329730, muito freqüentemente "impressões faltantes" são discutidas )))) - pesquisa

 
Aleksey Mavrin:
Andrew, os números são fixos em microssegundos quando o OnFunctions é acionado, e depois impressos todos juntos a partir da matriz. Talvez haja mais OnBooks no total - eu os contarei, mas não está claro porque eles saltam à frente dos OnTicks na fila. Ou nem todo OnTick corresponde a um OnBook?

Entendi.

Bem, há muitos OnBooks por aí de qualquer maneira. É difícil tirar qualquer conclusão com um tronco como esse.

 
Roman:

Pensei que você tinha escrito que estava usando pedidos da Async?
Eu estava me perguntando, que algoritmo você usa para controlar a execução do comércio?

Na OnTradeTransaction()+ função de verificação se não houver resposta do servidor por um longo tempo.

Geralmente por magia.

Eu reservo 65535 símbolos mágicos para cada símbolo ao definir um EA,

e ao enviar um pedido eu lhe atribuo um número mágico único que não intercepta de forma alguma outros símbolos.

que não se sobrepõe de forma alguma a outros instrumentos.

É assim que eu defino o número mágico inicial para um símbolo

//+------------------------------------------------------------------+
//|                                                    AutoMagic.mqh |
//|                                 Copyright 2017-2018 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//version   "1.01
ulong symb_magic;
//-------------------------------------------------------------------+
// Split string function                                             |
//+------------------------------------------------------------------+
string SplitString(const string a_str,ulong &a_month,ulong &a_year)
  {
   int str_size=StringLen(a_str);
   int str_tire=StringFind(a_str, "-");
   int str_tochka=StringFind(a_str, ".", str_tire);
   if((str_tire>0) && (str_tochka>0) &&(str_size > 0))
     {
      a_month= ulong(StringToInteger(StringSubstr(a_str,str_tire+1,str_tochka-str_tire-1)));
      a_year = ulong(StringToInteger(StringSubstr(a_str,str_tochka+1,str_size-str_tochka-1)));
      if((a_month > 0) && (a_year > 0)) return(StringSubstr(a_str, 0, str_tire));
     }
   return("");
  }
//-------------------------------------------------------------------+
// Get Magic function                                                |
//+------------------------------------------------------------------+
ulong GetMagic(const string a_symbol)
{
  symb_magic = 0;
  if(SymbolSelect(Symbol(), true) == false)
  {
    Print(__FUNCTION__, ": Нет такого символа!");
    return(0);
  }
  ulong month = 0;
  ulong year = 0;
  string new_str = SplitString(a_symbol,month,year);
  if(StringLen(new_str)>0)
  {
    uchar char_array[];
    int result=StringToCharArray(new_str,char_array,0,WHOLE_ARRAY,CP_ACP);
    if(result>0)
   {
     ulong value;
     for(int i = 0; i < result - 1; i++)
     {
       value=ulong(char_array[i]);
       value<<=(56 -(i*8));
       symb_magic += value;
     }
     month<<=24;
     symb_magic += month;
     year<<=16;
     symb_magic += year;
     return(symb_magic);
   }
 }
  return(0); 
}
//-------------------------------------------------------------------+
// Is my magic function                                              |
//+------------------------------------------------------------------+
bool IsMyMagic(const ulong m_magic)
{
  if(m_magic > 0)
  {
    ulong stored_magic=symb_magic;
    stored_magic>>=16;
    ulong in_magic = m_magic;
    in_magic>>=16;
    if(in_magic == stored_magic) return(true);
  }  
  return(false);
}
//-------------------------------------------------------------------+
// Get stored magic function                                         |
//+------------------------------------------------------------------+
ulong GetStoredMagic()
{
  if(symb_magic > 0) return(symb_magic);
  return(0);  
}
//+------------------------------------------------------------------+

Magia - ulong (8 bytes), por exemplo

GAZR-3.12

Byte[7] (byte alto) é "G".

Byte[6] é "A".

Byte[5] para "Z".

Byte[4] é "R

Byte[3] é "3

Byte[2] é "12".

Byte[1] e Byte[0] são magiks de reserva (65535)

É assim que eu passo pelos magos ao enviar um pedido:

  mem_magic = magic_storage + 1;
  if(magic_storage >= (magic_number + 65530)) mem_magic = magic_number;

Mas isso só funciona para FORTS, pois os nomes dos símbolos são padronizados!

Adicionado

Se o pedido for enviado com sucesso, então

lembrar o tempo

  if(OrderSendAsync(request, result) == true)
  {
    if((result.retcode == TRADE_RETCODE_PLACED) || (result.retcode == TRADE_RETCODE_DONE)) 
    {
      req_id = result.request_id;
      magic_storage = mem_magic;
      state = ORD_DO_SET;
      mem_time = GetMicrosecondCount();
      mem_start_time = TimeCurrent();
      SetTransCount();
    }
    else
    {
      mem_magic = 0;
      mem_time = 0;
      mem_start_time = 0;
      CheckError(result.retcode, "Place: Ордер не установлен! Причина: ", order_status, ticket);
    }
  }
mem_time = GetMicrosecondCount(); - для проверки времени задержки OnTradeTransaction
mem_start_time = TimeCurrent();   - для сужения рамок поиска в истории

E então (se não houver resposta na OnTradeTransaction)

ticket = FindOrderBuyMagic(mem_magic, start_time);

E então a própria funçãoFindOrderBuyMagic

#define  TIME_DELAY    180
//+------------------------------------------------------------------+
// Expert Find order Buy Magic function                              |
//+------------------------------------------------------------------+
ulong FindOrderBuyMagic(const ulong a_magic, const datetime set_time)
{
  if(a_magic > 0)
  {
    if(IsMyMagic(a_magic) == true)
    {
      ulong cur_ticket = 0;
      for(int i = OrdersTotal() - 1; i >= 0; i--)
      {
        cur_ticket = OrderGetTicket(i);
        if(OrderSelect(cur_ticket))
        {
          if( ulong(OrderGetInteger(ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }  
     }
      cur_ticket = 0;
      datetime start_time = datetime(ulong(set_time) - TIME_DELAY);
      datetime end_time = datetime(ulong(TimeCurrent()) + TIME_DELAY);    
      if(HistorySelect(start_time, end_time))
      {
        for(int i = HistoryOrdersTotal() - 1; i >= 0; i--)
        {
          cur_ticket = HistoryOrderGetTicket(i);
          if(ulong(HistoryOrderGetInteger(cur_ticket, ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }
      }
    }
  }
  return(0);
}

Adicionado por

"Boa idéia" para adicionar o identificador EA (0-255) ao primeiro byte do automágico,

mas ainda não preciso disso, então ainda não o fiz :)

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
В языке MQL5 предусмотрена обработка некоторых предопределенных событий. Функции для обработки этих событий должны быть определены в программе MQL5: имя функции, тип возвращаемого значения, состав параметров (если они есть) и их типы должны строго соответствовать описанию функции-обработчика события. Именно по типу возвращаемого значения и по...
 
prostotrader:

Na OnTradeTransaction()+ função de verificação se não houver resposta do servidor por um longo tempo.

Obrigado pela dica.

 
prostotrader:

1. O segundo terminal e os terminais subseqüentes no corretor são pay-as-you-go e eu não tenho estratégias onde eu negocio somente ações(carteiras de ações).

2. Se você vai emitir aGetMicrosecondCount() acumulada, então

fazê-lo sem temporizador no OnDeinit(), quando a EA sair, tudo será impresso.

Por favor, envie-me o link para o corretor, é possível na LC.

Este é um ramo interessante... :-)

 
Igor Makanu:

bem-vindo ao mundo do trabalho em rede ))))

A coisa mais fácil a fazer é administrar oNetstat - a -b sob o administrador.

Você verá portas e software, eu não quero incomodar, mas acho que o servidor MT5 passa de forma assíncrona pacotes com informações diferentes que o terminal coloca nas "prateleiras" necessárias.

HH: Você sabe sobre Impressão() e pulo de impressões, se você as imprimir muitas de uma só vez? - Basta escrever suas informações no arquivo - assim, você salvará tudo em ordem, mas não se esqueça de fechar o arquivo antes de fechá-lo. Em teoria e impressão() nos logs do arquivo devem estar completos, mas não verificaram e, em geral, não confio se muitos dados saem. Discutido aquihttps://www.mql5.com/ru/forum/329730, muito freqüentemente "impressões faltantes" são discutidas )))) - pesquisa

Igor, a perda de impressões é discutida por aqueles que ainda não abriram o arquivo de registro, cem vezes e o próprio Rinat Fatkullin escreveu que nada está perdido no arquivo de registro. Mas para seu cargo não foi em vão :) Eu adicionei a saída em um arquivo separado, além de ter feito o segundo arquivo, onde eu saio um pouco diferente (coletando todos os eventos no CArrayObj) para contornar possíveis erros do meu projeto, que ordena dois arrays, ou seja, eu coloco tudo no CArrayObj a partir de dois arrays, depois ordeno por microssegundos e saio com marcação de qual evento Tick ou Book.

E sim, o que isso tem a ver com portos, o que isso tem a ver com isso? Estou apenas testando a fila de eventos da EA. Se um tick chegar, dois eventos devem ser formados - OnTick, e OnBook correspondente, e OnBook é sempre colocado em fila, e OnTick pode desaparecer se já houver OnTick na fila (como no manual), ou seja, OnTick pode desaparecer se já houver OnTick na fila (como no manual). a situação quando um após outro OnTick sem o OnTick só pode ser se 1. o OnTicks for "sem fila" 2. houver um atraso do sistema OnBook, isto é o que eu quero verificar, isto pode explicar o atraso de segundos, previamente identificado pelos colegas. O Total OnBooks é 2+ vezes mais em um dia, mas por que eles estão atrasados? Se este atraso é devido a pacotes assíncronos e análise, talvez, mas eu só verifico o fato da chegada deles no Expert Advisor até agora. Como testar com o resto das nuances em mente, ainda não pensei sobre isso.

Aqui está o novo código, ao abrir vou testar a exatidão do trabalho e correr para o dia.

s.w. A razão também pode ser: se Tick passou pelos mesmos preços sem mudar o copo - OnBook não é formado? Eu não sou especialista em negociação de ações, quem pode me dizer. Pensei que OnTick sempre causa OnBook.

//+------------------------------------------------------------------+
//|                                                   TestOnBook.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Allex\Logger.mqh>
#include <Arrays\ArrayObj.mqh>
//---
bool is_book;
enum ENUM_BOOK_OR_TICK
{
        USE_BOOK,       // Use OnBookEvent
        USE_TICK        // Use OnTick
};
class CMcsOn: public CObject
{
public:
ulong mcs;
ENUM_BOOK_OR_TICK Ontype;
CMcsOn(ulong m, ENUM_BOOK_OR_TICK t):mcs(m),Ontype(t){};
int       Compare(const CObject*Object,const int mode=0) const
     {
      const CMcsOn* obj1=dynamic_cast<const CMcsOn*>(Object);
      CMcsOn* obj=(CMcsOn*)(obj1);
      if(!obj)return 0;
      return (mcs-obj.mcs);
      }
};
input ENUM_BOOK_OR_TICK Mode = USE_BOOK;
input int   SecForPrint =  3600;
//---
ulong TimeArrayBook[65536];
ulong TimeArrayTick[65536];
ushort curBook,curTick;
ulong  DelaySum=0,DelayCount=0,CountOnBook=0,CountOnTick=0;
int delay,delayMax=0;
CLogger* Logger,*Logger2;
CArrayObj ArrayObj;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   curBook=0;
   curTick=0; 
   DelaySum=0;DelayCount=0;CountOnBook=0;CountOnTick=0;delayMax=0;
   ArrayInitialize(TimeArrayBook,INT_MAX);
   ArrayInitialize(TimeArrayTick,INT_MAX);
   Logger=CLogger::GetLogger();
   Logger2= new CLogger();
   Logger.SetSetting(__FILE__+"\\",Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
   Logger2.SetSetting(__FILE__+"\\","Alt_"+Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
  if(Mode == USE_BOOK) is_book = MarketBookAdd(Symbol());
  ArrayObj.Shutdown();
  if (EventSetTimer(SecForPrint) &&  Logger.Init() && Logger2.Init()) 
  return(INIT_SUCCEEDED);
  else return (INIT_FAILED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(Mode == USE_BOOK)
  {
    if(is_book == true) MarketBookRelease(Symbol());
  }  
   delete Logger;
   delete Logger2;
}
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{  
  TimeArrayBook[curBook++]=GetMicrosecondCount();
  CountOnBook++;
  //Print(__FUNCTION__, " ",curBook);
}
void OnTick()
{
  TimeArrayTick[curTick++]=GetMicrosecondCount();
  CountOnTick++;
  //Print(__FUNCTION__, " ",curTick);

}
//+------------------------------------------------------------------+
void OnTimer()
  {
   string out=NULL;
   int total=MathMax(curBook,curTick);
   int i=0,k=0;
   while(i<total)
     {
      while(i<total && TimeArrayBook[i]<TimeArrayTick[k] )
        {
          MyPrint("Book "+TimeArrayBook[i++]);
        }    
      if(k<curTick-1)
        {
        if(i<total)
          {
           delay=TimeArrayBook[i]-TimeArrayTick[k];
           if (delay>delayMax) 
            delayMax=delay;
           if (delay>0)
              {
                 DelaySum+=delay;
                 DelayCount++;
              }
          }
         MyPrint("Tick "+TimeArrayTick[k++]+ " delay mcs "+delay);
        }       
        i++;
     }
     if (curTick>0)
     {
     MyPrint("Tick "+TimeArrayTick[curTick-1]+ " last");
     string out="Count Event Book after Tick "+DelayCount+". Delay Average "+DoubleToString(DelaySum/DelayCount,2)+". Max "+delayMax+" OnBooks "+CountOnBook+" OnTicks "+CountOnTick;
     MyPrint (out);
     Comment(out);
     }
     Logger.Logger();
     Alt();
     curBook=0;
     curTick=0;
  }
//---
void MyPrint(string out)  
{
   Print(out);
   Logger.Log(__FUNCTION__,out,2,false);
}
//---
void Alt()
{
int last=ArrayObj.Total();
for(int i=0;i<curBook;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayBook[i],USE_BOOK)))
      Logger2.Log(__FUNCTION__,"Error Book Add",0);   
  }
for(int i=0;i<curTick;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayTick[i],USE_TICK)))
      Logger2.Log(__FUNCTION__,"Error Tick Add",0);   
  }
  ArrayObj.Sort();
  int total=ArrayObj.Total();
  total-=last;
  CMcsOn*Obj;
  for(int i=0;i<total;i++)
    {    
     Obj=ArrayObj.At(i);
     if(CheckPointer(Obj)==POINTER_INVALID )
      { Logger2.Log(__FUNCTION__,"Error At Array",0); continue;}
      string out = Obj.USE_BOOK ? "Book ": "Tick ";
      out+= Obj.mcs  ;
      Logger2.Log(__FUNCTION__,out,2);
    }
   Logger2.Log("ArrayObj_","Last "+last+" total "+ArrayObj.Total(),1);  
   Logger2.Logger();
   //ArrayObj.Shutdown(); 
}
 
prostotrader:
Mas me pergunto se o responsável está satisfeito com as respostas à sua pergunta.

Eu já recebi todas as respostas e tirei minhas próprias conclusões.
Preciso analisar a faixa de ofícios por um período fixo de tempo - preços de ofícios, volumes realizados, etc.
Também preciso simular o funcionamento do algoritmo no testador de estratégia.
O evento OnTick lida perfeitamente com isso, os resultados da negociação real e os resultados da modelagem no testador concordam com um pequeno erro para minha satisfação.
Se você precisar de uma análise mais rápida da tira, você pode usar o OnTimer.

E não é necessário que cada carrapato que chega ao terminal seja colocado no OnBook - esta é a especificidade da execução de ordens do mercado.

 
Vladimir Mikhailov:


E cada carrapato que entra no terminal não precisa necessariamente entrar no OnBook - é específico para a execução de ordens de mercado.

Pelo contrário, cada carrapato(evento) que chega ao manipulador OnTick deve ser sincronizado com o OnBook.
Há três eventos no manipulador OnTick, a mudança do preço da melhor oferta, a mudança do preço da melhor oferta, e a(última) negociação.
Se o preço de compra ou venda mudar sem uma negociação, este será um evento e a OnTick receberá estes eventos.
E a OnBook também tem que pegar esses eventos, mas seus próprios eventos, seu manipulador, caso contrário haverá um descompasso de lances e preços de compra entre manipuladores.

E se a OnTick recebe um último evento, significa que uma troca já passou.
O comércio gera o evento na OnTick, porque após o comércio o preço ou o volume das ofertas e pede para mudar no mercado.
É um círculo vicioso.

Tanto no OnTick como no OnBook, há um evento Best Bid e Best Ask.
Estes eventos devem ser sempre síncronos em ambos os manipuladores.
E o evento por si só, ele gera um evento no OnBook após o comércio.
Portanto, qualquer evento que chegue ao manipulador OnTick deve ser refletido de forma sincronizada no OnBook.

Razão: