English Русский 中文 Deutsch 日本語 Português
preview
Cómo construir un EA que opere automáticamente (Parte 04): Gatillos manuales (I)

Cómo construir un EA que opere automáticamente (Parte 04): Gatillos manuales (I)

MetaTrader 5Trading | 25 enero 2023, 09:27
697 0
Daniel Jose
Daniel Jose

Introducción

En el artículo anterior, Cómo construir un EA que opere automáticamente (Parte 03) - Nuevas funciones, he finalizado la implementación del sistema de órdenes, por lo que, si no lo has leído o si no has conseguido asimilar el contenido allí presente, mi sugerencia es que vuelvas atrás e intentes absorber lo enseñado, ya que aquí no abordaré más el sistema de órdenes, a partir de ahora trataremos sobre otro tema, en particular de los gatillos.

El sistema de gatillos es quizás la parte más complicada y al mismo tiempo la que genera más confusión, dudas y problemas, esto debido a que no existe exactamente un método 100% infalible. Todos tienen algún tipo de falla o problema involucrado. Algunos contienen más posibilidades de fallas mientras que otros tienen menos posibilidades de fallas. Pero siempre debes estar atento a este concepto: no confíes en los gatillos, sea cual sea, ya que puede ocurrir que fallen en el momento en el que menos lo esperes. Y un fallo en el sistema de gatillo puede dejarte fuera de una buena oportunidad o puede causarte muchas pérdidas, así que siempre ten cuidado con estos gatillos.

Pero vamos a entender algunas cosas sobre este sistema. Primero, ¿para qué sirve un sistema de gatillo? Un sistema de gatillo sirve para diversas cosas, entre ellas está indicar el momento en que debería ocurrir un break-even o cuándo debería activarse un movimiento de trailing stop. Estos son ejemplos de los más simples, pero también el sistema de gatillo puede indicar cuándo el EA debe abrir una posición o cuándo debe cerrar una posición.

Todos estos eventos ocurren de forma completamente automática, sin que el operador necesite hacer algo, este solo indica al EA cuál será el gatillo o punto donde debería activar el evento. Después de esto, no se requiere intervención humana, salvo el caso en el que el EA entre en un bucle, para lo cual el operador deberá desactivarlo inmediatamente.

Para explicar y fijar mejor estas ideas y conceptos, tendremos que programar un EA manual. Pero aquí, haremos algo muy diferente a lo que normalmente hemos hecho como un EA manual. Esto será así porque agregaremos al EA, que estoy usando para ejemplificar los artículos, una forma de colocar órdenes pendientes y enviar órdenes para abrir una posición a precio de mercado. Entonces, ya que este EA es para fines de demostración y aprendizaje, te aconsejo que, si decides usarlo, lo hagas en una cuenta de demostración, la famosa cuenta DEMO, no uses este EA en una cuenta de producción o cuenta REAL, ya que existe el riesgo de que se trabe o se active de manera loca.


Cómo enviar órdenes y abrir posiciones en el mercado

En mi opinión, la mejor forma de operar en un gráfico es utilizando el mouse junto con el teclado. Para colocar órdenes pendientes, no existe una forma mejor, pero para colocar órdenes de mercado, solo el uso del teclado será suficiente. Pero la cuestión es cómo implementar un código que no sea tan complicado como para que no sea explicable, ya que un sistema de envío de órdenes utilizando el mouse y el teclado puede convertirse en algo bastante complejo de desarrollar.

Bueno, después de pensar por un tiempo, decidí crear un sistema ideal que es ideal en este artículo, algo bastante simple. Entonces no pienses en operar en cuenta real con este sistema. El sistema es solo para ayudarme a explicar algunas cosas sobre los gatillos, para que puedas entender cómo se implementa un gatillo y cómo debes abordarlo.

El código que necesitaremos desarrollar es el más simple que se puede construir, pero, aun así, suficiente para el resto de esta secuencia de artículos. Entonces veamos cómo se implementó el código.

En primer lugar, agregué un nuevo archivo de cabecera llamado C_Mouse.mqh, y el código de este archivo comienza de la siguiente manera:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_MouseName "MOUSE_H"
//+------------------------------------------------------------------+
#define def_BtnLeftClick(A)     ((A & 0x01) == 0x01)
#define def_SHIFT_Press(A)      ((A & 0x04) == 0x04)
#define def_CTRL_Press(A)       ((A & 0x08) == 0x08)
//+------------------------------------------------------------------+

Aquí, se ha definido un nombre para el objeto que vamos a crear, una línea horizontal para indicar la posición en el precio donde el puntero del mouse se encuentra en el gráfico. También se crearon 3 definiciones para poder tener un acceso más fácil a alguna información que generará un evento del mouse. Estas son una forma de probar los eventos de clic y teclas presionadas. Estas definiciones de acceso se utilizarán más tarde en el EA, mientras que la definición del nombre del objeto se finalizará al final del archivo, utilizando la siguiente línea:

//+------------------------------------------------------------------+
#undef def_MouseName
//+------------------------------------------------------------------+

Al agregar esta línea en el final del archivo de cabecera aseguramos que esta definición no se filtrará o aparecerá en ningún otro punto del código. Es decir, si intentas usar esta definición sin volver a declararla en otro punto que no sea este archivo de cabecera, el compilador generará un error alertando sobre esto.

Ahora vamos a comenzar a codificar nuestra clase, que será responsable de todo el trabajo con el mouse, ella comienza de la siguiente manera:

class C_Mouse
{
        private :
                struct st00
                {
                        long    Id;
                        color   Cor;
                        double  PointPerTick,
                                Price;
                        uint    BtnStatus;
                }m_Infos;
//+------------------------------------------------------------------+
                void CreateLineH(void)
                        {
                                ObjectCreate(m_Infos.Id, def_MouseName, OBJ_HLINE, 0, 0, 0);
                                ObjectSetString(m_Infos.Id, def_MouseName, OBJPROP_TOOLTIP, "\n");
                                ObjectSetInteger(m_Infos.Id, def_MouseName, OBJPROP_BACK, false);
                                ObjectSetInteger(m_Infos.Id, def_MouseName, OBJPROP_COLOR, m_Infos.Cor);
                        }
//+------------------------------------------------------------------+
inline double AdjustPrice(const double value)
                        {
                                return MathRound(value / m_Infos.PointPerTick) * m_Infos.PointPerTick;
                        }
//+------------------------------------------------------------------+

No te asustes al ver el código anterior, esta parte es solo una pequeña muestra. Todo lo que estamos haciendo es declarando una estructura de datos que contendrá algunas variables globales dentro de la clase, pero estas serán privadas de la clase. Luego utilizamos un procedimiento que creará un objeto gráfico en la plataforma MetaTrader 5, este objeto será una línea horizontal, ajustamos algunas de sus propiedades y seguimos adelante.

Ya esta función, creo que ya la habrás visto en un artículo anterior, si no la has visto, lee los artículos anteriores a estos en esta misma secuencia sobre el EA automático, ya que también son importantes para lo que vamos a hacer.

Ahora veamos los procedimientos que serán públicos de nuestra clase C_Mouse, comenzando con el constructor de la clase:

                C_Mouse(const color cor)
                        {
                                m_Infos.Id = ChartID();
                                m_Infos.Cor = cor;
                                m_Infos.PointPerTick = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
                                ChartSetInteger(m_Infos.Id, CHART_EVENT_MOUSE_MOVE, true);
                                ChartSetInteger(m_Infos.Id, CHART_EVENT_OBJECT_DELETE, true);
                                CreateLineH();
                        }

Aquí hay 2 líneas que pueden resultar extrañas para ti si no tienes mucho conocimiento sobre MQL5, así que vamos a dar una breve explicación sobre ellas. Esta línea informa a la plataforma MT5 que nuestro código, el EA, desea recibir eventos generados por el mouse. Hay otro tipo de evento también generado por el mouse que es cuando se utiliza la rueda (scroll), pero no queremos y no utilizaremos la rueda, entonces este tipo de evento aquí ya es suficiente para nosotros.

Ya esta línea aquí, le indicará a la plataforma MetaTrader 5 que deseamos saber si algún objeto gráfico fue eliminado. Si esto sucede, se generará un evento para informarnos sobre cuál fue el elemento eliminado del gráfico. Este tipo de evento es muy útil cuando deseamos mantener ciertos elementos críticos para una ejecución perfecta y correcta de la tarea. Entonces, si el usuario elimina de forma accidental algún elemento crítico, MetaTrader 5 informará al código, en este caso al EA, de que se ha eliminado un elemento, y podremos volver a crearlo. Ahora vamos a ver el código destructor de la clase:

                ~C_Mouse()
                        {
                                ChartSetInteger(m_Infos.Id, CHART_EVENT_OBJECT_DELETE, false);
                                ObjectDelete(m_Infos.Id, def_MouseName);
                        }

En este código, estamos haciendo dos cosas. Primero, estamos informando al MetaTrader 5 que ya no deseamos recibir notificaciones si algún elemento es eliminado del gráfico. Es importante hacer esto antes de continuar, ya que, si intentamos eliminar algún elemento, el MetaTrader 5 generará un evento informando que algo ha sido eliminado del gráfico. Y es precisamente lo que haremos a continuación, eliminar la línea que creamos para mostrar en qué rango de precio se encuentra el cursor del mouse.

La siguiente cosa que necesitamos hacer es crear una forma de leer los datos dentro de la clase, para saber en qué punto está el mouse y cuál es el estado de sus botones. Para esto usaremos la siguiente función:

const void GetStatus(double &Price, uint &BtnStatus) const
                        {
                                Price = m_Infos.Price;
                                BtnStatus = m_Infos.BtnStatus;
                        }

Aquí es importante explicar algo común entre personas con menos experiencia en programación orientada a objetos. Cuando usamos clases, no debemos permitir de ninguna manera que algún código fuera de la clase tenga acceso directo a las variables o procedimientos de la clase, sin que esto sea un punto de prueba para verificar lo que entra en la clase.

Utilizar y permitir que las variables o procedimientos de una clase reciban un valor que no ha sido debidamente comprobado es un grave error, ya que esto causará problemas a largo plazo. Tú puedes modificar en algún momento en algún punto del código el valor de una variable crítica presente en la clase, y cuando esta sea utilizada, puede poner en riesgo todo el código, además es extremadamente complicado lidiar con este tipo de situación para corregir el problema después.

Entonces siempre sigue esta práctica para convertirte en un buen programador: Si vas a leer el contenido de una clase, permítele ser leído pero no modificado, esto suele suceder con mucha frecuencia, especialmente cuando usamos punteros. Tú pides leer una variable y retornas un puntero. En este momento tu código ha comenzado a correr riesgo, ya que al utilizar un puntero, sabrás dónde escribir en la memoria, y esto es muy peligroso. Observa cómo se hacen los llamados cheats de juegos, esos programas para engañar en juegos electrónicos. Simplemente escribes en una posición de la memoria utilizando para esto un puntero.

Ten mucho cuidado al usar punteros. Si tienes dudas, siempre prefiere usar una función en lugar de un procedimiento. La diferencia entre ellos es que una función normalmente retorna un valor, pero, aun así, ten cuidado de no devolver un puntero.

Pero si, aun así, no hay otra opción, haz como yo hice anteriormente. Sé que es exceso de precaución, pero al iniciar la declaración del procedimiento o función con la palabra reservada const, estás garantizando que el llamador no podrá cambiar los datos contenidos en las variables, ya que el compilador tratará cualquier valor como una constante, y modificar una constante no es permitido.

Terminar la declaración del procedimiento o función con la palabra reservada const garantizará que, tú como programador, no modificarás accidentalmente y, a menudo sin darte cuenta, algún valor dentro del procedimiento o función. Esta es quizás la mejor práctica de programación que existe, a pesar de parecer extraña para muchos. Esto evita varios errores de programación, especialmente cuando estamos haciendo esto en POO (programación orientada a objetos), pero más adelante volveremos a esta cuestión con un ejemplo más claro, para que entiendas esta cuestión de terminar la declaración con una palabra const.

El último procedimiento que necesitamos es visto justo debajo:

                void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
                        {
                                int w;
                                datetime dt;
                                
                                switch (id)
                                        {
                                                case CHARTEVENT_OBJECT_DELETE:
                                                        if (sparam == def_MouseName) CreateLineH();
                                                        break;
                                                case CHARTEVENT_MOUSE_MOVE:
                                                        ChartXYToTimePrice(m_Infos.Id, (int)lparam, (int)dparam, w, dt, m_Infos.Price);
                                                        ObjectMove(m_Infos.Id, def_MouseName, 0, 0, m_Infos.Price = AdjustPrice(m_Infos.Price));
                                                        m_Infos.BtnStatus = (uint)sparam;
                                                        ChartRedraw();
                                                        break;
                                        }
                        }

Este procedimiento es muy curioso, ya que muchos programadores querrán colocar el código presente aquí dentro del evento de manejo de mensajes OnCharEvent. Pero me gusta tratar los eventos dentro de la clase objeto, esto evita a menudo que te olvides de tratar algo en particular o tratar algo de una manera diferente, lo cual a menudo te hará tener que verificar si el código está funcionando o no. Haciendo este tratamiento dentro de la clase, nos sentimos más tranquilos a largo plazo, ya que en el momento en que usemos la clase sabremos que el sistema de manejo de mensajes de la misma está funcionando como se espera. Esto agiliza mucho la creación de nuevos programas. Este es el camino de la reutilización, programa una vez y usa siempre.

Entonces, vamos a entender lo que está sucediendo en este sistema de tratamiento de mensajes. Bien, aquí estamos replicando exactamente los datos que serán recibidos por el tratador de eventos OnChartEvent, y esto es intencional, ya que queremos tratar los eventos aquí, dentro de la clase.

Una vez esto establecido, vamos a definir qué eventos vamos a tratar. El primero es el evento de eliminación de objeto gráfico, este se genera debido a que anteriormente le dijimos al MetaTrader 5 que queríamos ser informados si algún objeto era eliminado del gráfico, y si el objeto eliminado es la línea del mouse, este objeto será recreado inmediatamente.

El siguiente evento que queremos tratar aquí, dentro de la clase, son los eventos de movimiento del mouse. Nuevamente, este evento se generará porque le informamos al MetaTrader 5 que queríamos saber lo que está sucediendo con el mouse. Aquí simplemente convertiremos los valores que el MetaTrader 5 nos está dando en valores de tiempo y precio. Luego, posicionaremos el objeto línea horizontal en la posición del precio, de manera que quede en el punto correcto, no en un punto en el sistema de coordenadas de pantalla, sino en un punto en el gráfico de precio. Entonces, almacenaremos el valor de los botones y forzaremos una actualización inmediata del gráfico.

Es importante que esta actualización ocurra, ya sea aquí en el manejador de eventos de la clase, o en el manejador de eventos OnChartEvent, si no se hace, puedes tener la impresión de que el código está dejando la plataforma lenta, ya que la línea de precio se moverá de manera extraña.

Con esto, finalizamos nuestra clase C_Mouse, y ya podremos mandar órdenes pendientes directamente en el gráfico. Ahora, volveremos al código de nuestro EA, y agregaremos la clase C_Mouse para poder generar los eventos y mandar las órdenes pendientes. Para hacer esto, procederemos de la siguiente manera:

#include <Generic Auto Trader\C_Orders.mqh>
#include <Generic Auto Trader\C_Mouse.mqh>
//+------------------------------------------------------------------+
C_Orders *manager;
C_Mouse *mouse;
//+------------------------------------------------------------------+
input int       user01   = 1;           //Fator de alavancagem
input double    user02   = 100;         //Take Profit ( FINANCEIRO )
input double    user03   = 75;          //Stop Loss ( FINANCEIRO )
input bool      user04   = true;        //Day Trade ?
input color     user05  = clrBlack;     //Color Mouse
//+------------------------------------------------------------------+
#define def_MAGIC_NUMBER 987654321
//+------------------------------------------------------------------+
int OnInit()
{
        manager = new C_Orders(def_MAGIC_NUMBER);
        mouse = new C_Mouse(user05);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        delete mouse;
        delete manager;
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+

En el fragmento anterior, se describen los pasos cómo produciremos las cosas. Se están haciendo las cosas de manera tal que se pueda eliminar fácilmente la clase C_Mouse. Dado que para un EA automático esta clase no tiene ninguna utilidad, pero en este momento necesitamos una forma de probar nuestro EA, la mejor forma de hacer esto sin agregar gatillos es usando la clase C_Mouse que acabamos de construir. Por lo tanto, incluimos esta clase para que el compilador pueda agregar el código para nosotros. Definimos un color para ser utilizado en la línea horizontal de precio.

Inicializamos nuestra clase C_Order de tal forma que todas las órdenes tendrán un número mágico igual para este EA. Aquí es importante mencionar que siempre debes asignar un número mágico diferente para cada EA, ya que, si estás usando más de un EA al mismo tiempo en el mismo activo, la forma de separarlos de manera que cada uno solo observe las órdenes que él generó será a través de este número mágico. Si dos EAs tienen el mismo número, no podrás separarlos y uno podría interferir en las órdenes del otro. Entonces, cada EA debe tener un número mágico diferente.

Una vez hecho esto, inicializamos la clase C_Mouse y de esta forma el EA estará listo para su uso. No te olvides de llamar a los destructores al finalizar el EA. A pesar de todo, si te olvidas de hacerlo, el compilador normalmente lo hará por ti, pero siempre es una buena práctica hacerlo en el código para que todos sepan en dónde la clase deja de ser referenciada.

Aunque se mencionó que el EA está listo para su uso, todavía falta una cosa: El sistema de tratamiento de eventos de gráfico, este tendrá ahora el siguiente formato:

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
        uint    BtnStatus;
        double  Price;
        static double mem = 0;
        
        (*mouse).DispatchMessage(id, lparam, dparam, sparam);
        (*mouse).GetStatus(Price, BtnStatus);
        if (def_SHIFT_Press(BtnStatus) != def_CTRL_Press(BtnStatus))
        {
                if (def_BtnLeftClick(BtnStatus) && (mem == 0)) (*manager).CreateOrder(def_SHIFT_Press(BtnStatus) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL, mem = Price, user03, user02, user01, user04);
        }else mem = 0;
}

Aquí está él, muy simple, no quiero convertir un EA que está siendo construido para ser automático en un EA manual. Por esta razón, las líneas de precio que informan los límites de take profit y stop loss no serán creadas por el EA. Pero veamos cómo funciona este código y, a pesar de todo, todavía falta algo aquí, pero, aun así, veamos cómo funciona.

Cuando el MetaTrader 5 detecte que ha ocurrido un evento en el gráfico, sea cual sea, generará una llamada a este código de arriba. Tan pronto como este código sea activado y reciba el procesador para ser ejecutado, llamará al procedimiento de tratamiento de mensajes de la clase C_Mouse. De esta forma, los eventos relacionados con el mouse serán tratados de manera adecuada y siempre de la misma manera.

Una vez que el manejador de mensajes de la clase C_Mouse retorne, capturaremos el estado del mouse para poder usarlo aquí en esta función.

Ahora vamos a probar, usando las definiciones que se encuentran en el archivo de cabecera C_Mouse.mqh, el estado de las teclas Shift y Ctrl. Estas servirán para indicar si estamos enviando una orden de compra o de venta. Por esta razón, ellas deben tener valores diferentes. Si esto está ocurriendo, haremos una nueva prueba.

Pero esta vez, vamos a probar si hubo o no un clic con el botón izquierdo del mouseSi también esto es verdad y el precio de memoria es cero, enviaremos una orden pendiente al servidor usando los datos indicados en el área de interacción con el usuario. Quién decidirá si compramos o vendemos es el uso de las teclas Shift y Ctrl, la tecla Shift indica que compraremos, mientras que la tecla Ctrl indica que venderemos. De esta manera, podremos colgar tantas órdenes como necesitemos para probar el sistema, pero como se dijo antes, todavía falta algo aquí.

En el artículo anterior, dejé un desafío para que intentaras generar un código para poder ejecutar una operación al mercado. Si no pudiste hacerlo, está bien, no necesitas desanimarte, pero sería bueno si hubieras logrado hacerlo sin ver cómo sería mi solución. Está justo debajo, en la actualización del código de tratamiento de eventos OnChartEvent.

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
        uint    BtnStatus;
        double  Price;
        static double mem = 0;
        
        (*mouse).DispatchMessage(id, lparam, dparam, sparam);
        (*mouse).GetStatus(Price, BtnStatus);
        if (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL))
        {
                if (TerminalInfoInteger(TERMINAL_KEYSTATE_UP))  (*manager).ToMarket(ORDER_TYPE_BUY, user03, user02, user01, user04);
                if (TerminalInfoInteger(TERMINAL_KEYSTATE_DOWN) (*manager).ToMarket(ORDER_TYPE_SELL, user03, user02, user01, user04);
        }
        if (def_SHIFT_Press(BtnStatus) != def_CTRL_Press(BtnStatus))
        {
                if (def_BtnLeftClick(BtnStatus) && (mem == 0)) (*manager).CreateOrder(def_SHIFT_Press(BtnStatus) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL, mem = Price, user03, user02, user01, user04);
        }else mem = 0;
}

Aquí está una forma de enviar órdenes de mercado al servidor de comercio. Tenemos el siguiente comportamiento: Cuando se presiona la tecla CTRL, esta condición aquí será verdadera, es decir, ahora podremos probar una segunda condición. Esta segunda condición indica si compramos al mercado o vendemos al mercado. Para esto, usaremos las teclas de flecha, si presionas CTRL + Flecha hacia arriba, estarás comprando a precio de mercado siguiendo las instrucciones presentes en el área de interacción con el usuario, ahora si presionas CTRL + Flecha hacia abajo, estarás vendiendo a precio de mercado siguiendo las mismas instrucciones.

Estas instrucciones pueden verse en la figura 01:

Figura 1

Figura 01 - Configuraciones del EA.


Conclusión

Lo que acabo de explicar sobre el sistema de eventos y cómo se implementó es un tipo de mecanismo de gatillo. Pero en este caso, el mecanismo es manual, es decir, necesita la intervención de un operador humano para que la orden de apertura de posición o la colocación de una orden pendiente en el libro sea realizada mediante una interacción del usuario del EA con el propio EA. En este caso, no existe ningún mecanismo automático para colocar una orden en el libro o abrir una posición, todo depende de un operador.

Pero una vez que la orden haya sido colocada en el libro, el sistema dejará de depender del operador, la orden se convertirá en posición una vez que el precio alcance el punto indicado en la orden y la posición será cerrada si uno de los precios límite es alcanzado. Pero en este caso, debes estar atento ya que puede ocurrir un momento de gran volatilidad que podría hacer que el precio indicado sea saltado. Así, la posición continuará abierta hasta que el corredor de bolsa la cierre forzosamente o el tiempo límite, en el caso de operaciones de day trade, finalice debido al cierre del mercado. Pero de una manera u otra, debes estar atento con una posición abierta.

En el archivo adjunto, tendrás acceso al código actual. En el próximo artículo modificaremos este código para facilitar el uso del EA en modo manual, ya que será necesario hacer algunos cambios. Sin embargo, serán muy interesantes de implementar.


Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/11232

Archivos adjuntos |
Cómo construir un EA que opere automáticamente (Parte 05): Gatillos manuales (II) Cómo construir un EA que opere automáticamente (Parte 05): Gatillos manuales (II)
Aprenda a crear un EA que opere automáticamente de forma sencilla y segura. Al final del artículo anterior, pensé que sería apropiado permitir el uso del EA de forma manual, al menos durante un tiempo.
Cómo construir un EA que opere automáticamente (Parte 03): Nuevas funciones Cómo construir un EA que opere automáticamente (Parte 03): Nuevas funciones
Aprenda a crear un EA que opere automáticamente de forma sencilla y segura. En el artículo anterior, comenzamos a desarrollar el sistema de órdenes que se va a utilizar en el EA automático. Sin embargo, solo construimos una de las funciones o procedimientos necesarios.
Cómo construir un EA que opere automáticamente (Parte 06): Tipos de cuentas (I) Cómo construir un EA que opere automáticamente (Parte 06): Tipos de cuentas (I)
Aprenda a crear un EA que opere automáticamente de forma sencilla y segura. Hasta ahora nuestro EA puede funcionar en cualquier tipo de situación, pero aún no está listo para ser automatizado, por lo que tenemos que hacer algunas cosas.
DoEasy. Elementos de control (Parte 21): Elemento de control SplitContainer. Separador de paneles DoEasy. Elementos de control (Parte 21): Elemento de control SplitContainer. Separador de paneles
En este artículo, crearemos una clase de objeto auxiliar de separador de paneles para el control SplitContainer.