自動売買BOTを作る上で最低限絶対に必要なプログラミング構文

この記事では、文系初学者でも自動売買BOTを動かすために、プログラムのソースコードを「何となく読んで理解できる」レベルになることを目指します。そのために、最低限、必要なプログラミングの構文知識を3つだけ説明します。

それが、for文/if文/while文です。

実際のところ、単純なアルゴリズムによる自動売買BOTであれば、この3つの構文をキチンと理解するだけで実装が可能になります。

学習のポイント

当ブログはプログラミング学習サイトではないので、教科書のような詳しい構文の書き方は説明はしません。最低限、これらの3つの構文がどういう雰囲気で動くものなのか、ここでは大雑把に理解することを目指してください。

あとは当ブログに出てくる実際のソースコードを手打ちしたり、カスタマイズしながら実践で覚えていってください。キチンと基本を勉強したい方は、他の学習サイトを参考にしたり、一番簡単そうなPythonのプログラム教本を1冊だけ読むといいでしょう。

for文について

for文というのは、簡単にいうと、「〇個の要素すべてについて、1つずつ同じ処理を実行していきたい。だけど同じソースコードを〇回書くのは面倒くさい」というときに使います。

構文は以下のような感じです。

for 要素 in 配列等
   要素について1つずつ実行したい処理

例えば、ある仮想通貨の取引所で、取扱いのある通貨ペアをAPIで取得したところ、以下のような配列が返ってきたとします。

product = [“BTC_JPY”,”ETH_BTC”,”XRP_BTC”,”XEM_BTC”,”BCH_BTC”,”TRX_BTC”,”LTC_BTC”,……..]

これをすべてAndcondaプロンプト(黒い画面)に表示したい場合、以下のように書くことができます。

print(product[0])
print(product[1])
print(product[2])
print(product[3])
print(product[4])
print(product[5])
print(product[6])
print(product[7])
print(product[8])
....

しかし同じprint()を何度も書くのは面倒くさいですよね。

6~7回程度ならまだいいですが、過去2年分の価格データとか、すべての約定履歴とか、データ数が膨大になってくると、とても1つ1つを書くことはできません。しかも上記のように書く場合には、あらかじめデータ数が何個あるのかを数えて調べなければなりません。

for文を使えば、これを以下のようにシンプルに書けます。

for p in product:
	print(p)

これだけです!

上記の2行は、productという配列の中にある要素の1つずつを順番に「p」という変数に入れて、それをprint(p)で、黒い画面に出力する、という意味のプログラムです。

実践的な例

もう1つだけ、実践的な例をあげてみましょう。

「10日間の単純移動平均線を当日の終値が上回って引けた場合」をエントリーまたは利確の条件の1つ(フィルター)として使いたいとします。そこで過去のビットコインの終値の価格をAPIで取得したところ、以下のようなデータが得られました。

price = [1012104,1064332,981452,1026681,1040899,1103870,1214016,1346433,1319455,1312633]

知りたいのは、当日の終値が過去10日間の単純移動平均を上回ったかどうかなので、この平均を求めます。もしこれをfor文を使わずに書くとしたら、以下のようになります。

sum = 0
sum = sum + price[0]
sum = sum + price[1]
sum = sum + price[2]
sum = sum + price[3]
sum = sum + price[4]
sum = sum + price[5]
sum = sum + price[6]
sum = sum + price[7]
sum = sum + price[8]
sum = sum + price[9]

average = sum/10
print(average)

こちらもなかなか面倒くさいですね。
10期間単純移動平均くらいなら何とかなりますが、100期間移動平均などになると、とても手では書けません。これはfor文を使うと以下のように書けます。

sum = 0
for p in price:
	sum = sum + p
average = sum/10
print(average)

これだけです!
データが何百個あったとしても、上の5行だけで平均を調べることができます。

for文について、とりあえず知っておくべき基本的な説明はこれで終わりです。他にも、数字で指定した回数だけ実行するなど、いろいろと応用的な書き方はありますが、新しく出会うたびにGoogleで調べていけば問題ありません。

if文について

if文というのは、「〇〇の場合には~したい、××の場合には~したい、それ以外の場合には~したい」といった条件分岐を書くための構文です。おそらく自動売買BOTでも一番使うことになります。

構文は以下のかたちになります。

if 〇〇のとき:
   実行したい処理

簡単ですね。
もし、「それ以外の場合は~」までセットで書きたければ、以下のように書きます。

if 〇〇のとき:
   実行したい処理
else:
   それ以外で実行したい処理

3つ以上の条件分岐を書きたいときは、以下のように書きます。

if 〇〇のとき:
   実行したい処理
elif 〇〇のとき:
   実行したい処理
elif 〇〇のとき:
   実行したい処理
elif 〇〇のとき:
   実行したい処理
else:
   それ以外で実行したい処理

とりあえず、このイメージだけ理解しておいてください。あとは実際のソースコードを読んだり書き写したりしながら、使い方を確認していけば問題ありません。

実践的な例

せっかくなのでさっきの続きをやりましょう。
過去10日の終値の単純平均は、114万2187円でした。もし当日の終値がこれを上回っていたら買いエントリー、下回っていたら何もしない、というプログラムを、さっきの続きで書いてみましょう。

当日の終値は118万2475円だとします。

today_price = 1182475
sum = 0

for p in price:
	sum = sum + p
average = sum/10

if average <= today_price:
	print("買いエントリーする")
else:
	print("何もしない")

付け足したのは、最初の「today_price = 1182475」の部分と、最後のif文のところです。

この例では、当日の終値が過去10日の単純移動平均より大きければ、「買いエントリーする」と画面に表示します。そうでなければ「何もしない」と画面に表示します。実際の自動売買BOTでは、この「買いエントリーする」のところに、買い注文の関数を入れることになります。

while文について

最後はwhile文です。
while文というのは、「ある特定の条件を満たしている間は、ずーっと永久に以下の処理をループしてください」という構文です。

構文は以下のようになります。

while 条件:
   ループしたい処理

自動売買BOTを作る場合だと、例えば、10秒間おきに価格やテクニカル指標をチェックして、シグナルが出たら売る・買う・手仕舞う・損切りする、といった処理を、放置で自動的にループさせたい場合などに使います。

例えば、以下のようなイメージですね。

while true:
  APIで価格を取得する
  シグナルを計算する

  if ポジションを持っていない:
    if 買いシグナルが出た:
      買い注文を出す
   else:
    if 利確シグナルが出た:
      利確注文を出す
    elif 損切シグナルが出た:
      損切注文を出す

  sleep(10)//10秒待機

こちらは物凄く大雑把なロジックですが、

(1)価格を取得してシグナルを計算する
(2)まだポジションを取ってなければ、買いシグナルを確認し、シグナルが出ていれば買い注文を出す。出ていなければ何もしない。
(3)もし既にポジションを取っていれば、利確シグナルを確認する。シグナルが出ていれば利確注文を出す。出ていなければ、損切シグナルを確認する。シグナルが出ていれば損切注文を出す。両方出ていなければ何もしない。
(4)10秒間待機して、また(1)に戻る

というアルゴリズムを永久にループさせることができます。

この「シグナルを計算する」と書いた部分に、先ほどのfor文を使った実践例を組み込めば、「終値が短期移動平均を上回ったときに買い、下回ったときに売る」といった、ごくシンプルなアルゴリズムを作ることもできます。

ここでは大体、どのようにwhile文を使うのかのイメージが掴めればOKです。

CryptowatchのAPIで取得したbitcoin価格のJSONデータから欲しい数字を取り出す

前回の記事(「JSON形式のデータから自由に数字を取り出そう」)の、練習問題の答え合わせです。

まずCryptowatchのAPIで、過去のbitFlyerのビットコイン価格(日足データ)をまとめて取得します。この手順については、すでに説明済み(こちらの記事)なので省略します。以下のAPIをそのまま使ってで説明を進めていきます。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1514764800

このAPIでは2018年1月以降の日足データを取得しています。ここから、2018年1月16日、ビットコイン価格の大暴落があった日の終値と最安値を取得してみましょう。

取得したJSONデータの構造を把握する

取得したデータの最初の方の部分を切り取ってみると、以下のような構造になっていることがわかります。

{"result":{"86400":[[1514764800,1519999,1713306,1502242,1675100,20188.11,32083065000],[1514851200,1673600,1684270,1568150,1635320,10534.478,17226760000],[1514937600,1637228,1760110,1600000,1725726,10670.864,17824102000],....

最初の部分だけを見ると、

{“result”:{“86400”:[[

で始まっていますね。

この先のデータがものすごく長いのですが、少なくともこの先頭の文字列を見るだけでも、以下のようなデータ構造になっていることはわかります。

{ “result”: {“86400”: [[xx,xx,xx…],[xx,xx,xx…],[xx,xx,xx…]] }}

一番内側に

[xx,xx,xx…]

という数字が7個含まれた配列値のデータ群があり、これが1日分のデータです。

このデータ群が日付分だけ存在します。
つまり以下のように集まって、

[ [],[],[],[]…. ]

という大きな1つの配列値のデータ構造になっています。さらにこの大きな1つの配列値のデータが、

{ “86400” : [ [],[],[],[]…. ] }

と、{} のカッコで括られているため、”86400″(日足)をキーとして、[]内のデータ全てを1つの値とするデータ構造になっていることがわかります。さらに上記の{}内のすべてのデータを1つの値として、

{ “result” : {1つのデータ} }

と、result をキーとする構造になっていることがわかります。
ここで前回の記事で勉強したことを思い出せば、Pythonのプログラムで一番内側の価格データを指定するためには、

data[“result”][“86400”][0][0]

というように指定すればいいことがわかります。
※ 0 のところには、「左から何番目のデータか?」という数字が入ります。

目的の日付データを探す

さて、次に2018年1月16日(ビットコイン価格の大暴落があった日)のデータを探します。一番内側の数字データが、以下の順番で記載されていることはすでに説明しました。

[ 取引時間(クローズ) , 初値 , 高値 , 安値 , 終値 , 出来高 ]

実際に、JSONデータの先頭のUNIXタイムスタンプを、いくつか日時に直してみればわかりますが、Cryptowatchの価格データは毎日午前9時で区切られて日足データとしてまとめられていることがわかります。

ということは、2018年1月16日の暴落時の最安値が含まれた価格データを探すには、「2018年1月17日午前9時」までを区切りとするデータのまとまりを探せばいいことがわかります。これはUNIXタイムスタンプに変換すると、「1516147200」です。

UNIXタイムスタンプ変換ツール

JSONデータの配列値は、左から順番に0番目、1番目、2番目….、と数えることを思い出してください。

つまり今回の目的の価格データを探すためには、一番内側の[]のデータのまとまりのうち、先頭(0番目)が「1516147200」で始まっているデータの3番目の数字を取り出せばいいことがわかります。

このデータをどうやって探すのか?

さて、「自分で試してみてください」といっておいて申し訳ないのですが、実はここまで勉強した内容だけだと、ここで行き詰ってしまいます。なので、この部分までたどり着けた方はいったん合格です(笑)

ここから先に進むには、少し新しいプログラミングの知識が必要になります。

なぜなら先頭に「1516147200」を含むデータ群、[xx,xx,xx,xx….]が、その一つ外側のデータ構造[ [],[],[],[]….. ]の何番目にあるのかが、わからないからです。

前回の記事で紹介したbitFlyerのAPIのように、すべてのデータが、{ キー:値 } の形式になっていれば、キーを指定するだけで値を取り出すことができます。しかし、[[],[],[],[]…..]のようなデータ構造の場合は、目的の数字が何番目の[]に入っているのか、自分で調べなければわかりません。

for文を使ってループで探す

このような場合は、pythonのプログラミングで(先頭から順番に)片っ端から調べる、という方法を取ります。つまり、先頭の[]から順番に見ていき、一番内側の[]の先頭の数字が「1516147200」に一致するものを取り出す、というプログラムを組みます。

JSONのデータ形式によっては、このような処理が必要になることも多いので、ソースコードを理解しておきましょう。エディタを起動して以下のようなプログラムを書いてみてください。

import requests
response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1514764800")
data = response.json()

for item in data["result"]["86400"]:
	if item[0] == 1516147200:
		print(item[3])

先頭から4行目までは前回の記事と全く同じです。
なので、新しく出てきたforのところから意味を説明します。

for文とif文の意味

文系の初学者の方が、できるだけ勉強をすっ飛ばして、実践からプログラミングを始める場合でも、どうしても絶対に「if文」と「for文」だけは理解していないと先に進めなくなります。

for文/if文の概念自体が全くわからない方は、できれば以下の記事を先に読んで少しだけ勉強してみてください。15~30分くらいで大体、要領だけはつかめると思います。

自動売買BOTを作る上で最低限必要なプログラミングの構文

今回のコードの意味

今回のJSONデータは、{ “result”: {“86400”: [[0番目],[1番目],[2番目]….]} というデータ構造になっており、知りたいのは何番目の[]に、2018年1月16日の価格データが含まれているか?です。

[]の中の先頭(0番目)に日付の数字が含まれていて、3番目に最安値の価格が含まれていることはすでに知っています。

data[“result”][“86400”][???][0]

が 1516147200 に一致する場合に、

data[“result”][“86400”][???][3]

の数字を取り出せばいいことになります。
つまり、for文のループ処理としては、

data[“result”][“86400”][0]
data[“result”][“86400”][1]
data[“result”][“86400”][2]
data[“result”][“86400”][3]
data[“result”][“86400”][4]
data[“result”][“86400”][5]
data[“result”][“86400”][6]


というのを順番に自動的に試していけばいいわけです。

for item in data[“result”][“86400”]: の部分では、86400をキーとするデータの値( [[0番目],[1番目],[2番目]….] のこと)の中の要素について、[ 〇番目 ] のデータを1個ずつ item という変数名に置き換えて、for文のループ処理を実行しています。

また、一番内側の[]の先頭の数字が「1516147200」に一致するかどうかは、if文で判定します。こちらは、現在、for文でループしている

data[“result”][“86400”][?番目]
(→ これをfor文の中では item に置き換えている)

のデータのうち、

data[“result”][“86400”][?番目][0]
(→ これはfor文の中では、item[0] に置き換えられる)

が、「1516147200」に一致すればいいわけです。そのため、if item[0] == 1516147200:という条件分岐を記述し、一致した場合にはその3番目の要素(item[3])を、print()で黒い画面に表示するように指示しています。

実行してみる

これをAnacondaプロンプトで実行してみます。

最安値は101万5000円でした。

この日の最高値は168万1000円、前日の終値は171万7000円ですから、この1日で70万円近くも暴落したことになりますね。(ぜひ練習として、この日の最高値や前日の終値も取得してみてください)

JSON形式のデータから自由に欲しい数字を取り出そう

前回までの記事では、APIを叩いて過去のビットコインの価格データを取得したり、現在の取引所の板情報を取得する方法を説明しました。

API経由で取得したデータは、大体、以下のように、空白も改行も装飾もない数字と文字の羅列データです。

※bitFlyerのAPIで取得した約定履歴のデータ

このような形式のデータを「JSON形式」といいます。このままの形式だと、どうしていいかわからないと思います。そこで、このJSON形式のデータから欲しい数字だけをPythonで取り出す方法を説明します。

目的の数字だけを取り出す

この記事では、「JSON形式とは何なのか?」といった面倒くさい説明に立ち入ることはしません。興味がある方は自分で調べてみてください。ここでは、いきなり本題に入り、「どうやって目的の数字を探すか?」だけを説明します。

JSON形式のデータは、以下のようなカッコ[]で括られて記述されています。


[ 12320 , 12342 , 12246 , 12254]

このように、JSONでは[]で囲まれたデータを1つのまとまりとして扱います。(このような形式を配列値といいます)

そしてプログラムの世界では、これらの[]の中のデータを左から順に、0番目、1番目、2番目、3番目…とカウントします。一番左のデータは[0]、2番目のデータは[1]、3番目のデータは[2]と書いて指定します。

ここまでまずは、覚えておいてください。

JSON形式のデータには、もう1つの記述方法があります。
それが以下のような別のカッコ{}で囲う記述です。


{ “btc”:1205314 , “eth”:102478 , “xrp”:89.45 , “xem”:48.42 }

こちらはさっきと違い、1つのデータが「〇〇:××」という2つの値のセットで記述され、それが{}の中にたくさん格納される、という記述の形式です。(このような形式をオブジェクト値といいます)

「〇〇:××」というデータセットのうち、左側の〇〇をキー、右側を値といいます。こちらの{}のデータ形式は、キーを指定することで値の数字を取り出します。例えば、「”btc”:1205314」というデータであれば、btcというキーを指定することで、1205314という値を取り出すことができます。

さっきの[]のデータ形式と違って、順番(〇番目のデータ)で数字を指定することはできません。

はい、覚えるルールはこれだけでOKです。

複雑に見える入り組んだデータ形式

上記のようにJSON形式は、[]や{}のカッコを使ってデータをひとまとめにして扱う形式ですが、実際には、カッコの中にさらにカッコがたくさん入ったような入れ子構造になっている場合が多いです。

例えば、以下のようなイメージです。

{ “中学生”: {“1年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]} , “2年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]} , “3年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]}}, “高校生”: {“1年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]} , “2年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]} , “3年生”: {“男子”:[156.5,47.9],”女子”:[153.6,46.7]}}}

数字は適当なので気にしないでください(笑)

いきなりこれを見ると少し面食らうかもしれませんが、一番内側から分解してみていけば、データの構造がわかります。

データの取り出し方

一番内側のデータセットはこれです。

“男子”:[156,47]

これは左側の”男子”がキーで[156,47]が値のデータセットです。ちなみにこの値は0番目が身長で1番目が体重です。なので、男子の身長の数字にアクセスしたければ、Pythonで[“男子”][0]と書けば、指定できます。

その外側は、

{“1年生” : {“男子”:[],”女子”:[]}}

という構造になっていますね。これは、左側の”1年生”をキーとし、右側の{“男子”:[],”女子”:[]} をまるまる1つの値とするデータセットです。そのため、ここから男子の身長データを取り出したければ、Pythonで[“1年生”][“男子”][0]と書けばOKです。

一番外側の{}を見ると、

{ “中学生”: {1年生のデータ,2年生のデータ,3年生のデータ} , “高校生”:{1年生のデータ,2年生のデータ,3年生のデータ}}

の構造になっているのがわかります。そのため、もし高校2年生の女子の体重データを取り出したければ、Pythonで[“高校生”][“2年生”][“女子”][1]と記述すればいいことがわかります。

bitFlyerのAPIで試してみよう

では同じことを、前回の記事で勉強したbitFlyerのパブリックAPIで試してみましょう。今回は、現在のティッカー情報を取得する以下のAPIを使います。

https://api.bitflyer.jp/v1/ticker/

すると、以下のような結果が得られました(3月現在)

{"product_code":"BTC_JPY","timestamp":"2018-03-12T13:46:52.657","tick_id":2658019,"best_bid":1053564.0,"best_ask":1053565.0,"best_bid_size":0.06,"best_ask_size":0.01,"total_bid_depth":2960.87621693,"total_ask_depth":3323.14800491,"ltp":1053575.0,"volume":273330.16902808,"volume_by_product":25246.19923669}

今ならあなたもこのJSON形式のデータ構造の意味がわかるはずです。

ではPythonのプログラムで、上記のJSONデータから「買い気配値」だけを取り出してみましょう。※ 買い気配値とは、買い板にある注文のうち一番価格の高い注文価格のことをいいます。(参考記事

Pythonプログラムを書く

サクラエディタを起動して以下のように記述してみましょう。

import requests
response = requests.get("https://api.bitflyer.jp/v1/ticker/")
data = response.json()
print( data["best_bid"] )

一応、いつものようにこのプログラムの意味を説明しておきます。
なお1行目と2行目は前回の記事と同じなのでそちらを参考にしてください。

data = response.json()
URLから取得したJSON形式のデータをパースして、dataという名前の変数に入れます。これは簡単にいうと、pythonに「これはjsonデータだよ!」と教えてる、というくらいの意味に考えてください。この1行を書くことで、JSONデータとして取り扱うことができます。

print ( data[“best_bid”] )
さっきの data というJSONデータから、”best_bid”をキーとする数字を取り出して、それを print() で黒い画面に表示しています。この data[“best_bid”] を自分で書ければ、今回の記事の目標は達成です!

さて、これをAnacondaプロンプトで実行してみると、買い気配値を得ることができました。

長いデータの中から買い気配値だけを取り出すことができました。

もう少しだけ難しい練習問題

今回のデータは、{}が1個しかなくて全体の構造がシンプルだったので、簡単でしたね。もう少しだけ難しいJSONデータのパースに挑戦してみましょう。

前々回の記事で練習した、過去のビットコイン価格のデータを取得するAPIを利用して、2018年1月16日(ビットコインの価格の大暴落があった日)の終値と最安値を取得してみてください。利用するAPIは以下です。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1514764800

こちらはさっきより少し難しいですが、まずは自分で試行錯誤してみてください。なお、人間の日付(2018-01-16)を機械のUNIXタイムスタンプに変換するには、こちらのサイトを使ってください。

UNIXタイムスタンプ変換ツール

なお、こちらの練習のプログラムを書くためには、最低限の簡単な「if文」と「for文」を書く必要があります。if文とfor文だけは、プログラムを書く以上、どうしても絶対に勉強する必要があります。全くわからない方は、以下の正解記事を先に読んでおいてください。

正解は、以下の記事で解説しています。

練習問題の解説記事

JSONデータの取扱いまとめ

これであなたはPythonを使って、API経由で取得したデータの構造を把握して、目的の数字を自由に取り出すことができるようになりました!

この記事で学んだ内容は、例えば、API経由で「注文の一覧」を取得したり、現在のJPY残高を確認したり、「注文ID」を管理して約定しない注文をキャンセルしたり、自動売買BOTを作るすべての場面で使います。APIのあらゆる結果(レスポンス)はJSON形式で返ってきますので、このスキルは必須です。

次はいよいよ、bitFlyerのプライベートAPIを利用して、買い注文・売り注文を出すために必要なことを学んでいきましょう。

国内取引所BitflyerのパブリックAPIを使ってみよう

前回の記事で、文系初心者の方でも、おおまかにAPIが何なのかまでは理解できたのではないかと思います。

APIというのは要するに、URLの形式で外部のサーバーにWEB経由で何らかの指示やリクエストを出すためのコマンドのようなものです。仮想通貨の自動売買BOTを作成するときは、必ず各取引所が提供しているAPIを利用します。

今回はいよいよ、Bitflyerでビットコインの自動売買をするためのAPIを使ってみましょう。

パブリックAPIを使ってみよう

ここまで一口にAPIと説明してきましたが、実はAPIには「パブリックAPI」と「プライベートAPI」の2種類があります。

パブリックAPIとは

パブリックAPIは、誰でもアカウント登録をすることなく使えるAPIです。同じURLでリクエストを送りさえすれば、誰でも同じ結果を取得できます。そのため、主に外部のサーバーからデータなどを引っ張ってくるときに使います。

例えば、以下はBitflyerの現在のマーケット状況を取得する「パブリックAPI」です。

https://api.bitflyer.jp/v1/ticker/

こちらはBitflyerの「BTC現物」の買い気配値(best_bid)、売り気配値(best_ask)、それぞれの注文サイズ(単位:BTC)、最終取引価格(LTP)、24時間の取引量などを取得するパブリックAPIです。

参考:気配値とは

単にデータを引っ張るだけのAPIなので、誰が上記のURLを閲覧しても同じ内容が表示されます。前回の記事で勉強した「ビットコインの過去の価格データを引っ張るAPI」も、典型的なパブリックAPIですね。

プライベートAPIとは

一方、プライベートAPIは、個人ごとにアカウント認証をし、秘密のパスワードを知ってるユーザーだけが送ることのできるAPIです。本当に単純なイメージとしては、URLの末尾やヘッダーに自分しか知らないパスワードを暗号化して付けて送るような感じだと思ってください。

プライベートAPIは、例えば、売り注文・買い注文を出したり、個人のアカウントに紐づけられた残高や注文状況を確認するときに使います。当然、これらのリクエストは個人によって返ってくる結果が異なりますし、他の人に勝手に送られても困ります。そのため、プライベートAPIを使います。

プライベートAPIについては、また次回以降の記事で説明します。

BitflyerのパブリックAPIをPythonで使ってみよう

上記のURLにアクセスした方は、もう既にbitFlyerのパブリックAPIを「使った」ことになります。

ですが、せっかく前回までの記事でPythonのプログラムの書き方を覚えたので、ブラウザで閲覧するのではなく、Pythonのプログラムで情報を取りに行かせてみましょう。

テキストエディタを開いて、以下のプログラムを入力してみてください。

import requests
response = requests.get("https://api.bitflyer.jp/v1/ticker/")
print(response.json())

これをまた「test.py」というファイル名で保存しましょう。
そしてAnacondaプロンプトでこれを実行してみます。

手順は覚えていますね?
以下のコマンドを実行します。

※ 手順がわからない方はこちらの記事参照。

すると以下のような感じの結果が表示されたはずです。

{'product_code': 'BTC_JPY', 'timestamp': '2018-03-11T20:54:26.257', 'tick_id': 1657905, 'best_bid': 1032928.0, 'best_ask': 1033522.0, 'best_bid_size': 0.005, 'best_ask_size': 0.046, 'total_bid_depth': 2593.67397399, 'total_ask_depth': 3282.80941985, 'ltp': 1033522.0, 'volume': 305621.56955061, 'volume_by_product': 24942.44036488}

これはさっきブラウザで見たものと全く同じですね。
同じデータをpythonでプログラムに「取ってこさせる」ことができました。

一応、ここでもプログラムの意味を確認しておきましょう。
大雑把でいいので、はじめて見たコードの意味は、調べる癖を付けることが重要です。

1)import requests
requestsというライブラリをインポートしています。
pythonで外部のURLにアクセスするときには、大抵このライブラリを最初にインポートします

2)response = requests.get(“URL”)
外部のURLにアクセスしてその結果を「response」という変数にセットしています。変数の名前は何でも構いません。略で「r」などにすることも多いです。

3)print(response.json())
さっきWEBから取得したレスポンスのJSONデータをパースして、それを黒い画面に表示しています。「JSON形式のファイルをパースして…」の意味は次の記事で説明します。

実は、上記の3行をカスタマイズするだけで、bitFlyerのほとんどのパブリックAPIが利用できます。bitFlyerには、他にも以下のようなパブリックAPIがありますので、自分でも試してみてください。

板情報を取得するAPI

https://api.bitflyer.jp/v1/board/

直近からの約定履歴を取得するAPI

https://api.bitflyer.jp/v1/executions/

取引所の稼働状況が正常かどうかを確認するAPI

https://api.bitflyer.jp/v1/gethealth/

他にどのようなAPIがあるかは、こちらのbitFlyerのAPI仕様書を読みましょう。難しそうなAPIの仕様書に対してのアレルギーも少しずつ減らしていきましょうね。

返ってきた数字の羅列データを使いこなす

さて、これであなたもbitFlyerのパブリックAPIを利用して、板情報を取得したり、ティッカー情報(売り板や買い板の気配値)などを取得するPythonプログラムが書けるようになりました! もう少しだけプログラムを勉強すれば、「10秒に1回、自動的に気配値を取得する」といったプログラムも簡単にかけます。ぐんぐん幅が広がりますね!

ただしここで少し疑問に思ったことがあるはずです。

「取得したデータがゴチャゴチャしてて読めないんだけど」
「この数字の羅列のデータをどうやって使うの?」

その通りです。

前回の記事から2記事続けてAPIを利用する方法を説明してきましたが、どのサービスのAPIを利用しても、似たような形式のデータが返ってくることに気付いたはずです。つまり、改行も空白も装飾も何もない数字とカンマとカッコ({})だけの羅列データです。

実は、このデータ形式のことを「JSON形式」といいます。人間にはひたすら読みにくいデータの羅列でしかありませんが、実はこの形式は、プログラム(機械)にとっては効率よく読みやすいデータ形式なんです。

次回の記事では、このJSON形式のデータから必要なデータだけを取り出す方法を解説します。

JSON形式のデータから自由に欲しい数字を取り出そう

「API」って何?仮想通貨の価格データをAPIで取得してみよう

さて、前回までの記事を読んだ方であれば、現在時刻を取得してAnacondaプロンプトに表示するプログラムを、Pythonで書くことができたはずです。これであなたもプログラマーです!

これは別に冗談ではありません。

前回の記事では、自分で複雑なプログラムを書けなくても、最初に「import datetime」と記述することで、賢い人たちが開発したdatetimeというプログラム集を、そのまま借りて使うことができました。基本的な考え方はこれと同じです。

仮想通貨の売買を自動化するBOTを作成するときも、基本的には、取引所が提供している「API」や、他の賢いプログラマの人たちが開発している「ライブラリ」をそのまま使います。

まずは「API」というのが何なのか、簡単に理解しておきましょう。

「API」とは何か?

「APIを叩いてJSONをパースして….」とかっていう会話を聞くと、「り、理系ってすごい….何でも出来てカッコいいなぁ…」と思ってしまいがちです。

しかしAPI自体は、別に難しいものではありません。

要するに、APIというのは外部のサーバーに対して、何らかの指示(命令)をWEB経由で送るためのコマンドのようなものだと思ってください。自分でAPIを作るのは難しいですが、外部サーバーが用意してくれているAPIを使わせて貰うのは全然難しくありません(笑)

例えば、以下はAPIの1つの例です。このURLをそのままブラウザのURL欄に入力してみてください。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1514764800

リンクはこちら

ブラウザに打ち込むだけで構いません。
すると、以下のような画面が表示されたはずです。

はい!
これであなたも「APIを叩く」ことができました。

これは、実は、Bitflyerの2018年1月1日以降のビットコインの日足の価格データを取得するAPIです。
cryptowatchというサイトが用意してくれているAPIです。

このCryptowatchというサイトには、世界各国の取引所の多くの仮想通貨(BTC/ETH/XRP…)の価格データが蓄積されています。さらにサイト側がAPIを用意してくれているので、あなたは上記のURLを入力するだけで、cryptowatchのサーバーから、ありがたく価格データを引っ張ってくることができます。

「API」で取得したデータの中身

本質的には、APIを利用することと、WEBサイトを閲覧することは同じ行為です。どちらも外部のサーバにURLでリクエストを送って、サーバー側から情報を引っ張ってくる行為です。

ただしAPIの場合は、基本的には引っ張ってくるのは「プログラムで使うためのデータ」です。人間の目で見るためのWEBページではありません。そのため、デザイン・空白・装飾・改行といった邪魔なものはすべて取り払われています。

シンプルにデータ(数字)が決められた順番で、カンマで区切られて並んでいます。この形式の方がプログラムで扱いやすいからですね。例えば、取得されたデータの先頭部分を抜き出してみましょう。
以下のように記載されています。

{"result":{"86400":[[1514764800,1519999,1713306,1502242,1675100,20188.11,32083065000]

これは何を意味しているのでしょうか。

まず86400は「日足データ」を意味しています。
プログラムに慣れてくるとわかりますが、これは「86400秒」の意味です。つまり「1日」と同じ単位です。機械は大きな数を扱うのが得意なので、1時間・1日・1週間などと言われるよりも、3600秒・86400秒・604800秒と言われた方が、扱いやすいんですね。

その次に続く[]の中に含まれた数字を見てみましょう。
それぞれ以下になります。

1514678400 ・・・ UNIX時間で「2017/1/1 09:00:00」の意味
1519999 ・・・ この日のビットコインの始値 151万9999円
1713306 ・・・ この日のビットコインの高値 171万3306円
1502242 ・・・ この日のビットコインの安値 150万2242円
1675100 ・・・ この日のビットコインの終値 167万5100円
20188.11 ・・・ この日の出来高

なぜこれらの数字が日付とか、高値・安値とか、出来高を意味するとわかるのでしょうか? それは、CryptowatchのAPI仕様書にそう書いてあるからです(笑) 今は読まなくていいですが、以下のページをチラっと覗いてみてください。

CryptowatchのAPI仕様書

そこにこう書いてあります。

values are in this order:
[ CloseTime , OpenPrice , HighPrice , LowPrice , ClosePrice , Volume]

(訳):
数字はこの順番で並んでいます:
[ 日時 , 始値 , 高値 , 安値 , 終値 , 出来高 ]

APIは各サービスが独自に提供しているものなので、返ってきたデータが何の数字で、どの順番で並んでいるかを理解するには、そのAPIの仕様書を読む必要があります。

最初は億劫に感じるかもしれませんが、APIの意味を知りたければ、Googleで検索して出てきたブログを読むよりも、公式サービスが提供しているAPI仕様書を読んだ方がわかりやすいですし確実です。

APIを送るコマンドの仕組み

先ほどのAPIのコマンドは「Bitflyerの2018年1月1日以降の日足価格データを取得するAPIだ」と説明しました。もう1度、さっきのURLを見てみましょう。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1514764800

URLの中に、以下のような文字列が入っていますね?

bitflyer ・・・ 取引所の名前
btcjpy ・・・ BTC/円の通貨ペア
periods=86400 ・・・ 日足
after=1514764800 ・・・ UNIX時間で「2018/01/01 09:00:00」以降

カンの良い方ならわかると思いますが、「bitflyer」の部分を「poloniex」に換えればpoloniexの価格データが見れます。

poloniexにはJPY通貨ペアはないので、USDT(デザー)建てで調べてみましょう。ついでに価格データは週足で取得して、期間は2017年1月以降にしてみましょう。

以下のようなURLになるはずです。

https://api.cryptowat.ch/markets/poloniex/btcusdt/ohlc?periods=604800&after=1483228800

※ 「bitflyer」を「poloniex」に変更、「btcjpy」を「btcusdt」に変更、「periods=86400」を「periods=604800」に変更、「after=1514764800」を「after=1483228800」に変更

APIを叩いてみると、以下のような結果が得られます。

※ なお、「2017年1月1日 午前9時0分0秒」をUNIXスタンプ(1483228800)に変換するには、以下のようなサイトを使います。

UNIXタイムスタンプ変換サイト

色々とパターンを変えてブラウザに入力してみてください。
何も表示されなければ、その価格データはサーバーに存在しないという意味です。

(練習問題)
・2015年1月のリップル(XRP)の価格をpoloniexからBTC建てで取得してみよう!

APIを使うのは難しくない

これであなたもCryptowatchのAPIを使いこなすことができました。意外と難しくなかったですよね?(笑)

ただし初対面のAPIを自力で使いこなすためには、APIの仕様書だけは読まなければなりません。すべてのAPIの意味を手取り足取り教えてくれるブログはありません。

今回のURLも、なぜこの順番(markets/取引所名/通貨ペア/ohlc?periods=ローソク足の時間軸)で記述するのかは、API仕様書を見なければわかりません。

ただし仕様書を読むといっても、長い英語のAPI仕様書を先頭から全部読みこむ必要は全くありません。何となく「やりたいこと」を書いてそうな部分にアタリを付ければいいだけです。

例えば、上記のAPI仕様書であれば、F3キーを使って「price」と単語をページ内で検索します。これはただのカンです。すると大体、何カ所かに読む場所を絞ることができます。ざっとスクロールしてみて、「High price(高値)」「Volume(出来高)」などの単語にピンと来れば、すぐに該当箇所を特定することができます。

(英語が苦手な方は、最初に右クリックで「日本語に翻訳」して「価格」でページ内検索してみてください。プログラムの仕様書などは、かなり読めるレベルで翻訳できます。)

さて、APIが何かを理解したところで、次はいよいよ取引所のAPIを利用してみましょう。