【自動取引bot用】python初心者だけどローソク足のグラフを書く

pc関連tips

pythonでローソク足のグラフを書く

この記事では、前回pythonでbitmexで使用する自動取引botを作ってみた初心者が
理解をどんどん深めるためにローソク足のグラフを描くべく四苦八苦していきます。
ちなみにどのくらい初心者かというと、グラフを描いたことはないくらいです。
ちなみに、作ったbotは元気に動いています。
一回だけ不正落ちした(通信エラー処理不足かな)けど…
で、損益がやばい。
儲かってない。
ドテン君のようないわゆるトレンドフォロー型のbotは、レンジ相場(あまり上げ下げが無い)に弱く、
トレンド相場(それなりの期間上がり続けたり下がり続けたり)に強いというのがふつうのようです。
なんで?と言われると私も初心者なので困るのですが、トレンド相場は順張り、レンジ相場は逆張りするといいらしいですが、
そのからみなのではないでしょうか…
最近はレンジ相場の期間が長かったせいか、いわゆる往復ビンタ(買ったら下がって損をし、売ったら上がって損をする)を食らい続けていました。
それに耐えてトレンド相場を待つ…!!
というのが正攻法なのかもしれませんが、レンジ相場もそれなりに耐えきりたいじゃないですか。
まあどうやって耐えるのかよくわかってないんだけど。
わからないことを解明する…そのためにお勉強をするのです!!
まずはグラフ書くぞ!!
というわけでこのページができました。
グラフにあれこれしてエントリー箇所を改良すれば、botがもっとよくなるはず!
ただ、私超文系だし数学は2Bまでしかやってないし初心者だしシグマとかよくわからない(Bで出た気はする…?が理解はできなかった)ので、一歩一歩頑張ります。

step1.まずは基本的な線を引いてみる

まずは何かしら線を引いてみましょう。

いきなりローソク足とか書けるわけねえ。
ちなみに、前回の記事でも書きましたが、botはcloud9上で動かしています。
また、pythonのバージョンは3.6ですので、2系とはまた違った記述があるかもしれません。

参考にさせていただきました:[python]グラフ描画のためのライブラリMatplotlibの使い方
ふむふむ。初めてなのでそのままお借りしました。
すると…

import numpy as np
import matplotlib.pyplot as plt

# 描画範囲の指定
# x = np.arange(x軸の最小値, x軸の最大値, 刻み)
x = np.arange(0, 6, 0.1)

# 計算式
y = 2 * x

# 横軸の変数。縦軸の変数。
plt.plot(x, y)

# 描画実行
plt.show()

こ、この初歩の時点でエラーが…心折れる~

気を取り直して、「ModuleNotFoundError: No module named ‘tkinter’」が
いけないのかな?ということで調べてみる。
すると、どうやらGUIじゃないからだめらしい。
cloud9はCUIですからね…、そのままパッとは表示できない。
なので、一旦pngファイルに落としこむことにします。
(cloud9上で表示させる方法もあるようですが面倒そうだったので…)

新しいコード:

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# 描画範囲の指定
# x = np.arange(x軸の最小値, x軸の最大値, 刻み)
x = np.arange(0, 6, 0.1)

# 計算式
y = 2 * x

# 横軸の変数。縦軸の変数。
plt.plot(x, y)

# 描画実行
plt.savefig("test01.png")
plt.close()

今度は正常終了しました。
「test01.png」というファイルにグラフができた!やったー!
自分のために解説すると、
・「np.arange(0, 6, 0.1)」→x軸は、0~6まで、0.1づつの刻みで描画。
・y=2*x→y軸は、x軸の値を「かける2」した値で描画。
結果、右肩上がりの直線ができるわけですね。
(正直この辺の計算すら記憶が怪しいよ…)

このグラフを複雑怪奇にしていくと、ローソク足が表示できるってわけよ…多分…
うう楽しみ。続けます。

step2.データ元にcsvを使ってみる

最終的には、リアルタイムデータをそのまま描画していくのが理想です(のか?)。
ですが、まずは読み込んだ値を表示する…ということで
csvから描画させてみましょう。

csvの準備

正直どんなのでもいいのですが、こちらのページのデータを
お借りしました。日足、というやつですね。
Bitcoinの履歴データ
これをコピーして、価格に使用されているカンマを削除し、タブになっている区切り文字をカンマに変更します。
文字コードはUTF-8として保存しましょう。あと、日付を昇順でソートしました。
また、ヘッダは適当に英語をはめました(日本語が混じると要らないエラーが出たりしますからね…)
こんな感じ↓

これを読み込ませて描くコードを考えていきます。
(だいぶ泥臭いcsv準備ですが、今はグラフに集中したかったんです!!)

この時点でもう試行錯誤しすぎて疲れましたが、コードはこうなりました。

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=['date'])
print(df)

df.plot(y=['start','high','low','end'])

# 描画実行
plt.savefig("test06.png")
plt.close()

出来上がったファイルがこちら!
あまり意味は無いけど始値と終値と最高値と再安値を出してみた!
色は勝手に決まってカラフル。あと、右上の「この色はstart」みたいな小さい窓は、勝手に出てくれました。親切~

うーん、めっちゃ値段下がってますね。笑
X軸の日付の表示が不満(2018/06/01とかにしたいんだけどなー)なんですけど、改善の方法が良くわからず…。
まあおいおいなんとかしていきたいと思います。
これでCSVから読み込んでグラフを作ることができました!

step3.出来高を棒グラフにしてみる

出来高を棒グラフにしてみます。
はじめは折れ線グラフと棒グラフの同居を考えたんですが
ちょっと飛ばし過ぎたみたいでさっぱりわからず、一個づつ片づけることにしました…
コードはこちら。応用ですね。

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=['date'])
print(df)

df.plot.bar(y=['vol'])

# 描画実行
plt.savefig("test10.png")
plt.close()

できたやつ。
うーん、ちょっと単位とかが…イマイチですが…
一応できましたね。
日付的なところもはみ出ている…
今度は時間とかまで出てしまったようだな?
この辺のpython側の裁量、よくわかりませんね…
CSVは変えていません。

step4.折れ線グラフと棒グラフを同時に書き出す

この辺から私的には頭パーンです。
なかなかドンピシャなドキュメントが見つからず…
私の検索語句がうまくないんだろうなあ。
結果、こちらを発見し参考にさせていただきました!!
Python/matplotlibで2軸グラフを作る

コードはこちら。
★方針としては、「折れ線グラフ」と「棒グラフ」を2枚書いて重ねて表示する、ということになるようです。
ただ重ねると上になった1枚分しか出ないので、片方は透過します。


import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=['date'])
print(df)

#X軸用indexにする
x=df.index

#折れ線と棒グラフを作る為2個作る(ax1、ax2)
fig, ax1 = fig, ax1 = plt.subplots()
#twinxで、ax1のX軸を共有する
ax2 = ax1.twinx()

#ax1には、折れ線を描く。Y軸の範囲を値段から適当に規定する
ax1.plot(x,df['start'],label="start")
ax1.plot(x,df['high'],label="high")
ax1.plot(x,df['low'],label="low")
ax1.plot(x,df['end'],label="end")
ax1.set_ylim([5000,10000])
#ax2には、出来高の棒グラフを描く。色がかぶらないようgrayにしとく。範囲を適当に規定する。
ax2.bar(x,df['vol'],color="gray")
ax2.set_ylim([3000000000,8000000000])

#折れ線グラフを前面に
ax1.set_zorder(2)
ax2.set_zorder(1)

#重なってしまうグラフなので背景を透過しておく
ax1.patch.set_alpha(0)

#凡例を表示する(色がどのラインかというやつ、今回は書き方が違うせいか自動では出なかった)
ax1.legend(bbox_to_anchor=(0, 1), loc='upper left', borderaxespad=0.5, fontsize=10)

# 描画実行
plt.savefig("test15.png")
plt.close()

だんだんソースが込み入ってきましたね…
できたグラフがこちらです。

なんとなく方向性がわかってきました。
pandasのデータフレームのいじり方というか…まあまだまだですけど。
Y軸ですが、左側が出来高で右側が値段。
値段がオフセット?されて1ケタの数字になってしまっている…
この辺は調整したいですね。
理想を言えば左側が値段で右側が出来高、オフセットナシがいい。

step5.なんとなくつかめてきたのでローソクに挑戦

ほんとにもういけるのか…?
ちょっと不明ですが、そろそろローソク足でググってみようと思います。
データフレームアレルギーは無くなってきたからたぶん大丈夫だろう!

で、ここでぐぐりながら衝撃の知識を手に入れました。
OHLCって、よく見かけるけどopen high low closeのことだったのか。

csv作った時、特に何も考えず「start,high,low,end」とかにしましたけど、open、closeが正しいんですね。なるほどなー

こちらを主に参考にしました!
Pythonでローソク足と出来高を1つのチャートに簡単に描く方法

ちなみに、参考サイトでは読み込みコマンドが
「from matplotlib.finance import candlestick2_ohlc, volume_overlay」となっているのですが、
私の使用しているバージョンでは「matplotlib.finance」がもう使えないらしいです。
調べたら「mpl_finance」に移行しているということでしたので、そちらを使いました。
私のpython3環境への「mpl_finance」インストールコマンドです。

ec2-user:~/environment $ sudo pip-3.6 install git+https://github.com/matplotlib/mpl_finance

で、mpl_financeに含まれる「candlestick2_ohlc」コマンドを使用してグラフを描いていくことになります。
ですがここでまた問題が。

これがサンプルコード①です。シンプルにローソクだけやりたかったやつ。

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime as dt
import matplotlib.dates as mpd
import mpl_finance as mpf
from mpl_finance import candlestick2_ohlc, volume_overlay
from matplotlib.dates import date2num


#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=True)
print(df)

fig = plt.figure()
ax = plt.subplot()

candlestick2_ohlc(ax,df["start"], df["high"], df["low"], df["end"], width=0.9, colorup="b", colordown="r")

# 描画実行
plt.savefig("test19.png")
plt.close()

①コードの成果物。

できてるじゃん!という気分は味わえましたが、
X軸がダメなんですよね~。
0~30の、データ個数なのかこれは?超適当にラベル付いた。
本当は、データフレーム内の「日付」を採用したいのですが、
どうもこのコマンド、X軸にindexが使用できないようで、そのまま使おうとするとエラーになります。

X軸を変える(そもそもあってるのかなあ)

candlestick2_ohlc(ax,df["start"], df["high"], df["low"], df["end"], width=0.9, colorup="b", colordown="r")

candlestick2_ohlc(df.index,df["start"], df["high"], df["low"], df["end"], width=0.9, colorup="b", colordown="r")

書こうとするとこんな感じのエラーが。

AttributeError: ‘DatetimeIndex’ object has no attribute ‘update_datalim’
調べてみると、この「DatetimeIndex」は、一個めの引数(X軸を指します)には使えないよ、と。
他のグラフつくるときは受け入れてくれるんですが、少なくとも「candlestick2_ohlc」のX軸では使えないということのようです。
なんでやー。

で、ググり続けて早…数日…
こうなりました。


import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime as dt
import matplotlib.dates as mpd
import mpl_finance as mpf
from mpl_finance import candlestick2_ohlc, volume_overlay
from matplotlib.dates import date2num


#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=True)
print(df.index)

#グラフの枠的なものを作る
fig = plt.figure()
#subplot(行数, 列数, プロット番号)。全部一個。
ax = plt.subplot(1, 1, 1)

#グラフ部分の描画。左から、x,Y(o,h,l.c)
candlestick2_ohlc(ax,df["start"], df["high"], df["low"], df["end"], width=0.9, colorup="b", colordown="r")

#X軸のラベルにindexをごにょごにょした日付を突っ込む、ちょっと傾ける。
ax.set_xticklabels([(df.index[int(x)].strftime("%Y%m%d") if x < df.shape[0] else x) for x in ax.get_xticks()], rotation=30)

#ラベルが重ならないよう気を使ってくれるコマンドらしい
fig.tight_layout()

# 描画実行
plt.savefig("test23.png")
plt.close()

できるグラフはこちら。やった!日付が出たよー!!
最後の30が気になるが、たぶんcsvのデータ量が足りないのだろう。たぶん!

こちらをめちゃ参考にさせていただきました。↓
Pythonでローソク足と出来高を1つのチャートに簡単に描く方法

で、出来高も上記のページをほぼほぼそのまま使用できました。
ありがたすぎる。

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime as dt
import matplotlib.dates as mpd
import mpl_finance as mpf
from mpl_finance import candlestick2_ohlc, volume_overlay
from matplotlib.dates import date2num


#ファイルの読み込み用
import pandas as pd
df = pd.read_csv('etest.csv', encoding="UTF-8", index_col='date', parse_dates=True)
print(df.index)

#グラフの枠的なものを作る
fig = plt.figure()
#subplot(行数, 列数, プロット番号)。全部一個。
ax = plt.subplot(1, 1, 1)

#グラフ部分の描画。左から、x,Y(o,h,l.c)
candlestick2_ohlc(ax,df["start"], df["high"], df["low"], df["end"], width=0.9, colorup="b", colordown="r")

#X軸のラベルにindexをごにょごにょした日付を突っ込む
ax.set_xticklabels([(df.index[int(x)].strftime("%Y%m%d") if x < df.shape[0] else x) for x in ax.get_xticks()], rotation=30)


# ローソク足を上側75%に収める
bottom, top = ax.get_ylim()
ax.set_ylim(bottom - (top - bottom) / 4, top)

# 出来高のチャートをプロット
ax2 = ax.twinx()
volume_overlay(ax2, df["start"], df["end"], df["vol"], width=1, colorup="g", colordown="g")
ax2.set_xlim([0, df.shape[0]])

# 出来高チャートは下側25%に収める
ax2.set_ylim([0, df["vol"].max() * 4])
ax2.set_ylabel("vol")

#ラベルが重ならないよう気を使ってくれるおまじないらしい
fig.tight_layout()

# 描画実行
plt.savefig("test24.png")
plt.close()

グラフはこちら。

感想

pythonでグラフ、コードが簡単な反面、自動で頑張ってくれちゃう部分の調整の情報が手に入れづらく、大変でした。
わかる人が見たらわかるんだろうなっていうところがどう調べていいかわからず…
途中、そうだ、オライリーかお!!となって本屋に行ったのですが、pythonだけで5,6冊?出ていてどれを買っていいかわからず退散してきました。。
pandasとmatplotlibに詳しい本が欲しいなあ。データ分析入門というやつがそうなのかな?という感じ。

詳しそうなのは以下2冊。

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Wes McKinney オライリージャパン 2013-12-26
売り上げランキング : 57938

by ヨメレバ

Pythonデータサイエンスハンドブック ―Jupyter、NumPy、pandas、Matplotlib、scikit-learnを使ったデータ分析、機械学習

Jake VanderPlas オライリージャパン 2018-05-26
売り上げランキング : 3423

by ヨメレバ

かんたんにまとめ

なんか、ちょうど「matplotlib.finance」が過渡期のようであり、
情報が錯綜していて色々ググりづらかったです…
新しいのは「mpl_finance」ということでした。
インストールコマンドも改めて記載しておきます。(現在は、gitからしか落とせないらしいです)
・インストール cloud9のpython3に入れる場合。
sudo pip-3.6 install git+https://github.com/matplotlib/mpl_finance
・インポート
import mpl_finance as mpf
from mpl_finance import candlestick2_ohlc, volume_overlay

今後やりたいこと

・長めの5分足データを取得してくる
・15,50の移動平均線を描く
・取引に使用できるか勉強する

この記事、書き始めてからもう数日たっているんですが、
最近はbotが結構プラスで取引を終えることがあります。
多分、トレンド相場なんでしょうか(こんなに適当でいいのか)。

コメント

タイトルとURLをコピーしました