Aprendizaje automático y Data Science (Parte 45): Predicción de series temporales en Forex con el modelo Prophet de Facebook
Contenido
- ¿Qué es un modelo «Prophet»?
- Comprender el modelo «Prophet»
- Implementación del modelo «Prophet» en Python
- Añadir días festivos al modelo «Prophet»
- Creación del robot de trading para MetaTrader 5 basado en el modelo «Prophet»
- Conclusión
¿Qué es un modelo «Prophet»?
El modelo Prophet es una herramienta de código abierto para la predicción de series temporales desarrollada por Meta (antes Facebook). Está diseñado para ofrecer previsiones precisas y fáciles de usar con fines empresariales y analíticos, especialmente para datos de series temporales con una marcada estacionalidad y tendencias.
Este modelo fue presentado por Facebook (S. J. Taylor y Benjamin Letham, 2018), concebido originalmente para la previsión de datos diarios con estacionalidad semanal y anual, además de los efectos de los días festivos. Posteriormente se amplió para abarcar más tipos de datos estacionales. Funciona mejor con series temporales que presentan una marcada estacionalidad y que cuentan con datos históricos de varias temporadas.
Términos habituales:
- Tendencia: La tendencia muestra la dirección general de los datos a largo plazo y elimina las variaciones estacionales.
- Estacionalidad: La estacionalidad se refiere a las variaciones que se producen en un periodo breve y que no son lo suficientemente marcadas como para considerarse una «tendencia».

En este artículo, vamos a analizar e implementar este modelo a partir de datos del mercado de divisas y veremos cómo puede ayudarnos a superar al mercado; pero, antes de nada, dediquemos un momento a comprender este modelo en detalle.
Comprender el modelo «Prophet»
El modelo Prophet puede considerarse un modelo de regresión no lineal que viene dado por la fórmula:
Figura 1
Donde:
-
describe una tendencia lineal por tramos (o «término de crecimiento»). -
describe los distintos patrones estacionales. -
recoge los efectos de calendario, y
es un término de error de ruido blanco.
01: El componente de tendencia
El componente de tendencia
admite puntos de cambio, que se seleccionan automáticamente si no se especifican manualmente. Estos puntos de cambio representan momentos en los que la tendencia puede cambiar (por ejemplo, un crecimiento o un descenso repentino).
También puedes utilizar, si lo deseas, el modelo de crecimiento logístico en lugar del lineal, lo que introduce un parámetro de capacidad (cap) para modelar los efectos de saturación. Esto resulta útil cuando el crecimiento se ralentiza tras alcanzar un determinado límite natural.
02: Estacionalidad
En el modelo Prophet, la estacionalidad
se modela mediante series de Fourier.
Por defecto:
- Se utiliza un orden de 10 para la estacionalidad anual.
- Se utiliza un orden 3 para la estacionalidad semanal.
Estos términos de Fourier ayudan al modelo a capturar los efectos estacionales recurrentes.
03: La parte de efectos de días festivos
Los efectos de calendario
se incorporan como variables indicadoras (codificadas con el método «one-hot»), lo que permite al modelo ajustar su previsión en torno a fechas especiales que, históricamente, han provocado desviaciones en el comportamiento. Por ejemplo, noticias económicas o días festivos.
El modelo completo se estima utilizando un enfoque bayesiano, lo que permite la selección automática de los puntos de cambio y otros parámetros del modelo.
Aunque este modelo aditivo de descomposición básica parece sencillo, el cálculo de los términos que componen esta fórmula es de gran complejidad matemática, por lo que, si no tienes ni idea de lo que estás haciendo, este modelo puede dar lugar a previsiones erróneas.
Prophet nos ofrece dos enfoques de modelización.
- Modelo de crecimiento lineal por tramos (predeterminado)
- Modelo de crecimiento logístico
01. Modelo lineal por tramos
Este es el modelo predeterminado que utiliza Prophet. Se parte de la hipótesis de que la tendencia de los datos sigue una trayectoria lineal, pero que puede cambiar en momentos concretos (denominados «puntos de cambio»). Este modelo es adecuado para datos que presentan patrones de crecimiento o descenso constantes, aunque puedan presentar cambios bruscos.
Este enfoque de modelización es el que se representa mediante la fórmula de la Figura 1.
02. Modelo de crecimiento logístico
Este modelo es adecuado para datos que muestran un crecimiento saturado, es decir, que crecen rápidamente al principio, pero se ralentizan a medida que se acercan a una capacidad máxima o a un límite. Este tipo de patrón se observa a menudo en sistemas del mundo real con límites naturales o impuestos por el negocio (como la aceptación por parte de los usuarios en un mercado saturado).
El modelo de crecimiento logístico incorpora un parámetro de capacidad que define este límite superior.
Este enfoque de modelización viene dado por la siguiente fórmula:
Figura 2
Donde:
es la capacidad de carga,
es la tasa de crecimiento y
es un parámetro de desplazamiento.
Implementación del modelo «Prophet» en Python
Utilizando los datos del EURUSD del gráfico horario, intentemos detectar la tendencia y la estacionalidad, y pronosticar los valores futuros mediante este modelo.
Lo primero que tienes que hacer es instalar todas las dependencias del archivo requirements.txt — que se adjunta al final de este artículo
pip install -r requirements.txt
Importaciones:
import pandas as pd import numpy as np import MetaTrader5 as mt5 import matplotlib.pyplot as plt import seaborn as sns from prophet import Prophet plt.style.use('fivethirtyeight') sns.set_style("darkgrid")
Recopilemos los datos de MetaTrader 5.
if not mt5.initialize(r"c:\Program Files\MetaTrader 5 IC Markets (SC)\terminal64.exe"): print("Failed to initialize MetaTrader5. Error = ",mt5.last_error()) mt5.shutdown() symbol = "EURUSD" timeframe = mt5.TIMEFRAME_H1 rates = mt5.copy_rates_from_pos(symbol, timeframe, 1, 10000) if rates is None: print(f"Failed to copy rates for symbol={symbol}. MT5 Error = {mt5.last_error()}")
El modelo «Prophet» se basa en gran medida en la función «datetime» o «date stamp». Esta característica es imprescindible para que este modelo funcione.
Tras recibir los datos (cotizaciones) de MetaTrader 5, los convertimos en un objeto DataFrame de Pandas. A continuación, convertimos la columna «time», que contiene el tiempo en segundos, a un formato de fecha y hora.
rates_df = pd.DataFrame(rates) # we convert rates object to a dataframe rates_df["time"] = pd.to_datetime(rates_df["time"], unit="s") # we convert the time from seconds to datatime rates_df
Resultados:
| time | open | high | low | close | tick_volume | spread | real_volume | |
|---|---|---|---|---|---|---|---|---|
| 0 | 2023-11-10 23:00:00 | 1.06849 | 1.06873 | 1.06826 | 1.06846 | 762 | 0 | 0 |
| 1 | 2023-11-13 00:00:00 | 1.06828 | 1.06853 | 1.06779 | 1.06841 | 1059 | 10 | 0 |
| 2 | 2023-11-13 01:00:00 | 1.06854 | 1.06907 | 1.06854 | 1.06906 | 571 | 0 | 0 |
| 3 | 2023-11-13 02:00:00 | 1.06904 | 1.06904 | 1.06822 | 1.06839 | 1053 | 0 | 0 |
| 4 | 2023-11-13 03:00:00 | 1.06840 | 1.06886 | 1.06811 | 1.06867 | 1204 | 0 | 0 |
El modelo Prophet es un modelo univariado que solo requiere dos características para funcionar a partir de un DataFrame de Pandas, es decir, la característica de fecha y hora denominada «ds» (date stamp) y la variable objetivo marcada como «y» en el DataFrame.
Por ahora, vamos a crear un conjunto de datos sencillo a partir del recibido de MetaTrader 5 con dos características (tiempo y volatilidad). Estos son los datos que vamos a aplicar más adelante al modelo «Prophet».
prophet_df = pd.DataFrame({
"time": rates_df["time"],
"volatility": rates_df["high"] - rates_df["low"]
}).set_index("time")
prophet_df La volatilidad (calculada como la diferencia entre el precio máximo y el mínimo) es nuestra variable objetivo.
A diferencia de otros modelos de predicción de series temporales, como ARIMA y VAR (analizados anteriormente), que requieren que la variable objetivo sea estacionaria, el modelo Prophet no está sujeto a esta condición. También puede funcionar con datos no estacionarios, pero todos los modelos de aprendizaje automático suelen ofrecer buenos resultados con variables estacionarias, ya que, por su propia naturaleza (tienen media, varianza y desviación estándar constantes), a los modelos les resulta más fácil aprender de ellas.
Para este modelo, he optado por trabajar con una variable objetivo estacionaria para facilitarnos mucho el trabajo.
Representemos gráficamente el DataFrame y observemos las características.
# Color pallete for plotting color_pal = ["#F8766D", "#D39200", "#93AA00", "#00BA38", "#00C19F", "#00B9E3", "#619CFF", "#DB72FB"] prophet_df.plot(figsize=(7,5), color=color_pal, title="Volatility (high-low) against time", ylabel="volatility", xlabel="time")
Resultados:

Figura 3
Si lo deseamos, podemos crear variables X e y para evaluar el impacto de las variables temporales en la volatilidad del mercado.
def create_features(df, label=None): """ Creates time series features from datetime index. """ df = df.copy() df['date'] = df.index df['hour'] = df['date'].dt.hour df['dayofweek'] = df['date'].dt.dayofweek df['quarter'] = df['date'].dt.quarter df['month'] = df['date'].dt.month df['year'] = df['date'].dt.year df['dayofyear'] = df['date'].dt.dayofyear df['dayofmonth'] = df['date'].dt.day df['weekofyear'] = df['date'].dt.isocalendar().week X = df[['hour','dayofweek','quarter','month','year', 'dayofyear','dayofmonth','weekofyear']] if label: y = df[label] return X, y return X X, y = create_features(prophet_df, label='volatility') features_and_target = pd.concat([X, y], axis=1)
Resultados:
| hour | dayofweek | quarter | month | year | dayofyear | dayofmonth | weekofyear | volatility | |
|---|---|---|---|---|---|---|---|---|---|
| time | |||||||||
| 2023-11-13 16:00:00 | 16 | 0 | 4 | 11 | 2023 | 317 | 13 | 46 | 0.00122 |
| 2023-11-13 17:00:00 | 17 | 0 | 4 | 11 | 2023 | 317 | 13 | 46 | 0.00179 |
| 2023-11-13 18:00:00 | 18 | 0 | 4 | 11 | 2023 | 317 | 13 | 46 | 0.00186 |
| 2023-11-13 19:00:00 | 19 | 0 | 4 | 11 | 2023 | 317 | 13 | 46 | 0.00125 |
| 2023-11-13 20:00:00 | 20 | 0 | 4 | 11 | 2023 | 317 | 13 | 46 | 0.00150 |
Podemos representar gráficamente estas características en función de la volatilidad para realizar un análisis manual.
sns.pairplot(features_and_target.dropna(), hue='hour', x_vars=['hour','dayofweek', 'year','weekofyear'], y_vars='volatility', height=5, plot_kws={'alpha':0.45, 'linewidth':0.5} ) plt.suptitle(f"{symbol} close prices by Hour, Day of Week, Year, and Week") plt.show()
Resultados:


Figura 4
Como se puede observar en los subgráficos, la hora, el día de la semana, el año y la semana del año influyen en la volatilidad que se produce en cada hora del gráfico. Saber esto nos da la confianza necesaria para seguir adelante y utilizar estos datos en el modelo «Prophet».
Entrenamiento del modelo «Prophet»
Empezamos dividiendo los datos en conjuntos de entrenamiento y de prueba utilizando una fecha concreta.
split_date = '01-Jan-2025' # threshold date between training and testing samples, all values after this date are for testing prophet_df_train = prophet_df.loc[prophet_df.index <= split_date].copy().reset_index().rename(columns={"time": "ds", "volatility": "y"}) prophet_df_test = prophet_df.loc[prophet_df.index > split_date].copy().reset_index().rename(columns={"time": "ds", "volatility": "y"})
Entrenamos el modelo «Prophet» con los datos de entrenamiento.
model = Prophet() model.fit(prophet_df_train)
Una vez entrenado el modelo, a menudo queremos comprobar su eficacia con los datos fuera de muestra, es decir, la información que el modelo no ha visto antes. A diferencia de otros modelos, el modelo Prophet presenta una forma ligeramente diferente de generar las previsiones.
test_fcst = model.predict(df=prophet_df_test)
En lugar de devolver un vector con las predicciones, este modelo devuelve un DataFrame completo que contiene diversas características que representan las predicciones y el estado del modelo.
test_fcst.head()
Resultados:
ds trend yhat_lower yhat_upper trend_lower trend_upper additive_terms additive_terms_lower additive_terms_upper daily daily_lower daily_upper weekly weekly_lower weekly_upper multiplicative_terms multiplicative_terms_lower multiplicative_terms_upper yhat 0 2025-01-02 00:00:00 0.001674 0.000168 0.001993 0.001674 0.001674 -0.000571 -0.000571 -0.000571 -0.000510 -0.000510 -0.000510 -0.000061 -0.000061 -0.000061 0.0 0.0 0.0 0.001102 1 2025-01-02 01:00:00 0.001674 0.000161 0.001977 0.001674 0.001674 -0.000614 -0.000614 -0.000614 -0.000556 -0.000556 -0.000556 -0.000057 -0.000057 -0.000057 0.0 0.0 0.0 0.001060 2 2025-01-02 02:00:00 0.001674 0.000337 0.002123 0.001674 0.001674 -0.000483 -0.000483 -0.000483 -0.000430 -0.000430 -0.000430 -0.000054 -0.000054 -0.000054 0.0 0.0 0.0 0.001191
La siguiente tabla recoge el significado de algunas de las columnas (características) que devuelve el método predict.
| Columna | Significado |
|---|---|
| ds | La fecha y hora (marca de tiempo) del punto previsto. |
| yhat | El valor previsto final (lo que Prophet predice en ese momento). |
| yhat_lower, yhat_upper | Los límites inferior y superior del intervalo de confianza del 80 % (o del 95 %) para yhat. |
| trend | El valor del componente de tendencia en el instante ds (por ejemplo, un crecimiento lento o un descenso a lo largo del tiempo). |
| trend_lower, trend_upper | Intervalo de confianza del componente de tendencia. |
| additive_terms | La suma de todos los componentes estacionales y festivos en el momento ds (por ejemplo, diarios, semanales y festivos). |
| additive_terms_lower, additive_terms_upper | Límites para los componentes aditivos. |
| daily | El efecto de estacionalidad diario (por ejemplo, los patrones por horas a lo largo del día). |
| daily_lower, daily_upper | Intervalo de confianza para el componente diario. |
| weekly | El efecto de estacionalidad semanal (por ejemplo, los fines de semana difieren de los días laborables) |
| weekly_lower, weekly_upper | Intervalo de confianza para el componente semanal. |
Lo que más necesitamos son yhat, yhat_lower, yhat_upper, trend, los patrones de estacionalidad (diarios, semanales, anuales), días festivos (si se incluyen) y los límites de error de los componentes (*_lower y *_upper).
Representemos gráficamente los valores reales y las previsiones de la muestra de prueba, junto con los valores reales de la muestra de entrenamiento.
f, ax = plt.subplots(figsize=(7,5)) ax.scatter(prophet_df_test["ds"], prophet_df_test['y'], color='r') # plot actual values from the testing sample in red fig = model.plot(test_fcst, ax=ax) # plot the forecasts
Figura de resultados:

Figura 5
Los valores en negro representan la muestra de entrenamiento, los de color rojo son los valores reales de la muestra de prueba y los de color azul son las predicciones realizadas por el modelo para la muestra de prueba.
Es difícil comprender la eficacia del modelo con solo observar este gráfico. Creemos unos pequeños gráficos que representen los datos reales y las previsiones de la muestra de prueba.
Evaluemos el modelo en enero de 2025, el primer mes de los datos de prueba.
f, ax = plt.subplots(figsize=(7, 5)) ax.scatter(prophet_df_test["ds"], prophet_df_test['y'], color='r') fig = model.plot(test_fcst, ax=ax) ax.set_xbound( lower=pd.to_datetime("2025-01-01"), # starting data on the x axis upper=pd.to_datetime("2025-02-01")) # ending data on the x axis ax.set_ylim(0, 0.005) plot = plt.suptitle("January 2025, Actual vs Forecasts")
Resultados:

Figura 6
Según lo que vemos en la imagen anterior, el modelo «Prophet» acierta en algunas predicciones, pero no parece dar buenos resultados con los valores atípicos de los datos.
Si lo deseamos, podemos profundizar en las predicciones analizando los valores reales y comparándolos con las predicciones realizadas por el modelo durante la primera semana de enero (del 1 al 8 de enero).
f, ax = plt.subplots(figsize=(9, 5)) ax.scatter(prophet_df_test["ds"], prophet_df_test['y'], color='r') fig = model.plot(test_fcst, ax=ax) ax.set_xbound( lower=pd.to_datetime("2025-01-01"), upper=pd.to_datetime("2025-01-08")) ax.set_ylim(0, 0.005) plot = plt.suptitle("January 01-08, 2025. Actual vs Forecasts")
Resultados:

Figura 7
Queda mucho mejor. Sin embargo, aunque el modelo parece captar algunos patrones, sus previsiones (predicciones) no se acercan demasiado a los valores reales, algo que a menudo nos esforzamos por conseguir cuando utilizamos modelos de regresión.
Sin embargo, parece que ofrece una buena predicción generalizada.
Analicémoslo utilizando algunos indicadores de evaluación.
import sklearn.metrics as metric def forecast_accuracy(forecast, actual): # Convert to numpy arrays if they aren't already forecast = np.asarray(forecast) actual = np.asarray(actual) metrics = { 'mape': metric.mean_absolute_percentage_error(actual, forecast), 'me': np.mean(forecast - actual), # Mean Error 'mae': metric.mean_absolute_error(actual, forecast), 'mpe': np.mean((forecast - actual) / actual), # Mean Percentage Error 'rmse': metric.root_mean_squared_error(actual, forecast), 'minmax': 1 - np.mean(np.minimum(forecast, actual) / np.maximum(forecast, actual)), "r2_score": metric.r2_score(forecast, actual) } return metrics results = forecast_accuracy(test_pred, prophet_df_test["y"]) for metric_name, value in results.items(): print(f"{metric_name:<10}: {value:.6f}")
Resultados:
mape : 0.603277 me : 0.000130 mae : 0.000829 mpe : 0.430299 rmse : 0.001221 minmax : 0.339292 r2_score : -4.547775
Lo que me interesa es la métrica MAPE (error porcentual absoluto medio); un valor de aproximadamente 0,6 significa que, de media, las previsiones realizadas por el modelo se desvían un 60 % de los valores reales. En pocas palabras, el modelo hizo predicciones pésimas y es propenso al error.
Añadir días festivos al modelo «Prophet»
El modelo «Prophet» está diseñado para tener en cuenta el hecho de que, en cualquier conjunto de datos, pueden producirse eventos que provoquen cambios inusuales en una serie temporal; a estos eventos los denominamos «días festivos».
En la vida real, es probable que los días festivos provoquen fluctuaciones en los datos empresariales; estas pueden ser:
- Días festivos (por ejemplo, Año Nuevo, Navidad)
- Eventos empresariales (por ejemplo, el Black Friday, el lanzamiento de un producto)
- Acontecimientos financieros (por ejemplo, comunicados del banco central, cierres de trimestre)
- Acontecimientos locales (por ejemplo, elecciones, fenómenos meteorológicos extremos)
Estos eventos no siguen un patrón estacional regular, aunque sí se repiten, a menudo cada año, cada trimestre, cada día, etc.
En los datos financieros de trading, podemos considerar las noticias económicas como días festivos, ya que provocan la situación descrita. De este modo, podríamos ayudar a nuestro modelo a resolver su problema actual: la incapacidad de captar estos valores extremos.
Como se puede observar en la Figura 1, que recoge la fórmula del modelo Prophet, al añadir los días festivos si los hay, el modelo queda completo, ya que los días festivos son uno de los elementos fundamentales de la fórmula.
Dicho esto, tenemos que recopilar las noticias utilizando el lenguaje MQL5.
Nombre del archivo: OHLC + News.mq5
input datetime start_date = D'01.01.2023'; input datetime end_date = D'24.6.2025'; input ENUM_TIMEFRAMES timeframe = PERIOD_H1; MqlRates rates[]; struct news_data_struct { datetime time[]; //News release time double open[]; //Candle opening price double high[]; //Candle high price double low[]; //Candle low price double close[]; //Candle close price string name[]; //Name of the news ENUM_CALENDAR_EVENT_SECTOR sector[]; //The sector a news is related to ENUM_CALENDAR_EVENT_IMPORTANCE importance[]; //Event importance double actual[]; //actual value double forecast[]; //forecast value double previous[]; //previous value void Resize(uint size) { ArrayResize(time, size); ArrayResize(open, size); ArrayResize(high, size); ArrayResize(low, size); ArrayResize(close, size); ArrayResize(name, size); ArrayResize(sector, size); ArrayResize(importance, size); ArrayResize(actual, size); ArrayResize(forecast, size); ArrayResize(previous, size); } } news_data; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- if (!ChartSetSymbolPeriod(0, Symbol(), timeframe)) return; SaveNews(StringFormat("%s.%s.OHLC + News.csv",Symbol(),EnumToString(timeframe))); } //+------------------------------------------------------------------+ //| | //| The function which collects news alongsided OHLC values and | //| saves the data to a CSV file | //| | //+------------------------------------------------------------------+ void SaveNews(string csv_name) { //--- get OHLC values first ResetLastError(); if (CopyRates(Symbol(), timeframe, start_date, end_date, rates)<=0) { printf("%s failed to get price information from %s to %s. Error = %d",__FUNCTION__,string(start_date),string(end_date),GetLastError()); return; } uint size = rates.Size(); news_data.Resize(size-1); //--- FileDelete(csv_name); //Delete an existing csv file of a given name int csv_handle = FileOpen(csv_name,FILE_WRITE|FILE_SHARE_WRITE|FILE_CSV|FILE_ANSI|FILE_COMMON,",",CP_UTF8); //csv handle if(csv_handle == INVALID_HANDLE) { printf("Invalid %s handle Error %d ",csv_name,GetLastError()); return; //stop the process } FileSeek(csv_handle,0,SEEK_SET); //go to file begining FileWrite(csv_handle,"Time,Open,High,Low,Close,Name,Sector,Importance,Actual,Forecast,Previous"); //write csv header MqlCalendarValue values[]; //https://www.mql5.com/en/docs/constants/structures/mqlcalendar#mqlcalendarvalue for (uint i=0; i<size-1; i++) { news_data.time[i] = rates[i].time; news_data.open[i] = rates[i].open; news_data.high[i] = rates[i].high; news_data.low[i] = rates[i].low; news_data.close[i] = rates[i].close; int all_news = CalendarValueHistory(values, rates[i].time, rates[i+1].time, NULL, NULL); //we obtain all the news with their values https://www.mql5.com/en/docs/calendar/calendarvaluehistory for (int n=0; n<all_news; n++) { MqlCalendarEvent event; CalendarEventById(values[n].event_id, event); //Here among all the news we select one after the other by its id https://www.mql5.com/en/docs/calendar/calendareventbyid MqlCalendarCountry country; //The couhtry where the currency pair originates CalendarCountryById(event.country_id, country); //https://www.mql5.com/en/docs/calendar/calendarcountrybyid if (StringFind(Symbol(), country.currency)>-1) //We want to ensure that we filter news that has nothing to do with the base and the quote currency for the current symbol pair { news_data.name[i] = event.name; news_data.sector[i] = event.sector; news_data.importance[i] = event.importance; news_data.actual[i] = !MathIsValidNumber(values[n].GetActualValue()) ? 0 : values[n].GetActualValue(); news_data.forecast[i] = !MathIsValidNumber(values[n].GetForecastValue()) ? 0 : values[n].GetForecastValue(); news_data.previous[i] = !MathIsValidNumber(values[n].GetPreviousValue()) ? 0 : values[n].GetPreviousValue(); } } FileWrite(csv_handle,StringFormat("%s,%f,%f,%f,%f,%s,%s,%s,%f,%f,%f", (string)news_data.time[i], news_data.open[i], news_data.high[i], news_data.low[i], news_data.close[i], news_data.name[i], EnumToString(news_data.sector[i]), EnumToString(news_data.importance[i]), news_data.actual[i], news_data.forecast[i], news_data.previous[i] )); } //--- FileClose(csv_handle); }
Tras recopilar las noticias dentro de la función SaveNews, los datos obtenidos se guardan en un archivo CSV en la «ruta común» (carpeta).
Dentro del script de Python, cargamos estos datos desde la misma ruta.
from Trade.TerminalInfo import CTerminalInfo import os terminal = CTerminalInfo() data_path = os.path.join(terminal.common_data_path(), "Files") timeframe = "PERIOD_H1" df = pd.read_csv(os.path.join(data_path, f"{symbol}.{timeframe}.OHLC + News.csv")) df
Resultados:
| Time | Open | High | Low | Close | Name | Sector | Importance | Actual | Forecast | Previous | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2023.01.02 01:00:00 | 1.06967 | 1.06983 | 1.06927 | 1.06983 | New Year's Day | CALENDAR_SECTOR_HOLIDAYS | CALENDAR_IMPORTANCE_NONE | 0.0 | 0.0 | 0.0 |
| 1 | 2023.01.02 02:00:00 | 1.06984 | 1.07059 | 1.06914 | 1.07041 | New Year's Day | CALENDAR_SECTOR_HOLIDAYS | CALENDAR_IMPORTANCE_NONE | 0.0 | 0.0 | 0.0 |
| 2 | 2023.01.02 03:00:00 | 1.07059 | 1.07069 | 1.06858 | 1.06910 | New Year's Day | CALENDAR_SECTOR_HOLIDAYS | CALENDAR_IMPORTANCE_NONE | 0.0 | 0.0 | 0.0 |
| 3 | 2023.01.02 04:00:00 | 1.06909 | 1.06909 | 1.06828 | 1.06880 | New Year's Day | CALENDAR_SECTOR_HOLIDAYS | CALENDAR_IMPORTANCE_NONE | 0.0 | 0.0 | 0.0 |
| 4 | 2023.01.02 05:00:00 | 1.06881 | 1.07029 | 1.06880 | 1.06897 | New Year's Day | CALENDAR_SECTOR_HOLIDAYS | CALENDAR_IMPORTANCE_NONE | 0.0 | 0.0 | 0.0 |
Dado que hemos recopilado las noticias de cada fila de datos en nuestro script de MQL5, nos encontramos con algunas filas en la columna de noticias con el nombre «(null)», lo que indica que no había noticias en ese momento, por lo que tenemos que filtrar estas filas.
news_df = df[df['Name'] != "(null)"].copy()
Al igual que estructuramos los datos anteriores para este modelo en dos columnas — ds y y —, debemos asegurarnos de que el conjunto de datos de días festivos también tenga dos columnas: ds y holiday. La columna «holiday» sirve para guardar el nombre del evento o festivo.
holidays = news_df[['Time', 'Name']].rename(columns={ 'Time': 'ds', 'Name': 'holiday' }) holidays['ds'] = pd.to_datetime(holidays['ds']) # Ensure datetime format holidays
Resultados:
| ds | holiday | |
|---|---|---|
| 0 | 2023-01-02 01:00:00 | New Year's Day |
| 1 | 2023-01-02 02:00:00 | New Year's Day |
| 2 | 2023-01-02 03:00:00 | New Year's Day |
| 3 | 2023-01-02 04:00:00 | New Year's Day |
| 4 | 2023-01-02 05:00:00 | New Year's Day |
Además de estas características, el dataframe «holidays» puede incluir dos columnas opcionales (lower_window y upper_window). Estas columnas indican al modelo el impacto de cada festivo/evento, tanto antes como después de que se produzca.
Sabemos que cada festividad en el mundo real no tiene su impacto únicamente en la fecha concreta en la que se celebra, sino que a menudo tiene repercusiones tanto antes como después de su celebración.
holidays['lower_window'] = 0 holidays['upper_window'] = 1 # Extend effect to 1 hour after
La columna lower_window indica en qué medida el festivo/evento afectó a los datos de la serie temporal antes de que tuviera lugar, mientras que la columna upper_window indica en qué medida el festivo/evento afectó a la serie temporal después de que tuviera lugar.
- En el caso de la columna lower_window, sus valores pueden ser menores o iguales a cero (<=0); el valor por defecto es cero, lo que indica que el festivo/evento no afecta a ningún valor anterior de la serie temporal. Un valor de -1 indica que un determinado festivo/evento afecta al valor único anterior de la serie temporal antes de que se produjera dicho festivo/evento, etc.
- En el caso de la columna upper_window, sus valores pueden ser mayores o iguales a cero (>=0); el valor por defecto es cero, lo que indica que el festivo/evento no afecta a ningún valor de la serie temporal tras su celebración. Un valor de 1 indica que un determinado festivo/evento afecta al siguiente valor individual de la serie temporal tras su ocurrencia, y así sucesivamente.
Ahora, añadamos estas características tal y como se ha descrito.
holidays['lower_window'] = -1 # The anticipation of the news affect the volatility 1 bar before it's release holidays['upper_window'] = 1 # The news affects the volatility 1 bar after its release holidays
Nuestro DataFrame de días festivos queda ahora así:
| ds | holiday | lower_window | upper_window | |
|---|---|---|---|---|
| 0 | 2023-01-02 01:00:00 | New Year's Day | -1 | 1 |
| 1 | 2023-01-02 02:00:00 | New Year's Day | -1 | 1 |
| 2 | 2023-01-02 03:00:00 | New Year's Day | -1 | 1 |
| 3 | 2023-01-02 04:00:00 | New Year's Day | -1 | 1 |
| 4 | 2023-01-02 05:00:00 | New Year's Day | -1 | 1 |
| ... | ... | ... | ... | ... |
| 15369 | 2025-06-20 18:00:00 | Eurogroup Meeting | -1 | 1 |
| 15370 | 2025-06-20 19:00:00 | Eurogroup Meeting | -1 | 1 |
| 15371 | 2025-06-20 20:00:00 | Eurogroup Meeting | -1 | 1 |
| 15372 | 2025-06-20 21:00:00 | Eurogroup Meeting | -1 | 1 |
| 15373 | 2025-06-20 22:00:00 | Eurogroup Meeting | -1 | 1 |
Por último, le proporcionamos a nuestro modelo «Prophet» el DataFrame de días festivos y los datos de entrenamiento que habíamos preparado anteriormente.
model_w_holidays = Prophet(holidays=holidays) model_w_holidays.fit(prophet_df_train)
Podemos comprobar las predicciones realizadas por el modelo entrenado con los días festivos representando gráficamente los valores predichos junto a los valores reales, tal y como hicimos anteriormente.
# Predict on training set with model test_fcst = model_w_holidays.predict(df=prophet_df_test) test_pred = test_fcst.yhat # We get the predictions # Plot the forecast with the actuals f, ax = plt.subplots(figsize=(10,5)) ax.scatter(prophet_df_test["ds"], prophet_df_test['y'], color='r') fig = model_w_holidays.plot(test_fcst, ax=ax)
Resultados:

Figura 8
A diferencia de las predicciones realizadas por el modelo sin datos de noticias (días festivos) que se muestran en la Figura 5, que parecen estáticas, las predicciones realizadas por este nuevo modelo con datos de noticias (días festivos) parecen reflejar algunas de las fluctuaciones que el modelo anterior no tenía en cuenta.
Una vez más, evaluamos el modelo utilizando los mismos indicadores que empleamos para el modelo anterior.
results = forecast_accuracy(test_pred, prophet_df_test["y"]) for metric_name, value in results.items(): print(f"{metric_name:<10}: {value:.6f}")
Resultados:
mape : 0.549152 me : -0.000633 mae : 0.000970 mpe : -0.175082 rmse : 0.001487 minmax : 0.461444 r2_score : -2.793478
La métrica MAPE muestra que se ha producido una mejora de aproximadamente el 10 % en las predicciones realizadas por el modelo. El modelo anterior presentaba un porcentaje de errores de aproximadamente el 60 %, mientras que este presenta un porcentaje de errores de alrededor del 55 %. Esta mejora también se aprecia en el r2_score.
El modelo que comete un 55 % de errores sigue sin ser bueno; un modelo ideal tiene que cometer, como mínimo, menos del 50 % de errores (< 50 %). Aún podemos hacer algo con respecto a los días festivos (noticias) para mejorar este modelo.
En este ejemplo, hemos establecido los valores de lower_window y upper_window en -1 y 1, respectivamente, lo que significa que las noticias afectan a la volatilidad del mercado una barra antes y una barra después de su publicación. Aunque esto ha mejorado el modelo, dudo que sea la solución ideal.
Sabemos que las distintas noticias pueden tener horizontes de impacto y niveles de intensidad diferentes, por lo que aplicar estos valores fijos a todas las noticias es un error fundamental. Además, hemos tenido en cuenta todas las noticias, incluso aquellas de menor importancia, que a menudo ignoramos como operadores porque se producen con mucha frecuencia y resulta difícil medir y observar su impacto en el gráfico.
Para solucionar estos dos problemas, hay que establecer los valores de lower_window y upper_window de forma dinámica, en función del tipo de noticia y de su impacto observable históricamente.
Ejemplo de pseudocódigo:
def get_windows(name): if "CPI" in name: return (-1, 4) # CPI news affects one previous bar volatility, and it affects the volatility of four bars ahead (4 hours impact forward) elif "NFP" in name: return (-1, 2) # NFP news affects one previous bar volatility, and it affects the volatility of two bars ahead (2 hours impact afterward) elif "FOMC" in name or "Rate" in name: return (-2, 6) # NFP news affects two previous bar volatility, and it affects the volatility of six bars ahead (6 hours impact afterward) else: return (0, 1) # Default holidays[['lower_window', 'upper_window']] = holidays['holiday'].apply( lambda name: pd.Series(get_windows(name)) )
Dado que existen decenas de miles de tipos de noticias distintos y hay que asegurarse de los valores de impacto aplicados, este enfoque resulta muy difícil de poner en práctica, pero es la forma ideal. Así que, haz los deberes :).
Por ahora, lo más lógico que podemos hacer es filtrar algunas noticias para quedarnos solo con aquellas de mayor y moderada importancia.
news_df = df[ (df['Name'] != "(null)") & # Filter rows without news at all ((df['Importance'] == "CALENDAR_IMPORTANCE_HIGH") | (df['Importance'] == "CALENDAR_IMPORTANCE_MODERATE")) # Filter other news except high importance news ].copy() news_df
Resultados:
| Time | Open | High | Low | Close | Name | Sector | Importance | Actual | Forecast | Previous | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 7 | 2023.01.02 08:00:00 | 1.06921 | 1.06973 | 1.06724 | 1.06858 | S&P Global Manufacturing PMI | CALENDAR_SECTOR_BUSINESS | CALENDAR_IMPORTANCE_MODERATE | 47.10 | 47.400 | 47.400 |
| 8 | 2023.01.02 09:00:00 | 1.06878 | 1.06909 | 1.06627 | 1.06784 | S&P Global Manufacturing PMI | CALENDAR_SECTOR_BUSINESS | CALENDAR_IMPORTANCE_MODERATE | 47.80 | 47.800 | 47.800 |
| 31 | 2023.01.03 08:00:00 | 1.06636 | 1.06677 | 1.06514 | 1.06524 | Unemployment | CALENDAR_SECTOR_JOBS | CALENDAR_IMPORTANCE_MODERATE | 2.52 | 2.522 | 2.538 |
| 37 | 2023.01.03 14:00:00 | 1.05283 | 1.05490 | 1.05241 | 1.05355 | S&P Global Manufacturing PMI | CALENDAR_SECTOR_BUSINESS | CALENDAR_IMPORTANCE_HIGH | 46.20 | 46.200 | 46.200 |
| 38 | 2023.01.03 15:00:00 | 1.05353 | 1.05698 | 1.05304 | 1.05602 | Construction Spending m/m | CALENDAR_SECTOR_HOUSING | CALENDAR_IMPORTANCE_MODERATE | 0.20 | 0.200 | -0.300 |
Queda genial: tras extraer las columnas de hora y nombre al DataFrame «holidays», añadimos los valores lower_window y upper_window.
holidays = news_df[['Time', 'Name']].rename(columns={ 'Time': 'ds', 'Name': 'holiday' }) holidays['ds'] = pd.to_datetime(holidays['ds']) # Ensure datetime format holidays['lower_window'] = 0 holidays['upper_window'] = 1 holidays
Tras entrenar el modelo, a continuación se muestra un gráfico en el que aparecen los valores reales de las muestras de entrenamiento y de prueba, en negro y rojo respectivamente, y las predicciones de la muestra de prueba, en azul.

Figura 9
El modelo volvió a mejorar, con un porcentaje de errores de aproximadamente el 50 % según la métrica MAPE. Ahora podemos utilizar este modelo de regresión para realizar predicciones.
mape : 0.506827 me : -0.000053 mae : 0.000783 mpe : 0.271597 rmse : 0.001234 minmax : 0.320422 r2_score : -3.318859
Quizá hayas observado que hemos importado las noticias por separado desde un archivo CSV, mientras que las hemos utilizado junto con los datos de entrenamiento importados directamente desde MetaTrader 5.
El modelo Prophet sincroniza las fechas del DataFrame «holidays» con las del conjunto de datos de entrenamiento principal, siempre y cuando las marcas de tiempo del DataFrame «holidays» se encuentren dentro del periodo de entrenamiento o de predicción futura.
Aunque este modelo permite sincronizar las fechas, debes asegurarte expresamente de que ambos conjuntos de datos tengan las mismas fechas de inicio para sacar el máximo partido a ambos.
He tenido que volver atrás y modificar el proceso de obtención de información sobre precios desde MetaTrader 5 dentro de main.ipynb; ahora las fechas de inicio y fin coinciden con las utilizadas en el archivo de script OHLC + News.mq5.
# set time zone to UTC timezone = pytz.timezone("Etc/UTC") # create 'datetime' objects in UTC-time to avoid the implementation of a local time zone offset utc_from = datetime(2023, 1, 1, tzinfo=timezone) utc_to = datetime(2025, 6, 24, hour = 0, tzinfo=timezone) rates = mt5.copy_rates_range(symbol, timeframe, utc_from, utc_to)
Creación del robot de trading para MetaTrader 5 basado en el modelo «Prophet»
Para crear un robot de trading basado en el modelo Prophet, primero tenemos que ser capaces de utilizarlo para realizar predicciones en tiempo real sobre la variable objetivo (en este caso, la volatilidad).
Para lograrlo, necesitamos un pipeline que nos permita obtener la información más reciente del mercado (símbolos), incluidas las últimas noticias, todo de una sola vez. En el script de entrenamiento main.ipynb, hemos recopilado datos de MetaTrader 5 utilizando el paquete MetaTrader 5-Python; sin embargo, este paquete no ofrece ninguna forma de obtener noticias, por lo que, sin duda, tendremos que utilizar MQL5 para este proceso.
La idea es intercambiar datos entre el script de Python (robot de trading) y un Asesor Experto (EA) en MQL5.
- Un EA (Data for Prophet.mq5) asociado al gráfico de MetaTrader 5 guarda periódicamente los datos (noticias y valores OHLC) de MetaTrader 5 en un archivo CSV ubicado en la carpeta común.
- A continuación, el script de Python (Prophet-trading-bot.py) lee este archivo para entrenar periódicamente el modelo Prophet.
- Una vez entrenado, el modelo se utiliza para realizar predicciones que, a su vez, sirven para tomar decisiones de trading dentro del mismo script de Python.
Nombre del archivo: Data for Prophet.mq5
input uint collect_news_interval_seconds = 60; input uint training_bars = 1000; input ENUM_TIMEFRAMES timeframe = PERIOD_H1; //... other lines of code //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create timer EventSetTimer(collect_news_interval_seconds); if (!ChartSetSymbolPeriod(0, Symbol(), timeframe)) return INIT_FAILED; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- destroy timer EventKillTimer(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- MqlDateTime time_struct; TimeToStruct(TimeGMT(), time_struct); SaveNews(StringFormat("%s.%s.OHLC.date=%s.hour=%d + News.csv",Symbol(),EnumToString(timeframe), TimeToString(TimeGMT(), TIME_DATE), time_struct.hour)); }
Para asegurarnos de que estamos trabajando con el archivo correcto, se utilizan la fecha y la hora actual (en hora UTC) para nombrar el archivo CSV.
Este asesor experto recopila noticias y otros valores y los guarda en un archivo CSV cada minuto de forma predeterminada, según la función OnTimer.
Dentro de un script de Python, cargamos el archivo CSV desde la carpeta común de la misma forma e importamos los datos.
Nombre del archivo: Prophet-trading-bot.py
def prophet_vol_predict() -> float: # Getting the data with news now_utc = datetime.utcnow() current_date = now_utc.strftime("%Y.%m.%d") current_hour = now_utc.hour filename = f"{symbol}.{timeframe}.OHLC.date={current_date}.hour={current_hour} + News.csv" # the same file naming as in MQL5 script common_path = os.path.join(terminal.common_data_path(), "Files") csv_path = os.path.join(common_path, filename) # Keep trying to read a CSV file until it is found, as there could be a temporary difference in values for the file due to the change in time while True: if os.path.exists(csv_path): try: rates_df = pd.read_csv(csv_path) rates_df["Time"] = pd.to_datetime(rates_df["Time"], unit="s", errors="ignore") # Convert time from seconds to datetime print("File loaded successfully.") break # Exit the loop once file is read except Exception as e: print(f"Error reading the file: {e}") time.sleep(30) else: print("File not found. Retrying in 30 seconds...") time.sleep(30)
Preparamos la columna de volatilidad y extraemos los nombres de las noticias para los datos de entrenamiento y los datos de días festivos, respectivamente.
# Getting continous variables for the prophet model prophet_df = pd.DataFrame({ "time": rates_df["Time"], "volatility": rates_df["High"] - rates_df["Low"] }).set_index("time") prophet_df = prophet_df.reset_index().rename(columns={"time": "ds", "volatility": "y"}).copy() print("Prophet df\n",prophet_df.head()) # Getting the news data for the model as well news_df = rates_df[ (rates_df['Name'] != "(null)") & # Filter rows without news at all ((rates_df['Importance'] == "CALENDAR_IMPORTANCE_HIGH") | (rates_df['Importance'] == "CALENDAR_IMPORTANCE_MODERATE")) # Filter other news except high importance news ].copy() holidays = news_df[['Time', 'Name']].rename(columns={ 'Time': 'ds', 'Name': 'holiday' }) holidays['ds'] = pd.to_datetime(holidays['ds']) # Ensure datetime format holidays['lower_window'] = 0 holidays['upper_window'] = 1 print("Holidays df\n", holidays)
Al final de la función prophet_vol_pred, entrenamos el modelo con la información recibida y devolvemos un único valor previsto, que representa la volatilidad prevista que, según el modelo, se producirá en la próxima barra del mercado.
# re-training the prophet model prophet_model = Prophet(holidays=holidays) prophet_model.fit(prophet_df) # Making future predictions future = prophet_model.make_future_dataframe(periods=1) # prepare the dataframe for a single value prediction forecast = prophet_model.predict(future) # Predict the next one value return forecast.yhat[0] # return a single predicted value
Al igual que ocurre con otros modelos de aprendizaje automático utilizados en la previsión de series temporales, debemos actualizarlos con mucha frecuencia para garantizar que dispongan de la información más reciente que sea relevante para las previsiones futuras (predicciones). Esta es la razón principal por la que volvemos a entrenar el modelo antes de realizar nuevas predicciones.
Ejecutemos la función y veamos el resultado.
print("predicted volatility: ",prophet_vol_predict())
Resultados:
El archivo se ha cargado correctamente. Prophet df ds y 0 2025.04.29 01:00:00 0.00100 1 2025.04.29 02:00:00 0.00210 2 2025.04.29 03:00:00 0.00170 3 2025.04.29 04:00:00 0.00215 4 2025.04.29 05:00:00 0.00278 Holidays df ds holiday lower_window upper_window 8 2025-04-29 09:00:00 GfK Consumer Climate 0 1 14 2025-04-29 15:00:00 Retail Inventories excl. Autos m/m 0 1 31 2025-04-30 08:00:00 Consumer Spending m/m 0 1 33 2025-04-30 10:00:00 Unemployment 0 1 35 2025-04-30 12:00:00 GDP y/y 0 1 .. ... ... ... ... 978 2025-06-24 19:00:00 FOMC Member Williams Speech 0 1 979 2025-06-24 20:00:00 2-Year Note Auction 0 1 982 2025-06-24 23:00:00 Fed Vice Chair for Supervision Barr Speech 0 1 984 2025-06-25 01:00:00 Jobseekers Total 0 1 994 2025-06-25 11:00:00 Bbk Executive Board Member Mauderer Speech 0 1 [186 rows x 4 columns] 16:01:50 - cmdstanpy - INFO - Chain [1] start processing 16:01:50 - cmdstanpy - INFO - Chain [1] done processing predicted volatility: 0.0013592111956094713
Ahora que somos capaces de obtener el valor previsto, podemos utilizarlo en nuestra estrategia de trading.
symbol = "EURUSD" timeframe = "PERIOD_H1" terminal = CTerminalInfo() m_position = CPositionInfo() def main(): m_symbol = CSymbolInfo(symbol=symbol) magic_number = 25062025 slippage = 100 m_trade = CTrade(magic_number=magic_number, filling_type_symbol=symbol, deviation_points=slippage) m_symbol.refresh_rates() # Get recent information from the market # we want to open random buy and sell trades if they don't exist and use the predicted volatility to set our stoploss and takeprofit targets predicted_volatility = prophet_vol_predict() print("predicted volatility: ",prophet_vol_predict()) if pos_exists(mt5.POSITION_TYPE_BUY, magic_number, symbol) is False: m_trade.buy(volume=m_symbol.lots_min(), symbol=symbol, price=m_symbol.ask(), sl=m_symbol.ask()-predicted_volatility, tp=m_symbol.ask()+predicted_volatility) if pos_exists(mt5.POSITION_TYPE_SELL, magic_number, symbol) is False: m_trade.sell(volume=m_symbol.lots_min(), symbol=symbol, price=m_symbol.bid(), sl=m_symbol.bid()+predicted_volatility, tp=m_symbol.bid()-predicted_volatility)
La función anterior obtiene la volatilidad prevista del modelo Prophet y la utiliza para establecer los objetivos de stop-loss y take-profit en nuestras operaciones. Antes de abrir una operación aleatoria, comprueba si ya existe una posición (operación) del mismo tipo antes de abrirla.
Llamada a una función:
main()
Resultado:
Figura 10
Se abrieron dos operaciones opuestas en MetaTrader 5 con valores de stop loss y take profit que corresponden a la volatilidad prevista por el modelo.
Podemos automatizar este proceso de formación y supervisar periódicamente las operaciones de trading y las señales.
schedule.every(1).minute.do(main) # train and run trading operations after every one minute while True: schedule.run_pending() time.sleep(1)
Conclusión
Aunque algunos artículos, publicaciones y tutoriales en Internet afirman que el modelo Prophet es adecuado para la predicción de series temporales, creo que es uno de los peores modelos que hemos analizado en esta serie de artículos.
Puede que resulte útil para predecir algunos problemas sencillos de series temporales, como la demanda de una empresa que dependa de las condiciones meteorológicas, los días festivos o algún tipo de patrón estacional; sin embargo, los mercados financieros son mucho más complejos que eso, tal y como se aprecia en las figuras (05, 06, 07, 08, 09), que muestran los valores reales y los valores previstos en las muestras de prueba. El modelo «Prophet» no consigue que la mayoría de las predicciones se acerquen a los valores reales.
Entiendo que hay ciertas cosas que se pueden hacer para mejorarlo, pero yo recomendaría utilizarlo, por ahora, en problemas sencillos.
Entre las limitaciones de este modelo cabe destacar las siguientes:
- Estructura de modelo sencilla que no admite interacciones complejas.
- No se adapta bien a la volatilidad; como se ha visto anteriormente, no da buenos resultados con los datos del mercado de divisas.
- Sin modelos multivariantes: admite dos características: el tiempo y la variable de respuesta.
- No ofrece validación cruzada ni facilidades claras para el ajuste de hiperparámetros, ya que debes controlar tú mismo la tendencia, la estacionalidad y los puntos de cambio.
Saludos cordiales.
Fuentes y referencias
- https://facebook.github.io/prophet/
- https://otexts.com/fpp3/prophet.html
- https://www.geeksforgeeks.org/time-series-analysis-using-facebook-prophet/
- https://www.kaggle.com/code/omegajoctan/time-series-forecasting-with-prophet/edit
Tabla de archivos adjuntos
| Nombre del archivo | Descripción y uso |
|---|---|
| Python code\main.ipynb | Un cuaderno Jupyter para el análisis de datos y la exploración del modelo Prophet. |
| Python code\Prophet-trading-bot.py | Robot de trading MetaTrader 5 basado en Python. |
| Python code\requirementx.txt | Un archivo de texto que contiene las dependencias de Python y su número de versión. |
| Python code\error_description.py | Contiene la descripción de todos los códigos de error generados por MetaTrader 5. |
| Python code\Trade\* | Contiene las clases Trade (CTrade, CPositionInfo, etc.) para Python, similares a las disponibles en el lenguaje MQL5. |
| Experts\Data for Prophet.mq5 | Un asesor experto que recopila y almacena periódicamente los datos para entrenar el modelo Prophet en un archivo CSV. |
| Scripts\OHLC + News.mq5 | Un script para recopilar y almacenar en un archivo CSV los datos para entrenar el modelo Prophet. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/18549
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Utilizando redes neuronales en MetaTrader
Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 29): Boom and Crash Interceptor EA
Particularidades del trabajo con números del tipo double en MQL4
Dominando los registros (Parte 9): Implementación del patrón Builder y adición de configuraciones predeterminadas
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso