2014-02-18 4 views
0

Итак, я пишу класс, который будет вычислять простую скользящую среднюю по списку цен. Он вычисляет среднее значение каждого N числа цен без расчета первых N-1 дней. Это то, что у меня есть:Python простой скользящий средний класс на основе

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])', а затем делает метод CALCulate по «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, а также должно быть только 3 нуля, так как N равно 3. Это вывод I 'ищу:

0 
0 
2.0 
3.0 
4.0 
5.0 
6.0 
7.0 
8.0 
9.0 
+5

Зачем нужен класс для этого? Кажется, что нет объекта с состоянием или поведением, которое вы моделируете; это просто вычисление. Это будет работать лучше как функция. – user2357112

+0

Посмотрите на использование объекта [deque] (http://docs.python.org/2/library/collections.html#collections.deque) для скользящих средних. Он оптимизирован для добавления и всплытия на любом конце, а также фиксированных размеров (если необходимо) – mhlester

+1

Просто используйте [move_average recipe] (http://docs.python.org/2/library/collections.html#deque-recipes) из 'collections.deque'. –

ответ

0

ОК, вот уборка:

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++!).

И, наконец, это более общий, чем «список цен», усредненный по определенному количеству «дней», поэтому я переименовал параметры для большей общности.

+0

Зачем мне нужен +1 в «if i ​​+1

+0

Вы пробовали? Это (или 'i

+0

Для этого списка чисел мне нужны только 2 нули, может быть, вы не видели, что я его изменил; Сначала я положил 3 нуля, но это была ошибка. Он отлично работает с «if i ​​

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] 

Таким образом, проблема в том, что оператор список Нарезать питона возвращает до I в приведенном выше примере, но не я, (в в этом примере он возвращает i-3, i-2 и i-1), например

>>> word = "helpa" 
>>> word[0:2] 
'he' 

Смотрите здесь http://docs.python.org/2/tutorial/introduction.html

+0

Извините, что отвлекся, затем зафиксировал его на месте. –

+0

Также вы не нужен elif i == self._Nday: специальный случай? Также _Nday не соответствует руководству стиля python .. _n_days больше pythonic (если это имеет значение для вас). –

+0

Ты делаешь что-то немного странное здесь. Я не могу положиться пальцем на –

0

Вы имеете ошибаетесь индекс:

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 
1
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 ведущих 0s, что означает, что выходной список имеет ту же мощность, что и входной список, который, как я думаю, вам действительно нужен).

+0

Вам на самом деле не нужно, чтобы это было основано на классах, в этом нет необходимости. –

3
def sma_calc(prices_list, window_size): 
    return sum(prices_list[-window_size:])/window_size 
+0

В вашем ответе можно было бы использовать немного больше объяснений. –

+0

Достаточно честный, thx. Я не хочу отвлекаться от темы, цель заключалась в том, чтобы обрабатывать SMA с помощью класса. Просто подумал, что могут быть такие, как я, которые предпочитают держать вещи простыми, я использую эти строки в алгоритмическом торговом коде. Просто отправьте ему список чисел (поплавки в моем случае) и размер окна обратного просмотра (integer), и он вернет текущее простое скользящее среднее значение. Сейчас я использую 3 sma, поэтому я нахожу это удобным/удобным/гибким. Мы не видим, что price_list добавляется с ценой для каждой торговой панели перед отправкой на эту функцию. Надеюсь, это поможет. – gseattle

Смежные вопросы