English Русский 中文 Deutsch 日本語 Português
preview
Indicador personalizado: Trazado de puntos de entradas parciales en cuentas netting

Indicador personalizado: Trazado de puntos de entradas parciales en cuentas netting

MetaTrader 5Ejemplos |
216 0
Daniel Santos
Daniel Santos

Contenido

  1. Introducción
  2. ¿Qué es una cuenta netting?
  3. Trabajar con eventos comerciales
  4. Ejemplo práctico de utilización - introducción
  5. Propiedades de los indicadores
  6. Descripción del algoritmo
  7. Otro ejemplo práctico
  8. Integración con un Asesor Experto
  9. Conclusión


1. Introducción

Cuando hablamos de indicadores, podemos imaginar diversas funcionalidades: dibujar gráficos, como histogramas, líneas de tendencia, flechas o barras; calcular datos en función del movimiento de precios y volúmenes, y observar patrones estadísticos en nuestras transacciones. En este artículo, sin embargo, exploraremos una forma distinta de construir un indicador en MQL5 orientado a la gestión de nuestras propias posiciones: entradas, salidas parciales, etc. Utilizaremos intensivamente matrices dinámicas y algunas funciones comerciales (Trade) relacionadas con el historial de transacciones y las posiciones abiertas. 


2. ¿Qué es una cuenta netting?

Tal como sugiere el título de este artículo, este indicador solo tendrá sentido en una cuenta con sistema de registro netting, también conocido como sistema de compensación. En este sistema, solo se permite tener una única posición de un mismo símbolo. Si realizamos una transacción en la misma dirección, el volumen de la posición aumentará. En cambio, si la transacción es en dirección opuesta, la posición abierta tendrá tres posibilidades:

  1. Volumen menor -> disminución de la posición
  2. Volumen idéntico -> cierre de la posición
  3. Mayor volumen -> inversión de posiciones


Por ejemplo, en una cuenta hedge (o sistema de cobertura), podemos realizar dos transacciones de compra de un lote cada una en el par EURUSD, lo que dará lugar a dos posiciones distintas del mismo símbolo. Por otro lado, realizar dos transacciones de compra de un lote cada una del símbolo EURUSD en una cuenta netting resultará en una única posición de dos lotes de ese símbolo, con un precio promedio ponderado de las dos transacciones. Como los volúmenes de ambas transacciones fueron iguales, el precio de la posición es la media aritmética de los precios de cada una de ellas.

Este cálculo se realiza de la siguiente manera:

Cálculo de netting

Es decir, tenemos un promedio de precios (P) ponderado por el volumen (N) de los lotes de cada transacción.

Para conocer más detalles sobre la diferencia entre los sistemas, recomendamos leer el artículo escrito por MetaQuotes: "Se ha añadido a MetaTrader 5 el sistema de cobertura de registro de posiciones". A partir de aquí, en este artículo, consideraremos todas las operaciones realizadas en una cuenta netting. Si aún no dispones de este tipo de cuenta, puedes abrir gratuitamente una cuenta de demostración en MetaQuotes, como se muestra a continuación.

En MetaTrader 5, haz clic en Archivo > Abrir una Cuenta:

Seleccionar la empresa para abrir la cuenta

Después de elegir la apertura de una cuenta demo, haz clic en "Avanzar" y deja desmarcada la opción "Utilizar cobertura".

Finalizamos la apertura de cuenta demo


3. Trabajar con eventos comerciales

Trabajar con los eventos comerciales es esencial para gestionar con éxito las órdenes, las transacciones y las posiciones. Las solicitudes de trading pueden ser instantáneas o pendientes, y una vez que una orden se ejecuta, se generan transacciones que pueden abrir, cerrar o modificar una posición.

Los indicadores no tienen permiso para usar funciones como OrderSend(), pero sí pueden interactuar con la base histórica de transacciones y las propiedades de las posiciones. A través de la función OnCalculate, el indicador puede capturar información como el precio de apertura, el precio de cierre, el volumen, etc. Aunque la función OnTrade() se utiliza principalmente en Expert Advisors, también es aplicable a los indicadores, ya que estos pueden detectar eventos Trade fuera del simulador de estrategias, lo que hace que la actualización de los objetos gráficos sea más rápida y eficiente.


4. Ejemplo práctico de utilización - introducción

La siguiente figura ilustra un ejemplo práctico del uso del indicador personalizado que estamos desarrollando. Se trata de una posición de compra en tres lotes, derivada de una operación más amplia en la que hubo varias entradas y salidas parciales (e incluso reversiones). Esto explica la aparente divergencia entre el precio promedio mostrado en el gráfico y los precios y cantidades de lotes indicados. Al seguir los eventos comerciales, es posible comprender los criterios que el algoritmo utiliza para eliminar líneas y actualizar en pantalla el número de lotes conforme se producen salidas parciales.

Gráfico de entradas parciales y volúmenes


5. Propiedades de los indicadores

Las propiedades de los indicadores se definen obligatoriamente al inicio de la descripción y se configuraron de la siguiente forma:

#property indicator_chart_window                        // O indicador é visualizado na janela principal
#property indicator_buffers 0                           // Zero buffers
#property indicator_plots   0                           // Sem plotagens 
//--- plot Label1
#property indicator_label1  "Propriedades das linhas"
#property indicator_type1   DRAW_LINE                   // tipo de linha para a primeira plotagem
#property indicator_color1  clrRoyalBlue                // cor da linha para a primeira plotagem
#property indicator_style1  STYLE_SOLID                 // estilo da linha para a primeira plotagem
#property indicator_width1  1                           // largura da linha para a primeira plotagem

Este código se muestra en la pantalla de carga del indicador, donde se solicitan los parámetros iniciales.

Cargar indicador


6. Descripción del algoritmo

La función OnInit(), cargada al inicio del programa, se encarga de inicializar un array del tipo double llamado "Element", que actúa como el verdadero buffer del indicador. Este array está compuesto por tres columnas y cada índice almacena el precio (0), el volumen (1) y el número del ticket (2). Cada fila de esta matriz corresponde a una transacción del historial. Si la inicialización es exitosa, es decir, si se verifica que la cuenta no es del tipo hedge, se activa la función OnTrade(). Si hay un error en la inicialización, el indicador se cierra y se elimina del gráfico.

Mira:

int OnInit()
  {
   ArrayResize(Element,0,0);
   int res=INIT_SUCCEEDED;
   if(AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
      res=INIT_FAILED;
   else
      OnTrade();
   return(res);
  }

Después de la inicialización, la función OnTrade() se activa mediante la función OnCalculate() y de manera nativa cuando se producen eventos Trade. Para garantizar que solo se active una vez y únicamente cuando se forma una nueva vela, se implementa un filtro utilizando la función isNewBar y la variable booleana isOldBar. De este modo, la función OnTrade se activa en tres escenarios: durante la inicialización, cuando hay un cambio de vela y con cada evento comercial. Estos procesos aseguran la lectura actualizada de los eventos, su procesamiento y almacenamiento en el array Element, lo que se refleja fielmente en los objetos gráficos de la pantalla mediante líneas y textos.

La función OnTrade() actualiza variables clave en el algoritmo de negociación. Comienza con la variable del tipo datetime llamada "date", que almacena la hora de inicio para la selección del historial de órdenes. Si no hay una posición abierta al inicio del programa, la variable "date" se actualiza con el tiempo de apertura de la vela actual.

Cuando ocurre una negociación, la función PositionsTotal() devuelve un valor mayor que cero y, a través de un bucle, se filtran las posiciones del símbolo correspondiente al gráfico donde se insertó el indicador. A continuación, se selecciona el historial y se recuperan todas las órdenes ejecutadas para ese identificador. La variable "date" se actualiza con el tiempo más antiguo entre esas órdenes, que corresponde al momento en que se creó el identificador.

En el caso de una segunda posición con un identificador diferente, es necesario verificar si existen elementos gráficos que deben eliminarse mediante la función LimparRetângulos() para garantizar que todo esté actualizado. A continuación, el array Element se redimensiona a cero, lo que elimina los datos que contiene. Si no hay posiciones abiertas, la función también activa LimparRetângulos() y reinicia el array Element. La variable "date" almacena entonces el valor de la última hora conocida del servidor, es decir, la hora actual. Finalmente, el valor restante de la variable "date" se pasa a la función ListarOrdensPosicao().

void
 OnTrade()
  {
//---
   static datetime date=0;
   if(date==0)
      date=lastTime;
   long positionId=-1,numberOfPositions=0;
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==ativo000)
           {
            numberOfPositions++;
            positionId=m_position.Identifier();
            oldPositionId=positionId;
           }
   if(numberOfPositions!=0)
     {
      //Print("PositionId: "+positionId);
      HistorySelectByPosition(positionId);
      date=TimeCurrent();
      for(int j=0; j<HistoryDealsTotal(); j++)
        {
         ulong ticket = HistoryDealGetTicket(j);
         if(ticket > 0)
            if(HistoryDealGetInteger(ticket,DEAL_TIME)<date)
               date=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
        }
      if(HistoryDealsTotal()==1 && (ArraySize(Element)/3)>1)
         if(LimparRetangulos())
            ArrayResize(Element,0,0);
     }
   else
     {
      bool isClean=LimparRetangulos();
      ArrayResize(Element,0,0);
      if(isClean)
        date=TimeCurrent();        // O array não será manipulado enquanto não houver nova posição aberta
      ArrayPrint(Element);         // Se não houver erros, essa função não será chamado aqui: o array com tamanho zero
     }
   ListarOrdensPosicao(date);
  }

La función ListaOrdensPosicao() desempeña un papel importante, ya que es la encargada de activar las funciones para añadir o eliminar entradas del array Element, utilizando las funciones AddValue() y RemoveValue(). Al recibir el parámetro dateInicio, del tipo int, existen dos posibilidades. Si no hay historial de transacciones dentro del período especificado para la función HistorySelect(inicio, fin), esta irá directamente a su final, activando la función PlotarRetangulos(), lo que actualiza los objetos en la pantalla de acuerdo con el contenido del array Element. Por otro lado, si hay transacciones en el historial, la función HistoryDealsTotal() devolverá un valor no nulo. En este caso, se realiza una nueva verificación cuyo objetivo es inspeccionar cada transacción encontrada, clasificarla según el tipo de entrada, recoger el precio, el volumen y el número de ticket. Estas transacciones pueden ser: DEAL_ENTRY_IN (entrada), DEAL_ENTRY_OUT (salida) o DEAL_ENTRY_INOUT (reversión).

Si la transacción es de entrada, se activa la función AddValue; si es de salida, se activa RemoveValue, con los siguientes parámetros: el precio, el volumen y el número de ticket previamente recolectados. Si se trata de una reversión, también se activa la función AddVolume(), siempre y cuando el número de ticket no haya sido previamente ingresado en el array. Además, se pasan los parámetros de precio y volumen, calculando este último como la diferencia entre el volumen recolectado y el volumen de las transacciones anteriores que aún están presentes en el array.

Este proceso simula una reconstrucción de la posición histórica, de modo que, al llegar a la transacción de reversión, la posición se invierte e incluye en el array como si fuese una nueva entrada, ajustando la cantidad de lotes. Además, se eliminan las líneas que estaban en pantalla hasta ese momento. La función Sort() ordena el array Element en forma ascendente según la columna de precio y elimina los objetos del gráfico cuyos valores en la columna 1 (volumen) del array sean cero. Finalmente, esta función comprueba posibles inconsistencias y elimina las líneas del array cuyos índices 0 y 1 (precio y volumen) sean iguales a cero.

void ListarOrdensPosicao(datetime dateInicio)
  {
//Obtenção do Histórico
   datetime inicio=dateInicio,fim=TimeCurrent();
   if(inicio==0)
      return;
   HistorySelect(inicio, fim);
   double deal_price=0, volume=0,newVolume;
   bool encontrouTicket;
   uint tamanhoElement=0;
   for(int j=0; j<HistoryDealsTotal(); j++)
     {
      ulong ticket = HistoryDealGetTicket(j);
      if(ticket <= 0)
         return;
      if(HistoryDealGetString(ticket, DEAL_SYMBOL)==_Symbol)
        {
         encontrouTicket=false;
         newVolume=0;            // Necessário zerar a cada laço do for
         volume=HistoryDealGetDouble(ticket,DEAL_VOLUME);
         deal_price=HistoryDealGetDouble(ticket,DEAL_PRICE);
         double auxArray[1][3] = {deal_price,volume,(double)ticket};
         if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_IN)
            AddValue(deal_price,volume,(double)ticket);
         if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT)
            RemoveValue(deal_price,volume,(double)ticket);
         if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_INOUT)
           {
            tamanhoElement = ArraySize(Element)/3; //Checar tamanho do array sempre, pode variar com as funções Add/RemoveValue())
            for(uint i=0; i<tamanhoElement; i++)
               if(Element[i][2]==ticket)
                 {
                  encontrouTicket=true;
                  break;
                 }
            if(!encontrouTicket) // Se fizer toda a varredura anterior e não encontrar no array menção ao ticket
              {
               for(uint i=0; i<tamanhoElement; i++)
                 {
                  newVolume+=Element[i][1];
                  Element[i][1]=0;
                 }
               newVolume=volume-newVolume;
               AddValue(deal_price,newVolume,double(ticket));
              }
           }
        }
     }
   PlotarRetangulos();
  }


7. Otro ejemplo práctico

Confiando en que la descripción del algoritmo presentada anteriormente fue suficiente para proporcionar una comprensión más clara de su funcionamiento, pasaremos a visualizar todo esto de manera más detallada mediante un ejemplo, en el que se mostrarán las operaciones involucradas y el contenido de las variables más importantes. Consideremos que las operaciones se ejecutan fuera del simulador de estrategias, de modo que se detectarán los eventos Trade. Sabemos que, en una cuenta netting, las transacciones de cada posición tienen el mismo identificador, por lo que podemos filtrarlas basándonos en este criterio. A modo de ejemplo, en la siguiente figura se muestran los eventos de una posición específica:

 Time Symbol
 Deal Type
Direction
Volume
Price
2023.05.04  09:42:05
winm23
1352975
buy
in
1
104035
2023.05.04  09:43:16
winm23
1356370
sell
in/out
2
103900
2023.05.04 16:34:51
winm23
2193299
buy
out
1
103700
2023.05.04  16:35:05
winm23
2193395
buy
in
1
103690
2023.05.04  16:35:24
winm23
2193543
buy
in
1
103720
2023.05.04  16:55:00
winm23
2206914
sell
out
1
103470
2023.05.04  17:27:26
winm23
2214188
sell
in/out
2
103620
2023.05.04  17:30:21
winm23
2215738
buy
in/out
4
103675
2023.05.05  09:03:28
winm23
2229482
buy
in
1
104175
2023.05.05  09:12:27
winm23
2236503
sell
out
1
104005
2023.05.05  09:19:18
winm23
2246014
sell
out
1
103970
2023.05.05 09:22:45
winm23
2250253
buy
in
1
103950
2023.05.05  16:00:10
winm23
2854029
sell
out
1
106375
2023.05.05  16:15:40
winm23
2864767
sell
out
1
106275
2023.05.05  16:59:41
winm23
2884590
sell
out
1
106555

Independientemente de las operaciones previas, el array Element tendrá un tamaño de cero en este punto, en el que tampoco hay posiciones abiertas. A las 09:42:05 del 04 de mayo de 2023 se produce una transacción de entrada del tipo compra (que ya se registra en el historial de la plataforma), de 1 lote, lo que activa de inmediato la función OnTrade(). Teniendo en cuenta que MetaTrader 5 se inició en el ordenador unos minutos antes (09:15 h), hubo tiempo suficiente para que la variable date se actualizara a 2023.05.04 09:15:00, y este valor se ha mantenido desde entonces. En OnTrade(), se recorrerá la lista de posiciones abiertas y, en el tipo de cuenta que estamos usando, solo se permite una posición por símbolo: en este caso, WINM23. La variable numberOfPositions toma el valor 1 y la variable positionID recibe el valor 1352975, que coincide con el ticket de la primera transacción, que a su vez es el número de la orden que la originó. La variable date ahora se actualiza con el tiempo de la transacción y las transacciones futuras, hasta la número 2193299, recibirán el mismo tiempo de la función Identifier().

TimeCurrent() para consultar el historial. En el bucle de repetición, dado que se detecta una entrada de tipo "IN", la función AddValue() se activa con los valores precio=104 035, volumen=1 y ticket=1352975. AddValue() no encontrará ese ticket en el array vacío, por lo que insertará una fila que contiene los tres valores pasados. La función ArrayPrint(Element) mostrará la matriz con esta fila en el terminal.

A continuación, se llama a la función PlotarRetangulos(), que almacena los tiempos de la vela actual y de la vela 15.ª anterior, y estos serán los parámetros para definir el tamaño de las líneas que se van a trazar. Con la función GetDigits() se determina el número de dígitos del tamaño del tick del símbolo (que en este caso es cero) y este valor se usa para componer la cadena que formará los nombres de los objetos junto con los precios obtenidos del array Element. Los objetos rectángulo y de texto se crean siempre que el volumen correspondiente al precio del array no sea nulo y siempre que los objetos aún no existan en el gráfico. Si el objeto ya existe, entonces se actualizan atributos como el color, el texto y la posición. Los rectángulos funcionan como líneas en la pantalla, ya que su altura es nula. En las etapas iniciales del proyecto, se optó por usar OBJ_RECTANGLE porque se previó la implementación de una función que eliminara todos los objetos de este tipo del gráfico. Aunque este mecanismo genérico de eliminación no se implementó, se mantuvo el uso de rectángulos con altura cero. Así, se procesa la línea correspondiente a la transacción de compra en 104035. Como el volumen asociado no es nulo y aún no existe un objeto llamado "104035text", se crean los objetos de texto y rectángulo asociados.

Un minuto después, se realiza una transacción de venta de dos lotes. Dado que ya había una posición de compra de un lote, esto configura una reversión, por lo que ahora hay una posición de venta de un lote. MetaTrader también añade esta transacción al historial de manera inmediata.  De forma análoga, el flujo se repite tal como en el procesamiento de la transacción anterior, hasta llegar al bucle del historial de órdenes. Nuevamente, la transacción con ticket = 1352975 es devuelta, ya que está dentro del período seleccionado, y se pasa a la función AddValue(). Esta función encuentra el valor del ticket en el único elemento presente hasta ese momento en el array y, por ello, sale de la función sin añadir un nuevo elemento. El siguiente elemento encontrado es del tipo INOUT y la única transacción anterior que ya está en el array tiene el elemento Element[0][1] almacenado en newVolume, que luego se define como cero.

El volumen registrado en la transacción se calcula como (HistoryDealGetDouble(ticket, DEAL_PRICE) - newVolume), es decir, newVolume = 2 - 1 = 1. Entonces, la función llama a AddValue(103900, 1, 135370). Supongo que a estas alturas ya estás comprendiendo bien el mecanismo. De forma similar, la función PlotarRetangulos() ejecuta nuevamente su código y el primer precio del array es 103900, ya que se ha realizado el ordenamiento ascendente con la función Sort(). Los objetos relacionados con este precio no existen en el gráfico, por lo que se crean. El segundo elemento del array, con precio 104035, ya tiene sus objetos dibujados en la pantalla, por lo que se actualizan sus atributos. El contenido del array Element hasta este momento es: {{103900, 1, 1356370}, {104035, 0, 1352975}}.

En la tercera línea todo se procesa de manera similar hasta que se encuentra la transacción de salida con un precio de 103 700, un volumen de 1 y un ticket de 2193299. Una transacción de salida llama a la función RemoveValue() con los parámetros recién encontrados. La función se cierra si encuentra un volumen nulo o una línea en el array con el mismo ticket. Como estas condiciones no se cumplen, RemoveValue() continúa buscando el precio que debe eliminar utilizando la función ArrayBsearch(). Se trata de una búsqueda binaria, y para realizarla es necesario que el array esté ordenado (condición que ya se cumplió previamente mediante el método Sort()). El índice más cercano al precio 103700 es el primero del array. El volumen de esta primera línea también es 1 y se reduce a cero, por lo que se activa la función RemoverRetangulo correspondiente. Esta acción elimina de la pantalla los objetos asociados al precio 103900. A continuación, la función AddValue() inserta en el array la línea {103700, 0, 219299}, que no sufrirá modificaciones por la función Sort(). Se cierra la posición.  El contenido del array Element hasta este momento es: {{103700, 0, 219299}, {103900, 0, 1356370}, {104035, 0, 1352975}}.

Con la posición completamente cerrada, la variable numberOfPositions se iguala a cero y, al ejecutar con éxito LimparRetângulos(), la variable isClean se establece en true. El array se redimensiona a cero elementos y la variable date recibe el tiempo actual. De este modo, no hay órdenes que retornar dentro del nuevo período definido. El sistema queda a la espera de una nueva transacción para continuar alimentando el array y procesar las acciones subsiguientes.  El contenido de Element se convierte en: { }. Volvemos a una situación similar a la descrita al inicio de este ejemplo, y el mismo razonamiento puede aplicarse para comprender el funcionamiento del indicador frente a las transacciones siguientes. La operación mencionada en el apartado "5. Ejemplo práctico de utilización" comienza en el precio 103690 del ejemplo actual. Si se siguen paso a paso las operaciones, se podrá entender el cuestionamiento planteado en ese primer ejemplo. Sin embargo, adelanto que la explicación está relacionada con los precios de las transacciones de salida y con la forma en que el algoritmo elimina secuencialmente las líneas cuyos precios se acercan más a los de las transacciones del tipo DEAL_ENTRY_OUT.


8. Integración con un Asesor Experto 

Hay dos maneras de utilizar indicadores personalizados como este en el simulador de estrategias. La primera consiste en compilar un Asesor Experto u otro indicador que active nuestro indicador personalizado. Basta con garantizar la presencia del archivo compilado "Plotagem de Entradas Parciais.ex5" dentro de la carpeta "Indicators" e insertar las siguientes líneas de código en la función OnInit() del programa que actuará como disparador. Recordemos declarar previamente la variable global handlePlotagemEntradasParciais del tipo int:

   iCustom(_Symbol,PERIOD_CURRENT,"Plotagem de Entradas Parciais");
//--- se o manipulador não é criado
   if(handlePlotagemEntradasParciais ==INVALID_HANDLE)
     {
      //--- mensagem sobre a falha e a saída do código de erro
      PrintFormat("Falha ao criar o manipulador do indicador para o símbolo %s/%s, código de erro %d",
                  _Symbol,
                  EnumToString(_Period),
                  GetLastError());
      //--- o indicador é interrompido precocemente
      return(INIT_FAILED);
     }

La otra forma evita editar estas líneas en el Asesor Experto y puede utilizarse preferentemente para realizar pruebas, dada su simplicidad. Consiste en cargar el indicador en el gráfico de forma convencional y guardar la plantilla con el nombre Tester.tpl (puede sobrescribirla si ya existe otra con el mismo nombre). Así, en cada prueba del Asesor Experto, el indicador también se cargará. Cabe señalar que este tipo de prueba solo tiene sentido si está activado el "modo visual con visualización de gráficos".


9. Conclusión

El indicador de representación de entradas parciales se creó para explorar nuevas posibilidades de diseño y uso de indicadores en el lenguaje MQL5 en una de las plataformas de trading más modernas y avanzadas: MetaTrader 5. 


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

Archivos adjuntos |
Del básico al intermedio: Variables (III) Del básico al intermedio: Variables (III)
Aquí veremos cómo utilizar las variables y constantes predefinidas por el lenguaje MQL5. Además, echaremos un vistazo a otro tipo especial de variable: las funciones. Saber trabajar de manera correcta con estas variables puede marcar la diferencia entre una aplicación que funciona y una que no. Para comprender lo que se expondrá aquí es necesario haber entendido lo visto en los artículos anteriores.
Desarrollo de un Asesor Experto (EA) en MQL5 basado en la estrategia de ruptura del rango de consolidación Desarrollo de un Asesor Experto (EA) en MQL5 basado en la estrategia de ruptura del rango de consolidación
Este artículo describe los pasos para crear un Asesor Experto (EA) que aproveche las rupturas de precios después de los períodos de consolidación. Al identificar rangos de consolidación y establecer niveles de ruptura, los operadores pueden automatizar sus decisiones comerciales basándose en esta estrategia. El Asesor Experto tiene como objetivo proporcionar puntos de entrada y salida claros y evitar rupturas falsas.
Del básico al intermedio: Operadores Del básico al intermedio: Operadores
En este artículo, exploraremos los operadores básicos. Aunque es un tema fácil de comprender, existen pequeños detalles que marcan una gran diferencia a la hora de incorporar expresiones matemáticas en formato de código. Sin comprender adecuadamente estos detalles, muchos programadores con poca o ninguna experiencia terminan abandonando su intento de crear sus propias soluciones.
Desarrollamos un asesor experto multidivisa (Parte 18): Automatización de la selección de grupos considerando el periodo forward Desarrollamos un asesor experto multidivisa (Parte 18): Automatización de la selección de grupos considerando el periodo forward
Seguimos automatizando los pasos que antes realizábamos manualmente. Esta vez regresaremos a la automatización de la segunda etapa, es decir, a la selección del grupo óptimo de instancias únicas de estrategias comerciales, complementándola con la posibilidad de considerar los resultados de las instancias en el periodo anterior.