Aunque tu código ya te está dando el resultado correcto, casi me siento mal por ti porque tienes que esperar 5 segundos por una cantidad tan pequeña de datos. Tu código es lento porque estás reinventando la rueda en lugar de utilizar algunas funciones integradas de pandas y numpy. Por ejemplo, producto
y wma
en tu código pueden combinarse y lograrse utilizando la función de producto punto de numpy (np.dot
) que se aplica a toda la columna de forma iterativa con una función anónima encadenando los métodos .rolling()
y .apply()
de pandas. Siempre es mejor buscar soluciones predefinidas porque las funciones están optimizadas detrás de escena. Ejecuté tu código en mi máquina y los resultados tardan alrededor de 2 segundos para 5200 valores. Prueba algo así (agregué una funcionalidad básica como ejemplo para que empieces a pensar):
import pandas as pd
import numpy as np
def wma(df, column='close', n=20, add_col=False):
weights = np.arange(1, n + 1)
wmas = df[column].rolling(n).apply(lambda x: np.dot(x, weights) /
weights.sum(), raw=True).to_list()
if add_col == True:
df[f'{column}_WMA_{n}'] = wmas
return df
else:
return wmas
La función anterior tomará el mismo dataframe que estabas usando y devolverá la misma lista de la misma manera que la tenías originalmente. Solo llama a wma(df)
. Además, puedes cambiar el nombre de la columna, el valor del período, y puedes optar por no devolver una lista, sino agregar los valores como una nueva columna al dataframe que pasaste originalmente. Además, se ejecuta en mi máquina en aproximadamente 20 milisegundos, ¡casi 100 veces más rápido que tu código original...
1 votos
El código parece que dará el resultado correcto, pero no es dinámico y estás pidiendo errores al tener la longitud del período y el nombre de la columna codificados. Normalmente se pasarían como variables. Hay implementaciones mucho más rápidas de esto sin usar un bucle for y comprensión de listas anidadas. ¡Casi duele mirarlo!
0 votos
@amdopt cualquier consejo sería de ayuda. ¡Mi código tarda casi 5 segundos con una columna de solo 5,000 valores!