Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 856

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

Hmmm... Probablemente no he mirado la API con mucho cuidado, pero no he visto esa función.... Y probablemente sería útil.

Cualquier otro consejo... quizás la pregunta es demasiado... ridícula... ¿Cómo traduzco un número, por ejemplo, doble, en un array char? Es decir, en algunas API se requiere pasar los números como un puntero. Los punteros se pasan como matrices unidimensionales... Con las cadenas lo entiendo, las funciones StringToShortArray y StringToCharArray están previstas para ellas, pero con los números sigo sin entender cómo convertirlos en matrices de bytes (char).

¿Tal vez algún ejemplo?
 
. ... Rick D. ... .:
¿Tal vez algún ejemplo?

No iremos lo suficientemente lejos. Veamos cómo trabajar con el registro. El registro puede almacenar tanto valores de cadenas como de números (no como una cadena). Pasar un número al registro y obtener de vuelta un puntero al mismo se hace a través de arrays (según tu corrección). ¿Funcionaría este ejemplo?

 
pivomoe:

Estudio la historia de las garrapatas. No siempre funciona lo que ocurría en el mercado en el momento de los ticks.

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. ¿Qué es este misterioso tick con banderas simultáneasTICK_FLAG_BUY y TICK_FLAG_SELL? Incluso pude encontrar tales ticks con un volumen de 1 lote.

2. En la garrapata 988. Ask=133.93 Bid=133.9 ¿De dónde vienen los últimos 133.91 en 989?

¿Qué ha pasado en el mercado?

Es mejor que esas preguntas se publiquen en un hilo separado en la sección "Comercio de acciones" del foro.

En resumen, si ve que un tick tiene una bandera de compra y otra de venta al mismo tiempo, significa que el servidor del broker no está actualizado y emite operaciones de dirección desconocida.

¿En qué servidor se observan las garrapatas?
 
Vladimir Karputov:

Por favor, reescriba su pregunta o ponga signos de puntuación, o mejor aún, añada una imagen de qué, dónde y quién. De lo contrario, veo letras conocidas, pero no puedo entender el significado y su pensamiento.

Aquí hay una foto


 
Seric29:

Aquí hay una foto.


Entonces, ¿por qué poner mi foto (o el caché está loco?)?

 
Seric29:

Aquí hay una foto


Aclaración: ¿quieres mover el ratón directamente en el terminal y copiar el precio de la POSICIÓN a través del clic derecho del ratón?

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

No iremos lo suficientemente lejos. Veamos cómo trabajar con el registro. El registro puede almacenar tanto valores de cadenas como de números (no como una cadena). Pasar un número al registro y obtener de vuelta un puntero al mismo se hace a través de arrays (según tu corrección). ¿Funcionaría un ejemplo como éste?

Ahí lo tienes. Creo que puedes entenderlo.
Archivos adjuntos:
TestReg.mq5  33 kb
 
. ... Rick D. ... .:
Aquí tienes. Creo que te darás cuenta.

¡Eso es original! Ni siquiera había pensado en ello. )))

Siguiendo mi ejemplo anterior, he intentado averiguar qué es lo que provoca el bloqueo de la memoria y del terminal.

En primer lugar, he rechazado los arrays para obtener punteros a una sección de registro abierta. Es decir, simplemente pasé uint& phkResult en la API. Todo ha ido bien y sin errores. La documentación de mql dice que los tipos simples se pueden pasar por referencia, que, cuando se trabaja con la API, es la dirección de la variable, es decir, puntero. Todo fue un éxito en esta parte. También he devuelto los parámetros NULL y los he pasado sin usar arrays.

Además, trabajé en pasar el valor mismo al registro. La descripción de la función ha señalado que debe pasar una cadena con un cero al final. Esto es exactamente el tipo de cadena, por lo que en la primera versión estaba pasando sólo una variable. Esto no se cambió en la versión anterior confiando en la misma. Pero decidí experimentar con arrays e introduje el array ushort y lo llené con el valor necesario. Uno de los parámetros al pasarlo a la función

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

es el tamaño de los datos que se pasan. En tu ejemplo era así:

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

Aquí todo está claro. Tomamos la longitud de la cadena, añadimos un cero "final" y multiplicamos por 2 bytes, por el tamaño del ushort;

Lo intenté de esta manera:

ushort Datos[];

StringToShortArray(valor, Datos);

uint cbData = sizeof(Data);

Imagina mi sorpresa cuando el tamaño de los datos no era igual al del ejemplo anterior.

He comprobado el tamaño del array y era absolutamente igual a StringLen(valor)+1, pero el tamaño de los datos no era el mismo... Todavía no entiendo por qué.

Pero no importa.

El problema original al final era obtener el valor del registro, porque estaba pasando una variable de cadena por referencia como un puntero. Aquí es donde se produjo el choque.

"Si pasamos esta estructura o una referencia a ella a una DLL en lugar de la propia cadena, esperaríamos un resultado erróneo - porque la DLL del sistema seguramente aceptará una cadena honesta con un carácter cero al final y no esta estructura" - esta cita tiene diez años y no ha perdido su relevancia.

Por lo tanto, al pasar cualquier valor constante de cadena, como el nombre de la sección del registro o el valor del parámetro de cadena, todo es correcto. Y cuando se pasa una variable de cadena por referencia, como hice yo, se produce el problema indicado en la cita. )))

Y qué pasa con el tamaño recibido, hay un ejemplo en la documentación de la API, cuando en caso de error "hay más datos" aumentamos el tamaño del buffer de recepción en el bucle y volvemos a obtener datos.

Así que es así.

Gracias de nuevo por la ayuda. )))


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

¡Eso es original! Ni siquiera había pensado en ello. )))

La Unión es cómoda de usar. No tienes que pensar dónde está el byte alto y dónde el byte bajo. La unión se puede utilizar incluso para REG_BINARY. Describe su estructura de datos. Y lo añades en Union junto con un array de bytes por tamaño de estructura. Pero creo que no lo necesita realmente. Cualquier dato puede convertirse en una cadena y almacenarse como tal.

A juzgar por el ejemplo anterior, traté de entender qué es lo que causó exactamente la caída de la memoria y del terminal.

Tal vez porque la pila estaba volando, puede haber especificado long en lugar de int en la descripción de la función.

La documentación de mql dice que los tipos simples se pueden pasar por referencia, que cuando se trabaja con la API es la dirección de una variable, es decir, un puntero.

¿Puede descargar un enlace a esta sección de la documentación?

uint cbData = sizeof(Data);

Necesitas uint cbData = ArraySize(Data) * 2 si pasas un array ushort.

y uint cbData = ArraySize(Data) si se pasa un array uchar.

En el último ejemplo paso un array uchar como parámetro de la función API, para que sea totalmente compatible con el LPBYTE lpData de wind.

Es correcto. Pero añade complicaciones para convertir todos los datos en una matriz de bytes.

Y en cuanto al tamaño recibido, la documentación de la API da un ejemplo, donde en caso de error "hay más datos" aumentamos el tamaño del buffer recibido en el bucle y recibimos los datos de nuevo.

Echa un vistazo al último código. Allí en la implementación primero viene una solicitud para obtener el tamaño de los datos, luego se establece el tamaño del array, luego se toman todos los datos en su totalidad.

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

La Unión es cómoda de usar. No es necesario pensar dónde está el byte alto y dónde el byte bajo. Puedes utilizar Union incluso para REG_BINARY. Describe su estructura de datos. Y lo sumas en Union junto con el array de bytes por tamaño de estructura. Pero creo que no lo necesita realmente. Cualquier dato puede convertirse en una cadena y almacenarse como tal.

Tal vez también porque la pila estaba volando, especificaste long en lugar de int en la descripción de la función.

¿Puede descargar un enlace a esta sección de la documentación?

Necesitas uint cbData = ArraySize(Data) * 2 si pasas un array ushort.

y uint cbData = ArraySize(Data) si se pasa un array uchar.

En el último ejemplo, paso el array uchar como parámetro de la función API, para una total compatibilidad con el LPBYTE lpData de Windows.

Es correcto. Pero añade complicaciones para convertir todos los datos en una matriz de bytes.

Echa un vistazo al último código. Allí en la implementación primero viene una solicitud para obtener el tamaño de los datos, luego se establece el tamaño del array, luego se toman todos los datos en su totalidad.

¡Saludos de nuevo!

Realmente espero que nuestra discusión en este hilo sea útil no sólo para los novatos, sino también para los programadores experimentados.

Y qué hay de largo. Sí, es un error mío, pero fue la int la que se utilizó al principio. Usé Long porque estoy usando una terminal de 64 bits. Pero todo funciona bien con int.

Sobre los punteros. Creo que los siguientes artículos lo describen muy bien:https://www.mql5.com/ru/docs/basis/types/this,https://www.mql5.com/ru/docs/runtime/imports.

Yo también admito mi error con sizeof. Estamos utilizando una matriz dinámica para el intercambio, mientras que para las matrices dinámicas sizeof simplemente devuelve el tamaño de la propia matriz en lugar del tamaño de los datos:https://www.mql5.com/ru/docs/basis/operations/other

En cuanto a la obtención del tamaño completo de los datos. Sí, tienes razón. Efectivamente, en la primera llamada la función devuelve el tamaño de los datos colocados en el parámetro, por lo que se puede prescindir del bucle que escribí. Debo haber entendido mal la descripción de la función aquí, porque dice que la variable devuelve el tamaño de los datos leídos.

Volvamos a la cuerda... En principio, al recibir datos, podríamos pasar la variable por referencia, pero antes podríamos inicializarla con algún valor hasta la longitud máxima. Esto me parece una muletilla, ya que después habría que recortar el propio valor de esta cadena. Obtener los datos del buffer del array es una variante más óptima, es decir, nuestra solución es mejor en mi opinión ))).

Aquí sobre el paso de la cadena como un puntero:https://www.mql5.com/ru/forum/103532/page2#comment_2983919

Y Andriy nos habla muy bien del trabajo con dll:https://www.mql5.com/ru/articles/96


Creo que con tu ayuda hemos cubierto por completo el tema de trabajar no sólo con el registro, sino con los matices de la API de la biblioteca.

La clase de trabajo con el registro es muy útil para el intercambio de datos tanto entre herramientas de un mismo gráfico como entre gráficos y terminales en general.

Una vez en este foro dijeron que usar el registro para estos fines es equivalente a clavar clavos con una bombilla y sugirieron usar archivos virtuales (mapeo). Pero no estoy de acuerdo con esto, porque antes de escribir el registro en el disco es sólo un archivo virtual. Y cuando se utiliza el atributo REG_OPTION_VOLATILE el valor siempre será virtual. Y es muy conveniente almacenar los datos entre sesiones en el registro. EN MI OPINIÓN.

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