
Desarrollo de asesores expertos autooptimizables en MQL5 (Parte 2): Estrategia de scalping en el USDJPY
En nuestro último debate sobre la creación de asesores expertos autooptimizables en MQL5, creamos un modelo de regresión lineal para generar señales de entrada y salida para nuestra aplicación de trading. Puede encontrar un enlace al artículo anterior aquí. En retrospectiva, es posible que no necesitemos todas las partes móviles disponibles en un modelo de aprendizaje automático. Más bien, podemos observar los modelos de aprendizaje automático como un ejemplo de cómo resolver problemas del mundo real utilizando reglas dinámicas. Entonces, podemos utilizar los mismos principios simples de pensamiento y lógica para guiar potencialmente nuestras aplicaciones comerciales hacia niveles más altos de rentabilidad sin necesidad de crear una base de código gigantesca que mantener.
Para nuestro análisis de hoy, nuestro objetivo es operar con el par USDJPY de forma rentable en el marco temporal diario. Nuestra estrategia comercial se basará en patrones de velas japonesas. En concreto, operaremos con patrones de reversión creados por velas envolventes. Nuestras reglas para una vela envolvente alcista se cumplirán si nuestro precio de apertura es inferior al cierre del día anterior y el precio de cierre es superior al precio de apertura del día anterior. En la figura 1 se muestra un ejemplo. Se cree que estos patrones de velas japonesas muestran que un determinado nivel de precios fue rechazado con considerable fuerza.
Figura 1: Hemos identificado un ejemplo de nuestro patrón de velas alcistas.
Los operadores creen que los patrones de velas envolventes son una señal de que se está formando una nueva tendencia en el mercado. Si se identifican correctamente, suelen ir seguidas de una evolución constante de los precios en la dirección de la nueva tendencia, véase la figura 2 a continuación. Esto sienta las bases para la estrategia comercial, tratando de identificar correctamente el patrón comercial. Las velas envolventes bajistas pueden utilizarse para identificar el inicio de tendencias bajistas. Utilizamos las mismas reglas que acabamos de describir, pero de manera opuesta.
Figura 2: Nuestro patrón de velas japonesas resultó fiable en este ejemplo concreto.
Normalmente, se cree que estas estrategias son válidas en todos los marcos temporales. Sin embargo, creo que el marco temporal diario puede ser el más fiable y lo he seleccionado como nuestro marco temporal preferido para este ejercicio. Intentemos implementar una estrategia para operar con las señales de entrada generadas por nuestra comprensión de estos patrones particulares del mercado. También nos interesará ver si podemos aumentar nuestra rentabilidad realizando ajustes en la estrategia original.
Introducción a MQL5
Nuestro programa tendrá 6 partes principales que necesitaremos para lograr nuestro objetivo de operar con patrones de velas de manera rentable.
Parte | Objetivo |
---|---|
Inicialización | Esta parte de nuestro sistema será responsable de cargar y configurar las variables globales. |
Desinicialización | Libere recursos que nuestra aplicación ya no utiliza para garantizar una experiencia estable para el usuario final. |
OnTick | Actualiza las variables del sistema y analiza el gráfico actual en busca de nuestros patrones de velas japonesas. |
Funciones personalizadas | Realizar trabajos especializados necesarios para alcanzar nuestro objetivo. |
Constantes del sistema | Constantes que no están destinadas a ser modificadas por el usuario final. |
Variables globales | Realice un seguimiento del último tipo de orden que hemos realizado, los precios actuales de mercado que se ofrecen y los niveles de volatilidad. Para ello se crearon variables como «trade» y «bid». El rango medio verdadero (Average True Range, ATR) nos ayudará a colocar órdenes stop loss y take profit para nuestras posiciones. |
Inicialmente, nuestra estrategia solo realizará operaciones una vez que se haya identificado nuestro patrón de velas japonesas. Si se identifica el patrón y no tenemos posiciones abiertas, tomaremos la señal y utilizaremos el ATR para establecer y ajustar nuestro stop loss. De lo contrario, nuestro sistema gestionará todas las operaciones que hayamos abierto. Por lo tanto, las variables globales de nuestro sistema serán:
Variable | Description |
---|---|
trade | Con el fin de informarnos sobre el tipo de puesto que tenemos actualmente disponible, esto nos facilitará la actualización de nuestras paradas y cualquier otra tarea que se nos ocurra en el futuro. |
atr_handler | Importante para actualizar nuestros stop loss de forma coherente. |
bid, ask | Seguimiento de los precios de mercado. |
Para comenzar, primero crearemos una versión de referencia de nuestra estrategia comercial. Comencemos definiendo las constantes del sistema. Estas constantes se crearán utilizando la directiva #define. La directiva #define instruye al preprocesador integrado en nuestro editor MQL5 a reemplazar cualquier ocurrencia del identificador de macro que hemos especificado y colocar en su lugar lo que hemos asignado a la derecha del identificador de macro.
La primera constante del sistema que hemos definido es "SYMBOL". Cuando compilamos nuestra aplicación, el preprocesador sustituirá todas las instancias de «SYMBOL» en nuestro código por el valor «USDJPY». Esta sencilla función nos proporciona un control completo y predecible sobre el sistema, y nos garantiza la coherencia en todas nuestras pruebas, atributos que nos resultan muy atractivos.
//+------------------------------------------------------------------+ //| Dynamic Stops Benchmark.mq5 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //| This trading application is intended to serve as our benchmark. | //| Our goal is to learn what it will take to surpass the benchmark. | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| System constants | //+------------------------------------------------------------------+ #define SYMBOL "USDJPY" //--- System pair #define DAILY PERIOD_D1 //--- Daily time frame #define VOL 0.1 //--- Trading volume #define ATR_PERIOD 14 //--- Technical Indicator ATR Period #define ATR_MULTIPLE 2 //--- Stop loss ATR multiple
También necesitaremos cargar la biblioteca comercial.
//+------------------------------------------------------------------+ //| Libraries | //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> CTrade Trade;
Ahora definiremos nuestras variables globales. Estas variables nos ayudarán a realizar un seguimiento de nuestra posición abierta y las cotizaciones actuales del mercado.
//+------------------------------------------------------------------+ //| Global variables | //+------------------------------------------------------------------+ int trade = 0; int atr_handler; double atr[]; double bid,ask;
Al inicializar, llamaremos a una función especializada responsable de inicializar nuestras variables del sistema.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- setup(); //--- return(INIT_SUCCEEDED); }
Si ya no utilizamos nuestra aplicación comercial, entonces publicaremos los indicadores técnicos que ya no utilizamos.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Release the indicator release(); }
Actualizaremos nuestras variables del sistema una vez al final del día. Esto se puede cambiar a su gusto para una mejor gestión de riesgos. He optado por actualizar las variables del sistema solo una vez al día para que las pruebas retrospectivas se completen de manera oportuna, lo que nos permitirá comparar más fácilmente los cambios que estamos realizando.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- update(); } //+------------------------------------------------------------------+
La primera función personalizada que crearemos será responsable de liberar recursos del sistema que ya no consumimos.
//+------------------------------------------------------------------+ //| Custom Functions | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Release variables we don't need | //+------------------------------------------------------------------+ void release(void) { IndicatorRelease(atr_handler); }
Actualice nuestras variables del sistema una vez al día.
//+------------------------------------------------------------------+ //| Update system | //+------------------------------------------------------------------+ void update(void) { static datetime daily_timestamp; datetime daily_time = iTime(SYMBOL,DAILY,0); if(daily_timestamp != daily_time) { //--- Update the time daily_timestamp = daily_time; //--- Update system variables daily_update(); //--- Do we have an oppurtunity to trade? if((PositionsTotal() == 0)) find_setup(); //--- Do we have positions to manage? if(PositionsTotal() > 0) manage_setup(); } }
Gestione nuestras operaciones actualizando el stop loss y el take profit únicamente si la nueva posición del stop loss o take profit será más rentable.
//+------------------------------------------------------------------+ //| Manage our trades | //+------------------------------------------------------------------+ void manage_setup(void) { //--- Select the position if(PositionSelect(SYMBOL)) { //--- Get ready to update the SL/TP double initial_sl = PositionGetDouble(POSITION_SL); double initial_tp = PositionGetDouble(POSITION_TP); double buy_sl = (ask - (ATR_MULTIPLE * atr[0])); double sell_sl = (bid + (ATR_MULTIPLE * atr[0])); double buy_tp = (ask + (ATR_MULTIPLE * atr[0])); double sell_tp = (bid - (ATR_MULTIPLE * atr[0])); double new_sl = ((trade == 1) && (initial_sl < buy_sl))? (buy_sl) : ((trade == -1) && (initial_sl > sell_sl)) ? (sell_sl) : (initial_sl); double new_tp = ((trade == 1) && (initial_tp < buy_tp))? (buy_tp) : ((trade == -1) && (initial_tp > sell_tp)) ? (sell_tp) : (initial_tp); //--- Update the position Trade.PositionModify(SYMBOL,new_sl,new_tp); } }
Configurar indicadores técnicos. Hasta el momento solo tenemos un indicador técnico para gestionar.
//+------------------------------------------------------------------+ //| Get our technical indicators ready | //+------------------------------------------------------------------+ void setup(void) { atr_handler = iATR(SYMBOL,DAILY,ATR_PERIOD); }
Actualizar el estado del sistema.
//+------------------------------------------------------------------+ //| Daily update routine | //+------------------------------------------------------------------+ void daily_update(void) { //--- Get current prices ask = SymbolInfoDouble(SYMBOL,SYMBOL_ASK); bid = SymbolInfoDouble(SYMBOL,SYMBOL_BID); //--- Update Technical Indicators CopyBuffer(atr_handler,0,0,1,atr); //--- Check for engulfing candles. int candles_state = check_candles(); //--- Give feedback Comment("Candle State: ",candles_state); }
Consulte nuestro patrón de velas. Si se encuentra el patrón, devolveremos 1 o -1 y colocaremos una operación larga o corta. De lo contrario, esperaremos.
//+------------------------------------------------------------------+ //| Check if we have any engulfing candles | //+------------------------------------------------------------------+ int check_candles(void) { //--- Return 1 if we have a bullish engulfing candle if((iOpen(SYMBOL,DAILY,0) < iClose(SYMBOL,DAILY,1)) && (iClose(SYMBOL,DAILY,0) > iOpen(SYMBOL,DAILY,1))) return(1); //--- Return -1 if we have a bearish engulfing candle if((iOpen(SYMBOL,DAILY,0) > iClose(SYMBOL,DAILY,1)) && (iClose(SYMBOL,DAILY,0) < iOpen(SYMBOL,DAILY,1))) return(-1); //--- Otherwise return 0 return(0); }
Nuestro sistema sabrá que ha encontrado una configuración comercial si el estado de la vela no es 0. De lo contrario, no es necesario hacer nada más por ahora.
//+------------------------------------------------------------------+ //| Find setup | //+------------------------------------------------------------------+ void find_setup(void) { //--- Our sentiment is bullish int candles_state = check_candles(); if(candles_state == 1) { Trade.Buy(VOL,SYMBOL,ask,(ask - (ATR_MULTIPLE * atr[0])),(ask + (ATR_MULTIPLE * atr[0])),""); trade = 1; } //--- Our sentiment is bearish if(candles_state == -1) { Trade.Sell(VOL,SYMBOL,bid,(bid + (ATR_MULTIPLE * atr[0])),(bid - (ATR_MULTIPLE * atr[0])),""); trade = -1; } } //+------------------------------------------------------------------+
La figura 3 a continuación nos permite ver cómo luce nuestro sistema. Nuestro sistema realiza un seguimiento de la presencia o ausencia de nuestro patrón de velas y realiza operaciones si se encuentra el patrón. Con nuestra configuración actual, las posiciones de stop loss y take profit se moverán una vez al día, al final del día.
Figura 3: Visualización de nuestra estrategia comercial en el marco temporal diario del USDJPY
Probaremos nuestra nueva estrategia a lo largo de 4 años de datos históricos, desde el 1 de enero de 2020 hasta finales de noviembre de 2024. Si desea seguir adelante y desea realizar cambios en estas configuraciones, asegúrese de realizar también los cambios apropiados en las variables del sistema. De lo contrario, nuestro sistema continuará operando con el USDJPY en el marco temporal diario, independientemente de los símbolos y el marco temporal que especifiquemos.
Figura 4: La configuración principal para nuestra prueba retrospectiva
El retraso aleatorio es el más cercano a los escenarios comerciales reales y nos permite realizar pruebas de estrés a nuestro sistema. Asegúrese de ajustar el "Deposit" y el apalancamiento de la cuenta para que coincidan con su configuración comercial prevista si está considerando utilizar la estrategia en la práctica.
Figura 5: Selección del tipo de modelado y el tamaño de la cuenta para nuestra prueba retrospectiva
La curva de capital producida por la estrategia es prometedora. Nuestra estrategia de scalping aumentó el tamaño de la cuenta en aproximadamente un 4% en esta prueba retrospectiva. Como ocurre con cualquier estrategia comercial, atravesó períodos sostenidos de pérdidas. Pero lo más destacable de esta estrategia es su capacidad para recuperarse de períodos de pérdida.
Figura 6: Visualización del saldo de nuestra cuenta comercial a lo largo del tiempo
Veamos ahora más de cerca el desempeño de nuestra estrategia. En su forma actual, nuestra estrategia tenía un ratio de Sharpe de 1,12 y una tasa de éxito del 44,68%. ¿Qué se necesita para reducir el tamaño de la pérdida promedio de $133,22 y acercarla a 0 mientras minimizamos nuestro impacto en la ganancia promedio?
Figura 7: Un análisis detallado del rendimiento de nuestras pruebas retrospectivas
Mejorando nuestros resultados
Nuestro sistema es rentable en su estado actual. ¿Hay algún cambio que podamos hacer que nos permita ejercer más control sobre las operaciones perdedoras? Propondré algunos cambios a la estrategia original:
Cambio propuesto | Propósito previsto |
---|---|
Confirmación adicional | Al utilizar una estrategia de confirmación adicional junto con nuestra estrategia ya rentable, potencialmente podemos filtrar más operaciones no rentables. |
Añadir relleno adicional al stop loss | Queremos minimizar la cantidad de veces que nos impiden realizar operaciones ganadoras. |
Tenga en cuenta la volatilidad del mercado | Cada mercado tiene potencialmente niveles de volatilidad únicos. Nuestra estrategia comercial debe intentar considerar los niveles históricos de volatilidad, para analizar los niveles de precios actuales con cierto nivel de contexto, como lo hacen los traders humanos profesionales. |
Con suerte, al implementar estos cambios, reduciremos nuestra proporción de operaciones no rentables. Al tomar estas decisiones siempre hay que hacer concesiones. En última instancia, nuestra nueva estrategia ocasionalmente perderá operaciones rentables que nuestra estrategia anterior habría logrado fácilmente.
Es lógico que, al final, no ejercer ningún control sobre el tamaño de nuestra pérdida promedio podría potencialmente costarnos todas las ganancias que trabajamos para acumular. Para realizar los cambios deseados, tendremos que introducir cambios en nuestra versión actual de la aplicación.
Cambio de sistema | Description |
---|---|
Nuevas variables del sistema | Para tener en cuenta la volatilidad del mercado, primero tenemos que decidir cuántos datos del pasado debemos recuperar. Esto lo manejará una nueva variable del sistema, apropiadamente llamada “fetch”. Además, necesitaremos fijar los parámetros de cualquier indicador técnico que utilicemos. |
Indicadores técnicos | Podemos obtener confirmación adicional mediante el uso de estrategias comerciales con indicadores técnicos. Hoy emplearemos una estrategia de canal de media móvil. Por lo tanto, crearemos nuevos manejadores de indicadores y buffers para almacenar esta nueva información. |
Confluencia de señales | Crearemos una nueva variable global llamada “sentiment”. Su valor será 1 o -1 cuando tanto nuestro patrón de velas como nuestros indicadores técnicos sean alcistas (1) o bajistas (-1). En caso contrario su valor será 0. Nuestro sistema solo realizará operaciones cuando nuestro valor de sentimiento no sea igual a 0. |
Funciones personalizadas | Para lograr el comportamiento que deseamos de nuestro sistema, tendremos que ampliar algunas de las funciones personalizadas que ya hemos creado, así como crear algunas funciones nuevas. |
Descripción general de la estrategia de confirmación
Nuestra estrategia de confirmación se basará en estrategias de negociación de canales de media móvil. Esta estrategia se crea mediante 2 medias móviles que siguen los precios máximos y mínimos respectivamente. Las dos medias móviles crean un canal. Tenga en cuenta que las medias móviles no se cruzan entre sí. Por lo tanto, nuestras señales de entrada se generan cuando una vela se forma completamente fuera de la región entre las dos medias móviles.
El razonamiento detrás de esta estrategia es que los niveles de precios entre la media móvil alta y baja se consideran estables. Por el contrario, cuando los niveles de precios se forman más allá de la región entre las dos medias móviles, percibimos un desequilibrio en el mercado. La estrategia sugiere que se trata de la formación de una nueva tendencia en la dirección del desequilibrio. La figura 8 muestra cómo utilizaríamos la estrategia.
La flecha roja representa una región óptima para haber ocupado una posición corta según la estrategia. La configuración se considera válida, por lo general, hasta que los niveles de precios vuelven al canal. En ese momento, nuestras posiciones pueden cerrarse y esperaremos a que se detecte el siguiente desequilibrio. Este segundo desequilibrio está marcado por la flecha azul. Dado que el desequilibrio apareció por encima de nuestro canal de media móvil, lo habríamos interpretado como una señal para comprar.
Figura 8: Nuestra estrategia de canal de media móvil para identificar puntos de entrada y salida.
Ampliaremos aún más la idea, teniendo en cuenta también los máximos y mínimos históricos experimentados en el mercado. Calcularemos el punto medio formado por el último año hasta la fecha de los precios máximos y mínimos históricos ofrecidos en el mercado. Además, utilizaremos la información para restringir o aplicar únicamente posiciones largas cuando el precio de cierre esté por encima del punto medio histórico entre el máximo y el mínimo, y lo contrario se aplicará a nuestras posiciones cortas.
La línea horizontal roja de la figura 9 simboliza la media de los precios máximos y mínimos del último año hasta la fecha. Este punto medio se actualiza cada día por nuestro sistema y servirá como lente para que nuestra aplicación vea los niveles de precios.
Figura 9: El punto medio histórico del último año hasta la fecha de los precios máximos y mínimos ofrecidos en el mercado.
Tipo de posición | Nuevos criterios de posición |
---|---|
Largo | Se ha formado una vela alcista envolvente, por encima del canal de la media móvil, y los niveles de precios se han elevado por encima de los niveles de volatilidad medios anuales. |
Corto | Se ha formado una vela bajista envolvente por encima del canal de la media móvil y los niveles de precios se elevan por encima de los niveles de volatilidad promedio anual. |
Con suerte, al usar nuestras dos estrategias juntas, podremos filtrar las operaciones no rentables que causaron problemas a nuestro antiguo sistema y, al mismo tiempo, conservar las operaciones rentables que queremos conservar. Comencemos a implementar estos cambios para ver qué tan efectivos serán. Primero debemos definir nuevas variables del sistema que fijarán los períodos de nuestro canal de media móvil y la cantidad de datos históricos que obtendremos para calcular nuestro punto medio.
//+------------------------------------------------------------------+ //| USDJPY Price Action Benchmark 2 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //| This trading application is intended to surpass our benchmark. | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| System constants | //+------------------------------------------------------------------+ //--- I have intentionally omitted parts of the system that remained unchanged #define FETCH 365 //--- How much should we fetch? #define MA_PERIOD 90 //--- Moving average period
También necesitaremos algunas variables globales adicionales para realizar un seguimiento de los estados del mercado que hemos definido.
//+------------------------------------------------------------------+ //| Global variables | //+------------------------------------------------------------------+ int sentiment = 0; int trade = 0; int ma_high_handler, ma_low_handler; double ma_high[],ma_low[];
El cuerpo de nuestra aplicación seguirá siendo el mismo. Sin embargo, algunas de las funciones que se están llamando han cambiado.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Setup our system varaibles setup(); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Release any resources release(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Update system variables update(); } //+------------------------------------------------------------------+
Repasemos ahora los cambios realizados en las funciones personalizadas. Los dos primeros cambios consistirán en cargar nuestros indicadores técnicos y publicarlos posteriormente.
//+------------------------------------------------------------------+ //| Custom Functions | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Release our technical indicators | //+------------------------------------------------------------------+ void release(void) { IndicatorRelease(atr_handler); IndicatorRelease(ma_low_handler); IndicatorRelease(ma_high_handler); }
Estos cambios en nuestro código base van de la mano y son fáciles de entender.
//+------------------------------------------------------------------+ //| Get our technical indicators ready | //+------------------------------------------------------------------+ void setup(void) { atr_handler = iATR(SYMBOL,DAILY,ATR_PERIOD); ma_high_handler = iMA(SYMBOL,DAILY,MA_PERIOD,0,MODE_EMA,PRICE_HIGH); ma_low_handler = iMA(SYMBOL,DAILY,MA_PERIOD,0,MODE_EMA,PRICE_LOW); }
Nuestra rutina diaria de actualización también debe ampliarse. Ahora también nos interesa saber cómo se comparan los niveles de precios actuales con los niveles históricos de ruido esperados en este mercado. Si nuestros patrones de velas japonesas y los niveles de precios nos dan una señal coincidente, entonces buscaremos la validación de nuestro canal de media móvil para determinar si es un buen momento para ejecutar nuestra operación.
//+------------------------------------------------------------------+ //| Daily update routine | //+------------------------------------------------------------------+ void daily_update(void) { //--- Get current prices ask = SymbolInfoDouble(SYMBOL,SYMBOL_ASK); bid = SymbolInfoDouble(SYMBOL,SYMBOL_BID); //--- Update Technical Indicators CopyBuffer(atr_handler,0,0,1,atr); CopyBuffer(ma_high_handler,0,0,1,ma_high); CopyBuffer(ma_low_handler,0,0,1,ma_low); //--- Check for engulfing candles. int candles_state = check_candles(); //--- Compare current price levels to historical price levels in the market int price_state = check_price_levels(); //--- Check our tech //--- What is our sentiment? //--- Our sentiment is well defined. if(candles_state == price_state) sentiment = candles_state; //--- Wait. if(candles_state != price_state) sentiment = 0; //--- Give feedback Comment("Sentiment: ",sentiment,"\nCandle State: ",candles_state,"\nPrice State: ",price_state); }
Utilizaremos el tipo vectorial MQL5 para calcular y realizar un seguimiento de nuestras estadísticas de mercado sobre la marcha con facilidad.
//+------------------------------------------------------------------+ //| Check if we are closer to the all time high or low | //+------------------------------------------------------------------+ int check_price_levels(void) { //--- Get historical prices vector highs = vector::Zeros(FETCH); vector lows = vector::Zeros(FETCH); highs.CopyRates(SYMBOL,DAILY,COPY_RATES_HIGH,0,FETCH); lows.CopyRates(SYMBOL,DAILY,COPY_RATES_LOW,0,FETCH); //--- First we shall calculate the mid point between the all time high and low vector mid = ((highs + lows) / 2); //--- Return 1 if we are above the mid point if(iClose(SYMBOL,DAILY,0) > mid.Mean()) return(1); //--- Return -1 if we are above the mid point if(iClose(SYMBOL,DAILY,0) < mid.Mean()) return(-1); //--- Otherwise return 0 return(0); }Nuestras nuevas reglas para encontrar una configuración comercial tendrán en cuenta dos filtros adicionales. El nivel de precios en relación con el punto medio anual y el nivel de precios en relación con el canal de la media móvil. Si ambas estrategias concuerdan, realizaremos nuestra operación en consecuencia.
//+------------------------------------------------------------------+ //| Find setup | //+------------------------------------------------------------------+ void find_setup(void) { //--- Our sentiment is bullish if(sentiment == 1) { if((iOpen(SYMBOL,DAILY,0) > ma_high[0]) && (iClose(SYMBOL,DAILY,0) > ma_high[0])) { Trade.Buy(VOL,SYMBOL,ask,(ask - (ATR_MULTIPLE * atr[0])),(ask + (ATR_MULTIPLE * atr[0])),""); trade = 1; } } //--- Our sentiment is bearish if(sentiment == -1) { if((iOpen(SYMBOL,DAILY,0) < ma_low[0]) && (iClose(SYMBOL,DAILY,0) < ma_low[0])) { Trade.Sell(VOL,SYMBOL,bid,(bid + (ATR_MULTIPLE * atr[0])),(bid - (ATR_MULTIPLE * atr[0])),""); trade = -1; } } } //+------------------------------------------------------------------+
Podemos echar un vistazo a nuestra estrategia en acción. Tenga en cuenta que nuestra estrategia ahora realiza un seguimiento de tres condiciones que deben cumplirse antes de comprometernos con cualquier posición. Esperamos que, al seleccionar cuidadosamente las condiciones adecuadas, no todas se cumplan por casualidad.
Figura 10: Estamos probando nuevamente nuestra estrategia revisada de scalping del USDJPY con datos históricos del mercado.
Como dijimos anteriormente, las configuraciones sobre la duración y el período de la prueba retrospectiva se mantendrán fijas para mantener la coherencia en ambas pruebas. Por lo tanto, nuestras fechas corresponden con las fechas de la prueba anterior.
Figura 11: Nuestras configuraciones para la prueba retrospectiva se fijarán en ambas pruebas.
Recuerde que puede sentirse libre de ajustar estas configuraciones particulares para reflejar el entorno en el que desea utilizarlas.
Figura 12: El segundo lote de configuraciones para nuestra prueba retrospectiva
La curva de capital producida por nuestra nueva estrategia tiene menos períodos de caída en comparación con nuestra primera prueba retrospectiva. Por ejemplo, en el período comprendido entre enero de 2020 y cerca de diciembre de 2023, la curva de capital producida por nuestra estrategia inicial estaba en un lugar, oscilando alrededor del saldo inicial. Si bien nuestra nueva curva de capital no tiene esa característica indeseable. Nuestra curva de acciones creció en una tendencia menos volátil desde septiembre de 2022 hasta el final de la prueba retrospectiva.
Figura 13: La curva de capital generada por nuestra estrategia comercial revisada
Tras una inspección más detallada, observamos que logramos nuestro objetivo de acercar la pérdida promedio y la proporción de operaciones perdedoras a 0. Sin embargo, sólo redujimos marginalmente la proporción de operaciones con pérdidas, de aproximadamente el 55% a aproximadamente el 54%. Además, nuestros cambios también redujeron la rentabilidad de nuestra estrategia comercial. Esto no es un problema material porque podemos corregirlo aumentando de forma segura el tamaño de nuestro lote. Los mercados son entornos dinámicos, y las nuevas medidas de seguridad que hemos implementado pueden resultar muy valiosas en el futuro.
Figura 14: Análisis detallado de nuestra segunda estrategia comercial.
Conclusión
En este artículo, cubrimos el potencial que se puede descubrir al operar con las señales generadas por patrones de velas. Si bien existen muchas críticas contra dichas estrategias, como el hecho de que es posible observar la forma del patrón de velas, pero no siempre es seguido por la misma acción del precio después, lo que puede generar dudas sobre la validez de la estrategia.
Sin embargo, siguiendo los ajustes que hemos discutido en esta estrategia y agregando su propio entendimiento del mercado, creo que cualquier duda sobre la rentabilidad de la estrategia puede ser razonablemente disipada. El desafío es que no siempre nos resulta obvio cómo los cambios que estamos realizando afectarán la rentabilidad de la estrategia.
Archivo | Description |
---|---|
Acción del precio de referencia del USDJPY | Esta aplicación fue la versión inicial y volátil de nuestra estrategia comercial; era más rentable, pero también conllevaba más riesgo. |
Estrategia de acción del precio del USDJPY 2 | Esta es la versión refinada de la estrategia que construimos juntos, es igual de rentable y trata de minimizar sus pérdidas. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/16643
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.





- 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
¿Puedo probar el EA? Lo he descargado pero por alguna razón no aparece en EA. Cualquier ayuda es muy apreciada. Gracias.