algorithm - para - Encontrar el mínimo máximo de un gráfico de cotizaciones
graficas en excel ejemplos (8)
A menudo he encontrado que los extremos percibidos subjetivamente por los humanos (lea: los únicos extremos en los gráficos de cotización, que son en su mayoría ruido aleatorio) a menudo se encuentran después del filtrado de paso de banda de Fourier. Podrías probar este algoritmo:
- Realizar un FFT
- Hacer un paso de banda en el espacio de frecuencia. Seleccione los parámetros del paso de banda según el rango de datos en los que desea que sus extremos se vean bien, es decir, la escala de tiempo de interés.
- Realizar una FFT inversa.
- Seleccione los máximos locales de la curva resultante.
Los parámetros del segundo paso parecen bastante subjetivos, pero, una vez más, la subjetividad es la naturaleza misma del análisis de gráficos de stock.
¿Hay algún algoritmo específico que me permita encontrar los puntos mínimo y máximo en la imagen de arriba?
Tengo datos en formato de texto, por lo que no necesito encontrarlos en la imagen. El problema con las acciones es que tienen tantos minutos locales y los máximos derivados simples no funcionan.
Estoy pensando en usar filtros digitales (dominio z) y en suavizar el gráfico, pero aún me quedan demasiados mínimos y máximos localizados.
También intenté usar un promedio móvil para suavizar el gráfico, pero nuevamente tengo demasiados máximos y minutos.
EDITAR:
Leí algunos de los comentarios y simplemente no circulé algunos de los mínimos y máximos por accidente.
Creo que se me ocurrió un algoritmo que puede funcionar. Primero encuentra los puntos mínimos y máximos (máximo del día y mínimo del día). Luego, dibuje tres líneas, una de abierta a alta o baja, lo que ocurra primero, luego una línea de baja a alta o de alta a baja y finalmente se cierre. Luego, en cada una de estas tres regiones, encuentre el punto que está más alejado de la línea como mi punto alto y bajo y luego repita el ciclo.
Como lo mencionó Belisario, el mejor método parece involucrar el filtrado de datos sin problemas. Con una suavización suficiente, la búsqueda de cambios en la pendiente debe indicar los minutos y los máximos locales (la derivada ayudará aquí). Usaría una ventana deslizante centrada para una mediana / promedio en ejecución, o un EMA en curso (o un filtro IIR similar).
No sé a qué te refieres con "derivados simples". Entiendo que significa que ha probado un descenso de gradiente y lo encontró insatisfactorio debido a la abundancia de los extremos locales. Si es así, desea ver el recocido simulado :
El recocido es un proceso metalúrgico utilizado para atemperar metales a través de un tratamiento de calentamiento y enfriamiento. (...). Estas irregularidades se deben a que los átomos se atascan en el lugar equivocado de la estructura. En el proceso de recocido, el metal se calienta y luego se deja enfriar lentamente. El calentamiento les da a los átomos la energía que necesitan para desatraparse, y el lento período de enfriamiento les permite moverse a su ubicación correcta en la estructura.
(...) Sin embargo, para escapar de los óptimos locales, el algoritmo tendrá la probabilidad de dar un paso en una dirección incorrecta : en otras palabras, de dar un paso que incremente el valor de un problema de minimización o que disminuya el valor. Para un problema de maximización. Para simular el proceso de recocido, esta probabilidad dependerá en parte de un parámetro de "temperatura" en el algoritmo, que se inicializa en un valor alto y disminuye en cada iteración. En consecuencia, el algoritmo inicialmente tendrá una alta probabilidad de alejarse de un óptimo cercano (probablemente local) . A lo largo de las iteraciones, la probabilidad disminuirá y el algoritmo convergerá en el óptimo (con suerte global) del que no tuvo oportunidad de escapar. ( source , cortes y, énfasis mío)
Sé que el óptimo local es precisamente lo que representan los círculos en su dibujo, arriba, y por lo tanto, lo que quiere encontrar. Pero, como interpreto la cita " muchos derivados locales, máximos y mínimos, no funcionarán ", esto es precisamente lo que encuentra demasiado. Supongo que tiene problemas con todos los "zig-zag" que hace la curva entre dos puntos en círculo.
Todo lo que parece diferenciar los puntos óptimos que circulas del resto de los puntos de la curva es su globalidad , precisamente: para encontrar un punto más bajo que el primer punto que circulas a la izquierda, debes ir más lejos en la coordenada x de lo que necesita hacer lo mismo para sus vecinos cercanos. Eso es lo que te da el recocido: dependiendo del parámetro de temperatura, puedes controlar el tamaño de los saltos que te permites hacer. Tiene que haber un valor para el que se capturan los "grandes" locales óptimos, y aún así se pierden los "pequeños". Lo que estoy sugiriendo no es revolucionario: hay varios ejemplos (por ejemplo, 1 2 ) donde las personas han obtenido buenos resultados de datos tan ruidosos.
Notará que muchas de las respuestas van de derivados con algún tipo de filtrado de paso bajo. Un promedio móvil de algún tipo, por así decirlo. Tanto el pie derecho, el promedio móvil de ventana cuadrada como el promedio móvil exponencial son bastante similares en un nivel fundamental. Sin embargo, dada la elección sobre todos los promedios móviles, ¿cuál es el mejor?
La respuesta: la media móvil gaussiana; La de la distribución normal, de la que eres consciente.
La razón: el filtro gaussiano es el único filtro que nunca producirá un máximo "falso"; Un máximo que no estaba allí para empezar. Esto se ha comprobado teóricamente tanto para datos continuos como discretos (¡Asegúrate de usar el Gaussiano discreto para datos discretos, sin embargo!). A medida que aumenta el sigma gaussiano, los máximos y mínimos locales se fusionarán de la manera más intuitiva. Por lo tanto, si desea que no haya más de un máximo local por día, establezca sigma en uno, etcétera.
Puede usar el método Spline para crear un polinomio de aproximación de contenido para su función original [con el grado deseado]. Después de tener este polinom, busque un mínimo / máximo local [usando cálculo básico] en él [el polinom generado].
Tenga en cuenta que el método spline le proporciona un polinomio de aproximación que es "suave", por lo que es fácil encontrar mín / máx locales, y lo más cercano posible a la función original, y por lo tanto el mínimo / máximo local debería estar muy cerca de El verdadero valor, en la función original.
Para mejorar la precisión, después de encontrar los minutos / máx locales en el polinom generado, para cada x0
que representa un mínimo / máximo local, debe buscar en todo x tal que x0-delta < x < x0 + delta
, para encontrar el mínimo / max representa este punto.
Simplemente defina lo que quiere decir con mínimo y máximo de una manera precisa, pero ajustable, y luego afínelo hasta que encuentre el número correcto de mínimos y máximos. Por ejemplo, primero puede suavizar el gráfico reemplazando cada valor con el promedio de ese valor y los valores N a la izquierda y a la derecha. Al aumentar N, puedes reducir el número de mínimos y máximos que encuentres.
A continuación, puede definir un mínimo como un punto en el que, si omite los valores de A a la izquierda y a la derecha, los siguientes valores de B muestran una tendencia creciente constante. Al aumentar B, puedes encontrar menos mínimos y máximos. Al ajustar A, puede ajustar cuán ''plano'' se permite que sea el mínimo o el máximo.
Una vez que use un algoritmo ajustable, puede sintonizarlo hasta que se vea bien.
Usualmente uso una combinación de media móvil y media móvil exponencial. Resultó (empíricamente) estar bien preparado para la tarea (suficiente para mis necesidades, al menos). Los resultados se sintonizan con sólo dos parámetros. Aquí hay una muestra:
Editar
En caso de que sea útil para alguien, aquí está mi código de Mathematica:
f[sym_] := Module[{l},
(*get data*)
l = FinancialData[sym, "Jan. 1, 2010"][[All, 2]];
(*perform averages*)
l1 = ExponentialMovingAverage[MovingAverage[l, 10], .2];
(*calculate ma and min positions in the averaged list*)
l2 = {#[[1]], l1[[#[[1]]]]} & /@
MapIndexed[If[#1[[1]] < #1[[2]] > #1[[3]], #2, Sequence @@ {}] &,
Partition[l1, 3, 1]];
l3 = {#[[1]], l1[[#[[1]]]]} & /@
MapIndexed[If[#1[[1]] > #1[[2]] < #1[[3]], #2, Sequence @@ {}] &,
Partition[l1, 3, 1]];
(*correlate with max and mins positions in the original list*)
maxs = First /@ (Ordering[-l[[#[[1]] ;; #[[2]]]]] + #[[1]] -
1 & /@ ({4 + #[[1]] - 5, 4 + #[[1]] + 5} & /@ l2));
mins = Last /@ (Ordering[-l[[#[[1]] ;; #[[2]]]]] + #[[1]] -
1 & /@ ({4 + #[[1]] - 5, 4 + #[[1]] + 5} & /@ l3));
(*Show the plots*)
Show[{
ListPlot[l, Joined -> True, PlotRange -> All,
PlotLabel ->
Style[Framed[sym], 16, Blue, Background -> Lighter[Yellow]]],
ListLinePlot[ExponentialMovingAverage[MovingAverage[l, 10], .2]],
ListPlot[{#, l[[#]]} & /@ maxs,
PlotStyle -> Directive[PointSize[Large], Red]],
ListPlot[{#, l[[#]]} & /@ mins,
PlotStyle -> Directive[PointSize[Large], Black]]},
ImageSize -> 400]
]
El teorema de Fermat te ayudará a encontrar los mínimos y máximos locales.