Tiki en temps réel - page 22

 
Andrey Khatimlianskii:

Regardez le timing du journal. Tout cela s'est passé dans un ms, et à côté (dans le même ms) un tas d'OnBooks.

Vous pouvez compter tous les événements par des compteurs, mais même visuellement vous pouvez voir qu'il y a plus d'OnBooks.

Andrew, les chiffres sont des microsecondes fixes, lorsque les OnFunctions sont déclenchées, et tout est imprimé ensemble à partir du tableau. Il y a peut-être plus d'OnBooks au total - je vais les compter, mais on ne sait pas pourquoi ils passent avant les OnTicks dans la file d'attente. Ou bien chaque OnTick ne correspond pas à un OnBook ?
 
prostotrader:


N'avez-vous pas écrit que vous utilisez des commandes asynchrones ?
Je me demandais, quel algorithme utilisez-vous pour contrôler l'exécution des transactions ?

 
Aleksey Mavrin:
Andrew, les chiffres ici sont des microsecondes fixes lorsque les OnFunctions sont déclenchées, et tout est imprimé ensemble alors à partir du tableau. Il y a peut-être plus d'OnBooks au total - je vais compter, mais on ne sait pas pourquoi ils passent avant les OnTicks dans la file d'attente. Ou bien chaque OnTick ne correspond pas à un OnBook ?

bienvenue dans le monde des réseaux ))))

La chose la plus simple à faire est d'exécuterNetstat - a -b sous l'administrateur.

Vous verrez des ports et des logiciels, je ne veux pas m'embêter, mais je pense que le serveur MT5 transmet de manière asynchrone des paquets avec différentes informations que le terminal place dans les "étagères" nécessaires.

SZZY : à propos de Print() et du saut des impressions si vous en imprimez beaucoup à la fois, savez-vous ? - Il suffit d'écrire vos informations dans le fichier - de cette façon, vous sauvegarderez tout et dans l'ordre, mais n'oubliez pas de fermer le fichier avant de le clore. En théorie et Print() dans les journaux dans le fichier devrait être complète, mais n'ont pas vérifié et en général je ne fais pas confiance si un grand nombre de données de sortie. Discuté icihttps://www.mql5.com/ru/forum/329730, très souvent les "empreintes manquantes" sont discutées )))) - recherche

 
Aleksey Mavrin:
Andrew, les nombres sont fixés en microsecondes lorsque les OnFunctions sont déclenchées, puis imprimés tous ensemble à partir du tableau. Il y a peut-être plus d'OnBooks au total - je vais les compter, mais on ne sait pas pourquoi ils passent avant les OnTicks dans la file d'attente. Ou bien chaque OnTick ne correspond pas à un OnBook ?

Je l'ai.

Eh bien, il y a beaucoup d'OnBooks dans le coin de toute façon. Il est difficile de tirer des conclusions avec un tel registre.

 
Roman:

Je croyais que vous aviez écrit que vous utilisiez des commandes asynchrones ?
Je me demandais, quel algorithme utilisez-vous pour contrôler l'exécution des transactions ?

Dans la fonction OnTradeTransaction()+ vérifier s'il n'y a pas de réponse du serveur pendant une longue période.

Généralement par magie.

Je réserve 65535 symboles magiques pour chaque symbole lors du paramétrage d'un EA,

et lorsque j'envoie un ordre, je lui attribue un numéro magique unique qui ne croise en aucun cas d'autres symboles.

qui ne se chevauche en aucune façon avec d'autres instruments.

Voici comment je fixe le nombre magique initial pour un symbole

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

Magique - ulong (8 octets) par ex.

GAZR-3.12

L'octet [7] (octet de poids fort) est "G".

L'octet [6] est "A"

Octet [5] pour "Z"

L'octet [4] est "R

L'octet [3] est "3

L'octet [2] est "12".

L'octet [1] et l'octet [0] sont des réserves magiques (65535)

C'est ainsi que je procède aux magies lors de l'envoi d'une commande :

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

Mais cela ne fonctionne que pour les FORTS car les noms des symboles sont standardisés!

Ajouté

Si la commande est envoyée avec succès, alors

rappelez-vous le temps

  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();   - для сужения рамок поиска в истории

Et ensuite (s'il n'y a pas de réponse dans OnTradeTransaction)

ticket = FindOrderBuyMagic(mem_magic, start_time);

Et ensuite la fonctionFindOrderBuyMagic elle-même.

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

Ajouté par

"Bonne idée" d'ajouter l'identifiant de l' EA (0-255) au 1er octet dans l'automate,

mais je n'en ai pas encore besoin, donc je ne l'ai pas fait :)

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

Dans la fonction OnTradeTransaction()+ vérifier s'il n'y a pas de réponse du serveur pendant une longue période.

Merci pour le conseil.

 
prostotrader:

1. Le deuxième terminal et les suivants chez le courtier sont payants et je n'ai pas de stratégies où je ne négocie que des actions(portefeuilles d'actions).

2. Si vous voulez afficher les données accumulées dansGetMicrosecondCount(), alors

faites-le sans timer dans OnDeinit(), quand EA sort, tout s'imprimera.

Veuillez m'envoyer le lien vers le courtier, c'est possible dans le LC.

C'est une branche intéressante... :-)

 
Igor Makanu:

bienvenue dans le monde des réseaux ))))

la chose la plus simple à faire est de lancerNetstat - a -b sous l'administrateur

Vous verrez des ports et des logiciels, je ne veux pas m'embêter, mais je pense que le serveur MT5 transmet de manière asynchrone des paquets avec différentes informations que le terminal place dans les "étagères" nécessaires.

SZZY : à propos de Print() et du fait de sauter des impressions si vous en imprimez beaucoup à la fois, savez-vous ? - Il suffit d'écrire vos informations dans le fichier - de cette façon vous sauvegarderez tout et dans l'ordre, mais n'oubliez pas de fermer le fichier avant de le clore. En théorie et Print() dans les journaux dans le fichier devrait être complète, mais n'ont pas vérifié et en général je ne fais pas confiance si un grand nombre de données de sortie. Discuté icihttps://www.mql5.com/ru/forum/329730, très souvent les "empreintes manquantes" sont discutées )))) - recherche

Igor, la perte d'empreintes est discutée par ceux qui n'ont pas ouvert le fichier journal, une centaine de fois et Rinat Fatkullin lui-même a écrit que rien n'est perdu dans le fichier journal. Mais votre message n'a pas été vain :) J'ai ajouté la sortie dans un fichier séparé, en plus j'ai fait le deuxième fichier, où je sors un peu différemment (en rassemblant tous les événements dans CArrayObj) pour contourner les bugs possibles de ma conception, qui ordonne deux tableaux, c'est-à-dire que je mets tout dans CArrayObj à partir de deux tableaux, puis trier par microsecondes et sortie avec marquage de quel événement Tick ou Book.

Et oui, qu'est-ce que ça a à voir avec les ports, qu'est-ce que ça a à voir ? Je teste juste la file d'attente des événements EA. Si un tick arrive, deux événements doivent être générés - OnTick, et OnBook correspondant, et OnBook est toujours placé dans la file d'attente, et OnTick peut disparaître s'il y a déjà OnTick dans la file d'attente (comme dans le manuel), c'est à dire la situation où un OnTick après l'autre sans OnTick ne peut être que si 1. les OnTicks vont "sans file d'attente" 2. il y a un retard système de OnBook, c'est ce que je veux vérifier, cela peut expliquer le décalage de quelques secondes, précédemment identifié par des collègues. Le nombre total d'OnBooks est 2+ fois plus élevé en une journée, mais pourquoi sont-ils en retard ? Si ce retard est dû à des paquets asynchrones et au parsing, peut-être, mais je ne vérifie jusqu'à présent que le fait de leur arrivée dans l'Expert Advisor. Comment tester en tenant compte du reste des nuances, je n'y ai pas encore pensé.

Voici le nouveau code, à l'ouverture je testerai l'exactitude du travail et je fonctionnerai pour la journée.

s.w. La raison peut aussi être : si Tick est passé aux mêmes prix sans changer la coupe - OnBook n'est pas formé ? Je ne suis pas un spécialiste en bourse, qui peut me le dire. Je pensais que OnTick provoquait toujours 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:
Mais je me demande si le responsable est satisfait des réponses à sa question.

J'ai déjà reçu toutes les réponses et j'ai tiré mes propres conclusions.
J'ai besoin d'analyser la bande des transactions pour une période de temps fixe - prix des transactions, volumes réalisés, etc.
Et j'ai également besoin de simuler le fonctionnement de l'algorithme dans le testeur de stratégie.
L'événement OnTick s'en sort parfaitement, les résultats du trading réel et les résultats de la modélisation dans le testeur concordent avec une petite erreur à ma satisfaction.
Si vous avez besoin d'une analyse plus rapide de la bande, vous pouvez utiliser OnTimer.

Et il n'est pas nécessaire que chaque tick qui arrive au terminal soit placé dans l'OnBook - c'est la spécificité de l'exécution des ordres au marché.

 
Vladimir Mikhailov:


Et chaque tick qui entre dans le terminal ne doit pas nécessairement aller dans l'OnBook - il est spécifique à l'exécution des ordres de marché.

Au contraire, chaque tick(événement) arrivant au handler OnTick doit être synchronisé avec OnBook.
Il y a trois événements dans le gestionnaire OnTick, le changement du prix de la meilleure offre, le changement du prix de la meilleure demande, et la transaction (dernière).
Si le prix d'achat ou de vente change sans qu'il y ait de transaction, il s'agira d'un événement et OnTick recevra ces événements.
Et OnBook doit également attraper ces événements, mais ses propres événements, son gestionnaire, sinon il y aura un décalage des prix d'achat et de vente entre les gestionnaires.

Et si OnTick reçoit un dernier événement, cela signifie qu'une transaction est passée.
La transaction génère l'événement OnTick, car après la transaction, le prix ou le volume des offres et des demandes change sur le marché.
C'est un cercle vicieux.

Dans OnTick comme dans OnBook, il existe un événement Best Bid et Best Ask.
Ces événements doivent toujours être synchrones dans les deux gestionnaires.
Et l'événement dernier par lui-même, il génère un événement dans OnBook après la transaction.
Par conséquent, tout événement qui arrive au gestionnaire OnTick doit être reflété de manière synchrone dans OnBook.