さて、今回は仮想通貨BOTのプログラムの中で、シグナル判定に必要な関数を作成しましょう。実際のBOT用のコードを書く前の肩慣らしの様なものです。
BOTに必要なロジックの多くは実はそんなに難しいものでありませんが、BOTのプログラムを作る上で「関数化」はとても大事です。その理由についてはこちらを参考にして下さい。
プログラムは後で修正しやすい様に、各機能毎にまとめて作成しておくととっても便利です。関数を使わずにmain処理の中でコード書いていると、後から読み出すのがとっても難しくなります。
さて、今回はチャネルブレイクアウトというシグナルを判定するための必要な関数「過去n期間の高値を取得する関数」を作成します。シグナル判定について理解を深めながら関数を作ってみましょう。
■前提となる知識
・Pythonの基本文法を分かっていて、関数を作成できる
・cryptowatchでOHLC(ローソク足)の情報が取得できる
コンテンツ
シグナル判定に必要な関数を作り込む
仮想通貨BOTを作る時にはいくつかのシグナルを組み合わせる事が多いと思います。一つのmain処理の中でいくつかのシグナルの判定を行うと、内容が分かりにくくなり、後々の修正もし難くくなります。
そのため、基本的に1つのシグナルに対して、1つの関数(その中でさらに別の関数を呼ぶのはOK)を作るという考え方の方が、ソースは綺麗になるのではと思います。
それに、BOTというのは一度作成してしまえば、売買命令部分やデータを取得する部分などの処理は大きくは変わりません。変更しなければならないのはシグナルを出すロジック部分です。こちらは一定の期間毎に変更しなければなりません。
あまりこだわり過ぎると逆に見づらくなりますが。。。
チャネルブレイクアウトのためにOHLCの高値を判定したい
今回はチャネルブレイクアウトというシグナルを出すために必要な処理となる「OHLCの高値を取得する」という処理を実装します。
詳細は別のページに載せていますが、まず、簡単にチャネルブレイクアウトを説明すると、
・過去n期間の高値を上抜けたら買い
・過去n期間の底値を下抜けたら売り
というシグナルルールです。
ちなみに、上抜けたかどうかの判断はn期間の最後の日の「終値」で行うのが一般的な様です。※その期間の最後のOHLCのCloseの値になる訳ですね。
例えば2018/1/1~2018/1/20までの期間で判断する場合、この期間の高値を2018/1/20の終値が上抜ければ買いのシグナルという事になります。
このシグナルをコードに落とし込むには、まずは過去n期間の高値を上抜けたか?もしくは底値を下抜けたか?という判定が必要になります。
今回解説するコードは、過去20期間の高値を取得する関数になります。この関数ができれば(最終日の終値の値と高値を比較判定できれば)チャネルブレイクしたかどうかはすぐに分かります。
過去一定期間の高値を取得する関数を作ろう!
という事で実際に過去一定期間の高値を取得する関数を作りましょう。これは一度作っておくと後で重宝すると思います。都度関数の修正は必要になると思いますが、基本的な考え方は変わらないはずです。
■今回解説するコードの前提
・2018/3/1~2018/5/31のデータを取得
・過去20期間の高値を取得する
・一旦基準日は2018/3/20とする
つまり、2018/3/1~2018/3/20の期間の高値を取得する関数となります。
※冒頭でもお話した前提知識が必要になりますので、分からない場合はキャッチアップしておいて下さいね。
関数の処理の流れ
関数を作る上で、前提となるデータが必要になります。そのため、関数の呼び出し部分の処理も含めて解説します。
1)cryptowatchでOHLC(ローソク足)の情報 (作成関数の外)
2)OHLCをDataFrameに投入(作成関数の外)
3-1)ループしてOHLCの時刻を確認(作成関数)
3-2)基準日までループ(作成関数)
3-3)高値の最大値を取得(作成関数)
4)最大値を戻り値として返す(作成関数の外)
実際にPythonでコーディングしてみよう!
最初のOHLCの取得などは以前やっているので、「cryptowatchからデータを取得して簡単な編集などを行うコード」を基にしてプログラムを作成しました。追加しているのは判定用の関数と、main処理の一部なので、あまり大きな変化はないかなと思います。
■Pythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import requests from datetime import datetime import pandas as pd #OHLCデータ取得関数 def get_data(min, before=0, after=0): #パラメータ設定する params = {"periods" : min } if before != 0: params["before"] = before if after != 0: params["after"] = after #リクエスト送信 response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc",params) data = response.json() return data #過去○○日間の高値を算出する関数 def judge_high(df,ref_date,period_day): for j in range(len(df)): if str(df['Time'][j]) == str(ref_date): #DataFrameの中に「基準日」を見つけた! s_idx = j - (period_day-1) #20日前の日のインデックス ※基準日分を除いて-1 if s_idx >= 0 : #DataFrameの範囲内(最低限の判定) return df[s_idx:j]['high'].max() #過去○○日間の高値 break #main処理 min = 86400 after = 1519862400 #2018-03-01のタイムスタンプ before = 1527778799 #2018-05-31のタイムスタンプ ref_date = "2018-03-20 00:00:00" #基準日(この場合は2018/3/20) period_day = 20 #高値を判定する期間(この場合は20) out_data = get_data(min,before,after) Time_Data, Open_price, High_price, Low_price, Close_price = [],[],[],[],[] #DataFrameにOHLCを設定 for ohlc in out_data["result"][str(min)]: Time_Data.append(datetime.fromtimestamp(ohlc[0])) Open_price.append(ohlc[1]) High_price.append(ohlc[2]) Low_price.append(ohlc[3]) Close_price.append(ohlc[4]) df = pd.DataFrame({'Time':Time_Data, 'open':Open_price, 'high':High_price, 'low':Low_price, 'close':Close_price}) #高値を判定 high_val = judge_high(df,ref_date,period_day) #過去○○日間の高値を取得 print("過去" + str(period_day) +"日間の高値は" + str(high_val)) |
■結果
1 |
過去20日間の高値は1246120 |
■3/1~3/20のデータ
実際の結果を見て正しいかどうかも確認してみましょう。
正しく1246120という値が取得できている様ですね。
■解説
今回は事前の処理の流れの説明と同じロジックになっていますので、具体的な解説はいらないかもしれませんね^^
DataFrameの使い方によっては、ループ文を使わずに対象の日付を見つけたりもできるので、別の方法なども試してみてほしいです。
今回は昔ながらの処理らしくループして頭からDataFrameの中身を確認していくという形にしました。後々編集などもしやすい基本ロジックになります。
また今回作成した関数には、OHLCデータ、基準日、期間という引数を設けました。基準日や期間はロジックによってどんどん変わっていくと思うので変更ができる様にしています。
まとめ
さて、(チャネルブレイクアウトを行うために)高値を判定する関数を作成しました。実際にシグナルとしてこのロジックを使う場合には、基準日や期間をプログラムの中でどんどん変化させていけば良いだけです。
また、チャネルブレイクアウトでは底値を下抜けるケースもあるでしょ?と思いますよね。この場合は基本的にロジックの判定を逆にしてあげればOKです。
こういう小さいロジックの積み重ねで最終的にはシステムが作られていますので、結構重要な部分だと個人的には思っています。
今もシステムトラブルなどがニュースになる事がありますが、プログラム上の小さな誤りが原因になっている事が多いので、プログラムのロジックは細かく確認する様にしましょう。