English Русский 中文 Deutsch 日本語 Português
preview
Integración de MQL5 con paquetes de procesamiento de datos (Parte 2): Aprendizaje automático (Machine Learning, ML) y análisis predictivo

Integración de MQL5 con paquetes de procesamiento de datos (Parte 2): Aprendizaje automático (Machine Learning, ML) y análisis predictivo

MetaTrader 5Sistemas comerciales | 28 febrero 2025, 08:46
220 0
Hlomohang John Borotho
Hlomohang John Borotho

Introducción

En este artículo nos centramos específicamente en el aprendizaje automático (Machine Learning, ML) y el análisis predictivo. Los paquetes de procesamiento de datos abren nuevas fronteras para los operadores cuantitativos y los analistas financieros. Al incorporar capacidades de aprendizaje automático en MQL5, los operadores pueden elevar sus estrategias de negociación de sistemas tradicionales basados en reglas a sofisticados modelos basados en datos que se adaptan continuamente a la evolución de las condiciones del mercado.

El proceso implica el uso de las potentes bibliotecas de procesamiento de datos y aprendizaje automático de Python, como Scikit-learn, junto con MQL5. Esta integración permite a los operadores entrenar modelos predictivos a partir de datos históricos, comprobar su eficacia mediante técnicas de pruebas retrospectivas y, a continuación, desplegar esos modelos para tomar decisiones de negociación en tiempo real. La flexibilidad para combinar estas herramientas permite crear estrategias que van más allá de los indicadores técnicos típicos, incorporando análisis predictivos y reconocimiento de patrones que pueden mejorar significativamente los resultados de las operaciones.


Recopilación de datos históricos

Para empezar necesitamos datos históricos de MetaTrader 5 guardados en formato CSV, así que simplemente inicie su plataforma MetaTrader y en la parte superior de su panel MetaTrader 5 navegue a > Herramientas y luego > Opciones y llegará a las opciones de Gráficos. A continuación, deberá seleccionar la cantidad de barras del gráfico que desea descargar. Es mejor elegir la opción de barras ilimitadas ya que trabajaremos con fecha y no sabríamos cuántas barras hay en un periodo de tiempo determinado.

Herramientas > Opciones

Después tendrás que descargar los datos reales. Para ello tendrás que navegar a > Ver y luego a > Símbolos y aterrizarás en la pestaña Especificaciones simplemente navega a > Barras o Ticks dependiendo del tipo de datos que quieras descargar. Proceda e introduzca el periodo de fechas de inicio y fin de los datos históricos que desea descargar, después haga clic en el botón de solicitud para descargar los datos y guardarlos en formato CSV.

Barras a descargar

Después de todos estos pasos, habrá descargado con éxito los datos históricos de MetaTrader. Ahora necesitas descargar y configurar el entorno Jupyter Lab para el análisis. Para descargar y configurar Jupyter Lab puedes dirigirte a su página web oficial y seguir unos sencillos pasos para descargarlo. Dependiendo del tipo de sistema operativo que utilices, tendrás variedad de opciones de si instalar utilizando pip, conda o brew.


Procesar datos históricos de MetaTrader 5 en Jupyter Lab

Para cargar con éxito sus datos históricos de MetaTrader 5 en Jupyter Lab tendrá que conocer la carpeta que había seleccionado para descargar los datos, y luego en Jupyter Lab simplemente navegar a esa carpeta. Para empezar tendrá que cargar los datos e inspeccionar los nombres de las columnas. Tenemos que inspeccionar los nombres de las columnas para manejarlas correctamente y evitar errores que podrían surgir si utilizamos un nombre de columna incorrecto.

Código Python:

import pandas as pd

# assign variable to the historical data
file_path = '/home/int_junkie/Documents/ML/predi/XAUUSD.m_H1_201510010000_202408052300.csv'

data = pd.read_csv(file_path, delimiter='\t')

# Display the first few rows and column names
print(data.head())
print(data.columns)

Salida:

Salida de datos históricos

Estamos trabajando con datos históricos de MetaTrader 5 del año 2015 al 2024, es decir, aproximadamente 9 años de datos históricos. Este tipo de datos ayuda a capturar ciclos amplios del mercado. Es probable que el conjunto de datos capture diferentes fases del mercado, lo que permitirá una mejor comprensión y modelado de estos ciclos. Los conjuntos de datos más largos reducen la probabilidad de sobreajuste al proporcionar una gama más completa de escenarios.

Es más probable que un modelo entrenado en un conjunto de datos más amplio se generalice bien a datos no vistos, especialmente si el conjunto de datos corresponde a un período de tiempo menor, como H1. Esto es particularmente importante en el análisis de series de tiempo, donde tener más observaciones mejora la confiabilidad de los resultados. Por ejemplo, puede detectar tendencias seculares (direcciones del mercado a largo plazo) o efectos estacionales recurrentes que son relevantes para la previsión.

Gráfico de líneas a partir de datos históricos

data.plot.line(y = "<CLOSE>", x = "<DATE>", use_index = True)

Salida:

Gráfico de precios

Utilizamos el código anterior al visualizar datos de series de tiempo, como activos financieros a lo largo del tiempo. Si el índice de su marco de datos ya contiene fechas, puede omitir la especificación 'x="<DATE>"' y simplemente use 'use_index=True'.

del data["<VOL>"]
del data["<SPREAD>"]

Luego eliminamos las columnas especificadas de nuestros datos históricos, usamos la biblioteca pandas para eliminar estas columnas.

data.head()

Salida:

Marco de datos

De la salida anterior podemos ver que efectivamente se eliminaron las columnas especificadas.

# We add a colunm for tommorows price
data["<NexH>"] = data["<CLOSE>"].shift(-1)

1. 'data["<NexH>"]':

  • Esto añade una nueva columna llamada '<NexH>' (SIGUIENTE HORA) al marco de datos (Data-Frame) 'data'. El valor de esta columna representará los precios de cierre para la próxima hora en relación con cada fila.

2. 'data["<CLOSE>"].shift(-1)':

  • 'data["<CLOSE>"]' se refiere a la columna existente en el Data-Frame que contiene los precios de cierre de para cada fecha y hora.
  • El método '.shift(-1)' desplaza la fecha y hora de la columna '<CLOSE>' una fila hacia arriba (porque el argumento es '-1'), lo que efectivamente desplaza cada valor a la fila anterior.
  • Como resultado, el valor que originalmente correspondía a una fecha determinada ahora aparecerá en la fila correspondiente a la fecha anterior.

Salida:

Columna de la próxima hora

data["<TRGT>"] = (data["<NexH>"] > data["<CLOSE>"]).astype(int)

data

A continuación, utilizaremos el código anterior para crear una nueva columna en el Data-Frame '<data>' que contenga valores binarios (0 ó 1) que indiquen si el precio máximo del siguiente periodo (NexH) es mayor que el precio de cierre actual (<CLOSE>).

1. 'data["<TRGT>"]':

  • Esta es la nueva columna llamada '"<TRGT> "' (TARGET) en el marco de datos 'data'. Esta columna almacenará los valores objetivo binarios (0 o 1) según una condición.

2. '(data["<NexH>"] > data["<CLOSE>"])':

  • Esta expresión compara el valor de la columna '<NexH>' (precio máximo del período siguiente) con el valor de la columna '<CLOSE>' (precio de cierre actual) de cada fila.
  • Se trata de una serie booleana, donde cada valor es 'True' (si el siguiente máximo es mayor que el cierre actual) o 'False'.

3. '.astype(int)':

  • Esta función convierte los valores booleanos ('True' o 'False') en enteros ('1' o '0', respectivamente).
  • 'True' se convierte en “1” y 'Falso' en “0”.

Salida:

Objetivo (Target)

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators = 50, min_samples_split = 50, random_state = 1)

train = data.iloc[:-50]
test = data.iloc[-50:]

predictors = ["<CLOSE>","<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
model.fit(train[predictors], train["<TRGT>"])

Salida:

Random Forest

1. Importación del clasificador Random Forest

  • El 'Random-Forest-Classifier' es un modelo de aprendizaje automático ensamblado que crea múltiples árboles de decisión y fusiona sus resultados para mejorar la precisión predictiva y controlar el sobreajuste.

2. Inicialización del modelo:

  • 'estimator' especifica el número de árboles de decisión en el bosque. En este caso, el modelo construirá 50 árboles.
  • 'min_sample_split' establece el mínimo de muestras necesarias para dividir un nodo interno. Un valor más alto reduce el sobreajuste al garantizar que las divisiones solo ocurran cuando haya suficientes datos disponibles.
  • 'random_state' corrige la semilla aleatoria para garantizar la reproducibilidad insegura de los resultados. Usar la misma semilla (por ejemplo, '1') producirá los mismos resultados cada vez que se ejecute el código.

3. División de los datos en conjuntos de entrenamiento y prueba:

  • 'data.iloc[:-50]' selecciona todas las filas excepto las últimas 50 como datos de entrenamiento.
  • 'data.iloc[-50:]' selecciona las últimas 50 filas como datos de prueba
  • Esta división se utiliza comúnmente en datos de series de tiempo, donde el modelo se entrena con datos históricos y se prueba con los datos más recientes para evaluar el rendimiento en predicciones futuras.

4. Especificación de las variables predictoras:

  • La lista 'predictors' contiene los nombres de las columnas que representan las características utilizadas por el modelo para realizar predicciones. Entre ellos se incluyen (''«<CLOSE>», '«<TICKVOL>»', '«<OPEN>»', '«<HIGH>»', y '«<LOW>»').

El código prepara un clasificador Random Forest para predecir el comportamiento futuro del mercado a partir de datos pasados. El modelo se entrena utilizando características como precio de cierre, volumen de ticks y otras. Después de dividir los datos en conjuntos de entrenamiento y prueba, el modelo se ajusta a los datos de entrenamiento, aprendiendo de los patrones históricos para hacer predicciones futuras.

Medir la precisión del modelo

from sklearn.metrics import precision_score

prcsn = model.predict(test[predictors])

Importamos la función 'precision-score' del módulo 'sklearn.metrics'. La puntuación de precisión es una métrica utilizada para evaluar modelos de clasificación, particularmente útil cuando las clases están desequilibradas. Mide cuántos de los resultados positivos previstos son realmente positivos. Una alta precisión indica tasas positivas bajas.

Ecuación de precisión

prcsn = pd.Series(prcsn, index = test.index)

Luego convertimos las predicciones ('prcsn') en una 'Series' de Pandas mientras preservamos el índice del conjunto de datos de prueba.

precision_score(test["<TRGT>"], prcsn)

Obtenemos la precisión de las predicciones del modelo comparando los valores objetivo reales en el conjunto de prueba con los valores previstos.

Salida:

Puntuación de predicción

cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)

cmbnd.plot()

Combinamos los valores objetivo reales y los valores previstos del modelo en un único marco de datos para facilitar el análisis.

Salida:

Trazado vs. real

def predors(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict(test[predictors])
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

Esta función toma un conjunto de datos de entrenamiento y prueba, una lista de variables predictoras y un modelo de aprendizaje automático. La función entrena el modelo con los datos de entrenamiento, hace predicciones sobre los datos de prueba y devuelve un marco de datos que contiene los valores objetivo reales y los valores predichos uno al lado del otro.

def backtestor(data, model, predictors, start = 2500, step = 250):
    all_predictions = []

    for i in range(start, data.shape[0], step):
        train = data.iloc[0:i].copy()
        test = data.iloc[i:(i + step)].copy()
        predictions = predors(train, test, predictors, model)
        all_predictions.append(predictions)
    return pd.concat(all_predictions)

Esta función realiza una prueba retrospectiva en un conjunto de datos de series temporales utilizando un modelo de aprendizaje automático. La prueba retrospectiva evalúa el rendimiento del modelo simulando predicciones como si se hicieran en un entorno comercial del mundo real, donde los datos se revelan gradualmente con el tiempo.

predictions = backtestor(data, model, predictors)

Ejecuta la función 'backtestor' utilizando el conjunto de datos especificado ('data'), el modelo de aprendizaje automático ('model') y las variables predictoras ('predictors'). Realiza una prueba retrospectiva y las predicciones resultantes se almacenan en la variable 'predicitions'.

predictions["Predictions"].value_counts()

Contamos el número de apariciones de cada valor único en la columna «Predictions» del marco de datos «prediction».

Salida:

Predicciones

precision_score(predictions["<TRGT>"], predictions["Predictions"])

Calcula la precisión de la predicción del modelo. La precisión es una métrica que mide la exactitud de las predicciones positivas.

Salida:

P_score

Precision Eq

predictions["<TRGT>"].value_counts() / predictions.shape[0]

Calcula la proporción de cada valor único en la columna '<TRGT>' en relación con el número total de predicciones.

Salida:

Proporción

horizons = [2, 5, 55, 125, 750]
new_predictors = []

# Ensure only numeric columns are used for rolling calculations
numeric_columns = data.select_dtypes(include=[float, int]).columns

for i in horizons:
    # Calculate rolling averages for numeric columns only
    rolling_averages = data[numeric_columns].rolling(i).mean()
    
    # Generate the ratio column
    ratio_column = f"Close_Ratio_{i}"
    data[ratio_column] = data["<CLOSE>"] / rolling_averages["<CLOSE>"]
    
    # Generate the trend column
    trend_column = f"Trend_{i}"
    data[trend_column] = data["<TRGT>"].shift(1).rolling(i).sum()
    
    new_predictors += [ratio_column, trend_column]
data

Genera nuevas funciones basadas en promedios móviles y tendencias en diferentes horizontes temporales. Los predictores adicionales ayudan a mejorar el rendimiento de los modelos al proporcionarles más información sobre el mercado durante períodos variables.

Salida:

Nuevas columnas de predicción

data = data.dropna()

Eliminamos cualquier fila del Data-Frame con valores faltantes.

def predict(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict_proba(test[predictors])[:1]
    prcsn[prcsn >= .6] = 1
    prcsn[prcsn < .6] = 0
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

El modelo se entrena en el conjunto de datos de entrenamiento utilizando los predictores seleccionados y la variable objetivo. Para el umbral y las predicciones, aplicamos un umbral personalizado de 0,6. Si la probabilidad de la clase 1 es 0,6 o superior, el modelo predice "1". De lo contrario, predice "0". Este ajuste permite que el modelo sea más conservador, requiriendo una mayor confianza antes de señalar una operación.

predictions = backtestor(data, model, new_predictors)
predictions["Predictions"].value_counts()
precision_score(predictions["<TRGT>"], predictions["Predictions"])

Salida:

Segunda puntuación de precisión

Nuestra puntuación de precisión aumentó ligeramente, 0,52 si redondeamos hacia arriba.


Entrena el modelo y expórtalo a ONNX

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import onnx
import skl2onnx
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

# Load and preprocess your data (example)
# Replace this with your actual data loading process
#data = pd.read_csv('your_data.csv')  # Replace with your actual data source
#data = data.dropna()

# Define predictors and target
predictors = ["<CLOSE>", "<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
target = "<TRGT>"

# Split data into train and test sets
train, test = train_test_split(data, test_size=0.2, shuffle=False)

# Define and train the model
model = RandomForestClassifier(n_estimators=50, min_samples_split=50, random_state=1)
model.fit(train[predictors], train[target])

# Export the trained model to ONNX format
initial_type = [('float_input', FloatTensorType([None, len(predictors)]))]
onnx_model = convert_sklearn(model, initial_types=initial_type)

# Save the ONNX model to a file
with open("random_forest_model.onnx", "wb") as f:
    f.write(onnx_model.SerializeToString())

Entrenamos nuestro modelo, y lo convertimos, exportamos y guardamos en formato ONNX usando `skl2onnx`. Copiamos nuestro modelo guardado en la carpeta 'Files' de MQL5 donde podremos acceder a él.

Modelo guardado



Poniéndolo todo junto en MQL5

Cargue el modelo en Oninit().

#include <Trade/Trade.mqh>
#define   ModelName          "RandomForestClassifier"
#define   ONNXFilename       "random_forest_model.onnx"

// Single ONNX model resource
#resource "\\Files\\random_forest_model.onnx" as const uchar ExtModelDouble[];

input double lotsize = 0.1;     // Trade lot size
input double stoploss = 20;     // Stop loss in points
input double takeprofit = 50;   // Take profit in points

// Trading functions
CTrade m_trade;

Las variables 'includes' y globales en el ámbito global. También especificamos que el modelo ONNX está integrado en MQL5 como un recurso binario. El '#resource' se utiliza para incluir archivos externos.

//+------------------------------------------------------------------+
//| Run classification using double values                           |
//+------------------------------------------------------------------+
bool RunModel(long model, vector &input_vector, vector &output_vector)
{
    ulong batch_size = input_vector.Size() / 5; // Assuming 5 input features
    if (batch_size == 0)
        return (false);

    output_vector.Resize((int)batch_size);

    // Prepare input tensor
    double input_data[];
    ArrayResize(input_data, input_vector.Size());

    for (int k = 0; k < input_vector.Size(); k++)
        input_data[k] = input_vector[k];

    // Set input shape
    ulong input_shape[] = {batch_size, 5}; // 5 input features for each prediction
    OnnxSetInputShape(model, 0, input_shape);

    // Prepare output tensor
    double output_data[];
    ArrayResize(output_data, (int)batch_size);

    // Set output shape (binary classification)
    ulong output_shape[] = {batch_size, 2}; // Output shape for probability (0 or 1)
    OnnxSetOutputShape(model, 0, output_shape);

    // Run the model
    bool res = OnnxRun(model, ONNX_DEBUG_LOGS, input_data, output_data);

    if (res)
    {
        // Copy output to vector (only keeping the class with highest probability)
        for (int k = 0; k < batch_size; k++)
            output_vector[k] = (output_data[2 * k] < output_data[2 * k + 1]) ? 1.0 : 0.0;
    }

    return (res);
}

Esta función 'RunModel' es un modelo ONNX que hemos entrenado para realizar clasificaciones binarias. La función determina la clase prevista (0 o 1) en función de qué clase tiene la mayor probabilidad y almacena los resultados en un vector de salida.

//+------------------------------------------------------------------+
//| Generate input data for prediction                               |
//+------------------------------------------------------------------+
vector input_data()
{
    vector input_vector;
    MqlRates rates[];

    // Get the last 5 bars of data
    if (CopyRates(Symbol(), PERIOD_H1, 5, 1, rates) > 0)
    {
        input_vector.Resize(5 * 5); // 5 input features for each bar

        for (int i = 0; i < 5; i++)
        {
            input_vector[i * 5] = rates[i].open;
            input_vector[i * 5 + 1] = rates[i].high;
            input_vector[i * 5 + 2] = rates[i].low;
            input_vector[i * 5 + 3] = rates[i].close;
            input_vector[i * 5 + 4] = rates[i].tick_volume;
        }
    }

    return (input_vector);
}

//+------------------------------------------------------------------+
//| Check if there is a new bar                                      |
//+------------------------------------------------------------------+
bool NewBar()
{
    static datetime last_time = 0;
    datetime current_time = iTime(Symbol(), Period(), 0);

    if (current_time != last_time)
    {
        last_time = current_time;
        return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Check if a position of a certain type exists                     |
//+------------------------------------------------------------------+
bool PosExists(int type)
{
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionGetInteger(POSITION_TYPE) == type && PositionGetString(POSITION_SYMBOL) == Symbol())
            return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Script program initialization                                    |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Initializing ONNX model...");

    // Initialize the ONNX model
    long model = OnnxCreateFromBuffer(ExtModelDouble, ONNX_DEFAULT);
    if (model == INVALID_HANDLE)
    {
        Print("Error loading ONNX model: ", GetLastError());
        return INIT_FAILED;
    }

    // Store the model handle for further use
    GlobalVariableSet("model_handle", model);
    return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    if (NewBar()) // Trade at the opening of a new candle
    {
        vector input_vector = input_data();
        vector output_vector;

        // Retrieve the model handle
        long model = GlobalVariableGet("model_handle");
        if (model == INVALID_HANDLE)
        {
            Print("Invalid model handle.");
            return;
        }

        bool prediction_success = RunModel(model, input_vector, output_vector);
        if (!prediction_success || output_vector.Size() == 0)
        {
            Print("Prediction failed.");
            return;
        }

        long signal = output_vector[0]; // The predicted class (0 or 1)

        MqlTick ticks;
        if (!SymbolInfoTick(Symbol(), ticks))
            return;

        if (signal == 1) // Bullish signal
        {
            if (!PosExists(POSITION_TYPE_BUY)) // No buy positions exist
            {
                if (!m_trade.Buy(lotsize, Symbol(), ticks.ask, ticks.bid - stoploss * Point(), ticks.ask + takeprofit * Point())) // Open a buy trade
                    Print("Failed to open a buy position, error = ", GetLastError());
            }
        }
        else if (signal == 0) // Bearish signal
        {
            if (!PosExists(POSITION_TYPE_SELL)) // No sell positions exist
            {
                if (!m_trade.Sell(lotsize, Symbol(), ticks.bid, ticks.ask + stoploss * Point(), ticks.bid - takeprofit * Point())) // Open a sell trade
                    Print("Failed to open a sell position, error = ", GetLastError());
            }
        }
    }
}

//+------------------------------------------------------------------+
//| Script program deinitialization                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Release the ONNX model
    long model = GlobalVariableGet("model_handle");
    if (model != INVALID_HANDLE)
    {
        OnnxRelease(model);
    }
}
Durante la inicialización, se carga el modelo y se almacena su identificador para su uso posterior. En la función 'OnTick()', el script ejecuta el modelo cuando se detecta una nueva barra. Utilizamos la predicción del modelo (0 para bajista y 1 para alcista) y ejecutamos operaciones en consecuencia. Las operaciones de compra se realizan cuando el modelo predice una tendencia alcista, mientras que las operaciones de venta se realizan cuando una tendencia bajista.



Conclusión

En resumen, hemos utilizado un paquete de procesamiento de datos (Jupyter Lab) para procesar datos históricos, desarrollado y entrenado el modelo usando aprendizaje automático para poder hacer predicciones. Hemos explorado los pasos cruciales que son necesarios para una integración y un funcionamiento perfectos. Luego nos centramos en cargar y gestionar el modelo dentro de MQL5 incorporándolo como un recurso y garantizando que el modelo esté correctamente inicializado y disponible durante el tiempo de ejecución.

En conclusión, hemos integrado un modelo ONNX en un entorno comercial MQL5 para mejorar la toma de decisiones mediante el aprendizaje automático. El proceso comenzó con la carga del modelo en el entorno MQL5. Luego configuramos el Asesor Experto para recopilar datos relevantes del mercado, preprocesarlos en vectores de características y alimentarlos al modelo para realizar predicciones. La lógica fue diseñada para ejecutar transacciones basadas en el resultado del modelo. Las posiciones solo se abren cuando se detecta una nueva barra y no hay operaciones conflictivas activas. Además, el sistema gestiona la comprobación de posiciones, la gestión de errores y la desasignación de recursos para garantizar una solución comercial sólida y eficiente. Esta implementación demuestra una combinación perfecta de análisis financiero y conocimientos impulsados por inteligencia artificial, lo que permite estrategias comerciales automatizadas que se adaptan a las condiciones del mercado en tiempo real.


Referencias

Manual de referencia de MQL5 > Modelos ONNX > Creación de un modelo


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15578

Redes neuronales en el trading: Inyección de información global en canales independientes (InjectTST) Redes neuronales en el trading: Inyección de información global en canales independientes (InjectTST)
La mayoría de los métodos modernos de pronóstico de series temporales multimodales utilizan el enfoque de canales independientes. Esto ignora la dependencia natural de los diferentes canales de la misma serie temporal. Un uso coherente de ambos enfoques (canales independientes y mixtos) es la clave para mejorar el rendimiento de los modelos.
Algoritmo de colmena artificial — Artificial Bee Hive Algorithm (ABHA): Teoría y métodos Algoritmo de colmena artificial — Artificial Bee Hive Algorithm (ABHA): Teoría y métodos
En este artículo nos familiarizaremos con el algoritmo de colmena artificial (ABHA), desarrollado en 2009. El algoritmo está orientado a la resolución de problemas de optimización continua. Veremos cómo el ABHA se inspira en el comportamiento de una colonia de abejas, donde cada abeja tiene un papel único que les ayuda a encontrar recursos de forma más eficiente.
Algoritmo de colmena artificial — Artificial Bee Hive Algorithm (ABHA): Pruebas y resultados Algoritmo de colmena artificial — Artificial Bee Hive Algorithm (ABHA): Pruebas y resultados
En este artículo, continuaremos analizando el algoritmo de colmena artificial ABHA profundizando en la codificación y observando los métodos restantes. Recordemos que cada abeja en el modelo está representada como un agente individual cuyo comportamiento dependerá de información interna y externa, así como del estado motivacional. Probaremos el algoritmo con varias funciones y resumiremos los resultados presentándolos en una tabla de calificación.
Gestión de Riesgo (parte 3): Construyendo la Clase Principal para la Gestión de Riesgo Gestión de Riesgo (parte 3): Construyendo la Clase Principal para la Gestión de Riesgo
En este artículo daremos inicio a la creación de la clase principal de gestión de riesgo, la cual será fundamental para administrar el riesgo en el sistema. Nos enfocaremos en construir las bases, definiendo estructuras, variables y funciones esenciales. Además, implementaremos los métodos necesarios para asignar valores a las pérdidas y ganancias máximas, estableciendo así los cimientos de esta gestión.