Descargar MetaTrader 5

Clasificador bayesiano ingenuo para las señales de un conjunto de indicadores

20 junio 2017, 16:24
Stanislav Korotky
0
832
Nos guste o no, las estadísticas juegan un papel importante en el comercio. Comenzando por las noticias fundamentales, los números heterogéneos y confusos, y terminando por los informes comerciales o los informes de simulación, los índices estadísticos son un factor insoslayable. Además, la tesis sobre la aplicabilidad de la estadística en la toma de decisiones comerciales sigue siendo uno de los temas más discutidos. ¿Es el mercado casual, son las cotizaciones estacionarias, es aplicable el enfoque de probabilidad en su análisis? Podríamos discutir sobre ello toda una eternidad. En los amplios espacios de internet, así como en mql5.com, es sencillo encontrar materiales y conversaciones con los más diversos puntos de vista, con rigurosos cálculos científicos e impresionantes gráficos. Y sin embargo, normalmente a los tráders les interesa el aspecto aplicado, ya que este funciona en la práctica, en el terminal comercial. Este artículo es un intento de demostrar un enfoque pragmático de la probabilidad del modelo de toma de decisiones comerciales con ayuda de un conjunto de indicadores comerciales. Con un mínimo de teoría y el máximo de práctica.

La idea es evaluar el potencial de diferentes indicadores desde el punto de vista de la teoría de probabilidad y comprobar la capacidad de un grupo de indicadores de aumentar el porcentaje de ganancias del sistema comercial.

Esto exigirá la creación de un marco para el procesamiento de las señales de los indicadores aleatorios y un sencillo experto basado en él para la simulación.

Como indicadores para el trabajo, se supone que utilizaremos indicadores estándar, sin embargo, el marco permitirá conectar y analizar de manera independiente otros indicadores, como indicadores personalizados.

Pero antes de embarcarnos en el diseño y la implementación de algoritmos, todavía tendremos que sumergirnos un poco en la teoría.


Introducción al modelo de la probabilidad condicionada

En el nombre del artículo se menciona el clasificador bayesiano ingenuo. Se basó en la famosa fórmula de Bayes, que veremos aquí de forma breve. El adjetivo "ingenuo" se debe a la presuposición imprescindible sobre la independencia de las magnitudes aleatorias descritas por la fórmula. En lo que respecta a la independencia de los indicadores, volveremos a hablar, pero mientras tanto, pasemos a la propia fórmula.

 (1)

donde H — es una cierta hipótesis sobre el estado interno del sistema (en nuestro caso, es la hipótesis sobre el estado del mercado y el sistema comercial), E — es un evento observable (en nuestro caso, se trata de las señales de los indicadores), y también las probabilidades que los describen:

  • P(H) — probabilidad a priori, conocida por la historia de observaciones, del estado H;
  • P(E) — probabilidad completa del evento E teniendo en cuenta todas las hipótesis existentes, que normalmente son varias (aquí deberíamos advertir que las hipótesis deberán ser compatibles, es decir, el estado del sistema en cada momento es solo uno; para aquellos que quieran profundizar en la teoría, se adjuntan varios enlaces);
  • P(E|H) — probabilidad de que un evento E se cumpla en caso de que sea verdadera la hipótesis (estado) H;
  • P(H|E) — probabilidad a posteriori de la hipótesis (estado) H al observarse el evento E.

Si tomamos como ejemplo un sencillo sistema comercial, como hipótesis H se adoptan estados del mercado tales como el movimiento ascendente (compra), descendente (venta) y lateral (espera). Como eventos E, que describen el estado probable del mercado, se usan las señales de los indicadores.

Para las señales de un indicador concreto no es complejo calcular la probabilidad de la parte derecha de la fórmula (1) con la historia disponible y después aclarar el estado más probable del mercado P(H|E).

Sin embargo, para el cálculo es necesario definir con mayor precisión las hipótesis y la metodología de recopilación estadística en la que se basará la obtención de las probabilidades.

Ante todo, suponemos que el comercio se realiza por barras (no por ticks). La eficacia del comercio se puede estimar por el tamaño del beneficio, el factor de ganancia u otras características, pero para mayor simplicidad tomaremos el número de entradas ganadoras y perdedoras en el mercado. Esto relacionará de forma directa la valoración del sistema con la probabilidad de las transacciones ganadoras (señales procesadas).

Asismismo, nos limitaremos al sistema comercial sin niveles de take-profit y stop-loss, sin trailing stop y sin cambio de lote. Todos estos parámetros pueden ser introducidos en el modelo, pero complicarían sustancialmente los cálculos de probabilidad, transformándolos en distribuciones multidimensionales. El único parámetro del sistema comercial será la duración del mantenimiento de la posición en barras. En otras palabras, después de realizar la entrada en el mercado en la dirección elegida con la ayuda de los indicadores, la salida se lleva a cabo de forma automática tras un tiempo redefinido. Este enfoque es bueno porque hace hincapié en la corrección o en la falsedad de las hipótesis de crecimiento o de disminución de la cotización. De esta manera, comprobaremos la hipótesis limpiamente, sin salvavivdas ni red de seguridad.

Para simplificar aún más el tema, realizaremos dos movimientos cardinales adicionales.

Más arriba hablamos de que los principales parámetros adoptados como hipótesis comerciales son normalmente la "compra", la "venta" y la "espera". Tras descartar la "espera", podríamos acelerar los cálculos significativamente sin perjudicar el carácter general de la explicación. Puede parecer que esta simplificación afectará negativamente a la aplicabilidad de los resultados obtenidos, y hasta cierto punto esto es cierto. Sin embargo, si se presta atención a la cantidad de material que queda por leer, incluso con estas simplificaciones, es posible que usted esté de acuerdo con que, para el comienzo, es más sencillo conseguir un modelo de trabajo, y luego complementar sus partes posteriormente de forma gradual. Si alguien quiere construir modelos más complejos que tengan en cuenta la densidad de la probabilidad, podrá encontrar los trabajos correspondientes en internet, también en inglés, tales como Reasoning Methods for Merging Financial Technical Indicators, donde se describe un sistema de probabilidad híbrido de toma de decisiones.

Al final, el segundo paso cardinal será la combinación de los estados de "compra" y "venta" en uno solo, con el significado universal de "entrada en el mercado". Normalmente utilizamos las señales multidireccionales del indicador simétricamente de forma similar, es decir, por ejemplo, la sobrecompra según el indicador se convierte en señal de venta, y la sobreventa se convierte en la señal de compra.

En otras palabras, la hipótesis H suena ahora como una entrada rentable en el mercado en cualquiera de las dos direcciones (compra o venta).

En estas condiciones, el cálculo de la probabilidad de la parte derecha de la fórmula se puede ejecutar en la historia de cotizaciones elegida de la forma siguiente.


puesto que en cualquier barra existe la posibilidad de entrar con éxito en el mercado, una de las direcciones tendrá beneficios (aquí renegamos del spread, porque el marco temporal será D1, hablaremos sobre ello con más detalle a continuación).

P(E) = número de barras con señales del indicador / número total de barras

P(E|H) = número de barras con señales del indicador que coinciden con la dirección rentable del mercado / número total de barras

Después de simplificar, obtenemos la fórmula de cálculo en la historia de la probabilidad de que la señal del indicador elegido indique las condiciones de apertura de una transacción rentable:

 (2)

donde Nok — es el número de señales correctas, Ntotal — es el número total de señales.

Un poco después, implementamos el marco que permite calcular esta probabilidad para cualquier indicador. Como veremos, esta probabilidad normalmente se acerca a 0.5, y hay que realizar ciertas investigaciones para encontrar las condiciones con las que permanezca de forma estable por encima de 0.5. Sin embargo, los indicadores con índices elevados son algo muy poco común. Para los indicadores estándar, que precisamente vamos a investigar en primer lugar, esta probabilidad oscila dentro de los límites de 0.51-0.55. Está claro que estos valores son demasiado pequeños y probablemente permitan "quedarse con lo suyo", o si acaso aumentar el depósito de forma estable.

Para resolver este problema, es necesario usar no solo un indicador, sino varios. En sí, esta solución no constituye ninguna novedad, la mayoría de los tráders la usan. Pero la teoría de probabilidad permite realizar un análisis cuantitativo de la realidad de los indicadores en diferentes combinaciones y valorar su efecto potencial.

La fórmula (1) para los casos de los tres indicadores (A, B, C) tendrá el aspecto siguiente:

 (3)

Es necesario que le demos un aspecto cómodo para llevar a cabo cálculos algorítmicos. Por suerte, la teoría bayesiana se aplica en muchas ramas del saber, y por eso podemos encontrar en la misma una receta lista para nuestro caso.

En particular, existe una rama como el filtrado bayesiano de spam. No es necesario que la analicemos de cabo a rabo. Solo tenemos que conocer los conceptos básicos. Un docuemento (por ejemplo, un mensaje de correo electrónico) se marca como spam al encontrar en él unas palabras características determinadas. La recurrencia de las palabras en el lenguaje y la probabilidad de detectarlas en el spam son conocidas, justo igual que conocemos las probabilidades generales de las señales de los indicadores y el porcentaje de su "acierto". En otras palabras, basta sustituir la hipótesis "spam" por "transacción exitosa", y el evento "palabra" por "señal del indicador", para que la teoría de procesamiento del spam se ensamble con nuestra teoría de comercio de probabilidad.

Entonces, la fórmula (3) se puede revelar a través de la probabilidad de indicadores aparte de esta forma (mirar el enlace adjunto más arriba):

  (4)

Los cálculos P(H|A), P(H|B), P(H|C) se ejecutan según la fórmula (2) para cada indicador por separado.

Está claro que en caso necesario, la fórmula (4) se puede ampliar fácilmente al número de indicadores necesario. Para comprender de forma aproximada cómo el número de indicadores influye en la probabilidad de la solución comercial correcta, suponemos que todos los indicadores tienen un mismo valor de probabilidad:


Entonces la fórmula (4) tendrá el aspecto:

  (5)

donde N — es el número de indicadores.

El gráfico de esta función para los diferentes valores de N se muestra en la figura 1.

Aspecto de la probabilidad conjunta con un número distinto de magnitudes aleatorias

Fig. 1 Aspecto de la probabilidad conjunta con un número distinto de magnitudes aleatorias

Bien, con p = 0.51 obtenemos P(3) = 0.53, lo que no impresiona especialmente, pero con p = 0.55 - P(3) = 0.65, y esto sí que es una mejora considerable.


Independencia de los índices

Las fórmulas analizadas más arriba se basan en la suposición de la independencia de los procesos aleatorios analizados, los cuales son en nuestro caso las señales de los indicadores. ¿Pero se cumple esta condición?

Obviamente, algunos indicadores, entre los cuales hay muchos de la lista de indicadores estándar, tienen mucho en común. En la figura 2 se muestran como ejemplo visual algunos indicadores incorporados.

Grupos de indicadores estándar semejantes

Fig. 2 Grupos de indicadores estándar semejantes

Resulta fácil notar que los indicadores Stochastic y WPR están sobrepuestos uno sobre otro en la última ventana en un periodo, prácticamente se repiten mutuamente. Esto no es sorprendente, ya que sus fórmulas son aritméticamente equivalentes.

Los indicadores MACD y Awesome Oscillator, mostrados un poco más arriba en la captura, son idénticos, aunque con la corrección de tipo de las medias móviles. Además, puesto que ambos se construyen sobre medias móviles (MA), no se puede decir que sean independientes de las propias MA.

RSI, RVI, CCI también están fuertemente correlacionados. Debemos destacar que prácticamente todos los osciladores estándar son semejantes, los coeficientes de correlación están cercanos a 1.

Entre los indicadores de volatilidad, en particular ATR y StdDev, también se percibe una notoria coincidencia.

Todo esto debe tenerse en cuenta al formar el conjunto de indicadores para el sistema comercial, puesto que el efecto real del comité de indicadores dependientes será en la práctica bastante menor de lo esperado en la teoría.

A propósito, una situación semejante surgirá al entrenar redes neuronales. Con su ayuda, los tráders tratan con frecuencia de procesar los datos de muchos indicadores elegidos voluntariamente. Sin embargo, el suministro en la entrada de las redes de vectores dependientes reduce significativamente la efectividad del aprendizaje, puesto que la potencia de cálculo de la red se desperdicia en vano. El volumen de los datos analizados puede parecer grande, pero la información contenida en ellos está doblada, no tiene sentido.

Un enfoque riguroso sobre este problema exige del cálculo de la correlación entre indicadores y la composición de conjuntos con los menores valores por parejas. Se trata de una gran esfera de investigación aparte. Quien así lo desee, podrá encontrar en internet artículos sobre este tema. Aquí nos guiaremos por ideas generales basadas en las observaciones mostradas arriba. Por ejemplo, uno de los conjuntos puede tener el aspecto siguiente: Stochastic, ATR, AC (Acceleration/Deceleration) o WPR, Bollinger Bands, Momentum.

Aquí debemos aclarar que el indicador de Aceleración/Ralentización (AC) en esencia supone la derivada de un oscilador. ¿Por qué encaja para incluirlo en el grupo?

Imaginemos una serie de cotizaciones (o un oscilador derivado de ellas) de forma simplificada como vacilaciones periódicas, por ejemplo, un coseno o un seno. Recordemos que las derivadas de estas funciones son iguales respectivamente:

     (6)


Las correlaciones de estas funciones y sus derivadas son iguales a cero.

    (7)


Por eso, el uso de la primera derivada del indicador es en general un buen candidato al análisis como indicador adicional independiente.

La segunda derivada es un candidato ya más dudoso en semejantes procesos oscilantes, porque las oportunidades de obtener una réplica de la señal fuente son grandes.

Para finalizar la discusión sobre la independencia de los indicadores, tendrá sentido detenerse en la cuestión siguiente: ¿podemos considerar independiente la copia de un indicador calculado con diferentes periodos?

Podemos suponer que la respuesta depende de la proporción de los periodos. Una diferencia poco significativa, obviamente, mantiene la dependencia de los índices, y por eso es necesaria una diferencia notable. Esto es en parte consistente con los métodos clásicos tales como el método tres pantallas de Elder, donde los marcos temporales, que se diferencian, por lo general, en no menos de 5 veces, son equivalentes del análisis de indicadores con diferentes períodos de tiempo.

Conviene destacar que en el sistema analizado, las magnitudes independientes deberán ser en realidad, no los índices de los indicadores, sino las propias señales comerciales generadas por ellos. Sin embargo, para la mayoría de los indicadores de un mismo tipo, por ejemplo, los osciladores, los principios de formación de las señales son semejantes, y de ahí viene la dependencia fuerte o débil de las series temporales del equivalente de una dependencia fuerte o débil de las señales.


Planificación

Bien, ya hemos aclarado la teoría y vamos a hablar sobre qué codificar y cómo hacerlo.

Las estadísticas de las señales comerciales de los indicadores las vamos a reunir en un experto especial. Para que el experto pueda comerciar usando los índices de los indicadores aleatorios, necesitaremos desarrollar un marco de trabajo (en la práctica, un archivo mqh de encabezamiento), que recibirá la descripción de los indicadores utilizados y los métodos de formación de las señales basados en ellos a través de los parámetros de entrada. Por ejemplo, deberemos tener la posibilidad de establecer en los parámetros dos medias móviles de diferentes periodos y formar las señales de compra y venta, cuando la МА rápida cruza la más lenta de arriba hacia abajo, respectivamente.

El experto tendrá el control explícito de la apertura de barras, y también la capacidad de comerciar según los precios de apertura. No se trata de un experto real, sino de un instrumento para calcular la probabilidad y comprobar hipótesis. Para nosotros lo importante es que la comprobación tenga lugar rápidamente, porque el número de combinaciones de conjuntos de indicadores que podemos inventar es casi ilimitado.

Como marco temporal de trabajo, usaremos por defecto D1. Por supuesto, nadie va a evitar en lo sucesivo realizar análisis en cualquier otro marco temporal, pero D1 es menos propenso al ruido aleatorio, y el análisis de las leyes que existen desde hace varios años, en mayor parte corresponde plenamente a las características específicas del enfoque probabilístico. Además, para las estrategias comerciales en D1 normalmente se puede despreciar el spread, lo que equilibra nuestra reticencia a mantener el estado medio del sistema "esperar". Para el comercio intradía, por supuesto, no se podría permitir hacer esto, y necesitaríamos calcular la probabilidad de una gran cantidad de hipótesis.

Como ya hemos dicho con anterioridad, el experto abrirá posiciones según las señales de los indicadores, y las cerrará según un periodo de tiempo predeterminado. Para ello, introduciremos el parámetro de entrada correspondiente. Su valor por defecto será igual a 5 días. Este es el periodo característico para el marco temporal D1, se usa en muchos trabajos de investigación sobre trading que también utilizan D1.

El experto y el marco de trabajo será multiplataforma, es decir, se copilarán y ejecutarán tanto en MetaTrader 4, como en MetaTrader 5. Esta posibilidad se proporcionará gracias a los archivos-envoltorio de encabezamiento públicos ya disponibles, que permiten usar la sintaxis MQL API MetaTrader 4 en el entorno MetaTrader 5. Además, usaremos en ciertos casos la compilación condicional: partes específicas de los códigos estarán envueltas en las directivas del preprocesador #ifdef __MQL4__ и #ifdef __MQL5__.


Implementación en MQL

Marco de trabajo para los indicadores

Comenzaremos el vistazo general del marco de trabajo para el procesamiento de los indicadores discutiendo qué tipos de indicadores necesitaremos. La enumeración más obvia incluye todos los indicadores incorporados, así como un punto para los indicadores de usuario iCustom. La enumeración será necesaria para elegir los indicadores con la ayuda de los parámetros de entrada del marco de trabajo.

enum IndicatorType
{
  iCustom,

  iAC,
  iAD,
  tADX_period_price,
  tAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price,
  iAO,
  iATR_period,
  tBands_period_deviation_shift_price,
  iBearsPower_period_price,
  iBullsPower_period_price,
  iBWMFI,
  iCCI_period_price,
  iDeMarker_period,
  tEnvelopes_period_method_shift_price_deviation,
  iForce_period_method_price,
  dFractals,
  dGator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price,
  fIchimoku_tenkan_kijun_senkou,
  iMomentum_period_price,
  iMFI_period,
  iMA_period_shift_method_price,
  dMACD_fast_slow_signal_price,
  iOBV_price,
  iOsMA_fast_slow_signal_price,
  iRSI_period_price,
  dRVI_period,
  iSAR_step_maximum,
  iStdDev_period_shift_method_price,
  dStochastic_K_D_slowing_method_price,
  iWPR_period

};

El nombre de cada indicador incorporado contiene un sufijo con información sobre los parámetros del propio indicador. El primer símbolo del elemento designa el número de búferes disponibles, por ejemplo, i — un búfer, d — dos, t — tres. Todo esto son solo sugerencias para el usuario. Si indica un número incorrecto de parámetros o el índice de un búfer inexistente, el marco de trabajo mostrará un error en el log.

Por supuesto que en los parámetros de entrada habrá que establecer para cada indicador no solo su tipo, sino también los parámetros reales en forma de línea, el número de búfer y el número de barra desde donde se leerán los datos.

Basándonos en los índices de los indicadores, deberemos formar las señales. En principio, pueden ser muchas diferentes, pero las opciones principales las vamos a juntar en otra enumeración.

enum SignalCondition
{
  Disabled,
  NotEmptyIndicatorX,
  SignOfValueIndicatorX,
  IndicatorXcrossesIndicatorY,
  IndicatorXcrossesLevelX,
  IndicatorXrelatesToIndicatorY,
  IndicatorXrelatesToLevelX
};

De esta manera, las señales pueden formarse:

  • si el valor del indicador no está vacío;
  • el valor del indicador tiene el signo necesario (positivo o negativo);
  • el indicador cruza otro indicador, y aquí hay que tener en cuenta que al describir la señal deberemos imaginar la posibilidad de designar 2 indicadores;
  • el indicador cruza un cierto nivel, y aquí resulta claro que deberá haber dos campos para introducir el nivel;
  • el indicador está ubicado de la forma necesaria con respecto a otro indicador (por ejemplo, por encima o por debajo);
  • el indicador está ubicado de la forma necesaria con respecto al nivel establecido;

El primer elemento — Disabled — permite desactivar cualquier condición de generación de señales. Presentaremos varios grupos idénticos de parámetros de entrada para describir las señales, y cada señal estará activada por defecto.

Por los nombres de los puntos de la anterior enumeración podemos suponer que es necesario de alguna forma indicar el signo requerido de los valores y la posición de las líneas con respecto a las demás. Para ello, añadiremos otra enumeración más.

enum UpZeroDown
{
  EqualOrNone,
  UpSideOrAboveOrPositve,
  DownSideOrBelowOrNegative,
  NotEqual
};

EqualOrNone permite comprobar:

  • un valor vacío combinado con SignOfValueIndicatorX
  • la igualdad del nivel en combinación con IndicatorXrelatesToLevelX

UpSideOrAboveOrPositve permite comprobar:

  • el cruce de abajo hacia arriba con la ayuda de IndicatorXcrossesIndicatorY
  • la positividad del resultado con la ayuda de SignOfValueIndicatorX
  • el cruce del nivel de abajo hacia arriba con la ayuda de IndicatorXcrossesLevelX
  • el crecimiento de los valores del indicador en barras consecutivas con la ayuda de IndicatorXrelatesToIndicatorY, si X e Y son un mismo indicador
  • la ubicación de X sobre Y con la ayuda de IndicatorXrelatesToIndicatorY, si X e Y son indicadores distintos
  • la ubicación del indicador sobre el nivel, con la ayuda de IndicatorXrelatesToLevelX

DownSideOrBelowOrNegative permite comprobar:

  • el cruce de arriba hacia abajo con la ayuda de IndicatorXcrossesIndicatorY
  • un valor negativo con la ayuda de SignOfValueIndicatorX
  • el cruce del nivel de arriba hacia abajo con la ayuda de IndicatorXcrossesLevelX
  • el descenso de los valores del indicador en barras consecutivas con la ayuda de IndicatorXrelatesToIndicatorY, si X e Y son un mismo indicador
  • la ubicación de X por debajo de Y con la ayuda de IndicatorXrelatesToIndicatorY, si X e Y son indicadores distintos
  • la ubicación del indicador por debajo del nivel, con la ayuda de IndicatorXrelatesToLevelX

NotEqual permite comprobar:

  • la desigualdad del nivel (valor) con la ayuda de IndicatorXrelatesToLevelX

Cuando la señal se activa, es necesario procesarla. Para ello, definimos una enumeración especial.

enum SignalType
{
  Alert,
  Buy,
  Sell,
  CloseBuy,
  CloseSell,
  CloseAll,
  BuyAndCloseSell,
  SellAndCloseBuy,
  ModifyStopLoss,
  ModifyTakeProfit,
  ProceedToNextCondition
};

Aquí se muestran las acciones principales para procesar señales: muestra de mensajes, compra, venta, cierre de todas las órdenes abiertas (de compra, de venta, o ambas), viraje de la venta hacia la compra, viraje de la compra hacia la venta, modificación de los niveles de stop-loss y take-profit, así como el paso a la comprobación de la siguiente condición (señal). El último punto permite incorporar la comprobación de las señales en cadena (por ejemplo, comprobar si el búfer principal ha cruzado la línea de señal, y de ser así, comprobar a continuación si esto ha sucedido por encima o por debajo de cierto nivel).

Podemos notar que en la lista de acciones no existe la colocación de órdenes pendientes. Esto se ha dejado fuera del marco de este trabajo. Quien así lo desee, puede ampliar el marco de trabajo.

Teniendo todas estas enumeraciones, podemos describir varios grupos de atributos, con cuya ayuda se definen los indicadores de trabajo. Un grupo tendría este aspecto:

input IndicatorType Indicator1Selector = iCustom; // ·     Selector
input string Indicator1Name = ""; // ·     Name
input string Parameter1List = "" /*1.0,value:t,value:t*/; // ·     Parameters
input string Indicator1Buffer = ""; // ·     Buffer
input int Indicator1Bar = 1; // ·     Bar

El parámetro Indicator1Name sirve para establecer el nombre del indicador de usuario, cuando Indicator1Selector está en iCustom.

El parámetro Parameter1List permite indicar en forma de línea los parámetros del indicador, separados por comas. El tipo de cada parámetro de entrada se reconocerá de forma automática, por ejemplo, 11.0 — double, 11 — int, 2015.01.01 20:00 — date/time, true/false — bool, "text" — string. Algunos parámetros, por ejemplo, los tipos de media móvil o los tipos de precio pueden establecerse no con un número, sino con una línea sin comillas (sma, ema, smma, lwma, close, open, high, low, median, typical, weighted, lowhigh, closeclose).

Indicator1Buffer — número o nombre del búfer sin comillas. Nombres soportados para los búferes: main, signal, upper, lower, jaw, teeth, lips, tenkan, kijun, senkouA, senkouB, chikou, +di, -di.

Indicator1Bar — número de la barra, por defecto, tenemos 1.

Después de definir los indicadores, basándonos en ellos podemos formar señales, es decir, las condiciones de activación de los eventos. Cada señal es establecida por un grupo de parámetros de entrada.

input string __SIGNAL_A = "";
input SignalCondition ConditionA = Disabled; // ·     Condition A
input string IndicatorA1 = ""; // ·     Indicator X for signal A
input string IndicatorA2 = ""; // ·     Indicator Y for signal A
input double LevelA1 = 0; // ·     Level X for signal A
input double LevelA2 = 0; // ·     Level Y for signal A
input UpZeroDown DirectionA = EqualOrNone; // ·     Direction or sign A
input SignalType ExecutionA = Alert; // ·     Action A

Para cada parámetro de entrada se puede indicar un identificador en el parámetro __SIGNAL_.

Con la ayuda de Condition, se elige la condición de comprobación de la señal. A continuación, se establecen uno o dos indicadores o los dos valores de los niveles (el segundo nivel está reservado para el futuro y no se usará en este experimento). Los indicadores en los parámetros de Indicator son o bien el número del grupo correspondiente de atributos, o bien el prototipo del indicador en la forma:

indicatorName@buffer(param1,param2,...)[bar]

Esta forma de registro permite definir rápidamente el indicador utilizado sin describirlo detalladamente con la ayuda de un grupo de atributos. Por ejemplo,

iMA@0(1,0,sma,high)[1]

da los valores high, además, en cada barra actual del experto en funcionamiento se toma la barra 1 (la última finalizada, para la cual el precio high se conoce definitivamente).

De esta forma, los indicadores pueden establecerse tanto en grupos destacados de atributos (para el posterior enlace a los mismos desde las señales según un número), como directamente en las señales en el parámetro Indicator (X o Y). El primer método es cómodo si se debe usar el mismo indicador en diferentes señales o en calidad de X e Y dentro de una señal.

El parámetro Direction indica la dirección o el signo de valor para la activación de la condición. De acuerdo con Execution se ejecuta una u otra acción al activarse la señal.

A continuación, veremos ejemplos de definición de indicadores y señales sobre su base.

Dentro del marco de trabajo se ha establecido que el indicador no puede tener más de 20 parámetros, el número máximo de grupos destacados con atributos de los indicadores es 6 (pero, como recordamos, los indicadores se pueden definir directamente en la señal), y de señales, 8. Todo esto se puede cambiar en el código fuente. El archivo IndicatN.mqh se adjunta al final del artículo.

Asimismo, en este archivo se ha implementado en forma de varias clases toda la lógica de parseo de los parámetros del indicador, sus llamadas, la comprobación de las condiciones y el retorno de los resultados de comprobación al código de llamada (que será nuestro experto).

Concretamente, para transmitir las instrucciones sobre la necesidad de ejecutar cualquier acción de la enumeración SignalType, analizada más arriba, se usa la clase pública simple TradeSignals con campos lógicos que correspondan a los puntos de la enumeración:

class TradeSignals
{
  public:
    bool alert;
    bool buy;
    bool sell;
    bool buyExit;
    bool sellExit;
    bool ModifySL;
    bool ModifyTP;
    
    int index;
    double value;
    
    string message;
  
    TradeSignals(): alert(false), buy(false), sell(false), buyExit(false), sellExit(false), ModifySL(false), ModifyTP(false), value(EMPTY_VALUE), message(""){}
};

Al cumplir las condiciones necesarias, los campos se establecen en el valor true. Por ejemplo, si se ha elegido la acción CloseAll, en el objeto TradeSignals se muestran las banderas buyExit y sellExit.

El campo index contiene el número ordinal de la condición activada.

Con la ayuda del campo value podemos transmitir un valor aleatorio, por ejemplo, un nuevo volumen de stop-loss recibido desde los valores del indicador.

Y al final, el campo message contiene un mensaje para el usuario con la descripción de la situación.

Podrá familiarizarse con los detalles de la implementación de todas las clases en el código fuente. Él usa archivos auxiliares de encabezamiento fmtprnt2.mqh (muestra formateada en el log) y RubbArray.mqh (una matriz "de goma"), que también están adjuntos.

Recomendamos incluir el archivo de encabezamiento del marco de trabajo IndicatN.mqh en el código del experto con la ayuda de la directiva #include. Como resultado, después de compilar en la ventana de diálogo de la configuración de los parámetros del experto, obtendremos los grupos de parámetros de entrada con los atributos de los indicadores:

Ajustes de los indicadores

Fig.3 Ajustes de los indicadores

y con las definiciones de las señales:

Configuración de las señales comerciales

Fig.4 Configuración de las señales comerciales

En las capturas de pantalla se muestran las propiedades ya rellenadas. Las analizaremos en mayor profundidad cuando pasemos al concepto del experto y comencemos a ajustar estrategias comerciales concretas. Aquí debemos destacar que al establecer los atributos de los indicadores podemos sustituir cualquier parámetro numérico por una expresión del tipo =var1, =var2, etcétera. hasta 9. Hacen referencia a los parámetros de entrada homónimos del marco de trabajo var1, var2, etcétera, preparados para la optimización. Por ejemplo, aquí:

iMACD@main(=var4,=var5,=var6,open)[0]

esto significa que los parámetros de los periodos de la media móvil rápida, lenta y de señal de MACD pueden optimizarse a través de los parámetros de entrada var4, var5 y var6, respectivamente. Incluso con la optimización desactivada, durante la optimización individual, los valores de los atributos correspondientes del indicador se calcularán a partir de los parámetros de entrada del marco de trabajo.

Experto de prueba

Para facilitar la codificación, introduciremos todas las funciones comerciales en una clase especial y la compondremos como un archivo de encabezamiento individual Expert0.mqh. Puesto que queremos comprobar sistemas comerciales bastante sencillos, la clase permitirá solo abrir y cerrar posiciones.

De esta forma, todas las operaciones rutinarias con indicadores y las relacionadas con el comercio, se sacarán a un archivo de encabezamiento.

#include <IndicatN.mqh>
#include <Expert0.mqh>

Directamente en el archivo del experto indstats.mq4 habrá muy pocas líneas de código y una lógica sencilla.

Dado que, tras sustituir la extensión por mq5, el experto debe compilarse y funcionar en MetaTrader 5, añadimos los archivos de encabezamiento, que posibilitan el traslado de los códigos a un nuevo entorno.

#ifdef __MQL5__
  #include <MarketMQL4.mqh>
  #include <ind4to5.mqh>
  #include <mt4orders.mqh>
#endif

Ahora recurrimos a los parámetros de entrada del experto.

input int ConsistentSignalNumber = 1;
input int Magic = 0;
input float Lot = 0.01f;
input int TradeDuration = 1;

Magic y Lot son necesarios para crear el objeto Expert del archivo Expert0.mqh.

Expert e(Magic, Lot);

El parámetro ConsistentSignalNumber contendrá el número de señales comerciales que intentamos combinar para aumentar la fiabilidad.

El parámetro TradeDuration define el número de barras durante las cuales se mantendrá abierta la posición. Como se ha dicho anteriormente, abriremos las transacciones según las señales y saldremos de ellas tras 5 barras, es decir, días, ya que se usa el marco temporal D1.

En el procesador del evento OnInit, analizamos el marco de trabajo de indicador.

int OnInit()
{
  return IndicatN::handleInit();
}

En el procesador OnTick posibilitamos el control de la apertura de la barra.

void OnTick()
{
  static datetime lastBar;
  
  if(lastBar != Time[0])
  {
    const RubbArray<TradeSignals> *ts = IndicatN::handleStart();
    ...
    lastBar = Time[0];
  }
}

Al formar una nueva barra, comprobamos todos los indicadores y las condiciones relacionadas con ellos, llamando de nuevo el marco de trabajo de indicador. Como resultado, obtenemos una matriz de señales activadas, los objetos TradeSignals.

Ahora ha llegado el momento de hablar sobre la acumulación estadística.

Cada condición (evento) del marco de trabajo, en caso de tener lugar, genera por defecto una señal con la bandera alert. Usaremos esto para calcular el número de señales de los indicadores, así como el número de estados del sistema que se han realizado, es decir, los casos (barras) en los que la compra o la venta han tenido éxito.

Para calcular la estadística, describiremos las matrices.

int bars = 0; // total count of bars/samples
int bull = 0, bear = 0; // number of bars/samples per trade type
int buy[MAX_SIGNAL_NUM] = {0}, sell[MAX_SIGNAL_NUM] = {0};  // unconditional signals arrays
int buyOnBull[MAX_SIGNAL_NUM] = {0}, sellOnBear[MAX_SIGNAL_NUM] = {0}; // conditional (successful) signals arrays

En nuestro caso de comercio por barras, cada barra es una nueva entrada potencial en una transacción con una longitud de 5 barras. Cada segmento semejante se caracteriza por el crecimiento o el descenso de las cotizaciones y se marca como alcista o bajista, respectivamente.

Todas las señales de compra o venta se sumarán en las matrices buy y sell, y en este caso, si la señal correspondiente ha coincidido con el "carácter alcista" o el "carácter bajista" del segmento, es decir, si tiene éxito, también se acumulará en la matriz buyOnBull o sellOnBear, dependiendo del tipo.

Para rellenar las matrices, escribiremos el siguiente código dentro de OnTick.

    const RubbArray<TradeSignals> *ts = IndicatN::handleStart();
    bool up = false, down = false;
    int buySignalCount = 0, sellSignalCount = 0;
    
    for(int i = 0; i < ts.size(); i++)
    {
      // alerts are used to collect statistics
      if(ts[i].alert)
      {
        // while setting up events, enumerated by i,
        // hypothesis H_xxx should come first, before signals S_xxx,
        // because we assign up or down marks here
        if(IndicatN::GetSignal(ts[i].index) == "H_BULL")
        {
          bull++;
          buy[ts[i].index]++;
          up = true;
        }
        else if(IndicatN::GetSignal(ts[i].index) == "H_BEAR")
        {
          bear++;
          sell[ts[i].index]++;
          down = true;
        }
        else if(StringFind(IndicatN::GetSignal(ts[i].index), "S_BUY") == 0)
        {
          buy[ts[i].index]++;
          if(up)
          {
            if(PrintDetails) Print("buyOk ", IndicatN::GetSignal(ts[i].index));
            buyOnBull[ts[i].index]++;
          }
        }
        else if(StringFind(IndicatN::GetSignal(ts[i].index), "S_SELL") == 0)
        {
          sell[ts[i].index]++;
          if(down)
          {
            if(PrintDetails) Print("sellOk ", IndicatN::GetSignal(ts[i].index));
            sellOnBear[ts[i].index]++;
          }
        }
        
        if(PrintDetails) Print(ts[i].message);
      }
    }

Tras obtener la matriz de las señales activadas, pasamos por sus elementos en un ciclo. Si se muestra la bandera alert, se trata de la recopilación estadística.

Antes de analizar el código en mayor profundidad, introduciremos un acuerdo especial sobre la designación de las señales (eventos). Marcaremos las hipótesis sobre el estado alcista o bajista del mercado con los identificadores H_BULL y H_BEAR. Estos eventos deberán definirse con la ayuda de los parámetros de entrada del marco de trabajo en primer lugar, antes del resto de eventos (señales de los indicadores). Esto es necesario para que, usando como base las hipótesis confirmadas, se puedan establecer los rasgos existentes: las variables lógicas up y down.

Las señales de los indicadores deberán tener identificadores que comiencen por S_BUY o S_SELL.

Como vemos, con la ayuda del enlace al número del evento activado ts[i].index, obtenemos el identificador a través de la llamada de la función GetSignal. En el caso de que se realicen las hipótesis, actualizaremos los contadores de los segmentos alcistas o bajistas. En el caso de la generación de las señales, llevaremos a cabo el cálculo total de cada tipo de señal, controlando también su índice de éxito, es decir, el número de coincidencias con las hipótesis actuales.

Recordemos que o bien la hipótesis H_BULL, o bien la hipótesis H_BEAR es verdadera en cada barra.

Aparte de la recopilación estadística, el experto debe dar soporte al comercio con señales. Con este cometido, completamos el cuerpo del ciclo con la comprobación de las banderas buy y sell.

      if(ts[i].buy)
      {
        buySignalCount++;
      }
      else
      if(ts[i].sell)
      {
        sellSignalCount++;
      }

Tras el ciclo, realizamos la funcionalidad comercial. Antes de nada, tenemos que cerrar las posiciones abiertas (si las hay) cuando finalice el periodo dado.

    if(e.getLastOrderBar() >= TradeDuration)
    {
      e.closeMarketOrders();
    }

A continuación, realizamos la compra o venta, dependiendo de las señales compatibles.

    if(buySignalCount >= ConsistentSignalNumber
    && sellSignalCount >= ConsistentSignalNumber)
    {
      Print("Signal collision");
    }
    else
    if(buySignalCount >= ConsistentSignalNumber)
    {
      e.closeMarketOrders(e.mask(OP_SELL));
      
      if(e.getOrderCount(e.mask(OP_BUY)) == 0)
      {
        e.placeMarketOrder(OP_BUY);
      }
    }
    else
    if(sellSignalCount >= ConsistentSignalNumber)
    {
      e.closeMarketOrders(e.mask(OP_BUY));
      
      if(e.getOrderCount(e.mask(OP_SELL)) == 0)
      {
        e.placeMarketOrder(OP_SELL);
      }
    }

Si las señales de compra y venta se contradicen la una a la otra, omitimos este estado. Si el número de señales de compra o venta es igual o superior a la cantidad presupuesta ConsistentSignalNumber, abrimos la orden correspondiente.

Hay que destacar que, tras definir ConsistentSignalNumber en un valor inferior al número de señales configuradas, podremos simular el comercio del sistema en el modo de combinación de todas o la mayoría de las estrategias. En el modo estándar de funcionamiento, el experto usará el cruce, y no la combinación, puesto que para encontrar eventos conjuntos ConsistentSignalNumber deberá ser exactamente igual al número de señales. Por ejemplo, con 3 señales configuradas y ConsistentSignalNumber igual a 3, el comercio se realizará solo si se dan los tres eventos simultáneamente. Si establecemos ConsistentSignalNumber en 1, las transacciones se abrirán al darse cualquiera (aunque sea solo una) de las 3 señales.

En el procesador OnDeinit mostraremos la estadística recopilada de las alertas o de la historia de órdenes en el log.

Podrá ver el código fuente completo del experto en el archivo indstats.mq4.


Configuración de las señales comerciales

Todas las señales deberán ser comprobadas con respecto a las dos hipótesis sobre la compra o la venta. Para ello, ajustaremos las señales H_BULL y H_BEAR, así como sus indicadores.

Para obtener los precios de las barras, usaremos el indicador iMA con un periodo 1. En el grupo __INDICATOR_1 estableceremos:

Selector = iMA_period_shift_method_price

Parameters = 1,0,sma,open

Buffer = 0

Bar = 0

En el grupo __INDICATOR_2 realizaremos ajustes análogos con la excepción del número de barra, ahí hay que introducir 5, el número de barras que vamos a autilizar en el parámetro TradeDuration.

En otras palabras, en el modo de recopilación estadística, el experto no comercia, sino que analiza el cambio de las cotizzaciones entre la barra 5 y la 0, y también las señales de los indicadores en las barra 5 o 6, dependiendo del tipo de precio utilizado: para los indicadores que trabajan según los precios open, puede tomar los valores de la barra 5, y para todos los demás, los de la 6. En el modo de recopilación estadística, la barra número 5 es la barra virtual actual, y todas las siguientes proporcionan información sobre la realización "futura" de las hipótesis del mercado alcista o bajista.

Debemos matizar de inmediato que en el modo de comercio tomaremos las señales desde la barra 0 (si el indicador se construye según el precio open) o la barra 1 (en los demás casos). Si el experto no funcionara según los precios de apertura y analizara los ticks, deberíamos mirar en este modo los valores de los indicadores en la barra 0.

La presencia de estos dos modos - recopilación estadística y comercio - presupone la necesidad de crear diferentes conjuntos de parámetros que se distingan por el número de barras de trabajo. Vamos a comenzar por el conjunto de recopilación estadística, y después lo transformaremos en uno de comercio, real.

Con la ayuda de estas dos copias del indicador MA, construiremos las hipótesis. En el grupo __SIGNAL_A introducimos:

__SIGNAL_A = H_BULL
Condition = IndicatorXrelatesToIndicatorY Indicator X = 1 Indicator Y = 2 Direction or sign = UpSideOrAboveOrPositve Action = Alert

El grupo __SIGNAL_B lo construimos de forma análoga, excepto la dirección:

__SIGNAL_B = H_BEAR
Direction or sign = DownSideOrBelowOrNegative

Para comprobar el modelo de probabilidad del comercio, vamos a usar 3 estrategias estándar basadas en los indicadores:

  • Stochastic
  • MACD
  • BollingerBands

Destacaremos de antemano que los parámetros de todos los indicadores han sido optimizados, además, algunos se han dejado especialmente en forma de enlace a los parámetros de entrada var1, var2, etcétera, para demostrar esta posibilidad del marco de trabajo. Para reproducir los resultados positivos en los datos de su proveedor, es probable que cada estrategia requiera de una re-optimización.

La estrategia Stochastic consiste en comprar cuando el indicador cruce el nivel 20 de abajo hacia arriba y vender cuando el nivel cruce el nivel 80 de arriba hacia abajo. Para ello, definiremos el grupo __INDICATOR_3:

Selector = dStochastic_K_D_slowing_method_price
Parameters = 14,3,3,sma,lowhigh Buffer = main Bar = 6

Puesto que para el indicador se usan los precios high y low, es necesario tomar la barra 6: la última de las completamente formadas antes de la barra 5, en la que se comienza el comercio virtual si la señal se ha activado.

Configuraremos las señales de compra y venta basándonos en el indicador Stochastic. Grupo para la compra:

__SIGNAL_C = S_BUY stochastic
Condition = IndicatorXcrossesLevelX Level X = 20 Direction or sign = UpSideOrAboveOrPositve

Grupo para la venta:

__SIGNAL_D = S_SELL stochastic
Condition = IndicatorXcrossesLevelX Level X = 80 Direction or sign = DownSideOrBelowOrNegative

La estrategia MACD consiste en comprar cuando la línea main cruce la línea de señal hacia arriba y vender cuando el nivel cruce hacia abajo.

Vamos a configurar el grupo del indicador __INDICATOR_4:

Selector = dMACD_fast_slow_signal_price
Parameters = =var4,=var5,=var6,open Buffer = signal Bar = 5

Los periodos fast, slow, signal los calcularemos a partir de los parámetros var4, var5, var6, disponibles para la optimización. Ahora tenemos ahí 6, 21, 6, respectivamente. Usamos la barra 5, puesto que el indicador lo construimos según el precio open.

Dado que el número de grupos para el ajuste de los indicadores está limitado, el búfer main lo describiremos directamente en las señales. Grupo para la compra:

__SIGNAL_E = S_BUY macd
Condition = IndicatorXcrossesIndicatorY Indicator X = iMACD@main(=var4,=var5,=var6,open)[5] Indicator Y = 4 Direction or sign = UpSideOrAboveOrPositve

Grupo para la venta: 

__SIGNAL_F = S_SELL macd
Condition = IndicatorXcrossesIndicatorY Indicator X = iMACD@main(=var4,=var5,=var6,open)[5] Indicator Y = 4 Direction or sign = DownSideOrBelowOrNegative

La estrategia basada en BollingerBands consiste en comprar cuando el high de la barra anterior rompa la línea superior del indicador desplazado a la derecha 2 barras, y vender cuando el low de la barra anterior rompa la línea inferior del indicador desplazado a la derecha 2 barras. Más abajo se muestran los ajustes de las dos líneas del indicador.

__INDICATOR_5:

Selector = tBands_period_deviation_shift_price

Parameters = =var1,=var2,2,typical
Buffer = upper Bar = 5

__INDICATOR_6:

Selector = tBands_period_deviation_shift_price
Parameters = =var1,=var2,2,typical Buffer = lower Bar = 5

El periodo y la desviación han sido establecidos en var1 y var2 como 7 y 1, respectivamente. En ambos casos se puede usar la barra 5, a pesar del tipo de precio typical, porque las líneas del indicador están desplazadas 2 barras a la derecha, es decir, en la práctica se calculan sobre datos pasados.

Al fin, los grupos de ajustes de las señales tienen el aspecto siguiente.

__SIGNAL_G = S_BUY bands
Condition = IndicatorXcrossesIndicatorY Indicator X = iMA@0(1,0,sma,high)[6] Indicator Y = 5 Direction or sign = UpSideOrAboveOrPositve
__SIGNAL_H = S_SELL bands
Condition = IndicatorXcrossesIndicatorY Indicator X = iMA@0(1,0,sma,low)[6] Indicator Y = 6 Direction or sign = DownSideOrBelowOrNegative

Todos los ajustes en forma de archivos set se adjuntan al final del artículo.


Resultados

Estadística de los indicadores

Para calcular las probabilidades, usaremos la estadística del periodo 2014.01.01-2017.01.01 para la pareja EURUSD D1. Los ajustes del experto para el modo de recopilación estadística se encuentran en el archivo indstats-stats-all.set.

Los datos reunidos se muestran en el log. Más abajo se muestra el ejemplo:

: bars=778
: bull=328 bear=449
:    buy:    328      0     30      0     50      0     58      0 
:  buyOk:      0      0     18      0     29      0     30      0 
:   sell:      0    449      0     22      0     49      0     67 
: sellOk:      0      0      0     14      0     28      0     41 
: totals:   0.00   0.00   0.60   0.64   0.58   0.57   0.52   0.61 
: Stats by name:
:  macd=0.576 [57/99]
:  bands=0.568 [71/125]
:  stochastic=0.615 [32/52]

Él número total de barras es 778, de ellas, 328 han convenido para una transacción exitosa de compra de 5 días, y 449, para la venta de 5 días. Las 2 primeras columnas contienen los contadores de hipótesis, las mismas 2 cifras, y los siguientes pares de columnas se refieren a las estrategias comerciales correspondientes, cada una de las cuales se representa con una columna para la compra y otra para la venta. Por ejemplo, la estrategia basada en el estocástico ha dado 30 señales de compra, y 18 de ellas han sido rentables, asimismo, 22 han sido de venta, 14 de las cuales han tenido beneficios. Si sumamos para cada estrategia el número total de señales rentables y lo dividimos por el número de señales generadas, obtendremos la efectividad (la probabilidad de éxito basada en datos históricos) de cada una de ellas:

  • Stochastic — 0.615
  • MACD — 0.576
  • Bands — 0.568

Comercio de prueba

Para asegurarnos de que la estadística se ha calculado correctamente, necesitaremos iniciar el experto en el modo de comercio. Para ello, deberemos editar en los ajustes el número de barras, sustituyendo 5 por 0, y 6 por 1. Además, hay que activar de forma consecutiva una tras otra las estrategias comerciales, estableciendo los parámetros Action en Buy y Sell en lugar de Alert. Por ejemplo, para comprobar el comercio con el estocástico, en el grupo __SIGNAL_C (S_BUY stochastic) cambiamos en el parámetro Action el valor Alert por el valor Buy, y en el grupo __SIGNAL_D (S_SELL stochastic), el valor Alert por Sell.

Los ajustes correspondientes para las 3 estrategias se muestran, respectivamente, en los archivos indstats-trade-stoch.set, indstats-trade-macd.set, indstats-trade-bands.set.

Tras iniciar el experto 3 veces con estos conjuntos de parámetros, obtenemos 3 logs con breves informes comerciales. La estadística se halla al final del todo. Por ejemplo, para el estocástico obtenemos la línea:

: Buys: 18/29 0.62 Sells: 14/22 0.64 Total: 0.63

Son cifras sobre transacciones reales: 18 compras de 29 son rentables, 14 ventas de 22 son rentables, la efectividad general de la señal es 0.63.

Los resultados de las estrategias de MACD y BollingerBands están más ababjo.

: Buys: 29/49 0.59 Sells: 28/49 0.57 Total: 0.58

: Buys: 29/51 0.57 Sells: 34/59 0.58 Totals: 0.57

Reunimos todos los índices de todas las estrategias en una lista.

  • Stochastic — 0.63
  • MACD — 0.58
  • Bands — 0.57

Aquí podemos ver una correspondencia casi completa con la teoría de la anterior sección. La diferencia se explica porque las señales pueden solaparse una sobre otra si se encuentran en los límites de 5 barras, y entonces la nueva transacción repetida no se abre.

Como podemos ver, está claro que podemos analizar los informes comerciales para cada estrategia.

Informe de la estrategia basada en el indicador Stochastic

Fig.5 Informe de la estrategia basada en el indicador Stochastic


Informe de la estrategia basada en el indicador MACD

Fig.6 Informe de la estrategia basada en el indicador MACD


Informe de la estrategia basada en el indicador BollingerBands

Fig.7 Informe de la estrategia basada en el indicador BollingerBands

Según la fórmula (4), calculamos la probabilidad teórica de que la transacción tenga éxito al entrar según las señales sincrónicas de los tres indicadores.

P(H|ABC) = 0.63 * 0.58 * 0.57 / (0.63 * 0.58 * 0.57 + 0.37 * 0.42 * 0.43) = 0.208278 / (0.208278 + 0.066822) = 0.208278 / 0.2751 = 0.757

Para simular esta situación, deberemos incluir en el trabajo las tres señales, y también sustituir el valor del parámetro ConsistentSignalNumber de 1 a 3. Los ajustes correspondientes se encuentran en indstats-trade-all.set.

De acuerdo con la comprobación del comercio en el simulador, la efectividad total del sistema es en la práctica de 0.75:

: Buys: 4/7 0.57 Sells: 5/5 1.00 Total: 0.75

Aquí tenemos el informe de la simulación:

Informe de la combinación de las estrategias basadas en los 3 indicadores

Fig.8 Informe de la combinación de las estrategias basadas en los 3 indicadores

Abajo mostramos el recuadro de los índices comerciales de cada uno de los indicadores por separado y su superposición.


Profit,$ PF N DD,$
Stochastic 204 2.36 51 41
MACD 159 1.39 98 76
Bands 132 1.29 110 64
Total 68 3.18 12 30

Como podemos ver, el aumento de la probabilidad de obtener ganancias se alcanza gracias a entradas menos bruscas, pero más precisas; el número de transacciones y el beneficio general ha descendido, pero el profit-factor y la reducción máxima han mejorado como mínimo un 35%, y en algunos casos, hasta 2 veces y media.


Conclusión

En el artículo se ha analizado la variante más sencilla de realización de la probilidad de un enfoque sobre la toma de decisiones basado en las señales de los indicadores. Con la ayuda de un experto especial, se ha demostrado que los cálculos teóricos sobre el aumento de la probabilidad de las transacciones exitosas según la fórmula de Bayes se corresponden con los resultados obtenidos en la práctica.

Puesto que la generación de señales es discreta, las señales de diferentes indicadores pueden no coincidir, y es potencialmente posible la situación cuando la superposición de indicadores no da señales comunes que sean confirmadas por todos los indicadores. Una de las posibles soluciones a este problema es la introducción de un permiso temporal entre señales.

En un caso más general, podemos llevar a cabo el cálculo de la densidad de la probabilidad de la relización de señales comerciales dependiendo del estado (y no de las señales) de los indicadores. Por ejemplo, la magnitud de la sobrecompra o de la sobreventa, definida según el valor concreto de un oscilador, da un tanto por ciento (probabilidad) de entradas exitosas. De manera adicional, la probabilidad de una transacción exitosa depende, obviamente, de los parámetros elegidos de stop-loss y take-profit, de los métodos de gestión de los lotes y otros muchos parámetros del sistema. Todo ello puede ser analizado desde el punto de vista de la teoría de la probabilidad y usado para un cálculo más exacto, pero también más complejo, de las soluciones comerciales.

Más abajo se adjuntan los archivos:

  • indstats.mq4 (se trata de indstats.mq5) — experto;
  • common-includes.zip — directorio con los archivos mqh de encabezamiento usados;
  • additional-mt5-includes.zip — directorio con los archivos mqh de encabezamiento adicionales para МТ5;
  • instats-tester-sets.zip — directorio con los archivos set de los ajustes;


Traducción del ruso hecha por MetaQuotes Software Corp.
Artículo original: https://www.mql5.com/ru/articles/3264

Archivos adjuntos |
indstats.mq4 (15.63 KB)
common-includes.zip (17.46 KB)
Interfaces gráficas X: Selección del texto en el campo de edición multilínea (build 13) Interfaces gráficas X: Selección del texto en el campo de edición multilínea (build 13)

En este artículo vamos a implementar la posibilidad de seleccionar el texto usando diferentes combinaciones de teclas y eliminar el texto seleccionado, de la misma manera como se hace en cualquier otro editor de texto. Además de eso, seguiremos optimizando el código y prepararemos las clases para el traspaso al proceso final de la segunda fase del desarrollo de la librería, cuando todos los controles estarán dibujados en las imágenes separadas (lienzos para el dibujado).

¿Cuánto dura una tendencia? ¿Cuánto dura una tendencia?

En el artículo vamos a elegir varios métodos para identificar la tendencia y definir su duración con respecto al mercado plano. En la teoría, se considera que la proporición en tanto por ciento de la tendencia con respecto al flat es de un 30% frente a un 70%. Esto precisamente vamos a comprobar.

Ejemplo del indicador que construye las líneas de soporte y resistencia Ejemplo del indicador que construye las líneas de soporte y resistencia

En este artículo se muestra el ejemplo de la implementación del indicador para construir las líneas de soporte y resistencia a base las condiciones formalizadas. Usted podrá no sólo aplicar el indicador, sino también comprenderá qué fácil implementar eso. Ahora Usted podrá formular personalmente las condiciones para construir las líneas que considere necesarias, haciendo pequeñas modificaciones en el código del indicador a su medida.

Asesor Experto multiplataforma: Gestor de órdenes Asesor Experto multiplataforma: Gestor de órdenes

En este artículo se trata de la creación de un gestor de órdenes para el Asesor Experto multiplataforma. El gestor de órdenes se encarga de la apertura y del cierre de las órdenes y posiciones que realiza el Asesor Experto, así como de la ejecución del registro independiente sobre ellas, y estará disponible para ambas versiones del terminal.