Jupyter Notebook 上で主にシストレをテーマにしたデータいぢりを始めて1年あまり経ちますが、いまいち NumPy・Pandas・Matplotlib がマスター出来た気になれないので、公開しながら演習することにしました。プライベートのスニペットバンクにちまちま書き溜めるよりは気合いが入るのじゃないかと…
Python には TA-Lib というテクニカル分析ライブラリがありますが、これを使わずに NumPy や Pandas の機能をフル活用して自前で計算することでデータ処理のスキルを磨こうという狙いです。てな訳で、手始めに移動平均の類から。
尚、計算の対象は日経平均にします。日経平均プロフィルさんが2016年からの日足データ CSV を提供されているので、これを有り難く使わせて頂きます。
CSV_URL = "https://indexes.nikkei.co.jp/nkave/historical/nikkei_stock_average_daily_jp.csv" df = pd.read_csv(CSV_URL, encoding="SHIFT-JIS", names=['date', 'close', 'open', 'high', 'low'], header=1); df = df.dropna() # 最後のコメント行を削除
データフレームの列名は ASCII のほうが何かと便利なので、names= で列名を指定しておきます。では、この日足データフレームに、以下のように25日の各種移動平均を算出しながら列追加していきます。
まずは単純移動平均から。これは Pandas の窓関数平均で一発。
df['sma25'] = df.close.rolling(25).mean()
次に加重移動平均。これは関数を作って窓関数に apply してやります。
def calc_wma(prices): weights = np.arange(len(prices)) + 1 wma = np.sum(weights * prices) / weights.sum() return wma df['wma25'] = df.close.rolling(25).apply(calc_wma)
指数平滑移動平均は、当日株価と前回平均を計算するので窓関数での逐次計算では処理できず、全終値からまるっと計算する手法にしました。ループは極力使いたくなかったのですが、無理に行列指向な処理にするとコードの可読性が落ちそうだったので仕方なく…
def calc_ema(prices, period): ema = np.zeros(len(prices)) ema[:] = np.nan # NaN で初期化 ema[period-1] = prices[:period].mean() # 最初だけ単純移動平均 for d in range(period, len(prices)): ema[d] = ema[d-1] + (prices[d] - ema[d-1]) / (period + 1) * 2 return ema df['ema25'] = calc_ema(df.close, 25)
ついでに株価と移動平均の乖離率[%]も計算してみます。
def calc_devrate(prices): sma = prices.mean() return (prices[-1] - sma) / sma * 100 df['devrate'] = df.close.rolling(25).apply(calc_devrate)
以上、各種移動平均を計算・列追加されたデータフレームがこちらになりまつ。
最後にお約束の可視化グラフを。計算した各種移動平均を株価に重ねて作画してみます。期間が長いのでちと重なりがちですが、それぞれの移動平均線の特色がわかる…ような気がしますw 乖離率もその下に並べて置いときます。
上記のコードは Google Colaboratory で公開してあります(↓)。
https://colab.research.google.com/drive/1Od95PnZsuXXMHNA3HeKwRTsSui9XGqSacolab.research.google.com