Tiki in tempo reale - pagina 22

 
Andrey Khatimlianskii:

Guarda i tempi del registro. Tutto questo è successo in un ms, e accanto ad esso (nello stesso ms) un mucchio di OnBooks.

Puoi contare tutti gli eventi con i contatori, ma anche visivamente puoi vedere che ci sono più OnBooks.

Andrew, i numeri lì sono microsecondi fissi, quando le OnFunctions sono attivate, e tutto viene stampato insieme poi dall'array. Forse ci sono più OnBooks in totale - li conterò, ma non è chiaro perché saltano prima degli OnTick nella coda. O non ogni OnTick corrisponde a un OnBook?
 
prostotrader:


Non hai scritto che usi gli ordini Async?
Mi chiedevo, quale algoritmo usate per controllare l'esecuzione dei trade?

 
Aleksey Mavrin:
Andrew, i numeri lì sono microsecondi fissi quando le OnFunctions sono attivate, e tutto viene stampato insieme poi dall'array. Gli OnBooks in totale potrebbero essere di più - li conterò, ma non è chiaro perché saltano davanti agli OnTick nella coda o cosa. O non ogni OnTick corrisponde a un OnBook?

benvenuti nel mondo del networking ))))

La cosa più semplice da fare è eseguireNetstat - a -b sotto l'amministratore.

Vedrete porte e software, non voglio disturbare, ma credo che il server MT5 passi asincronicamente pacchetti con diverse informazioni che il terminale mette negli "scaffali" necessari.

SZZY: riguardo a Print() e al salto delle stampe se ne stampi molte alla volta, lo sai? - Scrivi solo le tue informazioni nel file - in questo modo salverai tutto e in ordine, ma non dimenticare di chiudere il file prima di chiuderlo. In teoria e Print() nei registri nel file dovrebbe essere completo, ma non hanno controllato e in generale non mi fido se un sacco di dati in uscita. Discusso quihttps://www.mql5.com/ru/forum/329730, molto spesso si parla di "impronte mancanti" ))) - ricerca

 
Aleksey Mavrin:
Andrew, i numeri sono fissati in microsecondi quando le OnFunctions sono attivate, e poi stampati tutti insieme dall'array. Forse ci sono più OnBooks in totale - li conterò, ma non è chiaro perché saltano prima degli OnTick nella coda. O non ogni OnTick corrisponde a un OnBook?

Capito.

Beh, c'è comunque un sacco di OnBook in giro. È difficile trarre conclusioni con un registro del genere.

 
Roman:

Pensavo avessi scritto che stavi usando gli ordini Async?
Mi chiedevo, quale algoritmo usate per controllare l'esecuzione degli scambi?

In OnTradeTransaction()+ controllare la funzione se non c'è una risposta del server per molto tempo.

Generalmente per magia.

Riservo 65535 simboli magici per ogni simbolo quando si imposta un EA,

e quando invio un ordine gli assegno un numero magico unico che non interseca in alcun modo altri simboli.

che non si sovrappone in alcun modo ad altri strumenti.

Ecco come ho impostato il numero magico iniziale per un simbolo

//+------------------------------------------------------------------+
//|                                                    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);  
}
//+------------------------------------------------------------------+

Magic - ulong (8 byte) ad es.

GAZR-3.12

Byte[7] (byte alto) è "G"

Byte[6] è "A"

Byte[5] per "Z"

Il byte[4] è "R

Byte[3] è "3

Byte[2] è "12"

Byte[1] e Byte[0] sono riserva di magia (65535)

Questo è il modo in cui passo attraverso i magiks quando invio un ordine:

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

Ma questo funziona solo per FORTS poiché i nomi dei simboli sono standardizzati!

Aggiunto

Se l'ordine viene inviato con successo, allora

ricorda il 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 poi (se non c'è risposta in OnTradeTransaction)

ticket = FindOrderBuyMagic(mem_magic, start_time);

E poi la stessa funzioneFindOrderBuyMagic

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

Aggiunto da

"Buona idea" aggiungere l'identificatore EA (0-255) al 1° byte nell'automagia,

ma non ne ho ancora bisogno, quindi non l'ho fatto :)

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

In OnTradeTransaction()+ controllare la funzione se non c'è una risposta del server per molto tempo.

Grazie per il suggerimento.

 
prostotrader:

1. Il secondo e i successivi terminali del broker sono pay-as-you-go e non ho strategie in cui commercio solo azioni(portafogli azionari).

2. Se avete intenzione di emettere ilGetMicrosecondCount() accumulato, allora

farlo senza timer in OnDeinit(), quando EA esce, tutto verrà stampato.

Per favore mandami il link al broker, è possibile nella LC.

È un ramo interessante... :-)

 
Igor Makanu:

benvenuti nel mondo del networking ))))

la cosa più semplice da fare è eseguireNetstat - a -b sotto l'amministratore

Vedrete porte e software, non voglio disturbare, ma credo che il server MT5 passi asincronicamente pacchetti con diverse informazioni che il terminale mette negli "scaffali" necessari.

SZZY: riguardo a Print() e al salto delle stampe se ne stampi molte alla volta, lo sai? - Scrivi solo le tue informazioni nel file - in questo modo salverai tutto e in ordine, ma non dimenticare di chiudere il file prima di chiuderlo. In teoria e Print() nei registri nel file dovrebbe essere completo, ma non hanno controllato e in generale non mi fido se un sacco di dati in uscita. Discusso quihttps://www.mql5.com/ru/forum/329730, molto spesso si parla di "impronte mancanti" ))) - ricerca

Igor, la perdita di stampe è discussa da coloro che non hanno aperto il file di log, un centinaio di volte e Rinat Fatkullin stesso ha scritto che non si perde nulla nel file di log. Ma per il tuo post non è stato invano :) ho aggiunto l'output in un file separato, inoltre ho fatto il secondo file, dove ho output un po 'diverso (raccogliendo tutti gli eventi in CArrayObj) per bypassare possibili bug del mio design, che ordina due array, cioè sto mettendo tutti in CArrayObj da due array, poi ordinare per microsecondi e uscita con marcatura quale evento Tick o Book.

E sì, cosa c'entra con i porti, cosa c'entra? Sto solo testando la coda degli eventi EA. Se arriva un tick, dovrebbero essere generati due eventi - OnTick, e il corrispondente OnBook, e OnBook è sempre messo in coda, e OnTick può scomparire se c'è già OnTick in coda (come in manuale), cioè la situazione in cui uno dopo l'altro OnTick senza OnTick può essere solo se 1. gli OnTick vanno "senza accodamento" 2. c'è un ritardo di sistema di OnBook, questo è quello che voglio controllare, questo può spiegare il ritardo di secondi, precedentemente identificato dai colleghi. Gli OnBooks totali sono 2+ volte di più in un giorno, ma perché sono in ritardo? Se questo ritardo è dovuto ai pacchetti asincroni e al parsing, forse, ma io controllo solo il fatto del loro arrivo nell'Expert Advisor finora. Come testare con il resto delle sfumature in mente, non ci ho ancora pensato.

Ecco il nuovo codice, all'apertura testerò la correttezza del lavoro ed eseguirò per la giornata.

s.w. La ragione può anche essere: se Tick è passato agli stessi prezzi senza cambiare la tazza - OnBook non è formato? Non sono uno specialista in commercio di azioni, chi può dirmi. Pensavo che OnTick causasse sempre 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:
Ma mi chiedo se il responsabile sia soddisfatto delle risposte alla sua domanda.

Ho già ricevuto tutte le risposte e ho tratto le mie conclusioni.
Ho bisogno di analizzare la striscia di scambi per un periodo di tempo fisso - prezzi degli scambi, volumi realizzati, ecc.
E ho anche bisogno di simulare il funzionamento dell'algoritmo nel tester di strategia.
L'evento OnTick si adatta perfettamente a questo, i risultati del trading reale e i risultati della modellazione nel tester concordano con un piccolo errore per mia soddisfazione.
Se avete bisogno di un'analisi più veloce della striscia, potete usare OnTimer.

E non è necessario che ogni tick che arriva al terminale sia messo in OnBook - questo è lo specifico dell'esecuzione degli ordini di mercato.

 
Vladimir Mikhailov:


E ogni tick che entra nel terminale non deve necessariamente andare in OnBook - è specifico per l'esecuzione degli ordini di mercato.

Al contrario, ogni tick(evento) che arriva al gestore OnTick deve essere sincronizzato con OnBook.
Ci sono tre eventi nel gestore OnTick, il cambiamento del prezzo della migliore offerta, il cambiamento del prezzo della migliore domanda e il trade (ultimo).
Se il prezzo bid o ask cambia senza una negoziazione, questo sarà un evento e OnTick riceverà questi eventi.
E OnBook deve anche catturare questi eventi, ma i propri eventi, il suo gestore, altrimenti ci sarà un mismatch dei prezzi bid e ask tra i gestori.

E se OnTick riceve un ultimo evento, significa che un trade è passato.
Il commercio genera l'evento in OnTick, perché dopo il commercio il prezzo o il volume di offerte e domande di cambiare nel mercato.
È un circolo vizioso.

In OnTick così come in OnBook, c'è un evento Best Bid e Best Ask.
Questi eventi dovrebbero essere sempre sincroni in entrambi i gestori.
E l'evento dura da solo, genera un evento in OnBook dopo lo scambio.
Pertanto, qualsiasi evento che arriva al gestore OnTick deve essere riflesso sincronicamente in OnBook.