Średnia ruchoma ważona dla kolumny

0

Chcę obliczyć średnią ruchomą ważoną, ale coś idzie nie tak. Mają być 2771 odpowiedzi, niejednakowe, ale otrzymuję te same liczby dla każdego wersu. Pierwsza odpowiedź ~` 222,384, ale drukuje mi 77933.848329. Dane w załączniku.

import pandas as pd
import numpy as np

#WMA = ( Price n + Price(1) n-1 + ...+Price( n-1 ) 1) / ( n ( n + 1 ) / 2 ), (n = time period).

def wma(data, N):
    #n = len(data)
    for i in range(N, 0, -1):
        data[i] = i * data[abs(i - N)]
    return sum(data) / ((N * (N + 1)) / 2)


data_pd = pd.read_csv('GS.csv')
format = '%m/%d/%Y'
data_pd['Date'] = pd.to_datetime(data_pd['Date'], format=format)
data_pd = data_pd.set_index(data_pd['Date'])  
data_pd = data_pd.drop(columns=['Date'])

p2 = 3

data_pd['wma'] = wma(data_pd['Close'].values, p2)

#print(data_pd['wma'])
0
Beata Griškevič napisał(a):

Chcę obliczyć średnią ruchomą ważoną, ale coś idzie nie tak. Mają być 2771 odpowiedzi, niejednakowe, ale otrzymuję te same liczby dla każdego wersu. Pierwsza odpowiedź ~` 222,384, ale drukuje mi 77933.848329. Dane w załączniku.

def wma(data, N):
    #n = len(data)
    for i in range(N, 0, -1):
        data[i] = i * data[abs(i - N)]
    return sum(data) / ((N * (N + 1)) / 2)

Zapisujesz wynik mnożenia z powrotem do tej samej listy, w dodatku odczytując z innej pozycji - czyli de facto nie nadpisujesz nawet wartości wynikami operacji na nich, tylko wynikami operacji na innych wartościach - prosi się o błędy ;)

  def wma(data, N):
     #n = len(data)
     out_data = 0.0
     for i in range(N, 0, -1):
         out_data += i * data[abs(i - N)])
     return out_data / ((N * (N + 1)) / 2)

Bezpieczniej byłoby utworzyć sobie pomocniczą listę i dorzucać do niej rezultaty, to raz. Dwa, funkcja zwraca skalar który przypisujesz do kolumny - to dlatego dostajesz tę samą wartość dla wszystkich wierszy.

Trochę poprawniej byłoby użyć Series.apply i np. przekazywać interesujący Cię podprzedział lub indeks startowy i końcowy:

close_col = data['Close']

# Dla uproszczenia pomijam walidację granic przedziałów i takie tam
K = N/2

# Dla każdego elementu w kolumnie wywołujemy wma na podprzedziale <i - K, i + K>
data['wma'] = close_col.apply(lambda x: wma(close_col[(x.index - K):(x.index + 1 + K)], N))

Nie daję głowy, czy poprawnie się odwołałem do tego i tamtego, piszę z pamięci a nie dłubałem w Pandas od jakiegoś czasu ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1