Questions des débutants MQL5 MT5 MetaTrader 5 - page 856

 
Алексей Барбашин:

Hmmm... Je n'ai probablement pas regardé l'API très attentivement, mais je n'ai pas vu une telle fonction..... Et ce serait probablement pratique.

D'autres conseils... peut-être que la question est trop... ridicule... Comment traduire un nombre, par exemple un double, en un tableau de caractères ? En effet, dans certaines API, il est nécessaire de transmettre les nombres sous forme de pointeur. Les pointeurs sont passés comme des tableaux unidimensionnels... Avec les chaînes de caractères, je comprends, les fonctions StringToShortArray et StringToCharArray sont prévues pour elles, mais avec les nombres, je ne comprends toujours pas comment les convertir en tableaux d'octets (char).

Peut-être un exemple ?
 
. ... Rick D. ... .:
Peut-être un exemple ?

Nous n'irons pas assez loin. Voyons comment travailler avec le registre. Le registre peut stocker à la fois des valeurs de type chaîne et des valeurs numériques (pas sous forme de chaîne). Passer un nombre au registre et récupérer un pointeur sur celui-ci se fait par le biais de tableaux (selon votre correction). Un tel exemple fonctionnerait-il ?

 
pivomoe:

J'étudie l'histoire des tiques. Il n'est pas toujours possible de savoir ce qui se passait sur le marché au moment des tics.

SBER

i=987 2016.06.27 10:00:30.274 Ask=133.91 Bid=133.9 Last=133.9 Vol=50 TICK_FLAG_ASK

i=988 2016.06.27 10:00:30.280 Ask=133.93 Bid=133.9 Last=133.9 Vol=50 TICK_FLAG_ASK

i=989 2016.06.27 10:00:30.280 Ask=133.93 Bid=133.9 Last=133.91 Vol=100 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY TICK_FLAG_SELL

i=990 2016.06.27 10:00:30.280 Ask=133.93 Bid=133.9 Last=133.92 Vol=300 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY TICK_FLAG_SELL

i=991 2016.06.27 10:00:30.280 Ask=133.93 Bid=133.9 Last=133.92 Vol=100 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY TICK_FLAG_SELL

i=992 2016.06.27 10:00:30.281 Ask=133.94 Bid=133.9 Last=133.92 Vol=100 TICK_FLAG_ASK

1. Quel est ce mystérieux tick avec des drapeaux simultanésTICK_FLAG_BUY et TICK_FLAG_SELL ? J'ai même pu trouver de tels ticks avec un volume de 1 lot.

2. Sur le tic-tac 988. Ask=133.93 Bid=133.9 D'où viennent les 133.91 derniers sur 989 ?

Que s'est-il passé sur le marché ?

Il est préférable de poser ces questions dans un fil de discussion distinct dans la section "Stock Trading" du forum.

En bref, si vous voyez qu'un tick a un drapeau d'achat et un drapeau de vente en même temps, cela signifie que le serveur du courtier n'est pas mis à jour et qu'il diffuse des transactions de direction inconnue.

Sur quel serveur observez-vous les tics ?
 
Vladimir Karputov:

Veuillez soit réécrire votre question, soit mettre des signes de ponctuation, ou mieux encore, ajouter une photo de quoi, où et qui. Sinon, je vois des lettres familières, mais je ne peux pas comprendre le sens ou votre pensée.

Voici une photo


 
Seric29:

Voici une photo.


Alors, pourquoi mettre ma photo (ou le cache est-il fou ?) ?

 
Seric29:

Voici une photo


Clarifiez : voulez-vous déplacer la souris directement dans le terminal et copier le prix de la POSITION via le clic droit de la souris ?

 
Алексей Барбашин:

Nous n'irons pas assez loin. Voyons comment travailler avec le registre. Le registre peut stocker à la fois des valeurs en minuscules et des valeurs numériques (pas sous forme de chaîne). Passer un nombre au registre et récupérer un pointeur sur celui-ci se fait par le biais de tableaux (selon votre correction). Un exemple comme celui-ci fonctionnerait-il ?

Et voilà. Je pense que tu peux le découvrir.
Dossiers :
TestReg.mq5  33 kb
 
. ... Rick D. ... .:
Voilà. Je pense que vous trouverez la solution.

C'est original ! Je n'y avais même pas pensé. )))

En suivant mon exemple précédent, j'ai essayé de comprendre ce qui cause le crash de la mémoire et du terminal.

Tout d'abord, j'ai refusé les tableaux pour obtenir des pointeurs vers une section ouverte du registre. C'est-à-dire que j'ai simplement passé uint& phkResult dans l'API. Tout s'est bien passé et aucune erreur. La documentation de mql indique que les types simples peuvent être passés par référence, ce qui, lorsqu'on travaille avec l'API, est l'adresse de la variable, c'est-à-dire un pointeur. Tout a été réussi dans cette partie. J'ai également renvoyé les paramètres NULL et les ai transmis sans utiliser de tableaux.

De plus, j'ai travaillé sur le passage de la valeur elle-même au registre. La description de la fonction indique qu'elle doit transmettre une chaîne de caractères avec un zéro à la fin. C'est exactement le type de chaîne, donc dans la première version je passais juste une variable. Vous n'avez pas changé cela dans la version précédente en vous appuyant sur la même. Mais j'ai décidé d'expérimenter avec les tableaux et j'ai introduit un tableau court et je l'ai rempli avec la valeur nécessaire. Un des paramètres lors de son passage à la fonction

uint RegSetValueExW(uint hKey, string lpValueName, uint Reserved, uint dwType, ushort &lpData[], uint cbData)

est la taille des données transmises. Dans votre exemple, c'était comme ça :

uint cbData = (StringLen(value)+1)*2 ;

Tout est clair ici. Nous prenons la longueur de la chaîne, ajoutons un zéro "final" et multiplions par 2 octets, par la taille ushort ;

J'ai essayé de cette façon :

ushort Data[] ;

StringToShortArray(valeur, Data) ;

uint cbData = sizeof(Data) ;

Imaginez ma surprise lorsque la taille des données n'était pas égale à celle de l'exemple précédent !

J'ai vérifié la taille du tableau et elle était absolument égale à StringLen(value)+1, mais la taille des données n'était pas la même... Je ne comprends toujours pas pourquoi.

Mais peu importe.

En fin de compte, le problème initial consistait à obtenir la valeur du registre, car je transmettais une variable de type chaîne par référence comme un pointeur. C'est là que l'accident s'est produit.

"Si vous passez cette structure ou une référence à celle-ci dans une DLL au lieu de la chaîne de caractères elle-même, vous ne pouvez pas vous attendre à un résultat correct - car la DLL du système acceptera certainement une chaîne de caractères honnête avec un caractère zéro à la fin et non cette structure" - cette citation a dix ans, elle n'a pas perdu sa pertinence.

Par conséquent, lors du passage de toute valeur constante de type chaîne, telle que le nom de la section du registre ou la valeur du paramètre de type chaîne, tout est correct. Et lorsque l'on passe une variable de type chaîne par référence, comme je l'ai fait, cela conduit au problème indiqué dans la citation. )))

Et qu'en est-il de la taille de réception, il y a un exemple dans la documentation de l'API, lorsqu'en cas d'erreur "il y a plus de données" nous augmentons la taille du tampon de réception dans la boucle et récupérons à nouveau les données.

Donc ça se passe comme ça.

Merci encore pour votre aide ! )))


 
Алексей Барбашин:

C'est original ! Je n'y avais même pas pensé. )))

L'Union est pratique à utiliser. Vous n'avez pas à vous demander où se trouve l'octet de poids fort et l'octet de poids faible. L'union peut même être utilisée pour REG_BINARY. Vous décrivez votre structure de données. Et vous l'ajoutez dans Union avec un tableau d'octets par taille de structure. Mais je pense que vous n'en avez pas vraiment besoin. Toute donnée peut être convertie en chaîne de caractères et stockée sous forme de chaîne.

En me basant sur l'exemple précédent, j'ai essayé de comprendre ce qui a causé exactement le crash de la mémoire et du terminal.

Peut-être parce que la pile était volante, vous avez peut-être spécifié long au lieu de int dans la description de la fonction.

La documentation de mql indique que les types simples peuvent être transmis par référence, ce qui, lorsqu'on travaille avec l'API, est l'adresse d'une variable, c'est-à-dire un pointeur.

Pouvez-vous télécharger un lien vers cette section de la documentation ?

uint cbData = sizeof(Data) ;

Vous avez besoin de uint cbData = ArraySize(Data) * 2 si vous passez un tableau ushort.

et uint cbData = ArraySize(Data) si vous passez un tableau uchar.

Dans le dernier exemple, je passe un tableau uchar comme paramètre de la fonction API, pour une compatibilité totale avec le LPBYTE lpData de Wind.

C'est correct. Mais la conversion de toutes les données en un tableau d'octets est plus compliquée.

Quant à la taille de réception, la documentation API donne un exemple où, en cas d'erreur "il y a plus de données", nous augmentons la taille du tampon de réception dans la boucle et recevons à nouveau des données.

Regardez le dernier code. Dans l'implémentation, il y a d'abord une demande pour obtenir la taille des données, puis la taille du tableau est définie, et enfin toutes les données sont prises dans leur intégralité.

 
. ... Rick D. ... .:

L'Union est pratique à utiliser. Il n'est pas nécessaire de se demander où est l'octet de poids fort et où est l'octet de poids faible. Vous pouvez utiliser l'Union même pour REG_BINARY. Vous décrivez votre structure de données. Et vous l'ajoutez dans Union avec le tableau d'octets par taille de structure. Mais je pense que vous n'en avez pas vraiment besoin. Toute donnée peut être convertie en chaîne de caractères et stockée sous forme de chaîne.

Peut-être aussi parce que la pile volait, vous avez spécifié long au lieu de int dans la description de la fonction.

Pouvez-vous télécharger un lien vers cette section de la documentation ?

Vous avez besoin de uint cbData = ArraySize(Data) * 2 si vous passez un tableau ushort.

et uint cbData = ArraySize(Data) si vous passez un tableau uchar.

Dans le dernier exemple, je passe le tableau uchar comme paramètre de fonction API, pour une compatibilité totale avec le LPBYTE lpData de Windows.

C'est correct. Mais la conversion de toutes les données en un tableau d'octets est plus compliquée.

Regardez le dernier code. Dans l'implémentation, il y a d'abord une demande pour obtenir la taille des données, puis la taille du tableau est définie, et enfin toutes les données sont prises dans leur intégralité.

Je vous salue à nouveau !

J'espère vraiment que notre discussion dans ce fil sera utile non seulement aux débutants, mais aussi aux programmeurs expérimentés.

Et si c'était long ? Oui, c'est mon erreur mais c'est int qui a été utilisé au début. J'ai utilisé Long parce que j'utilise un terminal 64 bits. Mais tout fonctionne bien avec int.

À propos des pointeurs. Je pense que les articles suivants décrivent très bien tout cela: https://www.mql5.com/ru/docs/basis/types/this,https://www.mql5.com/ru/docs/runtime/imports.

Je reconnais aussi mon erreur avec sizeof. Nous utilisons un tableau dynamique pour l'échange, alors que pour les tableaux dynamiques, sizeof renvoie simplement la taille du tableau lui-même au lieu de la taille des données: https://www.mql5.com/ru/docs/basis/operations/other.

Concernant l'obtention de la taille complète des données. Oui, vous avez raison. En effet, au premier appel, la fonction renvoie la taille des données placées dans le paramètre, ce qui permet de se passer de la boucle dont j'ai parlé. Je dois avoir mal compris la description de la fonction ici, car il est dit que la variable renvoie la taille des données lues.

Revenons à la ficelle... En principe, il s'est avéré que, lors de la réception de données, nous pouvions transmettre la variable par référence, mais nous pouvions d'abord l'initialiser avec une certaine valeur jusqu'à la longueur maximale. Cela me semble être une béquille, car après coup, la valeur elle-même devrait être coupée de cette chaîne. Obtenir des données à partir d'un tableau tampon est une variante plus optimale, c'est-à-dire que notre solution est meilleure à mon avis ;))).

A propos du passage d'une chaîne de caractères en tant que pointeur: https://www.mql5.com/ru/forum/103532/page2#comment_2983919

Et Andriy nous parle très bien du travail avec dll: https://www.mql5.com/ru/articles/96.


Je pense qu'avec votre aide, nous avons entièrement couvert le sujet du travail non seulement avec le registre, mais aussi avec les nuances de l'API de la bibliothèque.

La classe de travail avec le registre est très utile pour échanger des données à la fois entre les outils d'un même graphique et entre les graphiques et les terminaux en général.

Une fois sur ce forum, on a dit qu'utiliser le registre à ces fins revenait à planter des clous avec une ampoule et on a suggéré d'utiliser des fichiers virtuels (mapping). Mais je ne suis pas d'accord avec cela, car avant d'écrire le registre sur le disque, ce n'est qu'un fichier virtuel. Et lorsque vous utilisez l'attribut REG_OPTION_VOLATILE, la valeur sera toujours virtuelle. Et il est très pratique de stocker les données inter-session dans le registre. IMHO.

Документация по MQL5: Основы языка / Типы данных / Ссылки. Модификатор & и ключевое слово this
Документация по MQL5: Основы языка / Типы данных / Ссылки. Модификатор & и ключевое слово this
  • www.mql5.com
В MQL5 параметры простых типов можно передавать как по значению, так и по ссылке, в то время как параметры сложных типов всегда передаются по ссылке. Для указания компилятору на необходимость передачи параметра по ссылке, перед именем параметра ставится знак амперсанда Передача параметра по ссылке означает передачу адреса переменной, поэтому...