Erreurs, bugs, questions - page 2377

 
fxsaber:

Merci. Intéressant, si je ne l'ai pas remarqué, comment serait-il possible de le découvrir...


ZS Je le laisserais aux agents locaux seulement. Dans le Cloud, vous pouvez facilement spammer le journal de cette manière.

Dans Cloud, il n'apparaîtra pas. Parce qu'il n'y a aucune raison de le faire.
 
Slava:

Lorsque vous exécutez la génétique, optimisez-vous en fonction de votre critère personnalisé ?

D'après les journaux présentés, OnTester a retourné 0 dans tous les cas.

J'ai l'habitude d'optimiser en fonction de mon critère, mais ici j'ai également essayé le critère personnalisé. Le résultat est le même.

OnTester renvoie 0, c'est pourquoi il renvoie des zéros dans les résultats - c'est compréhensible. La question est de savoir pourquoi il renvoie "0" lors de l'exécution générale (optimisation) mais que lors d'une exécution unique à partir de "résultats zéro" (avec les mêmes paramètres), il renvoie un résultat normal, un graphique, etc. C'est-à-dire que quelque chose ne fonctionne pas en "Full overshoot" et pourtant la génétique fonctionne bien. D'autres réflexions/idées ?

 
Kuzmich:

D'autres réflexions/idées ?

Tirez toutes les informations de la passe d'optimisation de cette façon

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

MT5. TESTEUR DE STRATÉGIE. Divergence des résultats des tests et de l'optimisation.

fxsaber, 2017.08.22 11:06

Insérez ces lignes dans l'EA

#define  REPORT_TESTER // В тестере будут автоматически записываться отчеты
#include <Report.mqh>

Et cours d'optimisation. Ensuite, exécutez un parcours unique non concordant.

Comparez ensuite les deux rapports enregistrés de la passe correspondante de l'Optimisation et de la passe unique.

Le résultat de la comparaison des deux rapports révélera rapidement les causes.

 
Dans le cadre de la familiarisation avec la fonctionnalité Socket*, un certain nombre de questions sur l'implémentation actuelle ont été soulevées.
Le but étant d'améliorer autant que possible ce qui est fait, je demande aux développeurs de ne pas se sentir offensés par d'éventuelles critiques.



1. Je ne comprends pas les raisons d'une telle différence dans les "interfaces" des fonctions de lecture des sockets
: a) Pour une connexion cryptée, il y a deux fonctions de lecture, et pour une connexion non cryptée, une seule.
b) DansSocketRead, il est nécessaire de spécifier explicitement letimeout_ms, et dansSocketTlsRead etSocketTlsReadAvailable
, il n'y a pas du tout de paramètre de ce type (défini par la fonction séparée SocketTimeouts).
int  SocketTlsRead(int socket, uchar& buffer[], int buffer_maxlen);
int  SocketTlsReadAvailable(int socket, uchar& buffer[], int buffer_maxlen);

int  SocketRead(int socket, uchar& buffer[], int buffer_maxlen, uint timeout_ms);


2. Le nom de la fonction SocketIsReadable n'a rien à voir avec ce qu'elle exécute réellement :

bool  SocketIsWritable(const int  socket); // Return true if writing is possible, otherwise false.
uint  SocketIsReadable(const int  socket); // Number of bytes that can be calculated. In case of an error, 0 is returned.
bool  SocketIsConnected(const int socket); // New function without description. May be, it returns true if connection is not closed.

En fait, SocketIsReadable est analogue à la fonction ioctlsocket() avec le drapeau FIONREAD dans Ws2_32.dll.


3. Comment un utilisateur utilisant la fonctionnalité Socket* sur une connexion non cryptée peut-il obtenir une réponse du serveur avec un délai minimum, si le serveur ne rompt pas la connexion après le transfert de données ?

- La fonction SocketIsReadable sans utilisation explicite d'un délai (par exemple sans Sleep) renvoie 0.
- la fonction SocketRead ne sait pas combien lire, vous spécifiezbuffer_maxlen avec une réserve - vous devrez attendretimeout_ms

Oui, c'est comme ça que ça se passe :

- attendre 1 octet de données dans SocketRead ;
- puis trouver la taille de la réponse entière en utilisant SocketIsReadable ;
- lire la longueur restante dans SocketRead ;
- fusionner les résultats en copiant les tableaux :

#define  PRINT(x) Print(#x, ": ", string(x))
                
void OnStart() {
   string domain = "www.mql5.com";
   int port = 80;
 
   string request = "GET / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n";
   char req[];
   
   int socket = SocketCreate();
   PRINT(SocketConnect(socket, domain, port, 5000));
   int len=StringToCharArray(request,req)-1;
   PRINT(SocketSend(socket,req,len));
   
   
   
   uchar resp[];
   uchar result[];
   
   int resp_result;
   uint resp_len;
   int start_write;
   
   
   resp_len = 1;
   resp_result = SocketRead(socket, resp, resp_len, 5000);
   if (resp_result <= 0){
      PRINT(GetLastError());
      return;
   }
   start_write = ArraySize(result);
   ArrayResize(result, start_write + resp_result);
   ArrayCopy(result, resp, start_write);
   
   
   resp_len = SocketIsReadable(socket);
   resp_result = SocketRead(socket, resp, resp_len, 5000);
   if (resp_result <= 0){
      PRINT(GetLastError());
      return;
   }
   start_write = ArraySize(result);
   ArrayResize(result, start_write + resp_result);
   ArrayCopy(result, resp, start_write);
   
   
   PRINT(CharArrayToString(result));
};

Ce n'est pas trop de code ?


4. SocketIsReadable renvoie une fausse information.
Coupez l'internet et exécutez le code ci-dessus.
Par conséquent, SocketIsReadable renvoie une valeur saine de 1. Merveilles.


J'ai réussi à décrire environ un tiers de toutes les questions et problèmes liés à Socket*.
Malheureusement, j'ai eu besoin de beaucoup de temps pour tout vérifier, décrire et revérifier... (pour que ce ne soit pas un fait qu'il y aura une suite)

L'impression générale est que soit tout a été fait dans la précipitation, soit la fonctionnalité Socket* est parvenue au développeur junior.
Quoi qu'il en soit, la solution actuelle est très rudimentaire et couvre une approche plutôt étroite de l'utilisation des sockets.

 
MQL5\Include\Math\AlgLib\dataanalysis.mqh - CLinReg::LRLine ne fonctionne pas pour 1M ou plus de valeurs ?
 
Kuzmich:

J'ai l'habitude d'optimiser selon mes propres critères, mais ici j'ai également essayé les critères standards. Le résultat est similaire.

OnTester renvoie 0, c'est pourquoi il y a des zéros dans les résultats - c'est compréhensible. La question est de savoir pourquoi il renvoie "0" lors de l'exécution générale (optimisation) mais que lors d'une exécution unique à partir de "résultats zéro" (avec les mêmes paramètres), il renvoie un résultat normal, un graphique, etc. C'est-à-dire que quelque chose ne fonctionne pas en "Full overshoot" et pourtant la génétique fonctionne bien. D'autres réflexions/idées ?

Pouvez-vous partager un EA (ex5 en privé) et les conditions d'optimisation ?

Nous voulons reproduire le problème que vous avez mentionné.

Après la recherche, l'EA sera irrévocablement effacée.

 
Slava:

Pouvez-vous partager l'EA (ex5 dans un message privé) et les conditions d'optimisation ?

Nous voulons reproduire le problème que vous avez mentionné.

Après la recherche, l'EA sera irrévocablement effacée.

Voulez-vous regarder mon EA ? J'ai un problème similaire - le bénéfice n'est pas compté, par conséquent l'optimisation ne fonctionne pas.
 
Slava:

Pouvez-vous partager l'EA (ex5 dans un message privé) et les conditions d'optimisation ?

Nous voulons reproduire le problème que vous avez mentionné.

L'EA sera effacée de manière irrémédiable après la recherche.

Réponse dans un message privé.

 
Sergey Dzyublik:
Dans le cadre de la familiarisation avec la fonctionnalité Socket*, un certain nombre de questions sur l'implémentation actuelle ont été soulevées.
Le but étant d'améliorer autant que possible ce qui est fait, je demande aux développeurs de ne pas se sentir offensés par d'éventuelles critiques.



1. Je ne comprends pas les raisons d'une telle différence dans les "interfaces" des fonctions de lecture des sockets
: a) Pour une connexion cryptée, il y a deux fonctions de lecture, et pour une connexion non cryptée, une seule.
b) DansSocketRead, il est nécessaire de spécifier explicitement letimeout_ms, et dansSocketTlsRead etSocketTlsReadAvailable
, il n'y a pas du tout de paramètre de ce type (défini par la fonction séparée SocketTimeouts).


2. Le nom de la fonction SocketIsReadable n'a rien à voir avec ce qu'elle exécute réellement :

En fait, SocketIsReadable est analogue à la fonction ioctlsocket() avec le drapeau FIONREAD dans Ws2_32.dll.


3. Comment un utilisateur utilisant la fonctionnalité Socket* sur une connexion non cryptée peut-il obtenir une réponse d'un serveur avec un délai minimum, si le serveur ne rompt pas la connexion après le transfert de données ?

- La fonction SocketIsReadable sans utilisation explicite de la temporisation (par exemple sans Sleep) renvoie 0.
- La fonction SocketRead ne sait pas combien lire, si vous spécifiezbuffer_maxlen avec réserve - vous devrez attendre pourtimeout_ms

Oui, c'est comme ça que ça se passe :

- attendre 1 octet de données dans SocketRead ;
- puis trouver la taille de la réponse entière en utilisant SocketIsReadable ;
- lire la longueur restante dans SocketRead ;
- fusionner les résultats en copiant les tableaux :

Ce n'est pas trop de code ?


4. SocketIsReadable renvoie une fausse information.
Coupez l'internet et exécutez le code ci-dessus.
Par conséquent, SocketIsReadable renvoie une valeur saine de 1. Merveilles.


J'ai réussi à décrire environ un tiers de toutes les questions et problèmes liés à Socket*.
Malheureusement, j'ai eu besoin de beaucoup de temps pour tout vérifier, décrire et revérifier... (pour que ce ne soit pas un fait qu'il y aura une suite)

L'impression générale est que soit tout a été fait dans la précipitation, soit la fonctionnalité Socket* est parvenue au développeur junior.
Quoi qu'il en soit, la solution actuelle est très rudimentaire et couvre une approche plutôt étroite de l'utilisation des sockets.

1. c'est l'interface.

Les fonctions TLS sont auxiliaires pour prendre en charge les cas complexes. Aucun problème pour définir les SocketTimeouts - ce sont les meilleurs à utiliser.


2. il remplit correctement sa fonction.

Vous ne devez pas être au courant des problèmes de détection de rupture de connexion TCP. Il est assez difficile (gourmand en ressources au prix d'appels supplémentaires) de détecter qu'une connexion est garantie correctement. Toutes les mises en œuvre de réseaux souffrent de ce problème.

Notre implémentation de SocketIsReadible est suffisamment intelligente et possède un détecteur de rupture. Lorsqu'il détecte un 0 octet propre, il fait le travail supplémentaire de vérifier que la socket est complète :

   //+------------------------------------------------------------------+
   //| Доступно для чтения?                                             |
   //+------------------------------------------------------------------+
   UINT32 IsReadible(void)
     {
      unsigned long size=1;    // специально, чтобы убиться при попытке чтения, если сокет мертв
      //--- проверка
      if(m_socket!=INVALID_SOCKET)
        {
         //--- считаем количество доступных для чтения байт
         if(ioctlsocket(m_socket,FIONREAD,&size)!=0)
           {
            Close();
            return(1);        // вернем 1, чтобы убиться при попытке чтения
           }
         //--- если нет данных, проверим сокет на завершенность
         if(size==0)
           {
            timeval wait_time;
            fd_set  fd;
            //--- ждём
            FD_ZERO(&fd);
            FD_SET(m_socket,&fd);

            wait_time.tv_sec =0;          // секунды
            wait_time.tv_usec=1000;       // микросекунды
            //--- ждём
            if(select(0,&fd,NULL,NULL,&wait_time)>0)
               return(1);                 // вернем 1, чтобы убиться при попытке чтения
           }
        }
      //--- размер
      return(size);
     }

Puisqu'il renvoie le nombre d'octets sans indicateur de fin, il produit 1 octet de sorte qu'une tentative de lecture SocketRead ultérieure/imminente renverra normalement une erreur.

Pourquoi est-ce correct ? Parce que la plupart du code est écrit par les programmeurs de cette façon :

if(SocketIsReadible(...)>0)
  {
   if(SocketRead( )<1)
     return(false);
   ...
  }
... уходим на следующий круг ожидания

le résultat réel de l'opération est vérifié lors d'une tentative de lecture directe.


3. il faut faire SocketIsReadible() avant la lecture proprement dite, si vous ne connaissez pas la taille exacte des données à lire.

La liaison SocketisReadible/SocketRead vous donne la possibilité de ne pas perdre le contrôle (minimiser à une perte de contrôle presque nulle) sur le flux d'exécution de votre programme. Cela permet d'éviter de se heurter aux délais d'attente du réseau.

Oui, quelques lignes de code en plus, mais vous ne perdrez pas le contrôle pendant une milliseconde (à peu près). C'est à vous de décider ce qu'il faut faire dans les intervalles sans données réseau.


4. expliqué dans le deuxième paragraphe.

Délivrer 1 pour le bien de la stimulation de lecture et de sortie comme une erreur de lecture.



Vos conclusions sont fausses.

C'est la nature du transport TCP/IP, où il n'y a aucune garantie. Là aussi, vous pouvez vous retrouver dans des trous noirs de réseau sur les filtres/pare-feu lorsqu'il n'y a pas de signalisation TCP. Le contrôle brut des délais et du flux de données vous permet de les détecter et de mettre fin aux connexions vous-même.

Nous avons donné une interface d'accès brut/direct aux fonctions du réseau, y compris les implémentations TLS. Si vous les utilisez, c'est vous qui devez envelopper correctement les fonctions brutes dans un gestionnaire SocketIsReadible/SocketRead sécurisé/contrôlé.

Si vous souhaitez effectuer des requêtes de haut niveau sans avoir à réfléchir aux détails, il existe des fonctions WebRequest. Toutes les protections y sont intégrées.

 
Renat Fatkhullin:

1. C'est l'interface.

Les fonctions TLS sont auxiliaires pour prendre en charge les cas complexes. Aucun problème pour définir les SocketTimeouts - ce sont les meilleurs à utiliser.


2. il remplit correctement sa fonction.

Apparemment, vous n'êtes pas au courant des problèmes de détection des connexions TCP interrompues. Il est assez difficile (gourmand en ressources au prix d'appels supplémentaires) de détecter qu'une connexion est garantie correctement. Toutes les mises en œuvre de réseaux souffrent de ce problème.

Notre implémentation de SocketIsReadible est suffisamment intelligente pour avoir un détecteur de rupture. Lorsqu'il détecte un 0 octet propre, il fait le travail supplémentaire de vérifier que la socket est complète :

Puisqu'il renvoie le nombre d'octets sans indicateur de fin, il produit 1 octet de sorte qu'une tentative de lecture SocketRead ultérieure/imminente renverra normalement une erreur.

Pourquoi est-ce correct ? Parce que la plupart du code est écrit par les programmeurs de cette façon :

le résultat réel de l'opération est vérifié lors d'une tentative de lecture directe.


3. il faut faire SocketIsReadible() avant la lecture proprement dite, si vous ne connaissez pas la taille exacte des données à lire.

La liaison SocketisReadible/SocketRead vous donne la possibilité de ne pas perdre le contrôle (minimiser à une perte de contrôle presque nulle) sur le flux d'exécution de votre programme. Cela permet d'éviter de se heurter aux délais d'attente du réseau.

Oui, quelques lignes de code en plus, mais vous ne perdrez pas le contrôle pendant une milliseconde (à peu près). C'est à vous de décider ce qu'il faut faire dans les intervalles sans données réseau.


4. expliqué dans le deuxième paragraphe.

Émettre 1 dans le but de stimuler la lecture et sortir comme une erreur de lecture.



Vos conclusions sont fausses.

C'est la nature du transport TCP/IP, où il n'y a aucune garantie. Là aussi, vous pouvez vous retrouver dans des trous noirs de réseau sur les filtres/pare-feu lorsqu'il n'y a pas de signalisation TCP. Le délai d'attente brut et le contrôle du flux de données vous permettent de les détecter et de mettre fin aux connexions vous-même.

Nous avons donné une interface d'accès brut/direct aux fonctions du réseau, y compris les implémentations TLS. Si vous les utilisez, c'est vous qui devez envelopper correctement les fonctions brutes dans un gestionnaire SocketIsReadible/SocketRead sécurisé/contrôlé.

Si vous souhaitez effectuer des requêtes de haut niveau sans avoir à réfléchir aux détails, il existe des fonctionsWebRequest. Toutes les protections y sont intégrées.

Merci beaucoup pour la réponse fournie.

A mon humble avis :
1) Si les fonctions SocketRead et SocketTlsRead effectuent la même action, elles devraient avoir les mêmes interfaces adaptées, par tous les moyens.

2. a. Oui, je ne suis pas au courant des problèmes de détection de rupture de connexion TCP ;
b) la fonction SocketIs*, selon les recommandations de nommage des fonctions, est censée produire un résultat True/False, mais pas uint ; (Où avez-vous lu cela ? Si je ne me trompe pas, dans les travaux de Scott Meyers en 2014).
c) Merci d'expliquer pourquoi SocketIsReadible peut retourner 1 si aucune connexion TCP n'a été établie du tout (pas d'internet en avance ou domaine non ajouté à la liste autorisée).
Veuillez également ajouter une description appropriée à la documentation.

3,4) Je l'ai, merci.