前回の投稿 Zaif 開発者向けAPIキー 取得方法 で開発者向けAPIキーを取得しました。まだの方はAPIキーを取得しておいてください。
プライベートAPIは11種類ありますが、今回は get_info を使用して残高を取得しようと思います。
では、Zaifのドキュメント Zaifの現物取引APIの共通情報 を確認しましょう。
エンドポイントは 「https://api.zaif.jp/tapi」とありますね。BTC価格取得 の際のエンドポイントは「https://api.zaif.jp/api/1/」でした。このエンドポイントに、「ticker」というAPIと「btc_jpy」というパラメータを追加し、下記のようなURLを作成しましたね。
[python title="Source1"]
https://api.zaif.jp/api/1/ticker/btc_jpy
[/python]
今回も「https://api.zaif.jp/tapi」にAPIやパラメータを追加すれば良さそうです。
次に、リクエスト種別が「POST」となっています。BTC価格取得 の際は「GET」でした。HTTPリクエストを投げる際は大きく分けて、GETとPOSTの2つがあります。前回はGETでしたので、下記のように、requestsのgetメソッドを使用しました。
[python title="Source2"]
r = requests.get('https://api.zaif.jp/api/1/ticker/btc_jpy')
[/python]
今回はPOSTですので、requestsのpostメソッドを使用すればOKです。
次の認証のところを読んでみてください。…とても分かりづらいですね。
ここはちょっと後回しにして、先に戻り値を確認しましょう。
[python title="Source3"]
{
"success": 1,
"return": {
...
}
}
[/python]
{で始まり}で終わっているので、これは辞書ですね。successというキーとreturというキーの2つのキーを持つ辞書になります。return自体も{で始まり}で終わっているので辞書ですね。辞書に関してはZaif通貨ペア情報 currency_pair で説明しましたので、確認しておいてください。
successに1が入っていれば、API処理が成功したということです。
returnのところは、APIによって違うので、それぞれのAPIのドキュメントを確認しましょう。
ではget_info APIのドキュメントを見てみましょう。
get_infoAPIの戻り値のreturn辞書は下記のキーを含みます。型がdictとなっているのは、辞書ということです。intは整数です。
[table id=8 /]
パラメータは「なし」なので、上記エンドポイントに get_info APIを追加するだけですね。
では、先程飛ばした共通情報の認証のところに戻りましょう。ただドキュメントの説明だけでは分かりづらいので、ZaifのドキュメントにPythonのサンプルコードがあるので、これを参考にしてみましょう。
ただ、このサンプルコードはactive_orders API(現在夕刻な注文一覧を取得)を使用しているので、get_info APIを使用するようにちょっと変更しています。
[python title="Source4"]
import json
import hmac
import hashlib
import requests
from urllib.parse import urlencode
secret = 'your secret key'
key = 'your key'
params = {
'method': 'get_info',
'nonce': 1
}
encoded_params = urlencode(params)
signature = hmac.new(bytearray(secret.encode('utf-8')), digestmod=hashlib.sha512)
signature.update(encoded_params.encode('utf-8'))
headers = {
'key': key,
'sign': signature.hexdigest()
}
response = requests.post('https://api.zaif.jp/tapi', data=encoded_params, headers=headers)
if response.status_code != 200:
raise Exception('return status code is {}'.format(response.status_code))
print(json.loads(response.text))
[/python]
では、一度実行してみましょう。
AnacondaのSpyderの使い方 で説明したSpyderで実行してみます。
Spyderを起動したら、ファイル - 新規ファイル を選択し、新しく出来たファイルに上記ソースコードをコピペしてください。
Zaif 開発者向けAPIキー 取得方法 で取得したAPIキーとAPIシークレットキーをそれぞれ下記の部分にコピペしてください。
[python title="Source5"]
secret = 'your secret key'
key = 'your key'
[/python]
では、実行ボタンを押してみてください。下記のようにコンソールに結果が表示されましたでしょうか?
私の結果はこのようになりました。
[python title="Source6"]
{
'success': 1,
'return':
{
'funds':
{
'jpy': 261235.0,
'btc': 0.199,
'xem': 4000.05,
'mona': 0.0,
'ETH': 5.0
},
'deposit':
{
'btc': 0.199,
'jpy': 421235.0,
'mona': 0.0,
'xem': 4000.05,
'ETH': 5.0
},
'rights':
{
'info': 1,
'trade': 0,
'withdraw': 0,
'personal_info': 0,
'id_info': 0
},
'trade_count': 24,
'open_orders': 2,
'server_time': 1514769104
}
}
[/python]
'success': 1 となっているので、HTTPリクエストは成功していますね。return辞書内に残高などのデータが格納されています。
解説
1~5行目までは各種ライブラリのインポートです。
[python]
import json
import hmac
import hashlib
import requests
from urllib.parse import urlencode
[/python]
7、8行目は Zaif 開発者向けAPIキー 取得方法 で取得したAPIキーとAPIシークレットキーをそれぞれ変数に格納します。文字列なので、シングルクォーテーション(')で囲みます。
[python]
secret = 'your secret key'
key = 'your key'
[/python]
9~12行目はパラメータをHTTPリクエストで渡すための準備です。get_info APIのドキュメントのパラメータを参照してください。nonceとmethodの2つのキーをパラメータとして指定するとありますね。
POSTリクエストをPOSTパラメータ付きで送るには下記のように記述します。
[python title="Source7"]
parameters = {'key1' : 'value1', 'key2' : 'balue2'}
r = requests.post("http://sample.co.jp", data = parameters)
[/python]
つまり、パラメータを辞書変数に格納し、requests.postメソッドの引数(data)に渡す、ということです。
Source4の20行目でdataとして渡していますね。
2つのキーをパラメータで渡していますが、nonce が少し分かりづらいかと思います。今回は 'nonce':1 として実行しました。このままもう一度Source4を実行してみてください。
[python title="Source8"]
{
'success': 0,
'error': 'nonce not incremented'
}
[/python]
successが0なので、失敗してしまったようです。errorにエラー内容が書かれています。nonceがインクリメントされていない、というエラーです。インクリメント、とは「コンピュータ用語で、変数の値を1増やす」という意味になります。
Zaifドキュメントには「1以上の数を実行都度増分して送信します」と記載されていますね。つまり、最初 'nonce':1として実行したら、次に実行する際は 'nonce':2のようにして、「増分」した数値をnonceの値として使わなければならない、ということです。以前までは整数しか扱えませんでしたが、2016年7月ごろに小数点以下をサポートするようになりました。ですので、1の次は2ではなく、1.1でもOKということです。Zaifドキュメントのパラメータの注意のところにも書いてありますね。
nonceパラメータの値は実効毎に増分されていないとエラーが発生します。また増分量は少数点以下の値にも対応しております。
13~15行目はZaifドキュメントの認証のところに記載があるsignキーの準備をしているところです。
[python title="Source9"]
encoded_params = urlencode(params)
signature = hmac.new(bytearray(secret.encode('utf-8')), digestmod=hashlib.sha512)
signature.update(encoded_params.encode('utf-8'))
[/python]
urlencodeメソッドによって、引数の params をURLエンコードしています。
{'method': 'get_info', 'nonce': 1} という辞書データをURLエンコードすることによって、method=get_info&nonce=1 というクエリ形式に変換しているわけです。
その後、Secret Keyを用いてHMAC-SHA512で署名を行っています。
16~19行目では、HTTPヘッダとして渡す辞書を準備しています。先程、POSTリクエストをPOSTパラメータ付きで送るには、という説明をしましたが、今度はHTTPヘッダ付きで送るときのお話です。下記のように記述します。
[python title="Source10"]
HeaderParameters = {'key1' : 'value1', 'key2' : 'balue2'}
r = requests.post("http://sample.co.jp", header = HeaderParameters)
[/python]
data を header に変えるだけですね。
今回は、POSTパラメータ付き、かつHTTPヘッダ付きでPOSTリクエストを送ることになりますので、20行目のようになるわけですね。
[python title="Source11"]
response = requests.post('https://api.zaif.jp/tapi', data=encoded_params, headers=headers)
[/python]
かなりややこしい説明になってしまいました…。ソースとドキュメントを読み返してみてくださいね。