Promedio Móvil Sin Buffer


Introducción En mi artículo Los Principios de Cálculo Económico de Indicadores Hice pruebas razonablemente convincentes que demuestran el hecho de que no cada llamada de un indicador personalizado o técnico en un código es la Forma más óptima de realizar cálculos intermedios en un indicador desarrollado. La velocidad final de ejecución puede parecer mucho más baja, comparándola con lo que tendríamos si colocamos el código para cálculos intermedios justo en nuestro indicador. Este tipo de enfoque para escribir un código sería muy atractivo, si fuera bastante simple. De hecho, parece ser una complicación seria de un código con la descripción de buffers adicionales utilizados para almacenar los resultados intermedios de cálculo. A pesar de la variedad de cálculos intermedios, los más necesarios en ellos son diferentes algoritmos de promediación. En la mayoría de los casos, para ellos podemos usar funciones personalizadas simples y universales que simplifican considerablemente la tarea de escribir dicho código. El proceso de crear estas funciones y trabajar con ellas se describirá en este artículo. 1. La idea general de las funciones de promedio que trabajan con una barra El enfoque clásico para promediar en una barra actual consiste en un búfer indicador intermedio, que llenamos con la información requerida, y luego seleccionar un rango de valores anteriores, que es igual a El período promedio, y calcular el valor promedio. El procedimiento de procesamiento de esta selección es el siguiente: SmoothVar (bar) Función (Var (bar - (n-1)), Var (bar - (n-2)) Var (barra) Número de una barra, para la cual se realiza el cálculo Var (bar - (n-1)) parámetros medios con un cambio en (n-1) barras n número de barras para promediar. Tal aproximación al promedio, en nuestro caso, conduce a la aparición de dos ciclos de cálculo. En el primer ciclo, los datos se calculan y se ponen en un tampón intermedio. En el segundo ciclo, el promediado usando otro ciclo de búsqueda adicional de células del tampón indicador se realiza sobre la base de la fórmula sugerida anteriormente. Este cálculo se verá mucho más fácil, si acumulamos la selección de datos intermedios dentro de la propia función. En este caso, la función de promediar se verá como sigue: SmoothVar (barra) Función (Var (barra), bar) Un nuevo valor Var (barra) se escribe en la selección de valores dentro de la función en una barra actual y el Los valores de Var (bar - n) que se vuelven innecesarios se eliminan de la selección. Con este enfoque, un código de promediación parece bastante trivial y no requiere tampones indicadores adicionales. Dentro de la función, la matriz almacena la cantidad exacta necesaria de datos necesarios para el cálculo de una barra, no todos los datos del historial. En este caso, sólo hay un ciclo de cálculo de datos. Debe tenerse en cuenta que para llamar a esta función de promediación en una barra actual, debe llamarla a todas las barras anteriores primero 2. El promedio clásico como ejemplo de implementación de una función que funcione con una barra Estas funciones de promedio deben contener Variables que no deben perder sus valores entre las llamadas de esas funciones. Además, el promedio de un solo tipo con diferentes parámetros puede ser utilizado en un código por muchas veces por lo tanto, para evitar un conflicto de uso de recursos de memoria compartida, debemos implementar esas funciones como clases y eso es lo que he hecho. Los algoritmos del promediado clásico se describen en la clase CMovingAverage: Esta clase se deriva de la clase base CMovSeriesTools que contiene funciones protegidas adicionales-métodos y una verificación de la corrección del período de medias móviles. La clase base contiene un código universal adicional que se utiliza en todas las clases que sugiero, y no tiene sentido copiarlo muchas veces en las clases derivadas. En las tareas aplicadas de uso del promedio, los miembros de clase protegidos no se utilizan de forma explícita, por lo que permite suspender su visión general por el momento. La clase CMovingAverage consiste en cinco funciones de un solo tipo de promediación, cuyos nombres hablan por sí mismos, y no necesitan ser descritos en detalle. La primera función MASeries () es una colección integral de otras cuatro funciones que permiten seleccionar un algoritmo de promediación utilizando el parámetro MAMethod. El código de los algoritmos de promediación se optimiza para obtener el máximo rendimiento, por lo que los parámetros principales de las funciones (longitud, serie, barra) se complementan con parámetros adicionales iniciales, previos al cálculo, ratestotal y set, cuyo propósito es absolutamente idéntico a Las variables indicadoras con los mismos nombres. El conjunto de parámetros establece el indicador de la indización de elementos de una serie de series de precios en las funciones de promediar para que sean iguales a los conjuntos de variables. Debemos considerar que todas las funciones de promedio de esta clase tienen el parámetro Longitud fijo y no se puede cambiar cuando se ejecuta el código del programa La función EMASeries () de la clase CMovingAverage tiene este parámetro del tipo double Ahora, como nos conocimos Con la clase CMovingAverage. Podemos empezar a usarlo en indicadores. Para ello, utilizando la directiva include, añada el contenido del archivo MASeriesCls. mqh en el ámbito global al código de indicador que desarrolle: A continuación, debe determinar el número necesario de procedimientos de promediación en el código del indicador y, a continuación, en OnCalculate () (Antes de los operadores de bucle y los corchetes) declaran las variables estáticas de la clase CMovingAverage según el número requerido de procedimientos de promediación. Debe haber una variable separada de la clase y una celda separada en la matriz de la clase para cada procedimiento de promediado. Las variables de la clase en la función OnCalculate () se declaran como estáticas, ya que sus valores deben mantenerse entre las llamadas de esta función. Ahora podemos empezar a trabajar con el promediado. A modo de ejemplo, voy a mostrar cuatro procedimientos consecutivos de promediación de series de precios - SMA / EMA / SMMA / LWMA (el indicador MAx4.mq5): El resultado de cada promedio anterior (excluyendo el último) se utiliza en el siguiente algoritmo De promediado, y el resultado final se pasa al tampón indicador. Creo que la parte más crucial de este código es la inicialización preliminar muy cuidadosa de variables de índices que muestran el inicio de barras fiables. En esta situación, se verá como sigue: Tenga en cuenta, que en esta situación, el algoritmo LWMA de promediar es el último y no afecta a nada, pero si no fuera el último, entonces el cambio de inicio de información confiable sería igual A Length41, no Length4 Quiero añadir, si su no claro del código anterior, de qué número la información confiable comienza, toma un número más grande y después lo disminuye experimental si es necesario. 3. Comparar el Indicador Creado con Clases con sus Analogos que Utilicen Indicadores Técnicos y Personalizados Sería muy interesante comparar el rendimiento del indicador creado MAx4.mq5 con su análogo idéntico (iMAx4.mq5) que utiliza el indicador técnico iMA () . Bueno, tan pronto como hayamos decidido realizar la prueba, será razonable probar otro indicador (MAx3x1.mq5) similar a MAx4.mq5, pero teniendo el primer promedio hecho usando la llamada del indicador técnico iMA () y el Otros tres utilizando la clase CMovingAverage. Y tan pronto como el conjunto estándar de indicadores del terminal cliente incluye el indicador Custom Moving Average. mq5, he hecho otro indicador análogo en sus bases para fines de prueba (cMAx4.mq5). Para el próximo análisis que preparé para la prueba de asesores expertos: MAx4Test. mq5, iMAx4Test. mq5, MAx3x1Test. mq5 y cMAx4Test. mq5, respectivamente. Las condiciones para llevar a cabo estas pruebas se describen en detalle en el artículo Principios del cálculo económico de los indicadores. En este artículo, no voy a describir los detalles de la prueba, pero voy a mostrar los resultados finales de la ejecución de los cuatro expertos Asesor en el probador de estrategia para los últimos 12 meses en EURUSD 4 con el modelado de cada tick y el valor De los parámetros de entrada de período de todos los EAs igual a 500. Los peores resultados en nuestras pruebas se muestran por el indicador que llama indicadores personalizados, por lo tanto, esta variante de escribir un código sólo puede recomendarse a los perezosos Por supuesto, Pero uno que se basa en llamadas de indicadores técnicos tiene mejores resultados, sin embargo, están demasiado lejos de un ideal. El verdadero líder de las pruebas es el indicador que se desarrolla utilizando las clases El híbrido que utiliza las clases y los indicadores técnicos tomó el segundo lugar, pero no sucede siempre si el tiempo de prueba de un indicador es crucial, entonces es mejor comprobar tales variantes Personalmente para cada situación. Descripción de las clases implementadas de promedio La clase CMovingAverage descrita anteriormente incluye cinco algoritmos de promediación. La clase CCMO contiene algoritmos de promedio y oscilador. Las otras clases incluyen algoritmos simples de promediación. La ideología de usar cualquiera de las clases sugeridas es absolutamente igual al procedimiento de usar la clase CMovingAverage descrita anteriormente. El código de todos los algoritmos de promedio (excepto el parabólico) está optimizado para la máxima velocidad de ejecución. El código de promediación parabólica no fue optimizado, debido a la complejidad de este proceso. Los últimos tres algoritmos no representan un promedio. He añadido a ellos debido a su alta popularidad y compatibilidad con las obras de los analistas técnicos populares. Para facilitar la comprensión de la información, es mejor representar los algoritmos de promedio en archivos. mqh separados y para uso práctico, la mejor variante es tenerlos en un solo archivo. Para usar en indicadores, todas las clases sugeridas se empaquetan en el archivo SmoothAlgorithms. mqh. Además de ello, el archivo se complementa con las funciones del archivo iPriceSeries. mqh. Sólo se utiliza la función PriceSeries () en los ejemplos de este artículo: Esta función está diseñada para trabajar con indicadores bases en el uso del segundo tipo de llamada de la función OnCalculate (). La idea principal de crear esta función es extender el conjunto de series de tiempos de precios de la enumeración ENUMAPPLIEDPRICE con variantes personalizadas. La función devuelve el valor de un timeseries de precios por su número que varía de 1 a 11. 4. Ejemplos prácticos de implementación de un código de programa utilizando las clases de promedio Si es suficiente para mostrar otro ejemplo de uso de las otras clases, para asegurarse de que Todo se hace de la misma manera que con el promediado cuádruple. Im va a mostrar una variante de la aplicación de la función OnCalculate () en un análogo del indicador CCI utilizando las clases CJJMA y CJurX (JCCX. mq5) Pero esta vez he añadido las clases apropiadas de otro archivo en el ámbito global en el código Del indicador: Ahora, quiero llamar la atención sobre otra cosa. La cuestión es un gran número de indicadores que pueden representarse como funciones de una barra, que son realmente cómodos para trabajar con el uso de clases. Por ejemplo, sería interesante dibujar el canal de Bollinger sobre la base de la media móvil Vidya de Tushar Chande. En este caso, se utilizan dos clases CCMO y CStdDeviation. Usando la primera clase, obtenemos el valor del promedio móvil VIDYA y usando el segundo, calculamos el valor de la desviación estándar de la serie de precios para el promedio móvil. Después de eso, utilizamos esta desviación para el cálculo del borde superior e inferior del canal: Así, tenemos una clase simple y pequeña Los últimos tres parámetros de entrada de la función VidyaBandsSeries () pasan los valores necesarios del canal a través de un enlace . Me gustaría señalar que en este caso, no se pueden declarar las variables de las clases dentro de la función VidyaBandsSeries () y hacerlas estáticas, porque las variables estáticas en las clases tienen un significado muy diferente. Es por eso que esta declaración debe hacerse en el ámbito global de la clase: En un canal normal de Bollinger, el período de promediado de la media móvil y el período de promediación del canal en sí son siempre iguales. En esta clase, Ive hecho los parámetros separados para darle más libertad (EMAperiod y BBLength). El propio indicador (VidyaBBands. mq5) hecho sobre la base de esta clase es tan simple en el uso de la clase CVidyaBands que no necesitamos analizar su código en el artículo. Tales clases de funciones de indicador deben colocarse en un archivo mqh separado. He colocado tales funciones en el archivo IndicatorsAlgorithms. mqh. 5. Comparación del rendimiento de un indicador que utiliza clases con una que no es En primer lugar, quiero saber cómo el uso de las clases al escribir un código de un indicador disminuye su rendimiento Para este propósito, el código del indicador JJMA. mq5 se escribió sin usar las clases (JMA. mq5). Entonces se probó en las mismas condiciones que durante la prueba anterior. Los resultados finales de las pruebas no tienen una gran diferencia: Por supuesto, hay algunos cargos adicionales por utilizar las clases, pero no son significativos en comparación con las ventajas que ofrecen. 6. Ventajas de usar las clases de promedio Una ventaja de usar estos algoritmos, que es realmente convincente, es que la sustitución de llamadas de indicadores técnicos y personalizados lleva a un gran aumento del rendimiento del código desarrollado descrito anteriormente. Otra ventaja práctica de estas clases es una gran comodidad de usarlas. Por ejemplo, todo lo que se describe en el popular libro de William Blau Momentum, Dirección y Divergencia parece ser un verdadero campo de pruebas para este tipo de enfoque a la escritura de indicadores. El código de indicadores aparece como comprimido al máximo, comprensible ya menudo consiste en un solo ciclo de recálculo de barras. Usted puede desarrollar fácilmente cualquier indicador - un clásico o técnico, utilizando los métodos alternativos de promediar. Una amplia variedad de los algoritmos de promediar proporciona amplias posibilidades para crear sistemas de comercio no tradicionales, a menudo con una detección temprana de tendencias y un menor número de disparos falsos. 7. Algunas Recomendaciones sobre el Uso de los Algoritmos de Promedio en un Código de Indicador Específico Una simple mirada rápida a cualquier indicador desarrollado usando diferentes algoritmos de promediación descritos aquí es suficiente para entender cuán diferentes son esos algoritmos. Por lo tanto, sería razonable suponer que no todos los algoritmos sugeridos son igualmente buenos en cada situación. Aunque sería difícil determinar un límite estricto de uso de uno u otro algoritmo, es posible proporcionarle algunas recomendaciones generales sobre su uso. Por ejemplo, los algoritmos de Tushar Chande y Kaufman están destinados a determinar situaciones de tendencia y no son adecuados para suavizado adicional con el propósito de filtrar ruido. Por lo tanto, es mejor que ingrese series de precios sin procesar o valores indicadores sin promediar estos algoritmos. Aquí está el resultado del procesamiento de valores del indicador Momentum usando el algoritmo de Kaufmans (el indicador 4cMomentumAMA. mq5) Creo que los algoritmos de promediado clásico no necesitan recomendaciones especiales. Su área de aplicación es bastante amplia. En todas partes, donde se utilizan estos algoritmos, puede utilizar con éxito los cuatro algoritmos de la izquierda (JMA, T3, ultralinear y parabólico). Aquí está un ejemplo del indicador MACD donde EMA y SMA se reemplazan con el promedio JMA (el indicador JMACD. mq5): Y aquí está el resultado de suavizar el indicador calculado en lugar de cambiar su algoritmo de promediar para una mejor calidad de determinación La tendencia actual (el indicador JMomentum. mq5): No es una sorpresa que el comportamiento de los mercados cambia constantemente por lo tanto, sería ingenuo pensar que se puede encontrar el único algoritmo ideal para una cierta parte del mercado financiero ahora y Para siempre Alas Nada en este mundo dura para siempre Sin embargo, como para mí, por ejemplo, en este mercado eternamente cambiante que a menudo utilizan los indicadores de rápido y mediano plazo tendencias como JFATL. mq5 y J2JMA. mq5. Estoy bastante satisfecho con las predicciones sobre su base. Otra cosa que quiero añadir. Los algoritmos de promedio son reutilizables. Se pueden obtener buenos resultados al aplicar promedios repetidos a valores ya promediados. De hecho, en este artículo empecé analizando el proceso de dibujo de indicador desde el mismo (el indicador MAx4.mq5). 8. La Idea General del Código de Composición de los Algoritmos de Promedio. Y ahora, al final del artículo, quisiera llamar su atención sobre el mecanismo de las funciones de promediar. En primer lugar, la mayoría de los algoritmos de promediación incluyen matrices dinámicas de variables del tipo mSeriesArray para almacenar los valores de la serie de parámetros de entrada. Tan pronto como aparece la información significativa para el cálculo, debe asignar la memoria para dicha matriz por una vez. Se realiza utilizando la función SeriesArrayResize () de la clase CMovSeriesTools. Luego en cada barra debe escribir el valor actual de la serie de series de precios al valor más antiguo de la matriz y memorizar el número de su posición en la variable mcount. Se realiza mediante la función RecountArrayZeroPos () de la clase CMovSeriesTools. Y ahora, si necesitamos encontrar un elemento con un cambio relativo al elemento actual, deberíamos usar la función RecountArrayNumber () de la clase CMovSeriesTools: Normalmente en estas situaciones, el elemento más reciente se escribe en una posición cero y los demás ( Excepto el más antiguo) son sobrescritos preliminares a las posiciones siguientes por turno sin embargo, no está ahorrando los recursos de la computadora, y el acercamiento más complejo descrito arriba parece ser más racional Además de los algoritmos de promediar, los cuerpos de esas funciones contienen Las llamadas de funciones utilizadas para la determinación de las posiciones de las barras respecto al inicio del cálculo de las barras: el momento en que hay suficiente información para la inicialización inicial de las variables y situaciones cuando se cierra la última barra: No son suficientes barras para que la función de promedio funcione, y devuelve un resultado vacío. Una vez que la segunda comprobación se pasa con éxito y hay suficientes datos para el primer cálculo, la inicialización de las variables se realiza por una vez. Dos últimas comprobaciones son necesarias para el correcto procesamiento múltiple de valores en la barra no cerrada actual. Ya lo describí en mi artículo dedicado a la optimización de un código de programa. Y ahora unas pocas palabras sobre la optimización del código de programa de tales funciones para el máximo rendimiento. Por ejemplo, el algoritmo SMA implica el promedio de los valores seleccionados de un período de una serie de precios en cada barra. Esos valores se suman literalmente y se dividen por el período en cada barra. Pero la diferencia entre la suma en la barra anterior y la suma en la barra actual es la primera se suma con el valor de la serie de precios con un cambio en un período con respecto al período actual y el segundo con el valor actual . Por lo tanto, sería muy racional calcular dicha suma sólo una vez durante la inicialización de funciones, y luego en cada barra agregar sólo nuevos valores de la serie de precios a esta suma y restar los valores más antiguos de la misma. Esto se hace exactamente en tal función. Conclusión Sugerido en el artículo las implementaciones de los algoritmos de promediar el uso de las clases son simples, de tipo único y universal, por lo que no tendrá problemas para estudiarlos. Los archivos adjuntos al artículo contienen muchos ejemplos para facilitar la comprensión de este enfoque a la escritura de código de indicadores. En el archivo Includeen. zip todas las clases se distribuyen en archivos. El archivo Includeen. zip contiene sólo dos archivos que son suficientes para compilar todos los indicadores del archivo Indicators. zip. Los expertos asesores para la prueba están en el archivo Experts. zip. Estoy tratando de completar un proyecto de asignación Matlab con la siguiente pregunta: Escribir una función llamada movingaverage que toma un escalar llamado x como un argumento de entrada y devuelve un escalar. La función utiliza un búfer para contener entradas previas, y el búfer puede contener un máximo de 25 entradas. Específicamente, la función debe guardar las más recientes 25 entradas en un vector (el búfer). Cada vez que se llama a la función, copia el argumento de entrada en un elemento del búfer. Si ya hay 25 entradas almacenadas en el búfer, descarta el elemento más antiguo y guarda el actual en el búfer. Después de haber almacenado la entrada en el búfer, devuelve la media de todos los elementos del búfer. La solución que ofrezco es la siguiente: Según el nivelador automático, mi función funciona correctamente cuando los valores 1-50 pasan consecutivamente, pero falla cuando los valores de una onda senoidal ruidosa pasan consecutivamente (lo que me ha sido informado que podría deberse a algunos Tipo de un error de redondeo). Estaría agradecido si alguno de ustedes pudiera proporcionarme algunos consejos sobre los posibles pasos de error en mi código (adjunto anteriormente). Gracias de antemano Sé que esto es alcanzable con el impulso como por: Pero realmente me gustaría evitar el uso de impulso. He googled y no he encontrado ningún ejemplo adecuado o legible. Básicamente, quiero seguir el promedio móvil de una corriente en curso de una corriente de números de punto flotante utilizando los números 1000 más recientes como una muestra de datos. ¿Cuál es la manera más fácil de lograr esto que experimenté con el uso de una matriz circular, media móvil exponencial y una media móvil más simple y encontró que los resultados de la matriz circular se adapta a mis necesidades mejor. Si sus necesidades son simples, puede intentar usar una media móvil exponencial. Puesto simplemente, usted hace una variable del acumulador, y como su código mira cada muestra, el código actualiza el acumulador con el nuevo valor. Usted escoge un alfa constante que está entre 0 y 1, y calcule esto: Usted apenas necesita encontrar un valor del alfa donde el efecto de una muestra dada dura solamente cerca de 1000 muestras. Hmm, no estoy realmente seguro de que esto es adecuado para usted, ahora que he puesto aquí. El problema es que 1000 es una ventana bastante larga para un promedio móvil exponencial No estoy seguro de que haya un alpha que se extendería el promedio en los últimos 1000 números, sin subflujo en el cálculo del punto flotante. Pero si usted quisiera un promedio más pequeño, como 30 números o tan, esto es una manera muy fácil y rápida de hacerla. Respondió 12 de junio a las 4:44 1 en su puesto. El promedio móvil exponencial puede permitir que el alfa sea variable. Así, esto permite que se utilice para calcular promedios de base de tiempo (por ejemplo, bytes por segundo). Si el tiempo transcurrido desde la última actualización del acumulador es de más de 1 segundo, deje que alfa sea 1.0. De lo contrario, puede permitir que alpha be (usecs desde la última actualización / 1000000). Ndash jxh 12 de junio a las 6:21 Básicamente, quiero seguir el promedio móvil de una corriente en curso de una corriente de números de punto flotante usando los números 1000 más recientes como una muestra de datos. Tenga en cuenta que el siguiente actualiza el total como elementos añadidos / reemplazados, evitando costosos recorridos O (N) para calcular la suma - necesaria para el promedio - a la demanda. Total se hace un parámetro diferente de T a soporte, p. Usando un largo largo cuando totalizan 1000 long s, un int para char s, o un doble a total float s. Esto es un poco defectuoso en que numsamples podría ir más allá de INTMAX - si te importa que podría utilizar un unsigned mucho tiempo. O utilice un miembro de datos de bool extra para grabar cuando el contenedor se rellena primero mientras cicla numsamples alrededor de la matriz (mejor entonces cambia el nombre de algo inocuo como pos). Respondió el 12 de Junio ​​12 a las 5:19 se supone que el operador quotvoid (T sample) quot es realmente operador quotvoid (T sample) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. bien descrito. En realidad quería que fuera para ser operador vacío () (T muestra), pero por supuesto, usted podría utilizar cualquier notación que te gustaba. Se arreglará, gracias. Ndash Tony D Jun 8 14 en 14:27

Comments