Discusión sobre el artículo "Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte XXI): Clases comerciales - El objeto comercial multiplataforma básico"
Leí más de la mitad con mucha atención. Más adelante, mi conciencia empezó a desconectarse. El volumen del artículo es extremadamente grande.
Anatoly Kozharsky siempre tenía un esquema general de la biblioteca al final de sus artículos, mediante el cual uno podía hacerse una idea clara de su estructura. No he visto tal esquema en sus artículos y, por lo tanto, me siento como una "hormiga" arrastrándose sobre el cuerpo de un "elefante". Me estoy haciendo una idea concisa de la biblioteca, pero leyendo sus artículos es difícil formársela. Hay mucha información "masticada" en forma de detalles, explicaciones de código, referencias a otros artículos, pero no hay una descripción y esquema integral y conciso de la librería.
Por supuesto, el nivel de implementación es muy alto. Todo es muy profesional, y se nota. Pero, yo cuestionaría la necesidad de tantos "wrappers". Por ejemplo: El método " CTradeObj::SetOrder" tiene los siguientes wrappers:
//--- Establece orden pendiente (1) BuyStop, (2) BuyLimit, (3) BuyStopLimit bool PlaceBuyStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //--- Establece orden pendiente (1) SellStop, (2) SellLimit, (3) SellStopLimit bool PlaceSellStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //---
Todos ellos no son muy diferentes, pero ocupan mucho espacio. Con semejantes "envoltorios profundos" el material y los códigos crecerán como sobre "levadura" y el uso de la funcionalidad se complicará en proporción al crecimiento del número de entidades, que se multiplicará exponencialmente.
No, no estoy en contra. Supongo que en eso consiste el polimorfismo, cuando un método engendra muchos envoltorios, cada uno con su propia especificidad. El problema es que la estructura de la solución con este enfoque crece demasiado rápido y deja de ser útil en la práctica. Tenemos que limitar el crecimiento del material, de lo contrario será cada vez más difícil de entender y utilizar.
Leí más de la mitad con mucha atención. Más adelante, mi conciencia empezó a desconectarse. El volumen del artículo es extremadamente grande.
Anatoly Kozharsky siempre tenía un esquema general de la biblioteca al final de sus artículos, mediante el cual uno podía hacerse una idea clara de su estructura. No he visto tal esquema en sus artículos y, por lo tanto, me siento como una "hormiga" arrastrándose sobre el cuerpo de un "elefante". Me estoy haciendo una idea concisa de la biblioteca, pero leyendo sus artículos es difícil formársela. Hay mucha información "masticada" en forma de detalles, explicaciones de código, referencias a otros artículos, pero no hay una descripción y esquema completo y conciso de la biblioteca.
Por supuesto, el nivel de implementación es muy alto. Todo es muy profesional, y se nota. Pero, yo cuestionaría la necesidad de tantos "wrappers". Por ejemplo: El método " CTradeObj::SetOrder" tiene las siguientes envolturas:
Todos ellos no son muy diferentes, pero ocupan mucho espacio. Con tanta "envoltura profunda" el material y los códigos crecerán como sobre "levadura" y el uso de la funcionalidad se complicará en proporción al crecimiento del número de entidades, que se multiplicará exponencialmente.
No, no estoy en contra. Supongo que en eso consiste el polimorfismo, cuando un método engendra muchos envoltorios, cada uno con su propia especificidad. El problema es que la estructura de la solución con este enfoque crece demasiado rápido y deja de ser útil en la práctica. Tenemos que limitar el crecimiento del material, de lo contrario será cada vez más difícil de entender y utilizar.
Gracias por tu valoración, Peter. Deberías utilizar sólo lo que está disponible en CEngine, que a su vez está disponible en el programa.
Todo lo demás es la implementación de métodos a los que se pasan todos los parámetros necesarios. Estos métodos no son necesarios para el uso práctico en sus propios programas - son necesarios para la propia biblioteca. Por lo tanto, para el usuario final siempre no hay tantos métodos, y esto se muestra en los asesores de prueba.
Naturalmente, todo será descrito. Y la estructura, y todos los métodos disponibles para el usuario. Y se crearan funciones de usuario, ocultando la implementacion OOP, y no requiriendo usar acceso explicito a los objetos de la libreria.
Pero todo está por delante - tenemos que componer la funcionalidad principal, que puede ser descrita tanto estructural como tabularmente para que la descripción sea completa y no requiera modificaciones.
Y se podría hacer que el usuario rellenara las estructuras necesarias, pero es más fácil y amigable pasar los parámetros directamente al método que rellenar la estructura de antemano y luego pasarla al método. Se hace sólo para la comodidad de uso del usuario final, no para la comodidad de analizar los componentes de la biblioteca.
Gracias por tu valoración, Peter. Es necesario utilizar sólo lo que está disponible en CEngine, que a su vez está disponible en el programa.
Todo lo demás es la implementación de métodos a los que se pasan todos los parámetros necesarios. Estos métodos no son necesarios para el uso práctico en sus propios programas - son necesarios para la propia biblioteca. Por lo tanto, para el usuario final siempre no hay tantos métodos, y esto se muestra en los asesores de prueba.
Naturalmente, todo será descrito. Y la estructura, y todos los métodos disponibles para el usuario. Y se crearan funciones de usuario, ocultando la implementacion OOP, y no requiriendo usar acceso explicito a los objetos de la libreria.
Pero todo está por delante - tenemos que componer la funcionalidad principal, que puede ser descrita tanto estructural como tabularmente para que la descripción sea completa y no requiera modificaciones.
Para no quedarme sin fundamento, sugiero la siguiente medida para limitar el "envoltorio":
Reescribir el método " CTradeObj::SetOrder" para que reciba un parámetro adicional - el tipo de orden a establecer. Además, el propio método determinará cómo hacerlo. Inicializará la estructura requerida, establecerá los valores requeridos y llamará a los métodos requeridos. Así, comprimirá todas sus envolturas a un parámetro adicional enviado al método " CTradeObj::SetOrder". Recibirá PlaceBuyStop, PlaceSellStopLimit, o PlaceBuyLimit como parámetro y entonces - hará el trabajo necesario.
Por supuesto, esta opción es más complicada de implementar, pero asegurará la "compresión" de la funcionalidad de la biblioteca y la facilidad de su uso.
Buena suerte.
Para no ser insustancial, sugeriría la siguiente medida para limitar el "envoltorio":
El método " CTradeObj::SetOrder" debería reescribirse para que reciba un parámetro adicional: el tipo de orden a establecer. Además, el propio método determinará cómo hacerlo. Inicializará la estructura requerida, establecerá los valores requeridos y llamará a los métodos requeridos. Así, comprimirá todas sus envolturas a un parámetro adicional enviado al método " CTradeObj::SetOrder". Recibirá PlaceBuyStop, PlaceSellStopLimit, o PlaceBuyLimit como parámetro y entonces - hará el trabajo necesario.
Por supuesto, esta opción es más complicada de implementar, pero asegurará la "compresión" de la funcionalidad de la biblioteca y la facilidad de su uso.
Buena suerte.
Este método no es necesario para el usuario de la biblioteca. Lo necesita la propia biblioteca.
Pedro. Intenta abrir una posición estableciendo sólo su tipo. Justo en el terminal. Y luego mira qué más se te pide. El terminal no decidirá por ti en qué símbolo abrirla, con qué lote abrirla, qué niveles de stop-orders establecer, etc.
...
Y, por favor, mire OrderSend() para cada tipo de órdenes enviadas - qué parámetros requiere. Todos estos parámetros se pasan a los métodos. Por supuesto, sería posible pasar parámetros a través de estructuras descritas como en los indicadores, pero sería innecesario.
Desde mi punto de vista, la opción más amigable sería sólo una envoltura para OrderSend(). Esta envoltura aceptaría parámetros del usuario y decidiría cómo formatear la llamada. Yo lo haría así. Pero, tú lo sabes mejor.
Yo lo hago así - los métodos aceptan parámetros del usuario.
Yo lo tengo hecho así - los métodos aceptan parámetros del usuario.
Sí, lo tengo. Esta es una implementación "multicapa" del procesamiento de pedidos. El problema está en el "grosor" de las envolturas. Me confundí qué métodos se refieren a los mecanismos y qué métodos se refieren a la interfaz de usuario de la biblioteca. Perdón. Si hubiera menos envolturas, sería más fácil de entender, pero es tu elección.
Verás, Peter, intento dar no sólo un método de trabajo, sino muchas posibilidades.
En este artículo, se organiza el acceso de bajo nivel a las funciones de comercio. Todo lo que hace el objeto trade es organizar correctamente los parámetros recibidos en la función de enviar una orden al servidor. Para enviar una orden comercial, es necesario acceder a una colección de símbolos, obtener un objeto del símbolo requerido, y de este objeto obtener un objeto comercial. A continuación, trabajar con el objeto de comercio. Aquí hice más fácil para el usuario llenar la orden comercial - es suficiente pasar los parámetros necesarios. Pero estos parámetros deben ser comprobados de forma independiente, porque el objeto comercial considera que todos los parámetros que se le pasan ya son correctos.
Esto no es conveniente. Pero existe tal acceso. Quien lo necesite comprobará todo por sí mismo y enviará una orden comercial. No hay procesamiento de respuesta del servidor. Esto es lo primero que se ha hecho.
El próximo artículo describirá una clase de comercio, que tendrá el mismo conjunto de métodos de comercio con los mismos parámetros, pero ahora todo será comprobado para la corrección y devuelto al programa si los parámetros no son correctos (o uno de ellos, o no hay posibilidad de comercio). Esta es la segunda etapa - aquí ya hay dos maneras - la primera, que ya existe, y la segunda - cuando la propia biblioteca comprueba la corrección de los parámetros, y si todos son correctos, entonces se envía la orden, y si al menos uno de ellos no es correcto, o no hay posibilidad de negociación, entonces simplemente vuelve al programa de control. Aquí se organizará un acceso de nivel superior con comprobaciones de corrección.
Pero eso no es todo. Hay que reaccionar ante los errores. Y en el próximo artículo iremos aún más lejos - procesaremos los errores recibidos en los parámetros de las órdenes comerciales (incluso antes de enviarlas al servidor). Después de todo, usted puede negarse a abrir una posición en caso de error, y puede corregir los parámetros y enviar la solicitud de nuevo. Este es ya el tercer nivel de trabajo con objetos comerciales.
Y luego habrá un enfoque de nivel aún más alto - todo funcionará automáticamente de acuerdo con la configuración requerida. Y llegará a las solicitudes diferidas - cuando el Asesor Experto esperará el momento adecuado para enviar la orden requerida de nuevo, o simplemente saber en qué situación necesita enviar una solicitud. Todas esas solicitudes pendientes estarán en su hucha esperando el momento adecuado para enviar la solicitud.
Por lo tanto, Peter, es prematuro juzgar nada todavía.
Tú sugeriste hacer un acceso único a las funciones de negociación, pero yo quiero dar una variedad de métodos - a cada uno según sus necesidades. Aunque es imposible complacer a todos, por supuesto.
Artyom Trishkin:
...
Me ha gustado tu explicación, y a este respecto, ha surgido una contradicción interna.
1. Por un lado, dar a los usuarios acceso a todos los niveles del motor de la biblioteca mediante la construcción de una estructura "envolvente" escalonada, donde en lugar de algoritmos comprimidos se expanden las relaciones, y el "marco" algorítmico se escala para facilitar la percepción, proporciona una cómoda comprensión de la estructura de las soluciones. Es bello, estético, elegante. Por supuesto, es una cuestión de diseño y facilidad de uso. Más concretamente, la facilidad de uso para los investigadores, porque a los usuarios les importan más los resultados y la eficacia. Ahora veamos la solución desde otra perspectiva.
2- Eficiencia implica concisión, un conjunto mínimo de entidades y envoltorios, con el acceso más corto posible a los datos. Todo debe estar cerca, para no "estirarse" y no transferir una "carga" de parámetros de envoltorio a envoltorio. La eficiencia y el estilo desplegado, escalonado y elegante, con "vagabundeo" entre envoltorios "escuadrones" de parámetros, son cosas ajenas y casi incongruentes.
//-----------------------------------
Ante esta contradicción, propongo un compromiso. Limitar parcialmente el crecimiento del número de envoltorios aumentando la concisión de las soluciones. En principio, un wrapper es suficiente para la función OrderSend(). En un caso extremo - varios. Pero, en este caso, la solución será difícil de entender para los "investigadores", y el acceso a los "niveles" será más complicado. Por lo tanto, trate de combinar bloques comprimidos, eficientes y "vides" de OOP-jungle, tan amado por los programadores. Y encontrarás el justo medio.
...
Y luego habrá un enfoque de nivel aún más alto - todo funcionará en modo automático de acuerdo con la configuración requerida. Y llegará a las solicitudes diferidas - cuando el Asesor Experto esperará el momento adecuado para enviar la orden requerida de nuevo, o simplemente saber en qué situación tiene que enviar una solicitud. Todas estas solicitudes pendientes estarán en su alcancía y estarán esperando el momento adecuado para enviar la solicitud.
Por lo tanto, Peter, es prematuro juzgar nada.
Tú propusiste hacer un acceso único a las funciones comerciales, pero yo quiero dar una variedad de métodos: a cada uno según sus necesidades. Aunque es imposible complacer a todos, por supuesto.
Dividir la biblioteca en niveles y permitir que los usuarios trabajen en ellos está muy bien. Pero no olvides que la cantidad puede arruinar la calidad. Cuantos más métodos reciba un usuario, más probable es que se confunda. Es algo que hay que tener en cuenta.
Aparte de eso, estoy de acuerdo. Un enfoque por capas de las funciones comerciales es algo bueno.
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Artículo publicado Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte XXI): Clases comerciales - El objeto comercial multiplataforma básico:
En este artículo vamos a comenzar un nuevo apartado de la biblioteca, las clases comerciales, y también vamos a analizar la creación de un objeto comercial básico único para las plataformas MetaTrader 5 y MetaTrader 4. Dicho objeto comercial, al enviar una solicitud al servidor, presupondrá que los parámetros de la solicitud comercial que se le han transmitido han sido verificados y son correctos.
Disponer de multitud de datos diferentes y lograr un acceso sencillo a los mismos en cualquier momento es algo magnífico. Pero estos datos carecerán prácticamente de sentido si no podemos reaccionar a ellos según su sentido directo, es decir, comerciando. Naturalmente, aparte de la funcionalidad que ya tenemos, vamos a necesitar una funcionalidad comercial.
Este apartado será bastante voluminoso, por lo que lo construiremos paso a paso.
- Necesitaremos tener la posibilidad de enviar cualquier orden comercial desde cualquier plataforma, MetaTrader 5 o MetaTrader 4. En este caso, además, sin tener que pensar desde qué plataforma precisamente estamos enviando la orden comercial, todo será igual.
- Por ende, necesitaremos comprobar preliminarmente si las solicitudes comerciales son correctas, para no sobrecargar el servidor con solicitudes que ya sabemos erróneas.
- De esta forma, tendremos que tener en cuenta y procesar correctamente los códigos de retorno del servidor comercial. Porque, ¿qué es lo que hace en definitiva el asesor al enviar una orden al servidor? Mantiene un diálogo con el servidor, en forma de solicitud y respuesta. Y para que el asesor pueda comunicarse con el servidor, nuestra tarea consistirá en organizar este "canal de comunicación", es decir, crear los métodos de procesamiento de las respuestas del servidor comercial.
- Por este motivo, deberemos crear varias opciones de procesamiento de las respuestas del servidor, y es que a veces tenemos que abrir una posición "preferiblemente a cualquier precio". Para ello, deberemos organizar la repetición del envío de las órdenes al servidor, en el caso de que se nos deniegue la colocación de una orden: podemos, o bien corregir los parámetros de la solicitud comercial y enviarla de nuevo, o bien dejar los parámetros como están, pero esperar el momento adecuado en el que la orden con dichos parámetros será aceptada, enviando esta de inmediato. Además, también deberemos tener en cuenta el nivel de precio, para no enviar repetidamente una orden al peor precio, conocido de antemano.
- Asimismo, deberemos implementar el trabajo con las clases comerciales de tal forma que, al ubicar un programa creado sobre la base de la biblioteca
Estos son los planeas mínimos e inmediatos en lo que respecta a las clases comerciales.Sin embargo, a veces necesitamos simplemente enviar una orden comercial, e independientemente del resultado, continuar trabajando.
en el Mercado de mql5, no surja ningún problema: dicho programa tendrá que superar todas las comprobaciones sin complicación alguna.
Autor: Artyom Trishkin