MT5 y la velocidad en acción - página 23

 
Renat Fatkhullin:

Por si alguien no lo pilla, es la librería fxsaber que aplicada en código ajeno da frenos.

En lugar de señalarlo explícitamente, se puso a jugar a frenar la plataforma y a deslizar ejemplos suicidas. Y cuando hubo una oportunidad de llegar a la verdadera causa y limar asperezas, no la aprovechó.

En aras de la optimización local, estaba envenenando la caché del historial de la aplicación principal.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

MT5 y la velocidad en acción

fxsaber, 2020.09.02 00:02

Había un código MQL5 limpio y reproducible por muchos. La cronología del hilo primero estudia, en lugar de jugar a la teoría de la conspiración, que alguien te necesita tanto que está dispuesto a gastar su tiempo en ti para enlodar.

Estás haciendo un gran trabajo como pavo. Aquí no se ha hablado de ninguna biblioteca en concreto en el hilo porque no es constructivo.

La cuestión es que si alguien se aventura a utilizar librerías compartidas en las que el parámetro from-input no coincide, se va a llevar un frenazo. No se menciona esto en ninguna parte de la Documentación. Al menos algo de este tema te sacaron con pinzas. Y cuando se hizo, empezaron a acusarte de hacer trampa.


Esta característica de MQL debería estar escrita en la rama de Documentación y en la de Características. Ejecute los scripts MQL5 limpios de esta rama en las construcciones correspondientes a las fechas de su creación. Al parecer, se hicieron muchos arreglos a ciegas por si acaso.

 
fxsaber:

Estás haciendo un gran trabajo como indie. Aquí no se mencionaron específicamente las bibliotecas en el hilo, porque no es constructivo.

Porque has hecho todo lo posible por no hablar de tus bibliotecas. En presencia de estas bibliotecas. Con la constante oposición de "el mío es más rápido". Así que has enmascarado hábilmente el autodisparo sacando a relucir el "mira qué lento es".


La cuestión es que si uno se atreve a utilizar conjuntamente bibliotecas en las que el parámetro from-input no es el mismo, obtendrá retrasos. No se menciona esto en ninguna parte de la Documentación. Al menos algo de eso te sacaron con pinzas. Y cuando se hizo, empezaron a acusarte de hacer trampa.


Esta característica de MQL debería estar escrita en la rama de Documentación y en la de Características. Ejecuta los scripts MQL5 limpios de esta rama en las construcciones correspondientes a las fechas de su creación. Al parecer, se hicieron muchos arreglos a ciegas por si acaso.

La documentación de HistorySelect dice claramente:

La función HistorySelect() crea una lista de órdenes y una lista de tratos en el programa mql5 para la posterior referencia a los elementos de la lista mediante las funciones correspondientes. El tamaño de la lista de ofertas puede obtenerse mediante la función HistoryDealsTotal (), y el tamaño de la lista de pedidos en el historial puede obtenerse mediante la función HistoryOrdersTotal(). La enumeración de los elementos de la lista de pedidos se realiza mejor utilizando la función HistoryOrderGetTicket (), para los elementos de la lista de tratos, es apropiada la función HistoryDealGetTicket().

Tras el uso de la función HistoryOrderSelect(), la lista de pedidos en el historial, disponible para el programa mql5, se restablece y se vuelve a rellenar con el pedido, si la búsqueda de pedidos por ticket se ha completado con éxito. Lo mismo se aplica a la lista de ofertas, que están disponibles para el programa mql5 - se restablece mediante la función HistoryDealSelect() y se vuelve a rellenar si se obtiene con éxito una oferta por el número de ticket.


Cuando se trabaja con grandes volúmenes (y por algo se mostraron miles y decenas de miles de operaciones en el historial), que requieren un acceso atómico/de instantáneas, es necesario comprender su coste.

Sobre todo porque he explicado los detalles técnicos de estos cachés con mucho detalle en este hilo.


¿Has intentado por nada del mundo aleatorizar cada muestra y envenenar el caché lo máximo posible? Por el bien de su posición, ¿hay que disparar por sí mismo?

 
Renat Fatkhullin:

Porque hiciste todo lo posible para mantener tus bibliotecas en silencio. Por eso has enmascarado hábilmente los fallos autoinfligidos alardeando de "mira qué lento es".

El 99% de los errores se encuentran de esta manera. En primer lugar, el comportamiento extraño se encuentra en el código grande. Entonces la localización encuentra la causa. Estaba más preocupado por los frenos.

función comercial. Los problemas están en casi todas partes.

KD      0       16:00:33.382    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 34: HistoryOrderSelect(0)] = 25 ms.
PE      0       16:00:44.913    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 17: CopyTicks(Symb,Ticks,COPY_TICKS_ALL,0,1)] = 24 ms.
DP      0       16:00:44.888    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 46 ms.
FI      0       16:00:49.579    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 28: HistoryDealSelect(0)] = 22 ms.
EE      0       16:01:03.287    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 33: HistoryOrderGetDouble(0,ORDER_PRICE_CURRENT)] = 1 ms.
KE      0       16:01:07.013    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 50: OrderGetDouble(ORDER_PRICE_CURRENT)] = 1 ms.
JM      0       16:01:12.189    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 44: TimeCurrent()] = 39 ms.
MD      0       16:01:13.067    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 81: ResourceFree(NULL)] = 1 ms.
RS      0       16:01:13.572    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 41: SymbolInfoDouble(Symb,SYMBOL_POINT)] = 7 ms.
GL      0       16:01:27.816    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 79: GlobalVariableGet(NULL)] = 22 ms.
PD      0       16:01:33.892    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 58: PositionGetInteger(POSITION_MAGIC)] = 1 ms.
KP      0       16:01:39.864    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 67: OrderCheck(Request,CheckResult)] = 3 ms.
ML      0       16:01:39.970    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 62: AccountInfoInteger(ACCOUNT_MARGIN_MODE)] = 1 ms.
KM      0       16:01:41.045    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 55: PositionSelect(Symb)] = 2 ms.
NS      0       16:01:46.832    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 78: GlobalVariableCheck(NULL)] = 1 ms.
JP      0       16:01:49.211    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 75: SymbolName(0,true)] = 1 ms.
EL      0       16:01:59.101    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 19: CopyTicksRange(Symb,Ticks,COPY_TICKS_ALL,Tick.time_msc)] = 32 ms.
IM      0       16:02:07.462    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 70: AccountInfoInteger(ACCOUNT_TRADE_EXPERT)] = 7 ms.
PJ      0       16:02:11.735    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 37: IsStopped()] = 4 ms.
OG      0       16:03:08.178    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 32: HistoryOrderGetInteger(0,ORDER_MAGIC)] = 14 ms.
JH      0       16:03:16.385    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 40: SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE)] = 5 ms.
FM      0       16:03:16.601    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 59: PositionGetString(POSITION_SYMBOL)] = 1 ms.
GH      0       16:03:21.841    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 72: TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)] = 1 ms.
FJ      0       16:03:25.782    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 46: TimeTradeServer()] = 1 ms.
EO      0       16:03:26.772    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 45: TimeLocal()] = 10 ms.
HD      0       16:03:36.595    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 13: SymbolInfoTick(Symb,Tick)] = 13 ms.
...
El hombre decidió ayudar y ejecutó un código MQL5 limpio en su máquina. Una pequeña muestra arriba. Lee los nombres de las funciones anteriores.


La documentación de HistorySelect dice explícitamente:

La función HistorySelect() crea una lista de órdenes y una lista de operaciones en el programa mql5 para poder hacer referencia a los elementos de la lista mediante las funciones correspondientes. El tamaño de la lista de ofertas puede obtenerse mediante la función HistoryDealsTotal (), y el tamaño de la lista de pedidos en el historial puede obtenerse mediante la función HistoryOrdersTotal(). La enumeración de los elementos de la lista de pedidos se realiza mejor utilizando la función HistoryOrderGetTicket (), para los elementos de la lista de tratos, es apropiada la función HistoryDealGetTicket().

Tras el uso de la función HistoryOrderSelect(), la lista de pedidos en el historial, disponible para el programa mql5, se restablece y se vuelve a rellenar con el pedido, si la búsqueda de pedidos por ticket se ha completado con éxito. Lo mismo se aplica a la lista de ofertas, que están disponibles para el programa mql5 - se restablece mediante la función HistoryDealSelect() y se vuelve a rellenar si se obtiene con éxito una oferta por el número de ticket.

Me pregunto quién habrá visto algo entre líneas en este texto. Personalmente, he entendido (antes de esta rama), que HistoryDealSelect y HistoryOrderSelect deben ser escritos así.

  static bool HistorySelectOrder( const ulong Ticket )
  {
    return((::HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) || ::HistoryOrderSelect(Ticket));
  }

  static bool HistorySelectDeal( const ulong &Ticket )
  {
    return((::HistoryDealGetInteger(Ticket, DEAL_TICKET) == Ticket) || ::HistoryDealSelect(Ticket));
  }

De lo contrario, está garantizado que se produzcan retrasos.

Cuando se trabaja con volúmenes enormes, que requieren acceso atómico/snapshot, hay que entender su coste.

Sobre todo porque en este hilo he explicado los detalles técnicos de estos cachés con mucho detalle.

He ido recogiendo la información necesaria en este hilo.

 
Renat Fatkhullin:

¿No has intentado por nada del mundo aleatorizar cada muestra y envenenar el caché lo más posible? Por el bien de su posición, ¿hay que disparar por sí mismo?

Puedes ver todo cronológicamente en este hilo. El problema se mostraba originalmente sin ningún tipo de aleatoriedad.

Este hilo es un gran testimonio de cómo se pueden tergiversar las palabras del adversario. Aquí se guardan todas las fuentes y sus resultados.

 

¿Por qué el terminal no puede simplemente aumentar el caché cuando se solicita de nuevo el historial completo, recuperar y almacenar en caché el rango que falta? Eso parece resolver el problema. Al fin y al cabo, cuando se solicitan bares/boletos, se devuelven paquetes de datos que faltan, por lo que existe un mecanismo para ello.

 
Aleksey Vyazmikin:

¿Por qué el terminal no puede simplemente aumentar el caché cuando se solicita de nuevo el historial completo, recuperar y almacenar en caché el rango que falta?

Esto ya se ha hecho.

Pero si entre HistorySelect( 0, INT_MAX ) llama aHistorySelect( other_time, ... ), la caché se reconstruirá a partir de other_time y la siguiente petición deHistorySelect( 0,... ) llevará a una nueva construcción de la caché (será más lenta).

 
Andrey Khatimlianskii:

Esto ya se ha hecho.

Pero si entre las llamadas deHistorySelect( 0, INT_MAX ) llamamos aHistorySelect( otro_tiempo, ... ), la caché se reconstruirá a partir de otro_tiempo y la siguiente petición deHistorySelect( 0,... ) llevará a una nueva construcción de la caché (será más lenta).

Si lo has hecho, es bueno, la única cuestión es entonces sobre la conveniencia de trabajar con los datos recibidos, siempre y cuando el caché se construye.

No entendí tan profundamente las operaciones comerciales, pero si el rango de consulta cambia, entonces no hay posibilidad de buscar rápidamente los datos dentro de la historia sin la fuerza bruta completa?

 
Aleksey Vyazmikin:

No estoy tan metido en el comercio, pero si el rango de la consulta cambia, entonces no hay manera de buscar rápidamente los datos dentro de la historia sin una enumeración completa?

¿De qué sirven estos conocimientos si no los utilizas?

Ningún problema práctico = ninguna pregunta.

 
Renat Fatkhullin:

OrderExist y PositionExist son funciones especiales optimizadas que evitan el estúpido bucle de todas las órdenes o posiciones en busca de entradas por símbolo, tipo de transacción y medzhik.

El resultado es una serie de entradas.


Los programas pueden ahorrar mucho dinero utilizando estas funciones. Especialmente cuando se llaman posiciones y órdenes abiertas en masa, constante y repetidamente en bucles de sobregiro.

En el futuro implementaremos funciones más eficaces para acceder a los datos comerciales masivos.

También se reforzará y simplificará drásticamente el lenguaje con una funcionalidad más potente.

" OrderExist y PositionExist" - no se encuentran en la documentación, ¿dónde puedo leer sobre ellos?
 
HimOrik:
" OrderExist y PositionExist" - no se encuentran en la documentación, ¿dónde leer sobre ellos?

Lo más probable es que después de la próxima versión de lanzamiento (ahora en beta)