English Русский Deutsch 日本語
preview
Obtenga una ventaja sobre cualquier mercado

Obtenga una ventaja sobre cualquier mercado

MetaTrader 5Ejemplos | 8 agosto 2024, 12:08
71 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Contenido

  1. Sinopsis
  2. Introducción
  3. Visión general de la estrategia: Fuentes de datos alternativas
  4. Técnicas de aprendizaje automático
  5. Construir la estrategia
  6. Conclusión
  7. Recomendaciones


Sinopsis

Hoy elaboraremos una sólida estrategia de negociación diseñada para proporcionar a los operadores una ventaja competitiva significativa en diversos mercados. Mientras que los participantes convencionales en el mercado se basan exclusivamente en una combinación de datos relacionados con los precios, indicadores técnicos y anuncios de noticias públicas para la toma de decisiones, nuestra estrategia adopta un enfoque pionero al aprovechar fuentes de datos alternativas que siguen siendo en gran medida inexploradas por la mayoría.

La premisa de nuestra estrategia radica en la integración de datos alternativos, una opción que los principales participantes en el mercado suelen pasar por alto. Aprovechando estas fuentes de datos sin explotar y aplicando técnicas de aprendizaje automático, podemos posicionarnos para obtener ideas y perspectivas únicas y exclusivas de nuestra estrategia.

En nuestra exploración, examinaremos los datos proporcionados por el Banco de la Reserva Federal de San Luis, concretamente aprovechando su completa base de datos econométricos de series temporales conocida como FRED. FRED es accesible al público en todo momento, y sin duda ofrece datos cruciales para la toma de decisiones informadas en el comercio. Además, los datos procedentes de bancos centrales como la Fed de St. Louis suelen servir de indicadores adelantados, lo que mejora nuestra capacidad para programar eficazmente las entradas y salidas.

Además, estos datos son inmunes a la manipulación externa, lo que los convierte en un candidato ideal para integrarlos en nuestra estrategia de negociación.

Este artículo pretende servir de guía práctica, demostrando la fácil utilización de Python y MetaTrader 5 para construir estrategias de trading de vanguardia. Nuestro compromiso con la claridad y la simplicidad asegura que cada aspecto esté explicado de manera clara, permitiendo a los lectores comprender nuestro enfoque sin dificultad y comenzar hoy mismo.


Introducción: Este artículo pretende demostrar cómo aplicar fácilmente datos alternativos en las estrategias de negociación. 

Al final de este artículo, los lectores obtendrán información sobre las siguientes áreas clave:

  1. Cómo los datos alternativos pueden ayudar a tomar decisiones en medio del ruido y la incertidumbre.
  2. Técnicas de selección e identificación de fuentes fiables de datos alternativos.
  3. Mejores prácticas de análisis y preprocesamiento de datos alternativos para el análisis.
  4. Creación de estrategias de negociación sólidas que integren fuentes de datos alternativas para mejorar el proceso de toma de decisiones.

Un ejemplo que ilustra el impacto de los datos alternativos es el uso estratégico de imágenes satelitales. Los operadores avanzados aprovechan las imágenes de satélite para seguir las pautas del tráfico marítimo u observar los niveles de inventario de los petroleros. Estos datos exclusivos permiten a los operadores descubrir oportunidades de negociación rentables que, de otro modo, permanecerían ocultas.

Aunque el uso de imágenes por satélite puede ser más común entre los operadores adinerados, este artículo muestra cómo cualquier operador puede emplear datos alternativos de libre acceso para adelantarse al mercado. Además, mediante el uso de modelos de aprendizaje automático, podemos analizar múltiples fuentes de datos simultáneamente, mejorando aún más su capacidad de toma de decisiones.


Visión general de la estrategia de negociación: Fuentes de datos alternativas.

Nuestra estrategia de negociación está diseñada para ser fácilmente comprensible. Integraremos datos de mercado convencionales de nuestro terminal MetaTrader 5 con datos alternativos procedentes del Banco de la Reserva Federal de St. Louis, centrándonos específicamente en la previsión de los futuros movimientos de precios del par GBPUSD.

Para lograrlo, utilizaremos dos conjuntos de datos económicos clave como fuentes de datos alternativas. El primer conjunto de datos proporciona información sobre la libra esterlina, ofreciendo una serie temporal de los tipos de interés aplicados a las transacciones bancarias fuera de hora en el mercado de la libra esterlina británica. Estas fluctuaciones de los tipos de interés sirven para calibrar el nivel de demanda institucional de libras esterlinas, proporcionando valiosos indicadores para nuestros modelos de previsión.

Del mismo modo, el segundo conjunto de datos contiene información sobre el dólar estadounidense y comprende una serie temporal de los tipos de interés aplicados a los préstamos a un día a los bancos estadounidenses, regidos por la Reserva Federal. El control que ejerce la Reserva Federal sobre estos tipos de interés a través de los ajustes de la política monetaria ofrece perspectivas alternativas sobre las tendencias económicas que pueden repercutir en el dólar.

Analizando e interpretando estos datos de series temporales económicas y empleando técnicas de aprendizaje automático, es de esperar que podamos hacer realidad nuestro objetivo de descubrir indicadores adelantados que nos otorguen una ventaja competitiva en el mercado.

La piedra angular de la eficacia de nuestra estrategia depende de garantizar una fuente fiable de datos alternativos. La disponibilidad de fuentes de datos alternativas fiables varía en función de los mercados en los que se opere. Los mercados sintéticos, generados por generadores de números aleatorios, carecen prácticamente de fuentes de datos alternativas. Esto se debe a que los mercados sintéticos son independientes del mundo exterior.

  1. Credibilidad: ¿De qué manera obtiene tu fuente de datos alternativos la información en primer lugar? Examina la fiabilidad de los canales de información de los que dependen. Preguntas como "¿Cómo acceden a la información?" y "¿Son fiables sus canales de información?" son cruciales para evaluar la credibilidad. Cualquier duda sobre estos aspectos indica la necesidad de una evaluación más exhaustiva.
  2. Frecuencia de actualización: Nos centramos en fuentes de datos alternativas actualizadas diariamente, en consonancia con nuestro marco temporal de negociación. Sin embargo, hay que tener en cuenta que no todas las fuentes ofrecen actualizaciones diarias; algunas se actualizan mensual o anualmente.
  3. Reputación: Más allá de la credibilidad, dé prioridad a las fuentes con un historial reputado y un interés demostrado por mantener la exactitud. Un proveedor acreditado no sólo añade credibilidad a nuestros datos, sino que también demuestra responsabilidad.
  4. Presentación transparente: Opte por proveedores que presenten los datos de forma transparente y fácil de usar. La claridad y la sencillez en la presentación de los datos son primordiales para una toma de decisiones eficaz, sobre todo teniendo en cuenta la carga cognitiva asociada a los datos complejos.
  5. Estructura de precios: Evaluar los modelos de precios de fuentes de datos alternativas, equilibrando nuestras necesidades y las limitaciones presupuestarias. Mientras que algunas fuentes pueden ser gratuitas, otras pueden exigir un pago. Nuestra elección debe ajustarse a la propuesta de valor ofrecida por cada fuente.
  6. Términos y condiciones: Revise detenidamente y comprenda los términos y condiciones asociados a las fuentes de datos alternativas, en particular las que exigen un pago. Una comprensión clara de las restricciones y limitaciones de uso garantiza una toma de decisiones informada y evita cualquier problema de cumplimiento involuntario.

En resumen, una evaluación rigurosa de las fuentes de datos alternativas basada en la credibilidad, la frecuencia de actualización, la reputación, la transparencia, el precio y los términos y condiciones es esencial para aprovechar los datos con eficacia dentro de nuestra estrategia de negociación.

Empezaremos ahora a examinar algunos datos alternativos procedentes del Banco de la Reserva Federal de San Luis. Hay dos formas de obtener datos de la Reserva Federal de San Luis:

  1. De manera programática utilizando la biblioteca FRED para Python.
  2. Manualmente en el sitio web de FRED. 

Si es la primera vez que utiliza estos conjuntos de datos, le aconsejo que primero los recopile manualmente. Esto es aconsejable porque el sitio web de FRED tiene notas e información útiles sobre cada conjunto de datos, cómo se registraron, qué representan los datos, si están o no ajustados estacionalmente, las unidades y escalas de las mediciones y otros detalles de esa naturaleza. Una vez que esté familiarizado con la naturaleza de los datos, puede pasar a recopilarlos mediante programación. Así pues, para nuestra primera demostración, los conjuntos de datos se descargaron manualmente del sitio web de la Reserva Federal de San Luis. Pasaremos al enfoque programático cuando estemos elaborando la estrategia. 

Lo primero que vamos a hacer es recoger los datos de mercado de nuestro MetaTrader 5 utilizando un script MQL5, yo prefiero recoger los datos de esta manera porque puedes realizar cualquier preprocesamiento que necesites en el lado MQL5 donde tienes acceso ilimitado a los datos. Nuestro script es modestamente sencillo.

  • Comenzamos declarando manejadores para nuestros indicadores técnicos, utilizaremos 4 medias móviles.
  • Luego declaramos buffers para almacenar las lecturas de nuestras medias móviles, los buffers en nuestro caso son arrays dinámicos.
  • A continuación, necesitamos un nombre para nuestro archivo, el nuestro será el nombre del par que estamos negociando seguido de la cadena "Market Data As Series", y tendrá formato CSV.
  • A continuación, declaramos cuántos datos queremos recopilar. 
  • Tenga en cuenta que el script funciona con el marco temporal actual del gráfico al que se aplica.
  • Hemos llegado a nuestro manejador de eventos OnStart(), aquí es donde se encuentra el corazón de nuestro script.
  • Comenzamos inicializando los 4 indicadores técnicos.
  • A continuación, copiamos los valores de los indicadores en las matrices que hemos creado anteriormente.
  • Una vez hecho esto, creamos un manejador de archivos para crear, escribir y cerrar nuestro archivo.
  • A continuación, utilizamos un simple bucle 'for' para recorrer las matrices y escribirlas en nuestro archivo CSV. Tenga en cuenta que en la primera iteración de nuestro bucle, escribimos las cabeceras de las columnas, después escribimos los valores reales que queremos.
  • Una vez completado el bucle, cerramos nuestro fichero, utilizando el manejador de ficheros y ya estamos listos para fusionar los datos de nuestro terminal MetaTrader 5 con nuestros datos alternativos.

#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com"
#property version   "1.00"

//---Our handlers for our indicators
int ma_handle_5;
int ma_handle_15;
int ma_handle_30;
int ma_handle_150;

//---Data structures to store the readings from our indicators
double ma_reading_5[];
double ma_reading_15[];
double ma_reading_30[];
double ma_reading_150[];

//---File name
string file_name = _Symbol + " " + " Market Data As Series.csv";

//---Amount of data requested
int size = 1000000;
int size_fetch = size + 100;

void OnStart()
  {
      //---Setup our technical indicators
      ma_handle_5 = iMA(_Symbol,PERIOD_CURRENT,5,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_15 = iMA(_Symbol,PERIOD_CURRENT,15,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_30 = iMA(_Symbol,PERIOD_CURRENT,30,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_150 = iMA(_Symbol,PERIOD_CURRENT,150,0,MODE_EMA,PRICE_CLOSE);
      
      //---Copy indicator values
      CopyBuffer(ma_handle_5,0,0,size_fetch,ma_reading_5);
      ArraySetAsSeries(ma_reading_5,true);
      CopyBuffer(ma_handle_15,0,0,size_fetch,ma_reading_15);
      ArraySetAsSeries(ma_reading_15,true);
      CopyBuffer(ma_handle_30,0,0,size_fetch,ma_reading_30);
      ArraySetAsSeries(ma_reading_30,true);
      CopyBuffer(ma_handle_150,0,0,size_fetch,ma_reading_150);
      ArraySetAsSeries(ma_reading_150,true);

      //---Write to file
       int file_handle=FileOpen(file_name,FILE_WRITE|FILE_ANSI|FILE_CSV,",");
       
    for(int i=-1;i<=size;i++){
      if(i == -1){
            FileWrite(file_handle,"Time","Open","High","Low","Close","MA 5","MA 15","MA 30","MA 150");
      }
      
      else{
            FileWrite(file_handle,iTime(_Symbol,PERIOD_CURRENT,i),
                                 iOpen(_Symbol,PERIOD_CURRENT,i),
                                 iHigh(_Symbol,PERIOD_CURRENT,i),
                                 iLow(_Symbol,PERIOD_CURRENT,i),
                                 iClose(_Symbol,PERIOD_CURRENT,i),
                                 ma_reading_5[i],
                                 ma_reading_15[i],
                                 ma_reading_30[i],
                                 ma_reading_150[i]
                                 );
      } 
    }
  }
//+------------------------------------------------------------------+

Ahora estamos preparados para empezar a explorar nuestros datos alternativos junto con nuestros datos de mercado.

Como siempre, empezaremos por importar los paquetes necesarios.

import pandas as pd
import numpy as np 
import matplotlib.pyplot as plt
import seaborn as sns

Ahora leemos los datos que exportamos de nuestro script MQL5.

GBPUSD = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\MetaQuotes\\Terminal\\NVUSDVJSNDU3483408FVKDL\\MQL5\\Files\\GBPUSD Market Data As Series.csv")

Al preparar los datos de mercado para el aprendizaje automático, asegúrese de que el precio de hoy es el último y el más antiguo el primero. 

GBPUSD = GBPUSD[::-1]

A continuación, tenemos que restablecer el índice.

GBPUSD.reset_index(inplace=True)

Definamos con cuánta antelación queremos hacer la previsión.

look_ahead = 30
splits = 30

Ahora tenemos que preparar el objetivo. 

GBPUSD["Target"] = GBPUSD["Close"].shift(-look_ahead)
GBPUSD.dropna(inplace=True)

Ahora tenemos que hacer que la fecha sea el índice, esto nos ayudará a alinear fácilmente nuestros datos de mercado con nuestros datos alternativos más adelante.

GBPUSD["Time"] = pd.to_datetime(GBPUSD["Time"])
GBPUSD.set_index("Time",inplace=True)

El primer conjunto de datos alternativo que vamos a considerar es la media diaria del índice Sterling Overnight (SOIA, Sterling Overnight Index Average). Es un promedio de los tipos de interés que cobran los bancos por prestar libras esterlinas fuera del horario comercial habitual.

Si la media de los tipos de interés de la libra esterlina aumenta mientras que la media de los tipos de interés del dólar disminuye, esto podría indicar que la libra esterlina se está fortaleciendo frente al dólar a nivel institucional. 

SOIA = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Downloads\\FED Data\\Daily Sterling Overnight Index Average\\IUDSOIA.csv")

Limpiemos los datos alternativos. Primero haz que la columna de fecha sea un objeto de fecha.

SOIA["DATE"] = pd.to_datetime(SOIA["DATE"])

Nuestro conjunto de datos contiene puntos, presumiblemente para representar la falta de observación. Sustituiremos todos los puntos por ceros y, a continuación, sustituiremos los ceros por el valor medio de la columna. 

SOIA["IUDSOIA"] = SOIA["IUDSOIA"].replace(".","0")
SOIA["IUDSOIA"] = pd.to_numeric(SOIA["IUDSOIA"])
non_zero_mean = SOIA.loc[SOIA['IUDSOIA'] != 0, 'IUDSOIA'].mean()
SOIA['IUDSOIA'] = SOIA['IUDSOIA'].replace(0, non_zero_mean)

A continuación hacemos que la fecha sea el índice.

SOIA.set_index("DATE",inplace=True)

La siguiente fuente de datos alternativa que consideraremos será el Tipo de Financiación a un Día Garantizado (SOFR, Secured Overnight Financing Rate). Es el coste de los préstamos a un día garantizados, y lo publica diariamente el Banco de la Reserva Federal de Nueva York. 

SOFR = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Downloads\\FED Data\\Secured Overnight Financing Rate\\SOFR.csv")

Tenga en cuenta que los pasos de preprocesamiento aplicados al conjunto de datos SOFR son idénticos a los aplicados al conjunto de datos SOIA, por lo que, para facilitar la lectura del artículo de principio a fin, omitiremos estos pasos. 

Fusionemos ahora los 3 marcos de datos que tenemos. Al establecer 'left_index' y 'right_index' en 'true' nos aseguramos de que ambos conjuntos de datos se alinean sólo en los días en que tenemos observaciones completas para cada uno de ellos. Por ejemplo, el conjunto de datos GBPUSD no tiene registros durante el fin de semana, por lo que todos los puntos de datos alternativos observados durante el fin de semana no se incluyen en nuestro marco de datos fusionado final. 

merged_df = SOIA.merge(SOFR,left_index=True,right_index=True)
merged_df = merged_df.merge(GBPUSD,left_index=True,right_index=True)

A continuación, tenemos que restablecer nuestro índice.

merged_df.reset_index(inplace=True)
merged_df.drop(columns=["index"],inplace=True)

Definamos nuestros predictores.

normal_predictors = ['Open', 'High', 'Low', 'Close', 'MA 5', 'MA 15','MA 30', 'MA 150']
alternative_predictors = ['IUDSOIA', 'SOFR']
all_predictors = normal_predictors + alternative_predictors

A continuación, crearemos un marco de datos para almacenar los niveles de error de cada combinación de predictores.

accuracy = pd.DataFrame(columns=["Normal","Alternative","All"],index=np.arange(0,splits))

Este es el aspecto que tiene ahora nuestro marco de datos.

merged_df

Nuestro marco de datos fusionados

Fig. 3: Nuestro conjunto de datos que contiene tanto nuestros datos normales como nuestros datos alternativos.


La primera columna es el tipo de interés medio de la libra esterlina, la segunda contiene el tipo de interés medio del dólar estadounidense. A partir de ahí, las siguientes columnas ya deberían resultarte familiares. Recuerde que el objetivo es el precio de cierre a 30 días vista.

Por último, exportaremos nuestro marco de datos fusionado a un archivo CSV para su uso posterior.

merged_df.to_csv('Alternative Data Target Look Ahead 30.csv')

Escalemos nuestros datos.

from sklearn.preprocessing import StandardScaler
scaled_data = merged_df.loc[:,all_predictors]
scaler = StandardScaler()
scaler.fit(scaled_data)
scaled_data = pd.DataFrame(scaler.transform(scaled_data),index=merged_df.index,columns=all_predictors)

Preparémonos ahora para entrenar nuestro modelo y ver si nuestros datos alternativos nos ayudan o nos frenan.

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error 
from sklearn.model_selection import TimeSeriesSplit

Dividamos los datos en entrenamiento y prueba.

tscv = TimeSeriesSplit(gap=look_ahead+10,n_splits=splits)

for i,(train,test) in enumerate(tscv.split(merged_df)):
    model = LinearRegression()
    model.fit(scaled_data.loc[train[0]:train[-1],all_predictors],merged_df.loc[train[0]:train[-1],"Target"])
    accuracy["All"][i] = mean_squared_error(merged_df.loc[test[0]:test[-1],"Target"],model.predict(scaled_data.loc[test[0]:test[-1],all_predictors]))


Ahora estamos graficando los resultados como diagramas de caja.

fig,axs = plt.subplots(1,3,sharex=True,sharey=True,figsize=(16,4))

for i,ax in enumerate(axs.flat):
    ax.boxplot(merged_df.iloc[:,i])
    ax.set_title(accuracy.columns[i])

Combinaciones de predictores

Fig. 4: Análisis de los valores de error obtenidos al utilizar datos normales (izquierda), datos alternativos (centro) y todos los datos disponibles (derecha).

Interpretemos los resultados: podemos ver claramente que tanto el conjunto normal de predictores como el conjunto alternativo de predictores tienen colas largas que llegan hasta la parte superior del gráfico. Sin embargo, el último gráfico, el que tiene tanto los predictores normales como los alternativos, tiene una forma aplastada. Esta forma aplastada es deseable porque muestra que cuando utilizamos ambos conjuntos de predictores juntos, obtenemos menos variación en nuestros errores. Nuestra precisión es estable en el último gráfico, pero en los dos primeros, en los que nos basamos totalmente en datos normales o en datos alternativos, nuestra precisión no es tan estable. 

También podemos comprobar si existen efectos de interacción en nuestros datos. Crearemos un gráfico de dispersión con el objetivo en el eje Y y el tipo de interés de la libra esterlina en el eje X.

sns.scatterplot(x=merged_df["IUDSOIA"],y=merged_df["Target"])

Efectos de Interacción Sterling

Fig. 5: Análisis de la relación entre el tipo de interés aplicado a los Sterlings y el valor futuro del par GBPUSD.

He aquí una forma de interpretar este gráfico: cada línea que va desde la parte superior del gráfico hasta la parte inferior representa cómo cambia el objetivo cuando se fija el tipo de interés de la libra esterlina. El hecho de que podamos observar valores objetivo variables aunque el tipo de interés de la libra esterlina sea fijo es un indicio claro de la existencia de efectos de interacción en nuestros datos. Esto puede ser un indicador de que hay otras fuerzas poderosas en juego que influyen en el objetivo más allá de los datos alternativos que hemos recogido.


Técnicas de aprendizaje automático 

La selección de una técnica de aprendizaje automático adecuada depende de la naturaleza de los datos de que se disponga. Considere lo siguiente:

  • Tamaño del conjunto de datos: Para conjuntos de datos pequeños con menos de diez mil filas o menos de 30 columnas, es aconsejable emplear modelos más sencillos para mitigar el riesgo de sobreajuste. Los modelos complejos, como las redes neuronales profundas, pueden tener dificultades para aprender eficazmente con datos tan limitados.
  • Ruido de datos: Los conjuntos de datos ruidosos, es decir, con puntos de datos que faltan o fluctuaciones aleatorias inexplicables, son más adecuados para modelos más sencillos. Los modelos complejos tienden a presentar una varianza elevada, por lo que es más probable que se ajusten en exceso a datos ruidosos y, además, en días de mercado especialmente ruidosos, puede que incluso estemos mejor sin ellos.
  • Dimensionalidad de los datos: En los casos en los que el conjunto de datos tiene un elevado número de columnas, las técnicas de preprocesamiento pueden ser beneficiosas. Emplear modelos que sean eficaces en el manejo de datos de alta dimensión y aplicar la selección de características y la reducción de la dimensionalidad.
  • Tamaño de los datos y potencia computacional: Si dispone de grandes conjuntos de datos con niveles de ruido aceptables y, además, tiene acceso a recursos computacionales suficientes, entonces puede estar justificado el uso de modelos sofisticados como las redes neuronales profundas. Estos modelos pueden captar con eficacia pautas y relaciones complejas dentro de los datos si se dispone de las capacidades informáticas adecuadas y de datos limpios.

En conclusión, no existe una solución perfecta para la selección de modelos de aprendizaje automático. La naturaleza de los datos, incluidos el tamaño, el ruido, la dimensionalidad y la potencia de cálculo disponible, desempeña un papel fundamental a la hora de determinar el enfoque más adecuado. Adaptar la elección del modelo para alinearlo con las características de los datos es crucial para lograr resultados predictivos sólidos y precisos.
A continuación le mostraremos cómo puede seleccionar un buen modelo para sus datos.


Empezaremos importando las bibliotecas que necesitamos.

import statistics as st

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

from sklearn.linear_model import Lasso,Ridge,LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import TimeSeriesSplit
from sklearn.metrics import mean_squared_error
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler

from xgboost import XGBRegressor

Ahora leeremos los datos del CSV que hemos exportado. El CSV contenía todos nuestros datos fusionados.

csv = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Alternative Data.csv")

Preparémonos para escalar los datos.

predictors = ['IUDSOIA', 'SOFR', 'Open', 'High', 'Low', 'Close']
target = 'Target'
scaled_data = csv.loc[:,predictors]
scaler = StandardScaler()
scaler.fit(scaled_data)
scaled_data = scaler.transform(scaled_data)

Entrenemos nuestros modelos.

splits = 10
gap = 30
models = ['Linear','Lasso','Ridge','Random Forest','Linear SVR','Sigmoid SVR','RBF SVR','2 Poly SVR','3 Poly SVR','XGB']

Prepararemos nuestra división de entrenamiento/prueba y luego crearemos un marco de datos para almacenar las métricas de error.

tscv = TimeSeriesSplit(n_splits=splits,gap=gap)
error_df = pd.DataFrame(index=np.arange(0,splits),columns=models)

Ahora podemos observar las métricas de error de nuestro modelo.

for i,(train,test) in enumerate(tscv.split(csv)):
    model=XGBRegressor()
    model.fit(scaled_data.loc[train[0]:train[-1],predictors],csv.loc[train[0]:train[-1],target])
    error_df.iloc[i,9] =mean_squared_error(csv.loc[test[0]:test[-1],target],model.predict(scaled_data.loc[test[0]:test[-1],predictors]))

error_df

El error de cada modelo

Fig. 6: Valores de error obtenidos de cada uno de los modelos ajustados.


Visualicemos algunos de los datos en forma de gráficos de caja.

fig , axs = plt.subplots(2,5,figsize=(20,20),sharex=True)

for i,ax in enumerate(axs.flat):
    ax.boxplot(error_df.iloc[:,i])
    ax.set_title(error_df.columns[i])


Modelos lineales

Fig. 7: Valores de error de algunos de los modelos lineales utilizados.


Modelos no lineales

Fig. 8: Valores de error de algunos de los modelos no lineales utilizados.


Mostraremos algunas de las estadísticas resumidas obtenidas.

Variación      Error 
Varianza lineal: 1.3365981802501968e-06 Error cuadrático medio lineal: 0.0022242681292296462
Varianza de Lasso: 3.0466413126186177e-05 Error cuadrático medio de Lasso: 0.004995731270431843
Varianza de cresta: 2.5678314939547713e-06 Error cuadrático medio de la cresta: 0.002467126140156681
Varianza de Random Forest: 2.607918492340197e-06 Error cuadrático medio de Random Forest: 0.002632579355696408
Varianza lineal SVR: 3.825627012092798e-05 Error cuadrático medio SVR lineal: 0.004484702122899226
Varianza SVR sigmoidea: 27.654341711864102 Error cuadrático medio de SVR sigmoide: 1.6693947903605928
Varianza RBF SVR: 4.1654658535332505e-05 Error cuadrático medio RBF SVR: 0.004992333849448852
2 Varianza Poly SVR: 6.739873404310582e-05 2 Poly SVR error cuadrático medio: 0.008163708245600027
3 Varianza Poly SVR: 0.0005393054392191576 3 Poly SVR error cuadrático medio: 0.018431036676781344
Varianza XGB: 7.053078880392137e-06 Error cuadrático medio XGB: 0.003163819414983548


Obsérvese que ninguno de los modelos tiene un rendimiento sobresaliente, sino que todos se encuentran más o menos dentro de la misma banda de rendimiento. En tales circunstancias, el modelo más sencillo puede ser la mejor opción porque es menos probable que se ajuste en exceso. Por lo tanto, en este ejemplo utilizaremos la regresión lineal como modelo de elección para nuestra estrategia de negociación. Optamos por él porque su nivel de error es tan bueno como el de cualquier otro modelo que hubiéramos podido elegir y, además, su varianza es baja. Por tanto, es menos probable que el modelo lineal se ajuste en exceso y más probable que sea estable a lo largo del tiempo. 


Construir la estrategia 

Ahora estamos listos para aplicar todo lo que hemos discutido en las secciones anteriores en una estrategia comercial robusta utilizando la biblioteca de MetaTrader 5 para Python. 

Se darán explicaciones en cada paso del camino para garantizar que todo el código sea fácil de seguir.

Primero importamos los paquetes que necesitamos.

from fredapi import Fred
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import time
from datetime import datetime
import matplotlib.pyplot as plt

El paquete 'fredapi' nos permite extraer datos mediante programación de la base de datos FRED. Sin embargo, antes de poder utilizar la biblioteca, debe crear una clave API. Las claves API son gratuitas, pero solo puedes obtener una después de crear una cuenta de usuario gratuita en la Reserva Federal de St. Louis.

Ahora definiremos las variables globales.

LOGIN = ENTER_YOUR_LOGIN
PASSWORD = 'ENTER_YOUR_PASSWORD'
SERVER = 'ENTER_YOUR_SERVER'
SYMBOL = 'GBPUSD'
TIMEFRAME = mt5.TIMEFRAME_D1
DEVIATION = 1000
VOLUME = 0
LOT_MULTIPLE = 1
FRED = Fred(api_key='ENTER_YOUR_API_KEY')

Ahora iniciaremos sesión en nuestra cuenta de operaciones.

if mt5.initialize(login=LOGIN,password=PASSWORD,server=SERVER):
    print('Logged in successfully')
else:
    print('Failed To Log in')

Conectado correctamente

Let's define our trading volume.

for index,symbol in enumerate(mt5.symbols_get()):
    if symbol.name == SYMBOL:
        print(f"{symbol.name} has minimum volume: {symbol.volume_min}")
        VOLUME = symbol.volume_min * LOT_MULTIPLE

GBPUSD tiene un volumen mínimo: 0.01


Vamos a definir las funciones que vamos a utilizar a lo largo de nuestro programa.

Primero necesitamos una función para obtener el precio actual del mercado desde nuestro terminal MetaTrader 5.

def get_prices():
    start = datetime(2024,3,20)
    end   = datetime.now()
    data  = pd.DataFrame(mt5.copy_rates_range(SYMBOL,TIMEFRAME,start,end))
    data['time'] = pd.to_datetime(data['time'],unit='s')
    data.set_index('time',inplace=True)
    return(data.iloc[-1,:])

Ahora necesitamos una función para solicitar datos alternativos a la Reserva Federal de St. Louis.

def get_alternative_data():
    SOFR = FRED.get_series_as_of_date('SOFR',datetime.now())
    SOFR = SOFR.iloc[-1,-1]
    SOIA = FRED.get_series_as_of_date('IUDSOIA',datetime.now())
    SOIA = SOIA.iloc[-1,-1]
    return(SOFR,SOIA)

A continuación, necesitamos una función que prepare las entradas para nuestro modelo.

def get_model_inputs():
    LAST_OHLC = get_prices()
    SOFR , SOIA = get_alternative_data()
    MODEL_INPUT_DF = pd.DataFrame(index=np.arange(0,1),columns=predictors)
    MODEL_INPUT_DF['Open'] = LAST_OHLC['open']
    MODEL_INPUT_DF['High'] = LAST_OHLC['high']
    MODEL_INPUT_DF['Low'] =  LAST_OHLC['low']
    MODEL_INPUT_DF['Close'] = LAST_OHLC['close']
    MODEL_INPUT_DF['IUDSOIA'] = SOIA
    MODEL_INPUT_DF['SOFR'] = SOFR
    model_input_array = np.array([[MODEL_INPUT_DF.iloc[0,0],MODEL_INPUT_DF.iloc[0,1],MODEL_INPUT_DF.iloc[0,2],MODEL_INPUT_DF.iloc[0,3],MODEL_INPUT_DF.iloc[0,4],MODEL_INPUT_DF.iloc[0,5]]])
    return(model_input_array,MODEL_INPUT_DF.loc[0,'Close'])


Entonces necesitamos una función que nos ayude a hacer una previsión utilizando nuestro modelo.

def ai_forecast():
    model_inputs,current_price = get_model_inputs()
    prediction = model.predict(model_inputs)
    return(prediction[0],current_price)

Entrenemos nuestro modelo.

training_data = pd.read_csv('C:\\Enter\\Your\\Path\\Here\\Alternative Data.csv')

Configuración de nuestro modelo.

from sklearn.linear_model import LinearRegression
model = LinearRegression()

Definir nuestros predictores y nuestro objetivo.

predictors = ['Open','High','Low','Close','IUDSOIA','SOFR']
target     = 'Target'

Ajuste de nuestro modelo.

model.fit(training_data.loc[:,predictors],training_data.loc[:,target])

Ahora hemos llegado al corazón de nuestro algoritmo de negociación:

  • Primero definimos un bucle infinito para mantener nuestra estrategia en marcha.
  • A continuación, obtenemos los datos actuales del mercado y los utilizamos para realizar una previsión.
  • Después tendremos banderas booleanas para representar las expectativas de nuestro modelo. Si nuestro modelo espera que el precio suba, 'BUY_STATE' es 'true', de lo contrario, si nuestro modelo espera que el precio baje, 'SELL_STATE' es 'false'.
  • Si no tenemos posiciones abiertas, seguiremos la previsión de nuestro modelo.
  • Si tenemos posiciones abiertas, comprobaremos si la previsión de nuestro modelo va en contra de nuestra posición abierta. Si lo es, entonces cerraremos la posición. De lo contrario, podemos dejar el puesto vacante.
  • Por último, una vez completados todos los pasos anteriores, pondremos el algoritmo a dormir durante un día y recuperaremos los datos actualizados al día siguiente.

while True:
    #Get data on the current state of our terminal and our portfolio
    positions = mt5.positions_total()
    forecast , current_price = ai_forecast()
    BUY_STATE , SELL_STATE = False , False

    #Interpret the model's forecast
    if(current_price > forecast):
        SELL_STATE = True
        BUY_STATE  = False 

    elif(current_price > forecast):
        SELL_STATE = False
        BUY_STATE  = True

    print(f"Current price is {current_price} , our forecast is {forecast}")

    #If we have no open positions let's open them
    if(positions == 0):
        print(f"We have {positions} open trade(s)")
        if(SELL_STATE):
            print("Opening a sell position")
            mt5.Sell(SYMBOL,VOLUME)
        elif(BUY_STATE):
            print("Opening a buy position")
            mt5.Buy(SYMBOL,VOLUME)

    #If we have open positions let's manage them
    if(positions > 0):
        print(f"We have {positions} open trade(s)")
        for pos in mt5.positions_get():
            if(pos.type == 1):
                if(BUY_STATE):
                    print("Closing all sell positions")
                    mt5.Close(SYMBOL)
            if(pos.type == 0):
                if(SELL_STATE):
                    print("Closing all buy positions")
                    mt5.Close(SYMBOL)
    #If we have finished all checks then we can wait for one day before checking our positions again
    time.sleep(24 * 60 * 60)


Resultado final

Fig. 9: Nuestra operación el primer día que la abrimos.



Día 2

Fig. 10: Nuestra operación del día siguiente.


Conclusión 

Los datos alternativos tienen un enorme potencial para cambiar nuestra forma de ver los mercados financieros. Si elegimos con cuidado las fuentes de datos adecuadas, es posible que nos encontremos en el lado correcto de la mayoría de las operaciones en las que participamos. El componente más importante de esta estrategia es disponer de una fuente fiable de datos alternativos; de lo contrario, da igual que utilices datos normales. Tómese su tiempo e investigue por su cuenta, llegue a sus propias conclusiones y siga su instinto. Recuerde que, al fin y al cabo, crear estrategias es tanto una ciencia como un arte. Por lo tanto, aplica tu capacidad de razonamiento con criterio a la hora de seleccionar qué fuentes de datos alternativas serían útiles y, además, deja que tu imaginación encuentre aplicaciones y casos de uso novedosos en los que la mayoría de la gente no pensaría, y estarás en una liga propia. 


Recomendaciones

A los futuros lectores les puede resultar provechoso buscar más fuentes de conjuntos de datos alternativos y utilizar técnicas de aprendizaje automático, como la selección del mejor subconjunto, para escoger fuentes útiles de datos alternativos. Además, recuerde que el modelo lineal que utilizamos en nuestra demostración hace fuertes suposiciones sobre el proceso que generó los datos, si estas suposiciones se violan entonces la precisión de nuestro modelo se deteriorará con el tiempo. 

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

Archivos adjuntos |
Alternative_Data.zip (569.06 KB)
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Características del Wizard MQL5 que debe conocer (Parte 12): Polinomio de Newton Características del Wizard MQL5 que debe conocer (Parte 12): Polinomio de Newton
El polinomio de Newton, que crea ecuaciones cuadráticas a partir de un conjunto de unos pocos puntos, es un enfoque arcaico pero interesante para observar una serie temporal. En este artículo tratamos de explorar qué aspectos podrían ser de utilidad para los operadores desde este enfoque, así como abordar sus limitaciones.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Redes neuronales: así de sencillo (Parte 77): Transformador de covarianza cruzada (XCiT) Redes neuronales: así de sencillo (Parte 77): Transformador de covarianza cruzada (XCiT)
En nuestros modelos, a menudo utilizamos varios algoritmos de atención. Y, probablemente, lo más frecuente es utilizar transformadores. Su principal desventaja es la necesidad de recursos. En este artículo, estudiaremos un nuevo algoritmo que puede ayudar a reducir los costes informáticos sin perder calidad.