【相場分析】フィボナッチ・リトレースメントをPythonで算出する

![Fibonacci.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/e59b5272-58db-7442-2457-05f686a2125c.png)

## 概要

記事タイトル通り、フィボナッチ・リトレースメントをPythonで計算してみます。

## フィボナッチ・リトーレスメントとは

株だろうが為替だろうが仮想通貨だろうが、価格チャートを一度でも見た事のある方はわかると思いますが、相場というのは必ず上下に「波」を描きながら進行していきます。

片時も休みなくどちらか一直線に傾き続けるという事はありません。

その金融商品を買った（売った）人は利確や損切りのために必ずどこかのタイミングで売ら（買わ）なければなりませんし、ある程度トレンドの勢いが弱まったタイミングで逆張りを仕掛けてくる勢力が常に居たりするからですね。

そういった動きの事を金融業界では

- [綾押し](https://www.daiwa.jp/glossary/YST0037.html)
    - 相場が上昇傾向にある時、反動的に一時下がる事
- [綾戻し](https://www.daiwa.jp/glossary/YST0038.html)
    - 相場は下降傾向にある時、反動的に一時上がる事

なんて呼んだりするそうですが、じゃあ、その下げ（上げ）は一体どれくらいになるのか？

その目安としてフィボナッチ数列（[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, ...]）を使おうというのが今回のテーマである「フィボナッチ・リトーレスメント（Fibonacchi Retracement）」になります。（Retracementは「綾押し・綾戻し」の意）

フィボナッチ数列は、イタリアの数学者であるレオナルド・フィボナッチ氏にちなんで名付けられたもので、いわゆる「黄金比」を求めるためにしばしば用いられたりするようです。

参照記事: [自然界と人体の神秘 ～フィボナッチ数列、黄金比から垣間見える～](https://forest-clinic.jp/knowledge/etc/post-605.html)

たとえば、フィボナッチ数列の次のような性質を持っており、

- 数列「n」の数字を数列「n + 1」の数字で割ると約0.618になる
    - 13 / 21 = 0.6190...
    - 21 / 34 = 0.6176...
    - 34 / 55 = 0.6181...
- 数列「n」の数字を数列「n + 2」の数字で割ると約0.382になる
    - 13 / 34 = 0.3823...
    - 21 / 55 = 0.3818...
    - 34 / 89 = 0.3820...
- 数列「n」の数字を数列「n + 3」の数字で割ると約0.236になる
    - 13 / 55 = 0.2363...
    - 21 / 89 = 0.2359...
    - 34 / 144 = 0.2361...

こういった数字は自然界や人間の行動において広く影響を与えているんだとか。

相場においてもそれは同様で、実際、大きな価格変動を100%とした場合、そこから 一時的に23.6%・38.2%・61.8%の押し（戻り）を形成した後再び反発していくケースが多かったりするため、分析においては有力な数字とされていたりするわけですね。

![スクリーンショット 2021-10-04 22.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/e5ce51e7-e3fc-2f7a-e6d1-c69f8bc5d9d4.png)

↑の写真はわかりやすい一例ですが、レンジをブレイクして一旦上昇した後、価格調整のために一時押してちょうど61.8%あたりのところでまた上昇していっています。（上昇の起点と押しの起点（それぞれ青丸の部分）を結んだ幅が100%）


## 実行環境

- 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 twelvedata websocket
```

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


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

```py:セル2
from twelvedata import TDClient
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (20, 10)
```

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

### 関数の定義

```py:セル3
# ヒストリカルデータを取得
def get_historical_data(symbol, interval, outputsize, start_date, end_date):
    apikey = 'TWELVE_DATA_API_KEY'
    td = TDClient(apikey = apikey)
    
    res = td.time_series(symbol = symbol, interval = interval, outputsize = outputsize, start_date = start_date, end_date = end_date, timezone = 'Asia/Tokyo').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 calc_fibonacci_retracement(df, trend_direction):
    top = df['close'].max()
    bottom = df['close'].min()
    diff = top - bottom

    if trend_direction == 'upward':
        first_level = top - diff * 0.236
        second_level = top - diff * 0.382
        third_level = top - diff * 0.5  
        fourth_level = top - diff * 0.618
    elif trend_direction == 'downward':
        first_level = bottom + diff * 0.236
        second_level = bottom + diff * 0.382
        third_level = bottom + diff * 0.5  
        fourth_level = bottom + diff * 0.618

    return top, bottom, first_level, second_level, third_level, fourth_level
```

- Twelve Dataからヒストリカルデータを取得するための関数
- フィボナッチ・リトレースメントを計算するための関数

をそれぞれ定義。

なお、フィボナッチ・リトレースメントは次のようなプロセスで求める事が可能です。

- 天井（top）と底（bottom）の差分を算出（diff = top - bottom）
- その差分にフィボナッチ比率を掛け、天井（底）から引く（足す）
    - 上昇時
        - first_level = top - diff * 0.236
        - second_level = top - diff * 0.382
        - third_level = top - diff * 0.5  
        - fourth_level = top - diff * 0.618
    - 下降時
        - first_level = bottom + diff * 0.236
        - second_level = bottom + diff * 0.382
        - third_level = bottom + diff * 0.5  
        - fourth_level = bottom + diff * 0.618

0.5はフィボナッチ数列とは関係ありませんが、相場においては「半値押し（戻し）」といった50%分の押し（戻し）も良く見られたりするので計算に追加しています。

### フィボナッチ・リトレースメントを計算

```py:セル4
symbol = 'USD/JPY'
interval = '1day' # 時間軸
outputsize = 5000 # 最大取得件数
start_date = '2021-02-23' # 取得開始日
end_date = '2021-05-03' # 取得終了日
df = get_historical_data(symbol, interval, outputsize, start_date, end_date)
top, bottom, first_level, second_level, third_level, fourth_level = calc_fibonacci_retracement(df, 'upward')
```

先ほど定義した関数を使い、フィボナッチ・リトレースメントを計算します。

![スクリーンショット 2021-10-04 23.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/3552178d-96e6-a83b-ead5-407a0932880f.png)

今回は2月下旬〜5月初旬くらいのUSD/JPY（ドル円）相場にて「上昇 → 50% ~ 61.8% 程度の押し → 再度上昇」といったわかりやすい動きがあったため、そこを例にデータを取得してみました。

### チャートを作成

```py:セル5
plt.plot(df.index, df['close'])
plt.axhline(top, label = 'Top', linestyle = 'solid', alpha = 0.3, color = 'green')
plt.axhline(first_level, label = '23.6%', linestyle = 'dashed', alpha = 0.3, color = 'aqua')
plt.axhline(second_level, label = '38.2%', linestyle = 'dashed', alpha = 0.3, color = 'deeppink')
plt.axhline(third_level, label = '50.0%', linestyle = 'dashed', alpha = 0.3, color = 'orange')
plt.axhline(fourth_level, label = '61.8%', linestyle = 'dashed', alpha = 0.3, color = 'blue')
plt.axhline(bottom, label = 'Bottom', linestyle = 'solid', alpha = 0.3, color = 'red')
plt.legend(bbox_to_anchor=(1.05, 1), loc = 'upper left', borderaxespad = 0, fontsize = 18)
plt.ylabel('USD/JPY', fontsize = 18)
plt.show()
```

![ダウンロード (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688854/880151de-299a-6961-2c16-c746e78d07ee.png)

こんな感じで描画されれば成功ですね。

ローソク足ではなくバー表示なので先ほどの写真と比べて少し違和感はありますが、価格自体は同じように推移しているので問題無いはず。実際、50%押し（オレンジ色の点線）で反発していっているように見える事から各フィボナッチ・リトレースメントの計算も合っていそうです。

## あとがき

以上、フィボナッチ・リトレースメントをPythonで計算して可視化してみました。過去のチャートを遡ってみると、割とこれらの比率に沿った押しや戻しが存在していたりするので分析のしがいがありそうです。

ただ、唯一の問題点として、フィボナッチ・リトレースメントはどこを起点とするかで全く違った数字になってしまうため、その辺の見極めをどうするかといったものが挙げられるでしょう。

特にシステムトレードなどに組み込む際はどのように判断するのかもう一工夫しなければいけなそうなので、自分ももう少し色々いじってみたいと思います。

https://github.com/kazama1209/fibonacci-retracement/tree/master