[英]Python simple moving average class based
好的,所以我正在編寫一個類,該類將根據價格列表計算簡單的移動平均線。 它計算每N個價格的平均值,而不計算前N-1天。 這就是我所擁有的:
class Simplemovingaverage():
def __init__(self, Nday, list_of_prices):
self._Nday = Nday
self._list_of_prices = list_of_prices
def calculate(self):
for i in range(len(self._list_of_prices)):
if i < self._Nday:
average = 0
elif i == self._Nday:
average = sum(self._list_of_prices[:self._Nday])/self._Nday
else:
average = sum(self._list_of_prices[i-self._Nday:i])/self._Nday
print(average)
我通過在外殼程序上創建一個類對象'x = Simplemovingaverage(3, [1,2,3,4,5,6,7,8,9,10])'
,然后通過'x .calculate'我得到的輸出是:
0
0
0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
因此,從我的數字列表中,它最多可以計算到7、8、9,最后一個數字應該是9,因為那是8、9、10的平均值,並且因為N是3,所以也應該只有3個零。這是輸出I正在尋找:
0
0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
def sma_calc(prices_list, window_size):
return sum(prices_list[-window_size:]) / window_size
from __future__ import division
from itertools import islice, tee
def moving_average(n, iterable):
# leading 0s
for i in range(1, n):
yield 0.
# actual averages
head, tail = tee(iterable)
sum_ = float(sum(islice(head, n)))
while True:
yield sum_ / n
sum_ += next(head) - next(tail)
當以
list(moving_average(3, [1,2,3,4,5,6,7,8,9,10]))
回報
[0.0, 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
(從N-1前導0開始,這意味着輸出列表與輸入列表具有相同的基數,我認為這是您真正想要的)。
您出了一個錯誤。 嘗試這個:
for i in range(len(self._list_of_prices) + 1):
所以這可能說明發生了什么
>>> _list_of_prices = [1,2,3,4,5,6,7,8,9,10]
>>> len(_list_of_prices)
10
>>> range(len(_list_of_prices))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> i = 9
>>> _list_of_prices[i-3:i]
[7, 8, 9]
因此,問題在於在上面的示例中python的列表切片運算符最多返回i,但不返回i(在此示例中,它返回i-3,i-2和i-1),例如
>>> word = "helpa"
>>> word[0:2]
'he'
您誤認為了索引:
In [186]: class Simplemovingaverage():
...: def __init__(self, Nday, list_of_prices):
...: self._Nday = Nday
...: self._list_of_prices = list_of_prices
...:
...: def calculate(self):
...: for i in range(len(self._list_of_prices)):
...: if i < self._Nday-1:
#------------------------^^--------------------------
...: average = 0
...: elif i == self._Nday-1:
#---------------------------^^--------------------------
...: average = sum(self._list_of_prices[:self._Nday])/self._Nday
...: else:
...: average = sum(self._list_of_prices[\
i+1-self._Nday:i+1])/self._Nday
#-----------------^^^-------------^^^--------------------------
...: print(average)
In [187]: x = Simplemovingaverage(3, [1,2,3,4,5,6,7,8,9,10])
In [188]: x.calculate()
0
0
2
3
4
5
6
7
8
9
好,這是一個清理工作:
class Simplemovingaverage():
def __init__(self, navg, items):
self.navg = navg
self.items = items
def calculate(self):
av = []
for i in range(len(self.items)):
if i+1 < self.navg:
av.append(0)
else:
av.append(sum(self.items[i+1-self.navg:i+1])/self.navg)
return av
首先,您需要在所有地方使用i+1
,因為range
給出的是0...navg-1
而不是1...navg
(您也可以執行range(1, n+1)
)。
其次,您不需要特殊情況i+1==self.navg
( :m
與0:m
相同)。
第三,返回列表而不是打印結果更有意義(盡管我喜歡其他受訪者關於使用yield
使其成為生成器的想法!)
第四,沒有真正的理由隱藏數字和列表,因此我刪除了下划線(python不是java或c ++!)。
最后,這比在一定數量的“天”內平均的“價格清單”更為籠統,因此我將參數重命名為更通用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.