pythonで為替データを分析したり可視化してみたいと考えた。
今回は、リアルタイムでドル円相場を取ってきてローソク足をプロットし、その上に移動平均,ボラティリティ,ゴールデンクロス,デッドクロスを可視化してみるというところまでやってみる。
データを取ってくる
まずはデータを取ってこないといけない。
以前はCSVファイルを取ってこれるサイトを紹介したけれど、やっぱりリアルタイムでもデータを取ってきたい。(為替の分足CSVデータが無料でダウンロードできるサイト - 技術メモ)
そこで今回はOANDAのAPIを使うことにした。
調べた限りOANDAだけが無料でリアルタイムのデータを取れるAPIを出してくれているらしいからだ。
OANDAの登録からキーの取得までは色々なサイトで確認してほしい。
pythonでは、oandapyV20というラッパーを使えばうまく取ってこられるらしい。
The oandapyV20 REST-V20 API wrapper documentation — OANDA REST V20 API Wrapper 0.6.3 documentation
ひとまずサンプルコードを動かしてみる。
コードは下の参考サイトにも載せた ここ を参考にした。
必要なライブラリがなければインストールしておく
pip install pandas
pip install matplotlib
pip install seaborn
pip install oandapyV20
今回はデータの取得と可視化を別のプログラムで書いたのでいったん”candle.csv”としてCSV形式で保存することにした。
account_tokenには自分で取得したアクセストークンを入れてほしい。
import datetime
import pandas
from oandapyV20 import API
import oandapyV20.endpoints.instruments as oandapy
start = datetime.datetime(year=2018,month=5,day=1)
minutes = 150
start = start.strftime("%Y-%m-%dT%H:%M:00.000000Z")
access_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
api = API(access_token = access_token, environment="practice")
request = oandapy.InstrumentsCandles(instrument = "USD_JPY",
params = { "alignmentTimezone": "Japan", "from": start, "count": minutes, "granularity": "M1" })
api.request(request)
filename = "candle.csv"
candle = pandas.DataFrame.from_dict([ row['mid'] for row in request.response['candles'] ])
candle['time'] = [ row['time'] for row in request.response['candles'] ]
candle.to_csv(filename)
土日に動かしていたので日付は固定してしまっているが、スタート時刻を変えればリアルタイムでも動かせる。
(*土日は為替相場が閉まってるからデータが取れない!!!)
移動平均線、ボリバンを可視化する
import pandas
import seaborn
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick2_ohlc as plt_candle
seaborn.set_style("whitegrid")
candle = pandas.read_csv('candle.csv')
window_size = 5
avg_move = pandas.Series.rolling(candle.c, window = window_size).mean().dropna().reset_index(drop = True)
sigma = pandas.Series.rolling(candle.c, window = window_size).std(ddof = 0).dropna().reset_index(drop = True)
sigma_plus1 = avg_move + sigma
sigma_plus2 = avg_move + sigma * 2
sigma_plus3 = avg_move + sigma * 3
sigma_minus1 = avg_move - sigma
sigma_minus2 = avg_move - sigma * 2
sigma_minus3 = avg_move - sigma * 3
candle = candle[window_size:].reset_index(drop = True)
xticks_number = 15
xticks_index = range(0,len(candle), xticks_number)
xticks_date = [candle.time.values[i][11:16] for i in xticks_index]
figure, ax = plt.subplots()
plt_candle( ax,
opens = candle.o.values,
highs = candle.h.values,
lows = candle.l.values,
closes = candle.c.values,
width=0.6,
colorup='#DC143C',
colordown='#4169E1')
plt.plot(avg_move, color='#006400')
plt.plot(sigma_plus1, color='#3CB371')
plt.plot(sigma_plus2, color='#9ACD32')
plt.plot(sigma_plus3, color='#ADFF2F')
plt.plot(sigma_minus1, color='#3CB371')
plt.plot(sigma_minus2, color='#9ACD32')
plt.plot(sigma_minus3, color='#ADFF2F')
plt.xticks(xticks_index, xticks_date, rotation=80)
plt.show()
5分の移動平均を求めている。
移動平均線やボリンジャーバンドをアルゴリズム的に簡単に言うと
それぞれ「過去N本分のローソク足の終値の平均、標準偏差」のこと。
標準偏差は1σ、2σ、3σまで求めるのが普通だ。
ここがよくわからないかもしれない
candle = candle[window_size:].reset_index(drop = True)
これは、移動平均と実際のローソク足を合わせることをしている。
移動平均線は過去5分の平均を求めている事を意味するので、最初の4分は意味がないことになる。
5分の移動平均線に対しては4分ずらさないとローソク足が一致しないので、そもそもデータから取り除いてしまえということだ。
意外と手間取ったのが見た目に関してだった。
良い感じで15分毎くらいにX軸を出したかったがあんまり簡単にできる方法が見つからなかった。
xticksという関数を見つけて無理やり良い感じになるようにしたけれどもっといい方法があるかもしれない。
あと、seabornは素晴らしいのでとりあえず使っとけって感じはある。
import pandas as pd
import seaborn
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick2_ohlc as plt_candle
seaborn.set_style("whitegrid")
candle = pd.read_csv('candle.csv')
small_window = 5
big_window = 20
sma5 = pd.Series.rolling(candle.c, window = small_window).mean()
sma20 = pd.Series.rolling(candle.c, window = big_window).mean()
candle = candle[ big_window: ].reset_index(drop=True)
sma5 = sma5[ big_window: ].reset_index(drop=True)
sma20 = sma20[ big_window: ].reset_index(drop=True)
cross = sma5 > sma20
golden = (cross != cross.shift(1)) & (cross == True)
dead = (cross != cross.shift(1)) & (cross == False)
index_g = [i-1 for i, x in enumerate(golden) if x == True]
index_d = [i-1 for i, x in enumerate(dead) if x == True]
xticks_number = 15
xticks_index = range(0,len(candle), xticks_number)
xticks_date = [candle.time.values[i][11:16] for i in xticks_index]
figure, ax = plt.subplots()
plt_candle( ax,
opens = candle.o.values,
highs = candle.h.values,
lows = candle.l.values,
closes = candle.c.values,
width=0.6,
colorup='#DC143C',
colordown='#4169E1')
plt.plot(sma5, color='greenyellow', label='sma5')
plt.plot(sma20, color='darkgreen', label='sma20')
plt.scatter(index_g, sma20[index_g], color='red', s=500, label="golden cross")
plt.scatter(index_d, sma20[index_d], color='blue', s=500, label="dead cross")
plt.xticks(xticks_index, xticks_date, rotation=80)
plt.legend()
plt.show()
ゴールデンクロスとデッドクロスは5分と20分の移動平均に関するクロスを計算するようにした。
ここでは20分移動平均線を5分移動平均線が下から交差すればゴールデンクロス、上から交差すればデッドクロス、ということにしている。
注意しないといけないことは、こちらは20分の移動平均を使っていることだ。
つまりローソク足に関しては最初の19分、5分の移動平均線に関しては最初の14分が不要ということになる。
それがこの部分にあたる。
candle = candle[ big_window: ].reset_index(drop=True)
sma5 = sma5[ big_window: ].reset_index(drop=True)
sma20 = sma20[ big_window: ].reset_index(drop=True)
どうやらゴールデンクロスやデッドクロスについて調べてみると
長期移動平均線が上向きで短期移動平均が長期移動平均を下から上へクロスする場合、買い。(ゴールデンクロス)
長期移動平均線が下向きで短期移動平均が長期移動平均を上から下へクロスする場合、売り。(デッドクロス)
引用: http://fx.kakaku.com/fx/articleview/?no=21
と書かれてるところもあり、これに従うならもうすこし手を加える必要があるかもしれない。
改良版 ⇒ pythonでゴールデンクロスデッドクロスを可視化(2) - 技術メモ
OANDAのAPIは結構便利そうだ。
課金(口座に25万円以上入金)さえすればトレードに関するリクエストなんかも送れるらしく、リアルタイムで分析しながらシステムトレードなんかもできるかもしれない。
完全自動売買のプログラムによる不労所得生活もきっと夢じゃない。