Tuesday 14 November 2017

Media Móvil C ++


Estoy tratando de calcular el promedio móvil de una señal. El valor de la señal (un doble) se actualiza al azar. Estoy buscando una manera eficiente de calcular su tiempo promedio ponderado en una ventana de tiempo, en tiempo real. Podría hacerlo yo mismo, pero es más difícil de lo que pensaba. La mayoría de los recursos que he encontrado en Internet están calculando el promedio móvil de la señal periódica, pero la mina se actualiza al azar. ¿Alguien sabe buenos recursos para que El truco es el siguiente: Usted recibe actualizaciones en tiempos aleatorios mediante la actualización de void (tiempo int, valor de float). Sin embargo, también es necesario realizar un seguimiento cuando una actualización se cae de la ventana de tiempo, por lo que se establece una alarma que se llama en el momento N que elimina la actualización anterior de ser considerado de nuevo en el cálculo. Si esto sucede en tiempo real, puede solicitar al sistema operativo que realice una llamada a un método void dropoffoldestupdate (int time) que se llamará en el momento N Si se trata de una simulación, no puede obtener ayuda del sistema operativo y necesita Hágalo manualmente. En una simulación llamaríamos métodos con el tiempo suministrado como un argumento (que no se correlaciona con el tiempo real). Sin embargo, una suposición razonable es que las llamadas están garantizadas de tal manera que los argumentos de tiempo están aumentando. En este caso, debe mantener una lista ordenada de valores de hora de alarma y, para cada llamada de actualización y lectura, compruebe si el argumento de tiempo es mayor que el de la lista de alarmas. Mientras que es mayor que usted hace el proceso relacionado con la alarma (caiga la actualización más vieja), quite la cabeza y compruebe otra vez hasta que se procesen todas las alarmas antes del tiempo dado. A continuación, haga la llamada de actualización. Hasta ahora he asumido que es obvio lo que haría para el cálculo real, pero voy a elaborar por si acaso. Supongo que tienes un método float read (tiempo int) que usas para leer los valores. El objetivo es hacer que esta llamada sea lo más eficiente posible. Por lo tanto, no calcula el promedio móvil cada vez que se llama al método de lectura. En su lugar precompute el valor a partir de la última actualización o la última alarma y ajuste este valor por un par de operaciones de punto flotante para explicar el paso del tiempo desde la última actualización. (Es decir, un número constante de operaciones excepto para tal vez procesar una lista de alarmas acumuladas). Esperemos que esto esté claro - este debería ser un algoritmo bastante simple y bastante eficiente. Otra optimización. Uno de los problemas restantes es si un gran número de actualizaciones se producen dentro de la ventana de tiempo, entonces hay un largo tiempo para que no hay ni lecturas ni actualizaciones, y luego una lectura o actualización viene adelante. En este caso, el algoritmo anterior será ineficaz en la actualización incremental del valor para cada una de las actualizaciones que está cayendo. Esto no es necesario porque sólo nos preocupamos por la última actualización más allá de la ventana de tiempo por lo que si hay una manera de dejar de manera eficiente todas las actualizaciones anteriores, que ayudaría. Para ello, podemos modificar el algoritmo para realizar una búsqueda binaria de actualizaciones para encontrar la actualización más reciente antes de la ventana de tiempo. Si hay relativamente pocas actualizaciones que deben eliminarse, puede actualizar incrementalmente el valor de cada actualización eliminada. Pero si hay muchas actualizaciones que necesitan ser eliminados, entonces uno puede volver a calcular el valor desde cero después de dejar las antiguas actualizaciones. Apéndice sobre Cálculo Incremental: Debo aclarar lo que quiero decir con el cálculo incremental anterior en la frase ajustar este valor por un par de operaciones en coma flotante para explicar el paso del tiempo desde la última actualización. Cálculo inicial no incremental: luego iterar sobre las actualizaciones relevantes en orden creciente de tiempo: movilidad (sum latupdate timesincelastupdate) / windowlength. Ahora si exactamente una actualización cae de la ventana pero no llega ninguna nueva actualización, ajuste la suma como: (note que es priorupdate que tiene su timestamp modificado para iniciar el inicio de la última ventana). Y si exactamente una actualización entra en la ventana, pero no hay nuevas actualizaciones se caen, ajustar la suma como: Como debe ser obvio, este es un bosquejo aproximado, pero esperemos que muestra cómo se puede mantener el promedio tal que es O (1) operaciones por actualización Sobre una base amortizada. Pero tenga en cuenta la optimización adicional en el párrafo anterior. También tenga en cuenta los problemas de estabilidad aludidos en una respuesta anterior, lo que significa que los errores de coma flotante pueden acumularse en un gran número de operaciones incrementales tales que existe una divergencia con respecto al resultado del cálculo completo que es significativo para la aplicación. Si una aproximación es correcta y hay un tiempo mínimo entre las muestras, puede intentar el super-muestreo. Tenga una matriz que represente intervalos de tiempo uniformemente espaciados que son más cortos que el mínimo, y en cada período de tiempo almacene la última muestra que fue recibida. Cuanto más corto sea el intervalo, más cercano será el promedio al valor verdadero. El período no debe ser mayor de la mitad del mínimo o existe la posibilidad de que falte una muestra. Respondió Dec 15 11 at 18:12 respondió Dec 15 11 at 22:38 Gracias por la respuesta. Una mejora que se necesita para realmente quotcachequot el valor de la media total por lo que don39t lazo todo el tiempo. Además, puede ser un punto menor, pero ¿no sería más eficiente usar un deque o una lista para almacenar el valor, ya que asumimos que la actualización vendrá en el orden correcto. La inserción sería más rápida que en el mapa. Ndash Arthur 16 de diciembre a las 8:55 Sí, podría almacenar en caché el valor de suma. Resta los valores de las muestras que borres, agrega los valores de las muestras que insertas. También, sí, un dequeltpairltSample, Dategtgt podría ser más eficiente. Elegí el mapa para la legibilidad, y la facilidad de invocar map :: upperbound. Como siempre, escriba el código correcto primero, luego el perfil y mida los cambios incrementales. Ndash Rob Dic 16 11 at 15:00 Nota: Aparentemente esta no es la manera de abordar esto. Dejándolo aquí para referencia sobre lo que está mal con este enfoque. Compruebe los comentarios. ACTUALIZADO - basado en el comentario de Olis. No estoy seguro de la inestabilidad de la que habla. Utilice un mapa ordenado de los tiempos de llegada en función de los valores. Al llegar un valor agregue la hora de llegada al mapa ordenado junto con su valor y actualice la media móvil. Advirtiendo esto es pseudo-código: Allí. No se desarrolla completamente, pero tienes la idea. Cosas a tener en cuenta. Como dije lo anterior es pseudo código. Youll necesidad de elegir un mapa adecuado. No quite los pares a medida que pasa a través de lo que va a invalidar el iterador y tendrá que empezar de nuevo. Véase Olis comentar abajo también. Respondió Dec 15 11 at 12:22 Esto no funciona: no tiene en cuenta qué proporción de la longitud de la ventana de cada valor existe para. Además, este enfoque de sumar y luego restar es sólo estable para tipos enteros, no para flotantes. Ndash Oliver Charlesworth dic 15 11 at 12:29 OliCharlesworth - lo siento perdí algunos puntos clave en la descripción (doble y tiempo de ponderación). Voy a actualizar. Gracias. Ndash Dennis dic 15 11 at 12:33 La ponderación de tiempo es otro problema. Pero eso no es de lo que estoy hablando. Me refería al hecho de que cuando un nuevo valor entra por primera vez en la ventana de tiempo, su contribución al promedio es mínima. Su contribución continúa aumentando hasta que ingresa un nuevo valor. Ndash Oliver Charlesworth dic 15 11 at 12:35 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 de 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 12 en 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 at 14: 27Quiero desarrollar cálculo para la media móvil de precios de acciones. Pero los cálculos más complejos se han planeado más adelante. Mi primer paso para saber cómo calcular el promedio móvil de manera eficiente. Necesito saber cómo tomar la entrada y devolver la salida de manera eficiente. Fecha y Precio considerados. Fecha, Precio y Media Movente. Si tengo 500 registros y quiero calcular el promedio móvil para 5 días cuál es la manera effient en vez de ir hacia adelante y hacia atrás en la matriz de fecha y precio otra vez por favor sugest cuál es la mejor manera de recibir la entrada (ArrayList, Table, array Etc) y devolver la salida. Nota: MA de hoy de 5 días será promedio de los últimos 5 días, incluyendo el precio de hoy. Ayer MA será la media de los últimos 5 días de ayer. Quiero mantener los días flexibles en lugar de 5 podría ser 9, 14, 20 etc. Jueves, 10 de abril de 2008 3:21 PM Si necesita un cálculo simple sin su esfuerzo que puede utilizar TA-Lib. Pero si desea que su cálculo sea más eficiente que TA-Lib, entonces puede crear su propio indicador técnico. TA-Lib es genial, pero el problema es que esta biblioteca sólo tiene métodos estáticos. Esto significa que cuando se necesita calcular los valores de la matriz SMA basados ​​en 500 barras de precios, se enviará toda la matriz de barras y se devolverá una matriz de valores SMA. Pero si recibe un nuevo valor de 501-st entonces debe enviar de nuevo toda la matriz y TA-Lib de nuevo calculará y devolverá la matriz SMA de valores. Ahora imagine que necesita este indicador en el feed de precios reales, y para cada cambio de precio necesita un nuevo valor indicador. Si usted tiene un indicador no es un gran problema, pero si tiene cientos de indicadores de trabajo, podría ser un problema de rendimiento. Yo estaba en una situación así y empezar a desarrollar indicadores en tiempo real que son eficientes y hacer cálculos adicionales para la nueva barra de precios o para cambiar la barra de precios sólo. Desafortunadamente nunca he necesitado indicador SMA para mis sistemas comerciales, pero lo tengo para EMA, WMA, AD y otros. Uno de estos indicadores AD se publica en mi blog y se puede ver desde allí cuál es la estructura básica de mi clase de indicador en tiempo real. Espero que necesite pequeños cambios para implementar el indicador SMA, porque es uno de los más simples. La lógica es simple. Para calcular SMA todo lo que necesita es n valores de precio pasado. Así que la instancia de clase tendrá una colección de precios, que almacenará sólo el último n número de precios según se define SMA (en su caso 5). Así que cuando tengas una barra nueva, eliminarás la más antigua y añadirás una nueva y crearás un cálculo. Jueves, 10 de abril de 2008 16:04 Todas las respuestas Hay una biblioteca llamada TA-Lib que hace todo eso para usted y es de código abierto. Tiene unos 50 indicadores, creo. Weve lo utilizó en el ambiente de la producción y es muy eficiente y realible. Puede utilizarlo en C, Java, C, etc. Si necesita un cálculo simple sin su esfuerzo, puede utilizar TA-Lib. Pero si desea que su cálculo sea más eficiente que TA-Lib, entonces puede crear su propio indicador técnico. TA-Lib es genial, pero el problema es que esta biblioteca sólo tiene métodos estáticos. Esto significa que cuando se necesita calcular los valores de la matriz SMA basados ​​en 500 barras de precios, se enviará toda la matriz de barras y se devolverá una matriz de valores SMA. Pero si recibe un nuevo valor de 501-st entonces debe enviar de nuevo toda la matriz y TA-Lib de nuevo calculará y devolverá la matriz SMA de valores. Ahora imagine que necesita este indicador en el feed de precios reales, y para cada cambio de precio necesita un nuevo valor indicador. Si usted tiene un indicador no es un gran problema, pero si tiene cientos de indicadores de trabajo, podría ser un problema de rendimiento. Yo estaba en una situación así y empezar a desarrollar indicadores en tiempo real que son eficientes y hacer cálculos adicionales para la nueva barra de precios o para cambiar la barra de precios sólo. Desafortunadamente nunca he necesitado indicador SMA para mis sistemas comerciales, pero lo tengo para EMA, WMA, AD y otros. Uno de estos indicadores AD se publica en mi blog y se puede ver desde allí cuál es la estructura básica de mi clase de indicador en tiempo real. Espero que necesite pequeños cambios para implementar el indicador SMA, porque es uno de los más simples. La lógica es simple. Para calcular SMA todo lo que necesita es n valores de precio pasado. Así que la instancia de clase tendrá una colección de precios, que almacenará sólo el último n número de precios según se define SMA (en su caso 5). Así que cuando tengas una barra nueva, eliminarás la más antigua y añadirás una nueva y crearás un cálculo. Thursday, April 10, 2008 4:04 PM Yo calcularía el promedio móvil en la base de datos a través de un procedimiento almacenado o en un cubo. ¿Has mirado a Analysis Services, tiene la capacidad de calcular promedios móviles. Jueves, 10 de abril de 2008 16:05 Sí. TA-LIB es bueno pero puede no ser adecuado para mí. Cuando agrego nuevo valor o valor actualizado para el historial de registros haré el cálculo en una función separada solamente para esa nueva cotización y lo almacenaré en base de datos. Estoy planeando actualizar la cotización cada hora. Necesito hacer alrededor de 25 a 30 indicadores técnicos para 2200 acciones. El tiempo de ejecución de una llamada TA-Lib en una matriz de 10.000 elementos toma unos 15 milisegundos (en un Intel Core Duo 2.13 Ghz). Esta es la media de todas las funciones. Entre los más rápidos, SMA tarda menos de 2,5 milisegundos. El más lento, HTTRENDMODE, toma 450 milisegundos. Con menos elementos es más rápido. SMA toma alrededor de 0,22 milisegundos para 1000 elementos de entrada. La ganancia de velocidad es casi lineal (la sobrecarga de realizar la llamada de función es despreciable). En el contexto de su aplicación, TA-Lib es muy poco probable que sea su cuello de botella para el rendimiento de velocidad. También generalmente no recomiendo esta solución nquot quotlast. Lea a continuación para más detalles. Primero, una corrección a la instrucción de Boban. s Todas las funciones en TA-Lib también pueden calcular un solo último valor utilizando un mínimo de quotlast nquot elementos. Puede tener una matriz de tamaño 10000, tener datos inicializar sólo para los primeros 500 elementos, agregar un elemento y llamar a TA-Lib para calcular el SMA sólo para el elemento nuevo. TA-Lib mirará hacia atrás no más de lo necesario (si SMA de 5, entonces TA-Lib calculará un solo SMA usando los últimos 5 valores). Esto se hace posible con el parámetro startIdx y endIdx. Puede especificar un rango que se va a calcular o un valor único. En este escenario haría startIdx endIdx 500 para calcular el elemento 501st. ¿Por qué esta solución quotlast nquot es potencialmente peligrosa para algunos? Independientemente de la elección de la solución Boban. s o TA-Lib consideran que el uso de un pequeño número finito de datos pasados ​​no funcionará bien con la mayoría de las funciones TA. Con SMA, es obvio que sólo necesita n elemento para calcular un promedio sobre el elemento n. No es tan simple con EMA (y muchas otras funciones TA). El algo a menudo depende del valor anterior para calcular el nuevo valor. La función es recursiva. Esto significa que todos los valores pasados ​​influyen en los valores futuros. Si decides quotlimitquot tu algo para usar sólo una pequeña cantidad de pasado n valor, no obtendrás el mismo resultado que alguien que calcula sobre un gran número de valores pasados. La solución es un compromiso entre velocidad y precisión. A menudo he discutido esto en el contexto de TA-Lib (lo llamo el período quotunstable en la documentación y el foro). Para mantenerlo simple, mi recomendación general es si no puedes hacer la diferencia entre un algo con una respuesta de impulso finito (FIR) de un algo con una respuesta de impulso infinita (IIR), serás más seguro para calcular sobre todos los datos que tienes disponible. TA-Lib especifica en el código cuál de sus funciones tiene un período inestable (IIR). Editado por mfortier Viernes 15 de Agosto de 2008 4:25 AM ortografía correcta Viernes 15 de Agosto de 2008 4:20 AM

No comments:

Post a Comment