株やFXには移動平均、マcd、サイコロジカル、オシレータなど多くの分析指標があります。(私もまだ勉強中です。)実はPythonには「TA-Lib」というライブラリ簡単にテクニカル指標を表示させることができるのですが、まずは自分で分析指標の基礎となるローソク足を作るところからやってみましょう。
Bitflyerでbot開発を行なっていくのですが、Bitflyerには各時間軸のローソク足の情報(始値・高値・安値・終値)が、APIでは提供されていません。そのため、ローソク足のデータを使いたい場合は、Cryptowatchという外部APIを利用する必要があります。
Contents
Bitflyerの1分足の価格データの取得する
価格のデータセットを取得するのですが、OHLCというキーワードを目にすると思います。
OHLCとは4つの値の総称です。
- Open: 始値
- High: 高値
- Low: 安値
- Close: 終値
ここに出来高(Volume)も加えてOHLCVと表現している場合もあります。API仕様書で出てくることもあるので覚えておくと良いと思います。
さて、早速1分足のBitflyerFXのOHLC価格を取得してみましょう。以下のURLをブラウザでたたいてみてください。
https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60
以下のような画面になりましたでしょうか。
periods=60が60秒です。5分足のデータが欲しい場合はperiods=300となります。
上記のデータを15秒間間隔で取得し、表示させていくプログラムをかいていきましょう。
始値と終値を取得する
まずは最新の1分足の価格データだけを取り出して、始値と終値だけを抽出してみましょう。
import requests from datetime import datetime # CryptowatchのAPIで1分足を取得 response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60") response = response.json() # 最後から2番目のローソク足を取り出す data = response["result"]["60"][-2] # ローソク足から日時・始値・終値を取り出す close_time = datetime.fromtimestamp(data[0]).strftime('%Y/%m/%d %H:%M') open_price = data[1] close_price = data[4] print( "時間: " + close_time + " 始値: " + str(open_price) + " 終値: " + str(close_price) )
時間: 2022/09/13 00:13 始値: 3168537 終値: 3167788
プログラムの解説になります。
importしているライブラリは割愛します。
requests.get()で取得したデータをrequestsという変数に代入しています。
1分足の価格データのうち1番新しいものを取得しdataという変数に代入しています。Cryptowatchのデータは古い順に並んでいるので最後尾のデータが最新になります。ただ、プログラムでは[-2]としています。理由は[-1]では、まだ価格が固まっていないため、[-2]とし、一つ前の値を取得しています。
取得したデータは[日時, 始値, 高値, 安値, 終値, 出来高]でならなんでいます。close_timeでは「日時」、open_priceは「始値」、close_priceは「終値」を取得しています。リストは一番最初を「0」とするということは説明した?と思います。(忘れてしまった方はネットで検索するとすぐヒットしますので、そちらでお願いします。)
取得できた日時(先頭の値)はUNIX形式の日時表示ですので、このままでは人間はすぐに読めません。なので、datetime.fromtimestamp()関数を利用し、datetime型に変換しています。
そしてさらに、strftime()関数で、よりわかりやすく変換しています。
strftime(‘%Y/%m/%d %H:%M’)
→ 「年/月/日 時間:分」の形式の文字列に変換
最後にprintで出力しています。
これで、1つ前のローソク足の、始値と終値が取得ができました。
while文を使って自動ループにしてみる
先ほどの「最新の1分足の価格データだけを取り出して、始値と終値を取得する」を自動的に継続的に取得するプログラムです。
## ループ処理で1分足の価格データを取得する ## import requests from datetime import datetime import time while True: response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60") response = response.json() data = response["result"]["60"][-2] close_time = datetime.fromtimestamp(data[0]).strftime('%Y/%m/%d %H:%M') open_price = data[1] close_price = data[4] print( "時間: " + close_time + " 始値: " + str(open_price) + " 終値: " + str(close_price) ) time.sleep(15)
時間: 2022/09/17 12:21 始値: 2845933 終値: 2844993 時間: 2022/09/17 12:21 始値: 2845933 終値: 2844993 時間: 2022/09/17 12:21 始値: 2845933 終値: 2844993 時間: 2022/09/17 12:22 始値: 2845386 終値: 2845469 時間: 2022/09/17 12:22 始値: 2845386 終値: 2845469 時間: 2022/09/17 12:22 始値: 2845386 終値: 2845469 時間: 2022/09/17 12:22 始値: 2845386 終値: 2845469 時間: 2022/09/17 12:23 始値: 2845260 終値: 2846201 時間: 2022/09/17 12:23 始値: 2845260 終値: 2846201 時間: 2022/09/17 12:23 始値: 2845260 終値: 2846201 時間: 2022/09/17 12:24 始値: 2846227 終値: 2847532
自動的に継続的に処理を行うにはwhile文を利用します。
処理の流れは以下のようになっています。
- 最新の1分足の価格データだけを取り出して、始値と終値だけを抽出
- 15秒スリープ
- ※1.2を繰り返し
- ・
- ・
while true:は、無限に繰り返す処理になり、停止させるには「エラーが起きる」「手動で停止させる」必要があります。(while文で回数指定や停止処理を入れる場合のPythonプログラミングは別途勉強してみたください。)
while True:の以降、インデントを下げ「最新の1分足の価格データだけを取り出して、始値と終値を取得する」の処理を入れています。そうすることで始値と終値を取得し終えたら、また、最初(response=の部分)から処理が走ります。値が変わることも確認したいので、time.sleep(15)を入れ、15秒後に再処理スタートとしています。これで15秒間間隔で取得し、表示させていくプログラムができました。
コマンドプロンプトの手動停止は「control + C」で停止できます。
価格データに更新があった場合に表示させてみよう
15秒間間隔で価格データを取得し、表示させていくプログラムは完成しました。これからは好みの問題ですが、「同じ価格であれば表示させたくない」「価格が更新された場合のみ表示させたい」と考える方もいると思いますので、「価格が更新されたら表示させる」という条件を追加したプログラムを紹介します。
pythonには「if文」というものがあり、条件によって異なる結果を返すコードがあります。それを上手に使うことでさまざまな場合わけが可能となります。
まずプログラムを見てみましょう。以下のプログラムを実行してみてください。
import requests from datetime import datetime import time response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60") response = response.json() # 前回の時間を last_time に入れる last_data = response["result"]["60"][-2] last_time = datetime.fromtimestamp(last_data[0]).strftime('%Y/%m/%d %H:%M') time.sleep(10) while True: response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60") response = response.json() data = response["result"]["60"][-2] # 今回の時間を close_time に入れる close_time = datetime.fromtimestamp(data[0]).strftime('%Y/%m/%d %H:%M') open_price = data[1] close_price = data[4] # 前回の時間(last_time)と今回の時間(close_time)が違う場合のみprintする if close_time != last_time: print( "時間: " + close_time + " 始値: " + str(open_price) + " 終値: " + str(close_price) ) # 前回の時間(last_time)を今回の時間(close_time)で上書きする last_time = close_time time.sleep(15)
実行してみた結果はいかがでしたか?
さて、プログラムの中身の前に、どのような処理を行なっているのか概要を掴んで欲しいと思います。
今回は、「価格が変更された場合」という条件がります。変更されたことを確認(比較)するには、前の価格データと今回の価格データの2つが必要になります。そして、その二つを比較する処理を行い、差分があった場合、表示させるという流れです。ただし、データはどんどん更新されていくので、前の価格データ、今回の価格データの上書き処理も必要ですね。う〜ん、いっきに考えなくては多くなった気がします。なので、処理を一覧にしてみます。
- 前回取得したローソク足の日時を変数(last_time)に入れておく
- 今回新しく取得したローソク足の日時(close_time)に入れる
- if文の条件判定で、変数(last_time)と(close_time)を比べる
- 日時に変更があれば、if文の中身が実行されて価格データがprintされる。さらに今回新しく取得したローソク足の日時(close_time)が前回のローソク足の日時(last_time)に上書きされる
- 変更がなければif文の中身は実行されず、10秒待機してまたWhile文の先頭に戻る
※注意:本bot開発は「文系でもわかる!BitcoinのBOT自動売買トレードの始め方」をもとに開発・自分なりの解釈用備忘録としています。