【相場分析】移動平均線の傾きをPythonで算出する

![ma_slope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/1e69685b-089c-87a3-e9ee-efc92f84008b.png)


## 概要

相場と向き合う上では欠かす事のできない移動平均線。視覚的にもシンプルでわかりやすい分、おそらくほとんどの投資家が注目しているであろう重要なインジケーターの１つです。

「〇〇日移動平均線の上（下）にローソク足が突き抜けた場合は買い（売り）」といった感じでエントリーの根拠にしている人も多いでしょう。

実際、私も相場を見る上では必ずチャートに表示させているくらいお世話になっているわけですが、これをプログラミング言語（Python）で再現するならどんな風に書けば良いんだろう？となったので、メモとして残しておきます。

最近はシステムトレードの勉強もしているため、そちらにも組み込みたいなと。特に移動平均線の「傾き」などは相場の勢いを表す上で便利な指標になると思うので算出したいところです。

## 実行環境

- Google Colaboratory
    - ブラウザからPythonを記述、実行できるサービス。
- Twelve Data
    - 株、為替、仮想通貨といった金融商品の情報を取得できるサービス。

今回はPythonの実行環境として「[Google Colaboratory](https://research.google.com/colaboratory/)」を使っていきます。

![スクリーンショット 2021-09-19 23.19.07_censored.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/37f3c2d6-468d-016e-fb00-7b26054b8c47.jpeg)

Googleアカウントさえ持っていれば面倒な環境構築の必要も無くそのままPythonを実行していけるので非常に便利です。

また、ヒストリカルデータの取得元としては「[Twelve Data](https://twelvedata.com/)」を採用しました。

![スクリーンショット 2021-09-19 23.20.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/58106eaf-26f8-2b0f-cee9-67d8cdb364db.png)

海外のサービスではありますが、ドキュメントが豊富で使いやすいAPIを提供してくれているほか、取得できる情報も仮想通貨、株、為替と幅広いので何かと重宝しそうです。


![スクリーンショット 2021-09-19 23.17.20_censored.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/ab7d2823-efa4-655c-0a51-1be50eba1686.jpeg)

Twelve DataのAPIキーに関しては、ログイン後のダッシュボードでサクッと発行できるのであらかじめ済ませておいてください。

## 実装

それではコードを書いていきましょう。

### pip install

```py:1個目のセル
# pip install
pip install twelvedata websocket
```

Google Colaboratory にはすでに一部の基本的なライブラリがあらかじめ標準装備されていたりしますが、上記のライブラリは含まれていないため、「pip install」でインストールしておきます。

### 各種ライブラリの読み込み

```py:2個目のセル
# 各種パッケージの読み込み&設定
import datetime
import pandas as pd
pd.set_option('display.max_rows', None)

import requests
from termcolor import colored as cl
from twelvedata import TDClient
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (20, 10)
```

各種ライブラリの読み込みと設定を行います。

### 関数の定義

```py:3個目のセル
TWELVE_DATA_API_KEY = '****************************' # Twelve Data のAPIキー

# ヒストリカルデータを取得
def get_historical_data(symbol, interval, outputsize, start_date, end_date, timezone):
    td = TDClient(apikey = TWELVE_DATA_API_KEY)
    
    res = td.time_series(
              symbol = symbol,
              interval = interval,
              outputsize = outputsize,
              start_date = start_date,
              end_date = end_date,
              timezone = timezone
          ).as_json()
    
    df = pd.DataFrame(res).iloc[::-1].set_index('datetime').astype(float)
    df = df[df.index >= start_date]
    df.index = pd.to_datetime(df.index)

    return df

# 単純移動平均線を作成
def make_sma(close, span):
    return close.rolling(window = span).mean()

# 指数平滑移動平均線を作成
def make_ema(close, span):
    sma = make_sma(close, span)[:span]
    return pd.concat([sma, close[span:]]).ewm(span = span, adjust = False).mean()

# 移動平均線の傾きを作成
def make_ma_slope(ma, span):
    ma_slope = []
    
    for i in range(len(ma)):
        ma_slope.append((ma[i] - ma[i - span]) / (i - (i - span)))
    
    return ma_slope
```

- 単純移動平均線（SMA）を計算するための関数
- 指数平滑移動平均線（EMA）を計算するための関数
- 移動平均線の傾きを計算するための関数

をそれぞれ定義。

pandasには移動平均線を計算するために便利な関数（rollingやewm）が標準で備わっているので、それらを使いました。

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rolling.html

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.ewm.html

移動平均線の傾きに関しては、

- 前日〜当日の傾き
    - （ローソク足 n 本目の移動平均値 - ローソク足 n-1 本目の移動平均値） / １

- 3日間の傾き
    - （ローソク足 n 本目の移動平均値 - ローソク足 n-2 本目の移動平均値） / ３

といった感じの計算式で求める事が可能です。

### 移動平均線および傾きを計算

```py:4個目のセル
# 銘柄
symbol = 'AUD/JPY'

# 時間軸
interval = '1day'

# 取得件数
outputsize = 1000

# 取得開始日
start_date = '2019-01-01'

# 取得終了日
end_date = datetime.datetime.now().strftime('%Y-%m-%d')

# タイムゾーン
timezone = 'Asia/Tokyo'

# ヒストリカルデータを取得
df = get_historical_data(symbol, interval, outputsize, start_date, end_date, timezone)

# EMA50
df['ema50'] = make_ema(df['close'], 50)
df['ema50_slope'] = make_ma_slope(df['ema50'], 1)
```

平均値を求めるための期間などはお好みで設定してください。

### チャートを作成

```py:5個目のセル
# チャート描画
fig, (ax1, ax2) = plt.subplots(2, 1, gridspec_kw = { 'height_ratios':[3, 1] })

ax1.plot(df['close'], color = 'green', linewidth = 2, label = 'CLOSING PRICE')
ax1.plot(df['ema50'], color = 'orange', linewidth = 2, label = 'EMA50')
ax1.legend(loc = 'upper left')

# 移動平均値が0以上なら赤色、0以下なら青色
ax2.bar(np.arange(len(df.index)), df['ema50_slope'].fillna(0), color = [('red' if i > 0 else 'blue') for i in df['ema50_slope']])

plt.show()
```

![ma_slope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/1e69685b-089c-87a3-e9ee-efc92f84008b.png)

実行後、こんな感じでチャートが表示されれば成功です。

下の棒グラフに注目して欲しいのですが、

- 赤色: 移動平均線が上向き
- 青色: 移動平均線が下向き

を表しています。

また、傾きが急なほど各グラフが上下に飛び出るようになっており、トレンドの強さも何となく掴めますね。

![スクリーンショット 2021-10-23 5.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/6afad69e-4077-5727-6d49-8cec4701911e.png)

それぞれの値はデータフレームに格納されているので、あとは煮るなり焼くなり好きにしてください。

## あとがき

以上、移動平均線の傾きをPythonで算出してみました。

移動平均線だけで勝てるとは限りませんが、他のインジケーターと組み合わせてスクリーニングをする上では役立つと思うので色々工夫してみたいところです。

https://github.com/kazama1209/ma-slope