12章
libフォルダのarray.py
PythonにはRubyのオープンクラスというのはないようなので、
listを継承して作成。
Rubyのinjectやeach_consをPython用に変更するのに苦戦した。
each_consはまだいいとして、injectについて調べると
Pythonではreduceというのが近いということが分かりそれで作ったが、
最終チェックの指数移動平均をつくるところでどうしたらいいのかわからなくなった。
map_indicatorの作り方がまずいのかもしれない。
#!/usr/bin/env python # -*- coding: utf-8 -*- from functools import reduce # Array クラスの拡張 # 合計、平均、移動平均、区間高値・安値を求めるメソッドを追加 # 配列から指標計算するメソッドを定義 class Array(list): # 合計 def sum(self): return reduce(lambda a , b: a+b, self) # 平均 def average(self): return float(self.sum()) / len(self) # 元の配列と同じ要素数の配列を返す # 配列の各要素を span 個ずつ取り出した配列に対して、順番に # ブロックで実装された処理を実行する # 呼び出し方:array.map_indicator(span) {|span_array| ...} def map_indicator(self, span, func): indicator_array = Array([None for x in range(0, len(self))]) for i, x in enumerate(self._each_cons(span)): if None not in x: indicator_array[i + span - 1] = reduce(func , x) return indicator_array # 移動平均 def moving_average(self, span): func = lambda a , b : a + b return Array([x / span if x != None else None for x in self.map_indicator(span, func)]) # 区間高値 def highs(self, span): func = lambda a , b : a if a >= b else b return Array([x if x != None else None for x in self.map_indicator(span, func)]) # 区間安値 def lows(self, span): func = lambda a , b : a if a <= b else b return Array([x if x != None else None for x in self.map_indicator(span, func)]) def _each_cons(self, span): return zip(*(self[i:] for i in range(span))) if __name__ == '__main__': array = Array([100, 97, 111, 115, 116, 123, 121, 119, 115, 110]) print(array.sum()) print(array.average()) print(array.moving_average(4)) print(array.highs(3)) print(array.lows(3)) # 3区間高値と安値の中間 middle = Array([(x + y)/2 if x != None and y != None else None for (x, y) in zip(array.highs(3), array.lows(3))]) print(middle) # 前日との増減 func = lambda a, b : b - a changes = array.map_indicator(2, func) print(changes) # 3区間の増減の平均 average_changes = changes.moving_average(3) print(average_changes) # 指数移動平均(Exponential Moving Average) # ???