【问题标题】:Python simple moving average class based基于 Python 简单移动平均类
【发布时间】:2014-03-17 16:42:20
【问题描述】:

好的,所以我正在编写一个类来计算价格列表上的简单移动平均线。它计算每 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)

我通过在 shell '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 的平均值,而且应该只有 3 个零,因为 N 是 3。这是我正在寻找的输出:

0
0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0

【问题讨论】:

  • 为什么要为此开设课程?似乎没有任何对象具有您正在建模的状态或行为;它只是在做一个计算。这作为一个函数会更好。
  • 看看使用deque 对象作为移动平均线。它针对两端的追加和弹出以及固定大小(如果需要)进行了优化
  • 只需使用来自collections.dequemoving_average recipe
  • 我同意你为什么要使用一个类的问题,但更根本的是:你为什么要打印结果,而不是创建一个新列表并返回它?
  • 输出应该是0, 0, 2, 3, 4, 5, 6, 7, 8, 9,而不是0, 0, 0, ...

标签: python class methods average self


【解决方案1】:
def sma_calc(prices_list, window_size):
    return sum(prices_list[-window_size:]) / window_size

【讨论】:

  • 你的回答可以再解释一下。
  • 很公平,谢谢。我并不是要偏离主题,目标是使用类来处理 SMA。只是想可能有一些像我这样更喜欢保持简单的人,我在算法交易代码中使用了这些行。只需向它发送一个数字列表(在我的例子中是浮点数)和一个回溯窗口大小(整数),它就会返回当前的简单移动平均值。现在我使用 3 个 sma,所以我觉得很方便/方便/灵活。我们没有看到 prices_list 在发送到该函数之前被附加了每个交易柱的价格。希望对您有所帮助。
【解决方案2】:
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 开头,表示输出列表与输入列表具有相同的基数,我认为这是您真正想要的)。

【讨论】:

  • 你实际上不需要它是基于类的,没有必要。
【解决方案3】:

好的,这里是清理工作:

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 进行特殊处理(:m0:m 相同)。

第三,返回列表而不是打印结果更有意义(尽管我喜欢其他受访者使用yield 将其作为生成器的想法!)

第四,没有真正的理由隐藏数字和列表,所以我删除了下划线(python 不是 java 或 c++!)。

最后,这比特定“天”数内的平均“价格列表”更通用,因此我重命名了参数以更通用。

【讨论】:

  • 为什么我需要“if i +1
  • 你试过了吗?那(或i&lt;self.navg-1)是你需要在开始时获得正确数量(navg-1)的0:当i=0, 1, ... navg-2
  • 对于这个数字列表我只需要2个零,也许你没有看到我改变了它;我一开始输入了 3 个零,但那是一个错误。它只适用于“if i
  • 不,它没有!您希望 n-1 为零,而 range 从 0 开始计数。这就是您的代码不起作用工作的原因之一!
  • 正好我需要 n-1 个零,n 为 3 我得到两个零。零只是说你可以在没有前n-1的情况下计算n天的简单移动平均线。当我将零更改为 '' 一个空白空间时,它给了我 2 个空白空间,然后平均值从 3 开始,这就是我需要的。当我放 +1 时,它给了我 1 个空格和一个零,然后它开始计算 3 的平均值。我认为你误解了零的作用。
【解决方案4】:

你有一个错误。试试这个:

  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'

请看这里http://docs.python.org/2/tutorial/introduction.html

【讨论】:

  • 抱歉分心了,然后把它固定到位
  • 你也不需要 elif i == self._Nday: 特殊情况? _Nday 也不符合 python 风格指南。_n_days 更 Pythonic(如果这种事情对你很重要)。
  • 你在这里做的有点奇怪......我不能完全把我的手指放在我的手指上
  • 是的..你的出局在于你对列表切片运算符的理解。
【解决方案5】:

你弄错了索引:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-04
    • 2013-04-15
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 2011-03-07
    • 2021-12-26
    相关资源
    最近更新 更多