English Русский 中文 Deutsch 日本語 Português
preview
Integración de modelos ML con el simulador de estrategias (Conclusión): Implementación de un modelo de regresión para la predicción de precios

Integración de modelos ML con el simulador de estrategias (Conclusión): Implementación de un modelo de regresión para la predicción de precios

MetaTrader 5Ejemplos | 27 febrero 2024, 09:36
197 0
Jonathan Pereira
Jonathan Pereira

Introducción:

En el artículo anterior, finalizamos la implementación de la clase de gestión de archivos CSV para almacenar y recuperar datos relacionados con el mercado financiero. Con la infraestructura lista, estamos aptos para utilizar esos datos para alimentar y entrenar un modelo de aprendizaje automático.

En este artículo, nuestro objetivo es implementar un modelo de regresión que sea capaz de predecir el cierre del precio de un activo financiero en la semana. Esta predicción nos permitirá analizar el comportamiento del mercado y tomar decisiones informadas al negociar activos financieros.

La predicción de precios puede ser una herramienta útil para desarrollar estrategias de tráding y tomar decisiones en el mercado financiero. La capacidad de predecir tendencias de precios con precisión puede llevar a mejores decisiones de inversión, maximizando los beneficios y minimizando las pérdidas. Además, la predicción de precios puede ayudar en la identificación de oportunidades de tráding y en la gestión de riesgos.

Para implementar nuestro modelo de regresión, seguiremos los pasos a continuación:

  1. Recopilar y preparar los datos: utilizaremos script Python para recuperar información sobre precios históricos y otros datos relevantes. Estos datos serán utilizados para entrenar y probar nuestro modelo de regresión.

  2. Seleccionar y entrenar el modelo: elegiremos un modelo de regresión adecuado para nuestro problema y lo entrenaremos usando los datos recopilados. Existen diversos modelos de regresión disponibles, como la regresión lineal, regresión polinomial y regresión de soporte vectorial (SVR). La elección del modelo dependerá de su idoneidad para nuestro problema y del desempeño obtenido durante el entrenamiento.

  3. Evaluar el desempeño del modelo: para asegurar que nuestro modelo de regresión está funcionando correctamente, es necesario evaluar su desempeño en un conjunto de pruebas. Esta evaluación nos ayudará a identificar posibles problemas y ajustar el modelo, si es necesario.

Al final de este artículo, tendremos un modelo de regresión capaz de prever el cierre del precio de un activo financiero en la semana. Esta predicción nos permitirá desarrollar estrategias de tráding más eficientes y tomar decisiones informadas en el mercado financiero.


Sección 1: Selección del modelo de regresión

Antes de implementar nuestro modelo de regresión para predecir el cierre del precio de un activo financiero en la semana, es fundamental entender los diferentes tipos de modelos de regresión disponibles y sus características. Esto nos permitirá seleccionar el modelo más apto para nuestro problema. En esta sección, discutiremos algunos de los modelos de regresión más comunes utilizados para regresión:

  1. Regresión lineal: La regresión lineal es uno de los modelos de regresión más simples y ampliamente utilizados. Asume una relación lineal entre las variables independientes y la variable dependiente. El objetivo de la regresión lineal es encontrar la línea recta que mejor se ajuste a los datos, minimizando la suma de los errores cuadráticos. Aunque es fácil de entender e implementar, la regresión lineal puede no ser adecuada para problemas donde la relación entre las variables no es lineal.

  2. Regresión polinomial: La regresión polinomial es una extensión de la regresión lineal que tiene en cuenta las relaciones no lineales entre las variables. Utiliza polinomios de diferentes grados para ajustar la curva a los datos. La regresión polinomial puede proporcionar una mejor aproximación para problemas más complejos; sin embargo, es importante evitar el sobreajuste, que ocurre cuando el modelo se ajusta demasiado a los datos de entrenamiento, comprometiendo la capacidad de generalizar a datos no vistos.

  3. Regresión de árboles de decisión: La regresión de árboles de decisión es un modelo basado en árboles que divide el espacio de características en regiones distintas y no solapadas. En cada región, la predicción se hace con base en la media de los valores observados. La regresión de árboles de decisión es capaz de capturar relaciones complejas y no lineales entre variables, pero puede ser propensa al sobreajuste, especialmente si el árbol crece mucho. Técnicas de poda y validación cruzada pueden utilizarse para combatir el sobreajuste.

  4. Regresión de soporte vectorial (SVR): La regresión de soporte vectorial es una extensión del algoritmo de máquinas de soporte vectorial (SVM) para problemas de regresión. El SVR intenta encontrar la función que mejor se ajusta a los datos, manteniendo la máxima margen entre la función y los puntos de entrenamiento. El SVR es capaz de modelar relaciones no lineales y complejas, utilizando funciones de kernel, como la función de base radial (RBF). No obstante, el entrenamiento de un SVR puede ser computacionalmente más intensivo que otros modelos de regresión.

Para seleccionar el modelo de regresión más adecuado para predecir el cierre del precio de un activo financiero en la semana, es importante considerar la complejidad del problema y la relación entre las variables. Además, se debe tener en cuenta el equilibrio entre el desempeño del modelo y la complejidad computacional. En general, se recomienda experimentar con diferentes modelos y ajustar sus parámetros para obtener el mejor desempeño posible.

Al seleccionar un modelo de regresión, es importante considerar diversos criterios que influencian la calidad y la aplicabilidad del modelo. En esta sección, discutiremos los principales criterios a tener en cuenta durante la selección del modelo de regresión:

  1. Desempeño: El desempeño de un modelo de regresión es fundamental para asegurar predicciones precisas y útiles. Podemos evaluar el desempeño utilizando métricas como el error cuadrático medio (MSE) y el error absoluto medio (MAE), entre otras. Al comparar diferentes modelos, es importante seleccionar aquel que presenta el mejor desempeño en relación con estas métricas.

  2. Interpretabilidad: La interpretabilidad de un modelo es la capacidad de entender la relación entre las variables y cómo afectan a la predicción. Modelos más simples, como la regresión lineal, son generalmente más fáciles de interpretar que modelos más complejos, como las redes neuronales. La interpretabilidad es especialmente importante cuando se desea explicar las predicciones a otras personas o cuando se busca entender los factores que influencian los resultados.

  3. Complejidad: La complejidad de un modelo de regresión está relacionada al número de parámetros y a la estructura del modelo. Modelos más complejos pueden ser capaces de capturar relaciones más sutiles y no lineales en los datos, pero también pueden ser más propensos al sobreajuste. Es importante equilibrar la complejidad del modelo con la capacidad de generalización para datos no vistos.

  4. Tiempo de entrenamiento: El tiempo de entrenamiento es un aspecto importante a considerar, especialmente cuando se trabaja con grandes conjuntos de datos o cuando se desea entrenar modelos iterativamente. Modelos más simples, como la regresión lineal y polinomial, generalmente requieren menos tiempo de entrenamiento que modelos más complejos, como las redes neuronales o regresión de soporte vectorial. Es crucial encontrar un equilibrio entre el desempeño del modelo y el tiempo de entrenamiento para asegurar que el modelo sea aplicable a tiempo.

  5. Robustez: La robustez de un modelo de regresión se refiere a su capacidad para manejar valores atípicos y ruidos en los datos. Modelos robustos son menos sensibles a pequeñas variaciones en los datos y pueden proporcionar predicciones más estables. Es importante seleccionar un modelo que sea capaz de manejar la presencia de valores atípicos y ruidos en los datos.

Al seleccionar el modelo de regresión más adecuado para predecir el cierre del precio, es importante ponderar estos criterios y encontrar el equilibrio adecuado entre ellos. Experimentar con diferentes modelos y ajustar sus parámetros para optimizar el desempeño es una estrategia recomendada para asegurar la elección del mejor modelo para el problema en cuestión.

Basándonos en los criterios mencionados anteriormente, optamos por utilizar el modelo de regresión de árboles de decisión (Decision Tree Regression) para predecir el cierre del precio. La elección de este modelo se justifica por los siguientes motivos:

  1. Desempeño: Las árboles de decisión generalmente presentan buen desempeño en problemas de regresión, siendo capaces de capturar relaciones no lineales e interacciones entre variables. Al ajustar correctamente los hiperparámetros del modelo, como la profundidad del árbol y el número mínimo de muestras por hoja, podemos obtener un equilibrio entre ajuste y generalización.

  2. Interpretabilidad: Una de las ventajas de los árboles de decisión es su interpretabilidad. Los árboles de decisión representan una serie de decisiones basadas en atributos y sus valores, haciéndolos fáciles de entender y explicar. Esto es útil para justificar las predicciones y entender los factores que influencian el cierre del precio.

  3. Complejidad: La complejidad de los árboles de decisión puede ser controlada ajustando los hiperparámetros del modelo. Esto permite encontrar un equilibrio entre la capacidad de modelar relaciones complejas y la simplicidad del modelo, evitando el sobreajuste.

  4. Tiempo de entrenamiento: Las árboles de decisión generalmente tienen tiempos de entrenamiento relativamente rápidos en comparación con otros modelos más complejos, como redes neuronales o máquinas de soporte vectorial. Esto hace que el modelo de regresión de árboles de decisión sea adecuado para casos en los que el tiempo de entrenamiento es un factor relevante.

  5. Robustez: Los árboles de decisión son robustos a ruidos y valores atípicos en los datos, ya que cada decisión se basa en un conjunto de muestras y no en una única observación. Esto contribuye a la estabilidad de las predicciones y la confiabilidad del modelo.

Considerando los criterios discutidos y las ventajas ofrecidas por la regresión de árboles de decisión, creo que este modelo de ejemplo es una elección adecuada para predecir el cierre del precio semanal. Sin embargo, es importante recordar que la selección de modelos puede variar de acuerdo con el contexto y los requisitos específicos de cada problema. Experimentar y comparar diferentes modelos de regresión puede ser útil para asegurar la elección del modelo más apropiado.


Sección 2: Preparación de los datos

La preparación y limpieza de los datos son etapas cruciales en el proceso de implementación de un modelo de regresión, ya que la calidad de los datos de entrada tiene un impacto directo en la eficacia y el desempeño del modelo. Estas etapas son fundamentales por los siguientes motivos:

  1. Eliminación de ruidos y valores atípicos: Los datos brutos pueden contener ruidos, errores y valores atípicos que pueden afectar adversamente el rendimiento del modelo. Al identificar y tratar estas discrepancias, es posible mejorar la calidad de los datos y, consecuentemente, la precisión de las predicciones.

  2. Relleno y eliminación de valores ausentes: Los datos incompletos son comunes en conjuntos de datos, y la ausencia de valores puede llevar a un rendimiento insatisfactorio del modelo. Imputar valores ausentes, eliminar registros con datos faltantes o utilizar técnicas específicas para tratar con datos faltantes son esenciales para garantizar la integridad y fiabilidad de los datos. La elección entre imputación y eliminación de valores ausentes dependerá de la naturaleza de los datos, la cantidad de valores ausentes y el impacto potencial de esos valores en el rendimiento del modelo. Es importante analizar cuidadosamente cada situación y elegir el enfoque más adecuado para el problema en cuestión.

  3. Selección de variables: No todas las variables disponibles en un conjunto de datos pueden ser relevantes o útiles para la predicción del cierre del precio. La selección adecuada de las variables permite que el modelo se concentre en las características más relevantes, mejorando el rendimiento y reduciendo la complejidad del modelo.

  4. Transformación de datos: A veces, los datos brutos necesitan ser transformados para adecuarse a las suposiciones del modelo de regresión o para mejorar la relación entre las variables independientes y la variable dependiente. Ejemplos de transformaciones incluyen la normalización, estandarización y aplicación de funciones matemáticas, como el logaritmo o la raíz cuadrada.

  5. División de los datos: Es importante dividir el conjunto de datos en subconjuntos de entrenamiento y prueba para evaluar adecuadamente el rendimiento del modelo de regresión. Esta división permite entrenar el modelo con un subconjunto de datos y probar su capacidad para generalizar a datos no vistos, proporcionando una estimación del rendimiento del modelo en situaciones reales.

Dedicar tiempo y esfuerzo para la preparación y limpieza de los datos es una etapa vital en el proceso de implementación de un modelo de regresión, pues asegura que el modelo sea entrenado y evaluado con base en información de calidad, maximizando su eficacia y utilidad en la predicción del cierre del precio.

Haré un ejemplo básico de preparación de datos para un modelo de regresión utilizando Python. Sin embargo, es fundamental enfatizar la importancia de profundizar sus conocimientos sobre este tema, pues cada conjunto de datos y problema pueden requerir enfoques y técnicas específicas de limpieza y preparación. Por lo tanto, es altamente recomendable que inviertas tiempo en estudiar y entender los diferentes métodos y técnicas involucrados en la preparación de datos.

Para recoger los datos usaremos la función get_rates_between que fue construida para facilitar la recolección de datos financieros de un activo específico en un determinado período. Ella utiliza la biblioteca MetaTrader 5 (mt5) para conectarse a una plataforma de tráding y obtener informaciones históricas de precio en diferentes intervalos de tiempo.

La función tiene los siguientes parámetros:

  • symbol: una string que representa el símbolo del activo financiero (por ejemplo, "PETR3", "EURUSD").
  • period: un entero que indica el período de tiempo de los datos a ser recogidos (por ejemplo, mt5.TIMEFRAME_W1 para datos semanales).
  • ini: un objeto datetime que representa la fecha y hora iniciales del intervalo de tiempo para recoger los datos.
  • end: un objeto datetime que representa la fecha y hora finales del intervalo de tiempo para recoger los datos.

La función comienza verificando si MetaTrader 5 ha sido inicializado correctamente. Si la inicialización falla, la función devuelve una excepción y termina el programa.

A continuación, la función utiliza la función mt5.copy_rates_range() para obtener los datos financieros del activo y período especificados. Los datos son almacenados en un objeto DataFrame de pandas, que es una estructura de datos bidimensional etiquetada con ejes, adecuada para almacenar datos financieros.

Después de obtener los datos, la función verifica si el DataFrame está vacío. Si está vacío, la función devuelve una excepción, ya que esto indica un error al recoger los datos.

Si todo va bien, la función convierte la columna 'time' del DataFrame a un formato legible de fecha y hora, utilizando la función pd.to_datetime(). La columna 'time' es entonces definida como el índice del DataFrame, lo que facilita el acceso y la manipulación de los datos.

def get_rates_between(symbol:str, period : int, ini : datetime, end : datetime):
    if not mt5.initialize():
        print("initialize() failed")
        mt5.shutdown()
        raise Exception("Error Getting Data")

    rates = mt5.copy_rates_range(symbol, period, ini, end)
    mt5.shutdown()
    rates = pd.DataFrame(rates)

    if rates.empty:
        raise Exception("Error Getting Data")

    rates['time'] = pd.to_datetime(rates['time'], unit='s')
    rates.set_index(['time'], inplace=True)

    return rates

En este ejemplo, estaremos utilizando datos financieros para el par de divisas EUR/USD en el período semanal, abarcando desde el 1 de enero de 2000 hasta el 31 de diciembre de 2022. Para ello, utilizaremos la función get_rates_between. Primero, importa las bibliotecas necesarias:

import pandas as pd
from datetime import datetime, timezone
import MetaTrader5 as mt5
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split

A continuación, define la información del activo financiero que deseas analizar:

symbol = "EURUSD"
date_ini = datetime(2000, 1, 1, tzinfo=timezone.utc)
date_end = datetime(2022, 12, 31, tzinfo=timezone.utc)
period = mt5.TIMEFRAME_W1

Ahora, puedes llamar a la función get_rates_between usando la información definida anteriormente:

df = get_rates_between(symbol=symbol, period=period, ini=date_ini, end=date_end)

Tras obtener los datos, el próximo paso es preparar esos datos para el desarrollo de un modelo de aprendizaje automático. Esta preparación incluye la eliminación de ruidos y valores atípicos, selección de variables, transformación de datos y división de los datos en conjuntos de entrenamiento y prueba. Vamos detallar cada etapa.

Eliminación de ruidos y valores atípicos:

El primer paso es eliminar ruidos y valores atípicos de los datos. Los ruidos son variaciones aleatorias e indeseadas en los datos que pueden dificultar la identificación de patrones. Los valores atípicos son valores que difieren significativamente de los otros valores del conjunto de datos. Ambos pueden perjudicar el rendimiento del modelo.

Existen varias técnicas para eliminar ruidos y valores atípicos. En este artículo, usaremos la técnica de suavizado exponencial, que asigna un peso exponencialmente decreciente a los datos más recientes, ayudando a suavizar las variaciones. Para ello, utilizaremos la función ewm de pandas.

smoothed_df = df.ewm(alpha=0.1).mean()
Es importante resaltar que existen diversas técnicas para tratar con ruidos y valores atípicos en los datos, y el enfoque de suavizado exponencial utilizado en este artículo es solo uno de ellos. La elección de esta técnica se hizo con el objetivo de simplificar el ejemplo y demostrar un método de tratamiento de los datos. Sin embargo, en escenarios reales, es recomendable explorar y evaluar varias técnicas de eliminación de ruidos y valores atípicos, con el fin de encontrar el enfoque más adecuado para su conjunto de datos y problema específico. Algunas otras técnicas populares incluyen la filtración de media móvil, la eliminación basada en percentiles y técnicas de clustering.


Selección de variables

El siguiente paso es seleccionar las variables que se utilizarán como features y target. En este ejemplo, usaremos el precio de apertura (open), el indicador MACD (Moving Average Convergence Divergence) y la media móvil exponencial (EMA) como features. El precio de cierre (close) será utilizado como target.

# Função para calcular o MACD
def macd(df, fast_period=12, slow_period=26, signal_period=9):
    ema_fast = df['close'].ewm(span=fast_period).mean()
    ema_slow = df['close'].ewm(span=slow_period).mean()
    macd_line = ema_fast - ema_slow
    signal_line = macd_line.ewm(span=signal_period).mean()
    return macd_line, signal_line

# Função para calcular a EMA
def ema(df, period=30):
    return df['close'].ewm(span=period).mean()

# Calculando o MACD e a linha de sinal
smoothed_df['macd'], smoothed_df['signal'] = macd(smoothed_df)

# Calculando a EMA
smoothed_df['ema'] = ema(smoothed_df)

# Selecionando as variáveis
selected_df = smoothed_df[['open', 'macd', 'ema', 'close']].dropna()

Transformación de datos

La transformación de datos es importante para asegurar que las variables estén en la misma escala y puedan ser comparadas de manera justa. En este ejemplo, utilizaremos la normalización Min-Max, que transforma los datos a una escala entre 0 y 1.

scaler = MinMaxScaler()
normalized_df = pd.DataFrame(scaler.fit_transform(selected_df), columns=selected_df.columns, index=selected_df.index)

División de los datos

Por último, dividiremos los datos en conjuntos de entrenamiento y prueba. El conjunto de entrenamiento se usará para entrenar el modelo, mientras que el conjunto de prueba se usará para evaluar su rendimiento.

X = normalized_df[['open', 'macd', 'ema']]
y = normalized_df['close']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

En la sección 2, realizamos varias etapas importantes para asegurar que los datos estén listos para ser utilizados en un modelo de aprendizaje automático.

Comenzamos por cargar los datos del activo financiero usando la API de MetaTrader5, convirtiéndolos en un DataFrame de pandas y ajustando la columna de tiempo para ser usada como índice. A continuación, realizamos la limpieza de los datos, eliminando cualquier valor ausente y verificando la presencia de valores atípicos y datos inconsistentes. Esta limpieza es fundamental para garantizar que el modelo no sea afectado por valores inválidos o no relevantes.

Optamos por seleccionar las variables que serían utilizadas como feature y target del modelo, eligiendo Open, MACD y EMA como features y Close como el target. Sin embargo, cabe resaltar que tal selección fue realizada de forma aleatoria, con el propósito de proporcionar un ejemplo ilustrativo.

Realizamos la normalización de los datos, que es importante para evitar que las diferencias en las escalas de los datos afecten al modelo de aprendizaje automático. Y por último, dividimos los datos en un conjunto de entrenamiento y un conjunto de prueba, para evaluar la capacidad del modelo de generalizar para nuevos datos.

Estas etapas de preparación de los datos son cruciales para garantizar que el modelo sea preciso y eficaz en sus predicciones. Una vez que los datos están preparados, podemos proceder a la próxima etapa, que es la creación y entrenamiento del modelo de aprendizaje automático.


Sección 3: Entrenamiento y evaluación del modelo de regresión con árbol de decisión

Con los conjuntos de entrenamiento y prueba creados y los datos debidamente preparados, estamos listos para crear, entrenar y evaluar nuestro modelo de regresión con árbol de decisión. El árbol de decisión es un método de aprendizaje supervisado que puede ser aplicado tanto a problemas de clasificación como de regresión. En este caso, utilizaremos el árbol de decisión para predecir el precio de cierre de un activo financiero.

  • Importar bibliotecas y crear el modelo

Comenzamos importando las bibliotecas necesarias y creando una instancia del modelo DecisionTreeRegressor de scikit-learn.

from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error, r2_score

regressor = DecisionTreeRegressor(random_state=42)
  • Entrenar el modelo

A continuación, entrenamos el modelo usando el conjunto de entrenamiento (X_train y y_train).

regressor.fit(X_train, y_train)
  • Hacer predicciones

Con el modelo entrenado, podemos hacer predicciones en el conjunto de prueba (X_test) y comparar los resultados con los valores reales del conjunto de prueba (y_test).

y_pred = regressor.predict(X_test)
  • Evaluar el desempeño del modelo

Evaluar el desempeño del modelo es fundamental para entender cuán bien se está ajustando a los datos y realizando predicciones. Además del error cuadrático medio (MSE) y el coeficiente de determinación (R²), podemos utilizar otras métricas para evaluar el desempeño de nuestro modelo de regresión con árbol de decisión. Algunas métricas adicionales que podemos considerar incluyen:

  • Error absoluto medio (MAE): El MAE es la media de las diferencias absolutas entre las predicciones y los valores reales. Es una métrica fácil de entender y proporciona una medida de cuán lejos están las predicciones de los valores reales.
  • Error porcentual absoluto medio (MAPE): El MAPE es la media de los errores porcentuales absolutos entre las predicciones y los valores reales. Esta métrica proporciona una medida del desempeño del modelo en términos porcentuales, lo cual puede ser útil al comparar modelos con diferentes escalas de valores.
  • Raíz del error cuadrático medio (RMSE): El RMSE es la raíz cuadrada del MSE. Esta métrica tiene la ventaja de estar en la misma unidad que la variable de destino, lo que facilita la interpretación de los resultados.

Para calcular estas métricas adicionales, puedes usar la biblioteca Scikit-learn. Primero, importa las funciones necesarias:

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
A continuación, calcula las métricas usando las predicciones y los valores reales:
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)

Ahora puedes exhibir los resultados:

print(f"MAE: {mae:.4f}")
print(f"MSE: {mse:.4f}")
print(f"RMSE: {rmse:.4f}")
print(f"R²: {r2:.4f}")
  • Ajustar y optimizar el modelo

Dependiendo de los resultados obtenidos, puede ser necesario ajustar y optimizar el modelo. Esto puede hacerse ajustando los hiperparámetros del árbol de decisión, como la profundidad máxima (max_depth), el número mínimo de muestras necesarias para dividir un nodo interno (min_samples_split) y el número mínimo de muestras necesarias para estar en un nodo hoja (min_samples_leaf), entre otros.

Para optimizar los hiperparámetros, podemos utilizar técnicas como la búsqueda en rejilla (GridSearchCV) o la búsqueda aleatoria (RandomizedSearchCV) de scikit-learn. Estas técnicas permiten probar varias combinaciones de hiperparámetros y encontrar la mejor configuración para el modelo.

from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeRegressor


regressor = DecisionTreeRegressor(random_state=42)

param_grid = {
    'max_depth': [3, 4, 5, 6, 7, 8],
    'min_samples_split': [2, 3, 4],
    'min_samples_leaf': [1, 2, 3]
}

grid_search = GridSearchCV(estimator=regressor, param_grid=param_grid, scoring='neg_mean_squared_error', cv=5, n_jobs=-1)
grid_search.fit(X_train, y_train)

best_params = grid_search.best_params_
print(f"Melhores hiperparâmetros: {best_params}")

best_regressor = DecisionTreeRegressor(**best_params, random_state=42)
best_regressor.fit(X_train, y_train)

y_pred_optimized = best_regressor.predict(X_test)

mae_optimized = mean_absolute_error(y_test, y_pred_optimized)
mse_optimized = mean_squared_error(y_test, y_pred_optimized)
rmse_optimized = np.sqrt(mse_optimized)
r2_optimized = r2_score(y_test, y_pred_optimized)

print(f"MAE otimizado: {mae_optimized:.4f}")
print(f"MSE otimizado: {mse_optimized:.4f}")
print(f"RMSE otimizado: {rmse_optimized:.4f}")
print(f"R² otimizado: {r2_optimized:.4f}")

  • Desnormalizar los precios y crear un gráfico

Para desnormalizar los precios y crear un gráfico, puedes usar el inverse_transform del MinMaxScaler. Primero, desnormaliza el precio real (y_test) y el precio previsto (y_pred_optimized), y luego crea un gráfico usando la biblioteca matplotlib. Aquí está el código actualizado:

import matplotlib.pyplot as plt

# Função para desnormalizar os preços
def denormalize_price(scaler, normalized_price, column_name):
    dummy_df = pd.DataFrame(np.zeros((len(normalized_price), len(selected_df.columns))), columns=selected_df.columns)
    dummy_df[column_name] = normalized_price
    denormalized_df = scaler.inverse_transform(dummy_df)
    return denormalized_df[:, selected_df.columns.get_loc(column_name)]

# Desnormalizar os preços reais e previstos
y_test_denorm = denormalize_price(scaler, y_test, 'close')
y_pred_optimized_denorm

Esta sección concluye la implementación de un modelo de regresión con árbol de decisión para prever el cierre del precio de un activo financiero. Al entrenar y evaluar el modelo, obtuvimos métricas de rendimiento y ajustamos los hiperparámetros para optimizar su rendimiento.

Sin embargo, es importante destacar que este ejemplo es solo un enfoque básico, y existen muchas técnicas y estrategias avanzadas disponibles para mejorar la precisión y el rendimiento del modelo. Además, la elección del modelo de regresión y la preparación de los datos pueden variar dependiendo del contexto y de los requisitos específicos de cada problema.

Finalmente, es fundamental resaltar la importancia de probar, validar e iterar el modelo en diferentes escenarios y conjuntos de datos, con el fin de asegurar que sea robusto y confiable en la predicción de precios en el mercado financiero.


Sección 4: Integración del modelo de regresión en el simulador de estrategias

En esta sección, vamos a explorar en detalle la idea de construir un sistema que permite probar un modelo Python directamente en el Strategy Tester del MetaTrader. Este enfoque añadirá una capa adicional de flexibilidad a la creación de modelos, aprovechando la simplicidad del Python. El proceso de validación ocurrirá en el propio MetaTrader, ya que el modelo será exportado en formato ONNX para el MQL5. Esto significa que podrás moldear y perfeccionar tu modelo con facilidad, mientras que la validación rigurosa sucede en el ambiente MetaTrader, asegurando que esté listo para enfrentar las complejidades del mercado financiero.

Comunicación eficiente entre Python y MQL5

En el centro de este sistema, surge la necesidad crucial de establecer una comunicación eficaz entre el Python y el MQL5. Para alcanzar este objetivo, se creará una clase en Python que simplificará el intercambio de mensajes con el simulador de estrategias del MQL5. Mientras el programa Python esté en ejecución, monitorizará atentamente las operaciones realizadas en el simulador de estrategias, transmitiendo prontamente los datos de precios del activo a Python tan pronto como el simulador sea iniciado. Este flujo constante de información es esencial para proporcionar datos en tiempo real al modelo de regresión, permitiendo, por lo tanto, que tome decisiones basadas en esos datos. Además, es importante recordar la implementación en MQL5 de una clase que facilite la manipulación de archivos CSV, como se explica en este artículo.

Construcción de la clase File para comunicación entre Python y MQL5

La clase File desempeña un papel crucial en la comunicación eficaz entre Python y el simulador de estrategias del MQL5. Vamos a analizar las principales funcionalidades de esta clase, que simplifica el intercambio de datos y la manipulación de archivos entre estos dos lenguajes.

Inicialización de la clase

La clase File está diseñada como un Singleton, asegurando que solo haya una instancia de ella en todo el programa. Esto es importante para mantener la integridad de la comunicación entre Python y MQL5.

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


Verificación y manipulación de archivos

La clase File proporciona métodos esenciales para verificar la existencia de archivos, manejar errores asociados con archivos y realizar operaciones de lectura y escritura.

  • El método __init_file verifica si un archivo existe. Si el archivo no existe, espera un segundo antes de retornar False. Esto es útil para asegurar que el archivo esté listo para ser accedido.

  • El método __handle_error maneja excepciones que pueden ocurrir al interactuar con archivos. Identifica errores comunes, como PermissionError y FileNotFoundError, y proporciona información detallada sobre estos errores.

  • Los métodos check_init_param y check_open_file son fundamentales para leer archivos CSV. El primero verifica si el archivo existe y, en caso afirmativo, lee el archivo y retorna un valor específico de la columna typerun del DataFrame. El segundo método verifica la existencia del archivo y lo lee como un DataFrame completo.

from pathlib import Path
from time import sleep
from typing import Tuple
import pandas as pd
from pandas.core.frame import DataFrame
import os
from errno import EACCES, EPERM, ENOENT
import sys

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

CSV_SEPARATOR = ';'

class File(metaclass=Singleton):

    def __init__(self) -> None:
        pass

    def __init_file(self, name_arq: str) -> bool:
        return Path(name_arq).is_file() or sleep(1) or False

    def __handle_error(self, e, name_arq: str):
        ERRORS = {
            EPERM: "PermissionError",
            EACCES: "PermissionError",
            ENOENT: "FileNotFoundError"
        }
        print(f"{ERRORS.get(e.errno, 'Unknown error')} error({e.errno}): {e.strerror} for:\n{name_arq}")

    def check_init_param(self, name_arq : str) -> Tuple[str]:
        while True:
            try:
                if self.__init_file(name_arq):
                    df = pd.read_csv(name_arq, sep=CSV_SEPARATOR)
                    return (df.typerun.values[0])
            except (IOError, OSError) as e:
                self.__handle_error(e, name_arq)
            except:
                print('Unexpected error:', sys.exc_info()[0])

    def check_open_file(self, name_arq: str) -> pd.DataFrame():
        while True:
            try:
                if self.__init_file(name_arq):
                    return pd.read_csv(name_arq, sep=CSV_SEPARATOR)
            except (IOError, OSError) as e:
                self.__handle_error(e, name_arq)
            except:
                print('Unexpected error:', sys.exc_info()[0])

    @staticmethod
    def save_file_csv(name_arq: str, dataset:DataFrame = pd.DataFrame({'col':['ok']})):
        dataset.to_csv(name_arq, sep=CSV_SEPARATOR)

    @staticmethod
    def save(name_arq:str, data:str):
        with open(name_arq, 'w') as f:
            f.write(data)

    @staticmethod
    def delete_file(name_arq: str):
        try:
            os.remove(name_arq)
        except:
            pass


Guardar y eliminar archivos

La clase File también facilita la tarea de guardar y eliminar archivos.

  • El método save_file_csv permite que guardes un DataFrame en un archivo CSV. Esto es útil cuando deseas almacenar datos en un formato accesible para análisis futuros.

  • El método Save se usa para guardar datos en un archivo de texto. Esto es útil cuando necesitas almacenar información simple en un formato legible.

  • El método delete_file proporciona una manera sencilla de eliminar un archivo del sistema.

Procesamiento de datos en Python

En el lado de Python, el programa recibe los datos de precios del activo y ejecuta una serie de pasos de preprocesamiento. Estos pasos son esenciales para asegurar que los datos estén listos para ser usados por el modelo de regresión. Vamos a echar un vistazo más detallado a cómo funciona esto:

  1. Normalización de los datos: Un paso inicial implica la normalización de los datos. Esto significa ajustar los valores para que estén en un rango específico, generalmente entre 0 y 1. La normalización es vital para asegurar que diferentes características (como precios de acciones y volúmenes de tráding) estén en la misma escala, evitando así cualquier sesgo en el modelo.

  2. Detección y eliminación de valores atípicos: Los datos financieros pueden ser volátiles, y los valores atípicos pueden distorsionar los resultados del modelo. El programa Python detecta y, cuando es apropiado, elimina estos valores atípicos para garantizar la calidad de los datos de entrada.

  3. Creación de características adicionales: En muchos casos, se crean características adicionales a partir de los datos de entrada. Esto puede incluir medias móviles, indicadores técnicos, u otras métricas que el modelo puede usar para tomar decisiones más informadas.

Solo después de la preparación completa de los datos, el modelo de regresión entra en acción.

El modelo de regresión en acción

El modelo de regresión, que puede ser una regresión lineal, regresión de árbol de decisión u otro modelo apropiado, ya ha sido entrenado previamente con base en datos históricos. Ahora, se carga en el programa Python y se emplea para realizar predicciones basadas en los datos de precios más recientes. Estas predicciones son fundamentales para la toma de decisiones de tráding, ya que proporcionan información valiosa sobre el comportamiento futuro del activo. Cabe destacar que, aunque en este ejemplo estamos utilizando un modelo de regresión específico, como una regresión lineal, este enfoque puede ser aplicado a una variedad de modelos, como redes neuronales, algoritmos de árbol de decisión y otros, dependiendo de los requisitos específicos de tu estrategia de tráding. Por lo tanto, la flexibilidad de este sistema permite la incorporación de modelos diversificados para satisfacer las necesidades individuales de cada estrategia.

Integración de ONNX para mejorar MetaTrader 5

Quiero compartir un consejo interesante que puede mejorar nuestro sistema en MetaTrader 5: la integración con ONNX (Open Neural Network Exchange). ONNX es una herramienta muy amigable para la inteligencia artificial, que facilita mucho la transferencia de modelos al MetaTrader 5.

Después de realizar pruebas rigurosas y confirmar la eficacia de nuestro modelo en MetaTrader 5, podemos considerar la opción de exportarlo al formato ONNX. Esto no solo mejora las capacidades del MetaTrader 5, sino que también facilita la utilización de este modelo en diversas estrategias y sistemas dentro de la plataforma.

Con la integración nativa de ONNX en MetaTrader 5, este consejo ofrece oportunidades emocionantes para mejorar aún más la utilización de modelos en nuestras estrategias de tráding en la plataforma.

Pruebas exhaustivas antes de la exportación

La elección de nuestro enfoque actual, que implica la interacción con el ambiente MQL5, está fundamentada en la necesidad de realizar pruebas exhaustivas en un ambiente controlado antes de proceder con la exportación del modelo al formato ONNX. La construcción y la integración directa de modelos dentro del MQL5 pueden revelarse procesos intrincados y susceptibles a errores. Así, esta metodología nos posibilita perfeccionar y ajustar los modelos de manera meticulosa, asegurando que alcancen el rendimiento deseado, antes de ser efectivamente exportados al formato ONNX.


Conclusión

En resumen, este artículo exploró un enfoque integral para la implementación de un modelo de regresión. En la sección 1, discutimos la selección del modelo de regresión, enfocándonos en la importancia de elegir el algoritmo adecuado para el problema en cuestión. En la sección 2, hablamos sobre la preparación de los datos, resaltando la necesidad de procesar y limpiar los datos para asegurar que estén listos para el entrenamiento del modelo.

En la sección 3, nos centramos en el entrenamiento y evaluación del modelo de regresión, utilizando el árbol de decisión como ejemplo. Además, explicamos la importancia de dividir los datos en conjuntos de entrenamiento y prueba, así como de ajustar hiperparámetros para optimizar el desempeño del modelo.

Finalmente, en la sección 4, exploramos la integración del modelo de regresión en el simulador de estrategias de MetaTrader, destacando la necesidad de comunicación eficiente entre Python y MQL5, además de resaltar la posibilidad de usar el formato ONNX para mejorar la implementación en MetaTrader 5.

En resumen, este artículo proporcionó una visión general de los pasos esenciales para incorporar modelos en estrategias de tráding, destacando la importancia de la elección adecuada del modelo, la preparación de datos, el entrenamiento y evaluación, y la integración efectiva en el ambiente de tráding. Estos pasos forman la base para crear sistemas de tráding más robustos e informados por datos.
El código mencionado está disponible en el repositorio de Git para referencia adicional.

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

Teoría de categorías en MQL5 (Parte 22): Una mirada distinta a las medias móviles Teoría de categorías en MQL5 (Parte 22): Una mirada distinta a las medias móviles
En el presente artículo intentaremos simplificar los conceptos tratados en esta serie centrándonos en solo un indicador, el más común y probablemente el más fácil de entender: la media móvil. También veremos el significado y las posibles aplicaciones de las transformaciones naturales verticales.
Algoritmos de optimización de la población: Algoritmo Mind Evolutionary Computation (Computación Evolutiva Mental, (MEC) Algoritmos de optimización de la población: Algoritmo Mind Evolutionary Computation (Computación Evolutiva Mental, (MEC)
En este artículo, analizaremos un algoritmo de la familia MEC llamado algoritmo MEC Simple de evolución mental (Simple MEC, SMEC). El algoritmo se caracteriza por la belleza de la idea expuesta y su sencillez de aplicación.
Desarrollo de un sistema de repetición (Parte 29): Proyecto Expert Advisor — Clase C_Mouse (III) Desarrollo de un sistema de repetición (Parte 29): Proyecto Expert Advisor — Clase C_Mouse (III)
Ahora que hemos mejorado la clase C_Mouse, podemos concentrarnos en crear una clase destinada a establecer una base totalmente nueva de estudios. Como mencioné al inicio del artículo, no utilizaremos herencia o polimorfismo para crear esta nueva clase. En cambio, vamos a modificar, o mejor, agregar nuevos objetos a la línea de precio. Esto es lo que haremos en este primer momento, y en el próximo artículo, mostraré cómo cambiar los estudios. Pero, realizaremos esto sin cambiar el código de la clase C_Mouse. Reconozco que, en la práctica, esto sería más fácilmente logrado mediante herencia o polimorfismo. No obstante, existen otras técnicas para alcanzar el mismo resultado.
Desarrollando un cliente MQTT para MetaTrader 5: metodología de TDD (Parte 3) Desarrollando un cliente MQTT para MetaTrader 5: metodología de TDD (Parte 3)
El presente artículo supone la tercera parte de la serie que describe las etapas de desarrollo de un cliente MQL5 nativo para el protocolo MQTT. En esta ocasión, hablaremos con detalle sobre la aplicación de un desarrollo basado en pruebas para implementar el intercambio de paquetes CONNECT/CONNACK. Al final de este paso, nuestro cliente DEBERÁ poder comportarse adecuadamente al lidiar con cualquier posible resultado del servidor al intentar conectarse.