Aprendizaje automático y Data Science (Parte 41): Detección de patrones en los mercados de divisas y de valores mediante YOLOv8
Contenido
- Introducción
- ¿Qué es YOLOv8?
- Obtención de patrones gráficos desde MetaTrader 5
- Uso de YOLOv8 para la detección de patrones
- Sesgos, riesgos y limitaciones de YOLOv8
- Detección de patrones gráficos en MetaTrader 5 usando YOLOv8
- Conclusión
Introducción
La detección de patrones en los mercados financieros es una tarea compleja en el aprendizaje automático y la inteligencia artificial. Aunque para nosotros, los seres humanos, parezca algo sencillo, una máquina necesita cierto esfuerzo para detectar e interpretar estos patrones, simplemente porque, a diferencia de los datos tabulares bidimensionales que solemos usar en el trading, la detección de patrones se extiende a datos de imágenes bidimensionales que normalmente se almacenan en formatos como .png, .jpg, etc.
Existe una gran cantidad de operadores con estrategias que dependen de la acción del precio y de patrones gráficos específicos en los mercados, tales como:
- Escaleras ascendentes y descendentes
- Triángulo ascendente
- Triángulo descendente
- Triángulo simétrico
- Bandera
- Cuña
- Techo doble
- Doble fondo
- Cabeza y hombros
- Techo o suelo redondeado
- Taza y asa
- y muchos más.
En lo que respecta a la programación, patrones como los de velas japonesas y las reacciones de los indicadores, que pueden identificarse incluso sin líneas de código sofisticadas, los patrones gráficos mencionados anteriormente son bastante complejos.
Se necesitaría un código sofisticado, bien escrito y optimizado para poder detectar incluso un patrón simple como la base en forma de W, así que ¿por qué no usar la IA para que nos ayude con esta tarea tediosa?
Para abordar este problema mediante la inteligencia artificial (IA), en este artículo vamos a analizar un modelo muy interesante llamado YOLOv8 que descubrí en huggingface.co.
Este modelo ayuda a detectar patrones gráficos en imágenes y gráficos con una precisión aceptable.
Para comprender plenamente el contenido de este artículo, es necesario tener conocimientos básicos sobre aprendizaje automático y el lenguaje de programación Python.
¿Qué es YOLOv8?
Según su documentación.
YOLOv8s es un modelo de detección de objetos basado en el marco YOLO (You Only Look Once). Este modelo está diseñado para detectar diversos patrones gráficos en tiempo real a partir de datos de negociación bursátil capturados en pantalla.
Este modelo ayuda a los operadores e inversores automatizando el análisis de los patrones gráficos y proporcionando información oportuna para la toma de decisiones informadas.
El modelo se ha perfeccionado con un conjunto de datos diverso y logra una alta precisión en la detección y clasificación de patrones del mercado de valores en escenarios de negociación en tiempo real.
Tal como está actualmente, este modelo puede predecir con precisión un par de patrones, entre ellos:
Patrón de cabeza y hombros superior
Una breve descripción del patrón
Este patrón indica que es posible un cambio de tendencia en el mercado.
Los operadores creen que tres conjuntos de picos y valles, con un pico más grande en el medio, indican que el precio de una acción comenzará a caer.
La línea del cuello representa el punto en el que los operadores bajistas comienzan a vender. Más información.
Patrón de cabeza y hombros inferior
Este es el patrón opuesto al de cabeza y hombros superior.
Patrón M Head:
Una breve descripción del patrón
También conocido como doble techo, este patrón se forma a partir de dos partes superiores redondeadas consecutivas.
Estos techos redondeados suelen indicar un cambio de tendencia bajista, ya que a menudo se producen después de un repunte alcista prolongado.
Si se forma un doble techo, el segundo techo redondeado suele quedar ligeramente por debajo del máximo del primero, lo que indica resistencia y agotamiento.
Los dobles techos son fenómenos poco frecuentes, y su formación suele indicar que los inversores buscan obtener los beneficios finales de una tendencia alcista. Más información.
Patrón W Bottom:
Esto funciona igual que el patrón M Head, pero a la inversa; más información.
Stock Line
No pude encontrar referencias al respecto en la documentación ni en internet, así que dejémoslo de lado por ahora.
Patrón de triángulo(s):

Estos patrones pueden ser un patrón de continuación, si se validan, o un potente patrón de reversión, en caso de fallo.
Los operadores utilizan triángulos para determinar cuándo se produce una reducción del rango de negociación de una acción o valor tras una tendencia bajista o alcista. Más información.
Obtención de patrones gráficos desde MetaTrader 5
Dado que YOLOv8 trabaja con imágenes (datos de imagen), necesitamos extraer una gran cantidad de imágenes de alta calidad que podamos usar para probar y experimentar con el modelo.
Por suerte, MetaTrader 5 y el lenguaje de programación MQL5 ofrecen una funcionalidad para tomar una captura de pantalla de cualquier gráfico y símbolo que deseemos. Vamos a recopilar un par de imágenes usando un script.
Archivo: ChartScreenshots.mq5
#property script_show_inputs input uint BarsToCapture = 1000; //Total Bars input uint BarsShift = 50; //Bars Shift //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Save current chart position long firstVisibleBar = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR); long chartShift = ChartGetInteger(0, CHART_SHIFT); double priceMax = ChartGetDouble(0, CHART_PRICE_MAX); double priceMin = ChartGetDouble(0, CHART_PRICE_MIN); //--- Set chart properties for clean screenshots ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images ChartSetInteger(0, CHART_SHOW_VOLUMES, false); ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false); ChartSetInteger(0, CHART_AUTOSCROLL, false); // prevent scrolling int steps = (int)MathCeil((double)BarsToCapture / BarsShift); for(int i = 0; i < steps; i++) { // Shift chart view int shift = i * (int)BarsShift; ChartNavigate(0, CHART_END, -shift); // Wait a moment for the chart to update Sleep(500); // Take screenshot string filename = StringFormat("Screenshots\\%s.%s.%d.png", Symbol(), EnumToString(Period()), i+1); FileDelete(filename); //we delete a previous screenshot with the same name if(!ChartScreenShot(0, filename, 640, 480, ALIGN_CENTER)) { printf("Failed to take screenshot #:%d Error = %d", i+1, GetLastError()); continue; } else { printf("Screenshot saved: %s", filename); } } //--- Restore original chart position ChartNavigate(0, CHART_END, -(int)firstVisibleBar); ChartSetDouble(0, CHART_PRICE_MAX, priceMax); ChartSetDouble(0, CHART_PRICE_MIN, priceMin); ChartSetInteger(0, CHART_SHIFT, chartShift); }
Esta función captura varias capturas de pantalla del gráfico actual durante 1000 barras (valor predeterminado), desplazando 50 barras (valor predeterminado) hacia atrás desde la captura de pantalla anterior.
Antes de llamar a la función de captura de pantalla, debemos asegurarnos de que el gráfico esté lo más limpio posible. Incluso pequeñas fuentes de ruido, como las líneas de la cuadrícula y el volumen de los ticks, podrían distraer a los modelos e impedirles detectar patrones importantes que aparecen en el gráfico.
ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); // Showing the timescale on a chart ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images ChartSetInteger(0, CHART_SHOW_VOLUMES, false); //Prevent displaying the tick volumes ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false); //Prevent drawing arrows that displays trading history ChartSetInteger(0, CHART_AUTOSCROLL, false); // prevent scrolling
Todas las imágenes se guardarán en la ruta MQL5\Files\Screenshots.
Uso de YOLOv8 para la detección de patrones
Según su documentación, a continuación se muestra el código mínimo necesario para ejecutar este modelo y obtener el resultado previsto.
Instalación
$pip install ultralytics
Primeros pasos.
from ultralytics import YOLOvv8 model = YOLOvv8.from_pretrained("foduucom/stockmarket-pattern-detection-yolov8") source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True)
Sin embargo, este código generará errores en su entorno, ya que actualmente no existe YOLOvv8 de Ultralytics (la documentación está algo desactualizada). A continuación se indica la forma correcta de hacerlo.
En primer lugar, necesitamos importar el objeto YOLO y completarlo con un modelo entrenado para la tarea.
from ultralytics import YOLO import os model = YOLO(os.path.join('Models','model.pt'))
El archivo model.pt se encuentra aquí. Una vez descargado el archivo, guárdelo en una subcarpeta denominada Models dentro de su directorio de trabajo actual.
A continuación, debemos llamar al método «predict» desde un objeto de modelo y pasarle el nombre de la imagen, y eso es todo: obtendrá el resultado previsto :).
model.predict("image_name.png", save=True)
Cuando save=True, el modelo guarda la imagen resultante, que contiene los patrones resaltados.
Pero esto es demasiado simple e insuficiente; vamos a crear una clase para este predictor para asegurarnos de tener un código fiable y robusto para analizar y predecir múltiples imágenes de una carpeta que contiene nuestras capturas de pantalla.
Además, necesitamos la mejor manera de gestionar las predicciones y visualizar el resultado.
Detección de patrones en una sola imagen
El constructor de nuestra clase recibe como entrada el objeto del modelo YOLO y la carpeta de imágenes, que contiene todas las capturas de pantalla tomadas de MetaTrader 5.
class YOLOv8deploy: def __init__(self, model: YOLO, images_folder: str): """A simple class for deploying YOLOv8 model for detecting trading patterns in chart images Args: model (YOLO): YOLO model object images_folder (str): A path where images will be imported from """ self.model = model self.images_folder = images_folder
También necesitamos una función en la clase para obtener todas las imágenes presentes en la carpeta especificada.
Esta función será útil al realizar múltiples predicciones, ya que nos permite saber la cantidad de imágenes disponibles en una carpeta al devolver una tupla que contiene la cantidad total de imágenes y sus nombres en una lista de Python.
def _get_images(self, folder: str, img_extensions: list=['*.png', '*.jpg', '*.jpeg']) -> tuple: """ A function to help us detect the number of images present in a folder Args: folder (str): A path where images are located img_extensions (list, optional): Image filenames extensions. Defaults to ['*.png', '*.jpg', '*.jpeg']. Returns: tuple: Returns the number of images present in a folder and their names """ image_files = [] for ext in img_extensions: image_files.extend(glob.glob(os.path.join(folder, ext))) return (len(image_files), image_files) # Get the number of images and their names
Ampliemos la función de predicción para que pueda predecir una sola imagen; esta función también debería informarnos sobre los patrones detectados y el nivel de confianza para dichos patrones.
def predict_image(self, img_name: str, hist: bool=True): """This function predicts a single image Args: img_name (str): name of the image hist (bool, optional): When set to false it means the function isn't predicting multiple instances and the outcome will be displayed. Defaults to True. """ if os.path.exists(img_name) == False: # Check if an image exists print(f"Failed to detect patterns, {img_name} not found") return results = self.model.predict(source=img_name, save=True) # Predict an image # Loop through the results for result in results: boxes = result.boxes # Contains bounding boxes and confidence names = result.names # Class index to name mapping if boxes is not None and len(boxes) > 0: for box in boxes: cls_id = int(box.cls[0]) # class id conf = box.conf[0].item() # confidence score label = names[cls_id] print(f"Detected: {label} (confidence: {conf:.2f})") # Open the saved image if this is a single (non-historical) run if not hist: base_name = os.path.splitext(os.path.basename(img_name))[0] + ".jpg" saved_path = os.path.join(result.save_dir, base_name) print("saved path: ",saved_path) if os.path.exists(saved_path): print(f"Opening detected image: {saved_path}") img = cv2.imread(saved_path) cv2.imshow("Detected Patterns", img) cv2.waitKey(0) cv2.destroyAllWindows() else: print("No detections.")
La función de predicción que ofrece YOLOv8 devuelve un diccionario que contiene información sobre el cuadro, el cual se muestra dentro de una imagen. Este cuadro envuelve un patrón detectado, seguido del nivel de confianza para un patrón gráfico específico detectado.
Tras extraer esta información, la imprimimos en una consola de Python o en el Símbolo del sistema (CMD).
Al final de la función, cuando hist se establece en False, se utiliza el módulo cv2 para mostrar el resultado previsto en un cuadro de diálogo.
Esto resulta práctico cuando se desea visualizar la imagen resultante que contiene los patrones producidos por el modelo.
Ejemplo.
images_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files\Screenshots" # Change this for to the right path on your pc :) symbol = "EURUSD" timeframe = "PERIOD_H1" imgs = 100 pattern_detector = YOLOv8deploy(model=model, images_folder=images_path) pattern_detector.predict_image(img_name=os.path.join(images_path, f"{symbol}.{timeframe}.{11}.png"), hist=False)
Tenemos una imagen tomada de EURUSD.PERIOD_H1 con el número 11 marcado dentro de la carpeta Capturas de pantalla que pretendemos visualizar.
Imagen original.

A continuación se muestra la imagen resultante generada por el modelo tras la función de predicción, en una ventana independiente.

Detección de patrones en varias imágenes
Una vez recibidas las imágenes de la carpeta «Screenshots», las recorremos todas y pasamos cada imagen a la función predict_image que acabamos de crear anteriormente.
def predict_images(self): _, image_names = self._get_images(self.images_folder) # Get all images from a folder for image_name in image_names: self.predict_image(img_name=image_name)
Ahora, vamos a llamar a esta función para predecir varias imágenes que hemos recopilado. Esto es similar a las pruebas retrospectivas: al pasar varias imágenes recopiladas históricamente, podemos comprobar si este modelo es adecuado o no.
pattern_detector.predict_images()Resultados.


Todos los resultados previstos y las imágenes generadas por este modelo se encuentran en el directorio de trabajo actual, en la carpeta runs\predict*
Como se puede observar, el modelo obtuvo algunas predicciones decentes, pero al igual que cualquier modelo de aprendizaje automático jamás creado, tiene algunas debilidades y limitaciones. A continuación se muestran algunos ejemplos.
Sesgos, riesgos y limitaciones de YOLOv8
01: El rendimiento puede verse afectado por variaciones en los estilos de los gráficos, la resolución de la pantalla y las condiciones del mercado.
Es fundamental asegurarse de que los colores de las velas japonesas en el gráfico sean menos confusos; el fondo y los colores de las velas deben ser muy distintos entre sí para obtener mejores resultados.
La escala del gráfico también es importante: una escala más amplia en MetaTrader 5 podría dar lugar a patrones incompletos, mientras que una más reducida podría introducir ruido.
Hay que encontrar el equilibrio adecuado entre la escala del gráfico y el tamaño de la imagen.
02: Las rápidas fluctuaciones del mercado y el ruido en los datos de negociación pueden afectar la precisión.
Las fluctuaciones pueden dar lugar a falsas rupturas y patrones extraños. Es inevitable que este modelo cometa errores en este tipo de gráficos y mercados.
03: Los patrones específicos del mercado que no están bien representados en los datos de entrenamiento pueden plantear dificultades para su detección.
Hay que evitar los mercados y marcos temporales con patrones poco definidos; la mejor manera de garantizar que se obtenga el máximo rendimiento del modelo es aplicarlo en el mercado o mercados adecuados.
Detección de patrones gráficos en MetaTrader 5 usando YOLOv8
Una vez más, el modelo YOLOv8 trabaja con imágenes y produce el resultado previsto en formato de imagen, lo cual es imposible de leer e interpretar en el lenguaje nativo MQL5. Sin embargo, el lenguaje tiene la capacidad de trabajar con imágenes en formato de mapa de bits .BMP, lo cual es un buen punto de partida.
Dado que es posible crear un objeto basado en imágenes o incrustar una imagen en el fondo del gráfico de MetaTrader 5 utilizando MQL5, como se ha hecho varias veces, abramos estas imágenes generadas por YOLOv8, que muestran los patrones gráficos detectados en MetaTrader 5 en la parte inferior del gráfico, tal y como se hizo en este artículo.
Tras añadir una imagen en la parte posterior del gráfico (fondo), podemos ocultar las barras actuales que se muestran en primer plano y actualizar el gráfico como una imagen con velas.
Para lograr esto, tenemos que modificar un par de cosas en nuestra clase de Python, comenzando por mejorar la función predict, para que sea capaz de guardar todas las imágenes que contienen predicciones en un directorio específico.
Nombre del archivo: deploy.py
def predict_image(self, img_name: str, save_path: str): """This function predicts a single image Args: img_name (str): name of the image hist (bool, optional): When set to false it means the function isn't predicting multiple instances and the outcome will be displayed. Defaults to True. """ if os.path.exists(img_name) == False: # Check if an image exists print(f"Failed to detect patterns, {img_name} not found") return results = self.model.predict(source=img_name, save=True, project=save_path, name="YOLOv8 Images", exist_ok=True ) # Predict an image # Loop through the results for result in results: boxes = result.boxes # Contains bounding boxes and confidence names = result.names # Class index to name mapping # Convert a jpg image to bmp suitable for MQL5 diplay purposes base_name = os.path.splitext(os.path.basename(img_name))[0] + ".jpg" saved_path = os.path.join(result.save_dir, base_name) convert_jpg_to_bmp(saved_path, os.path.join(result.save_dir, os.path.splitext(os.path.basename(img_name))[0] + '.bmp')) if boxes is not None and len(boxes) > 0: for box in boxes: cls_id = int(box.cls[0]) # class id conf = box.conf[0].item() # confidence score label = names[cls_id] print(f"Detected: {label} (confidence: {conf:.2f})") else: print("No detections.")
Dada esta capacidad de guardar las imágenes en una carpeta específica usando la función predict, podemos guardar todos los archivos en una subcarpeta llamada YOLOv8 Images creada bajo la ruta principal de los archivos MQL5.
YOLOv8 genera una imagen en formato JPEG o JPG; si queremos usar esta imagen en MetaTrader 5, debemos convertirla a formato Bitmap (BMP). A continuación se muestra la función para la tarea.
def convert_jpg_to_bmp(jpg_path, bmp_path): """ Convert a JPG image to 24-bit RGB BMP format Args: jpg_path (str): Path to input JPG file bmp_path (str): Path to save output BMP file """ try: # Open the JPG image with Image.open(jpg_path) as img: # Convert to RGB if not already (handles CMYK, grayscale, etc.) if img.mode != 'RGB': img = img.convert('RGB') # Save as 24-bit BMP img.save(bmp_path, 'BMP') print(f"Successfully converted {jpg_path} to {bmp_path}") return True except Exception as e: print(f"Conversion failed: {str(e)}") return False
Ahora bien, así es como podemos detectar y predecir los patrones presentes en una sola imagen.
files_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files" images_path = os.path.join(files_path, "Screenshots") # Change this for to the right path on your pc :) # .... # .... pattern_detector = YOLOv8deploy(model=model, images_folder=images_path) pattern_detector.predict_image(img_name=image_filename, save_path=files_path)
Podemos automatizar este proceso. Una vez transcurridos varios minutos, queremos que nuestro script lea una imagen de MQL5\Files\Screenshots, realice predicciones y guarde una imagen en MQL5\Files\YOLOv8 Images.
files_path = r"C:\Users\Omega Joctan\AppData\Roaming\MetaQuotes\Terminal\F4F6C6D7A7155578A6DEA66D12B1D40D\MQL5\Files" images_path = os.path.join(files_path, "Screenshots") # Change this for to the right path on your pc :) symbol = "EURUSD" timeframe = "PERIOD_H1" def scheduledYOLOv8Run(): now = datetime.now() # Get the current local date and time # Extract current day and hour date = now.day current_day = now.weekday() # e.g., 'Wednesday' current_hour = now.strftime("%H") # e.g., '14' for 2 PM in 24-hour format image_filename = os.path.join(images_path, f"{symbol}.{timeframe}.{date}.{current_day+1}.{current_hour}.png") pattern_detector = YOLOv8deploy(model=model, images_folder=images_path) pattern_detector.predict_image(img_name=image_filename, save_path=files_path) print(f"Processed image at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # Schedule the pattern detection after every minute(s) schedule.every(1).minutes.do(scheduledYOLOv8Run) print("Scheduler started. Press Ctrl+C to stop.") # Run forever while True: schedule.run_pending() time.sleep(1)
Ahora, preparemos el entorno adecuado para mostrar la imagen generada, presente en formato Bitmap (.BMP), en un gráfico de MetaTrader 5.
Comenzamos inicializando la función de gestión del temporizador para ayudarnos a automatizar el proceso de tomar una captura de pantalla y actualizar el gráfico con la imagen que contiene los patrones predichos (detectados).
Nombre del archivo: YOLOv8 EA.mq5
input uint chart_scale = 3; input uint timer_seconds = 60; int chart_width, chart_height; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if (!EventSetTimer(timer_seconds)) { printf("%s failed to set the timer, Error = %d",__FUNCTION__,GetLastError()); return INIT_FAILED; } showBars(true); //--- return(INIT_SUCCEEDED); }
La función denominada showBars se encarga de limpiar y preparar el entorno adecuado en el gráfico para realizar una captura de pantalla.
void showBars(bool show=true) { //--- Cleaning the chart ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); ChartSetInteger(0, CHART_SHOW_GRID, false); // Disable grid for cleaner images ChartSetInteger(0, CHART_SHOW_VOLUMES, false); ChartSetInteger(0, CHART_SHOW_TRADE_HISTORY, false); ChartSetInteger(0, CHART_AUTOSCROLL, true); // prevent scrolling ChartSetInteger(0, CHART_SHIFT, true); if (ChartGetInteger(0, CHART_SCALE) != chart_scale) ChartSetInteger(0, CHART_SCALE, chart_scale); if (show) { ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite); ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack); ChartSetInteger(0, CHART_COLOR_CHART_UP, clrTomato); ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrTomato); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrLightSeaGreen); ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrLightSeaGreen); ChartSetInteger(0, CHART_SHOW_ASK_LINE, true); ChartSetInteger(0, CHART_SHOW_BID_LINE, true); ChartSetInteger(0, CHART_COLOR_ASK, clrTurquoise); } else { ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite); ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack); ChartSetInteger(0, CHART_COLOR_CHART_UP, clrWhite); ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrWhite); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrWhite); ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrWhite); ChartSetInteger(0, CHART_SHOW_ASK_LINE, true); ChartSetInteger(0, CHART_SHOW_BID_LINE, true); ChartSetInteger(0, CHART_COLOR_ASK, clrTurquoise); } ChartRedraw(); }
Cuando se invoca esta función con un valor false, todas las propiedades del gráfico (incluidos los colores de las velas) se establecen en el mismo color que el fondo del gráfico; esto se hace para que todo quede oculto.
Esto es necesario porque vamos a colocar una imagen de fondo en el gráfico actual, por lo que no queremos que las barras del primer plano aparezcan sobre la imagen, ya que podrían crear una imagen confusa.
A continuación se muestra la función para convertir una imagen Bitmap (.BMP) en un objeto y, a continuación, asignarla al fondo del gráfico actual.
//+------------------------------------------------------------------+ //| Function to set a BMP image as chart background | //+------------------------------------------------------------------+ bool chartBackGroundSet(string filename, int width, int height) { string obj_name = "background-img"; if(!ObjectCreate(0,obj_name,OBJ_BITMAP_LABEL,0,0,0)) { printf("%s failed to create a bitmap in the chart window! Error = %s",__FUNCTION__,ErrorDescription(GetLastError())); return(false); } //--- set the path to the image file if(!ObjectSetString(0,obj_name,OBJPROP_BMPFILE, filename)) { printf("%s failed to load the image! Error = %s",__FUNCTION__,ErrorDescription(GetLastError())); return(false); } //--- Position the image to cover the entire chart ObjectSetInteger(0, obj_name, OBJPROP_XDISTANCE, 0); ObjectSetInteger(0, obj_name, OBJPROP_YDISTANCE, 0); ObjectSetInteger(0, obj_name, OBJPROP_XSIZE, width); ObjectSetInteger(0, obj_name, OBJPROP_YSIZE, height); //--- Send the image to the background ObjectSetInteger(0, obj_name, OBJPROP_BACK, true); ObjectSetInteger(0, obj_name, OBJPROP_ZORDER, -1); //--- Make sure the object is visible ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, obj_name, OBJPROP_HIDDEN, true); //--- Redraw the chart to see changes ChartRedraw(0); //--- return true; }
Por último, automatizaremos el proceso de realizar capturas de pantalla y enviarlas a la ruta de capturas de pantalla para que nuestro script de Python las lea; también automatizaremos el proceso de leer las imágenes predichas de la carpeta YOLOv8 Images, así como el proceso de trazar la imagen en el gráfico de MetaTrader 5.
void OnTimer(void) { //--- showBars(true); //explicitly show the bars // Clear the objects before taking a screenshot ObjectsDeleteAll(0); ObjectsDeleteAll(0,0); if (takeScreenShot()) { Print("Screen shot taken: ",TimeCurrent()); Sleep(100); } chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS); chart_height = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS); //--- Take screenshot MqlDateTime time_struct; TimeToStruct(TimeLocal(), time_struct); string filename = StringFormat("\\Files\\YOLOv8 Images\\%s.%s.%d.%d.%d.bmp",Symbol(),EnumToString(Period()),time_struct.day, time_struct.day_of_week, time_struct.hour); string fileshort_name = filename; bool checkfile = false; if (StringReplace(fileshort_name, "\\Files\\","")>0) checkfile = true; //If the parent folder was removed we can proceed to check if a file exists before drawing an object if (checkfile) while (!FileIsExist(fileshort_name)) { printf("%s not found",fileshort_name); return; } //--- Set the image with patterns detected to a chart if (!chartBackGroundSet(filename, chart_width, chart_height)) return; showBars(false); }
Por último, se adjuntó un asesor experto (EA) al gráfico EURUSD, en el timeframe PERIOD_H1 (igual que en el script de Python). El script de Python estaba en funcionamiento y el temporizador estaba configurado en 60 segundos.
Transcurridos 60 segundos en el gráfico EURUSD, MetaTrader 5 recibió una imagen del modelo.

¡Muy interesante!
El método utilizado para insertar una imagen como fondo del gráfico anterior es rudimentario y parte del supuesto de que el tamaño del gráfico es constante, o que permanece igual durante un tiempo (al menos durante el tiempo establecido en la función de temporizador).
Por lo tanto, al ajustar el tamaño del gráfico se interrumpirá durante un tiempo el proceso de dibujo de una imagen en el gráfico; le recomiendo que utilice el método que se describe aquí para disponer de una forma fiable de visualizar la imagen como fondo del gráfico.
Reflexiones finales
En mi opinión, YOLOv8 es un modelo impresionante. Como cualquier otro modelo de aprendizaje automático, tiene sus limitaciones y desventajas, pero a la hora de detectar los patrones gráficos mencionados anteriormente, acierta en algunos. Por eso, felicito a sus creadores, ya que en el pasado intenté crear un modelo similar para esta tarea y obtuve malos resultados.
Si bien siempre utilizamos modelos de IA para automatizar nuestras estrategias de trading, este modelo no es práctico para el trading algorítmico, ya que produce imágenes que, por ahora, solo un ser humano puede interpretar. Se trata más bien de una forma interesante de detectar patrones para los operadores manuales; si desea utilizarlo para estrategias algorítmicas, puede buscar la manera de establecer una conexión entre Python y MetaTrader para enviar información sin procesar, en formato de texto o JSON, sobre el estado del modelo y las predicciones que ofrece el método predict de este modelo.
Atentamente.
Manténgase al tanto y colabore en el desarrollo de algoritmos de aprendizaje automático para el lenguaje MQL5 en este repositorio de GitHub.
Tabla de archivos adjuntos
Nombre y ruta del archivo | Descripción y uso |
|---|---|
| Experts\YOLOv8 EA.mq5 | Un asesor experto para recopilar capturas de pantalla del gráfico y agregar la imagen predicha por YOLOv8 al gráfico actual. |
| Include\errordescription.mqh | Una biblioteca para convertir códigos de error generados en MetaTrader 5 y MQL5, de números enteros a cadenas de texto legibles para humanos. |
| Scripts\ChartScreenshots.mq5 | Un script para tomar varias capturas de pantalla históricas de un gráfico específico en MetaTrader 5. |
| YOLOv8 Proj\test.py | Un script de Python para probar el modelo YOLOv8 en múltiples imágenes. |
| YOLOv8 Proj\deploy.py | Un script de Python para desplegar y ejecutar el modelo YOLOv8 de forma continua. |
| YOLOv8 Proj\requirements.txt | Contiene todas las dependencias de Python utilizadas en el proyecto y su número de versión. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/18143
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
Estrategia de Evolución de Adaptación de la Matriz de Covarianza — Covariance Matrix Adaptation Evolution Strategy (CMA-ES)
Particularidades del trabajo con números del tipo double en MQL4
Características del Wizard MQL5 que debe conocer (Parte 65): Uso de los patrones FrAMA y Force Index
- 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



