相場商売

トレーディングビジネスあれこれ

12章改

指数移動平均ができないので作り直したarray.pyあらためmyarray.py

#!/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):
        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] = x
        return indicator_array
    
    # 移動平均
    def moving_average(self, span):
        return Array([sum(x) / span if x != None else None for x in self.map_indicator(span)])
    
    # 区間高値
    def highs(self, span):
        return Array([max(x) if x != None else None for x in self.map_indicator(span)])     

    # 区間安値
    def lows(self, span):
        return Array([min(x) if x != None else None for x in self.map_indicator(span)])      
            
    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([(max(x)+min(x))/2 if x != None else None for x in array.map_indicator(3)])
    print(middle)
    
    # 前日との増減
    changes = Array([x[1] - x[0] if x != None else None for x in array.map_indicator(2)])
    print(changes)
    
    # 3区間の増減の平均
    average_changes = changes.moving_average(3)
    print(average_changes)
    
    # 指数移動平均(Exponential Moving Average)
    span = 4
    alpha = 2.0 / (span + 1)
    ema = None
    ema_array = Array([None for x in range(0, len(array))])
    for i, x in enumerate(array.map_indicator(span)):
        if x != None:
            if ema == None:
                ema = sum(x) / span
            else:
                ema += alpha * (x[span - 1] - ema)
            ema_array[i] = ema
    print(ema_array)

map_incidatorを配列を返すだけに変えた。
map_incidatorの役割を変えてしまって大丈夫か心配だが、
目的はRubuのコードをPythonに変えるのではなく、
Pythonシステムトレードをすることなのでとりあえずこれでよしとする。