Bot

仮想通貨botの開発を本格的に始めてみる#5(2023/9/3)

2023年9月3日

前回の内容に続いて、仮想通貨botの開発状況をまとめていきます。

今回は、こちらの記事からスタートです。

いよいよ、bitFlyerに買い注文を出すところまでやってきました!

APIキーの取得

こちらの作業は、すでにbitFlyerの口座を開設していたためすぐに完了しました。

また、FX取引用に一定額の証拠金を預け入れておく必要があります。(この記事を書いている時点では4万円ほど預け入れていれば買い注文を出すことができました)

こちらの記事でbitFlyerの解説をしています。

注意点としては、よく分からないプログラムやライブラリには「APIシークレット」を入力してはいけないということです。

自動売買botのプログラムなども多数販売していますが、自分でも最低限のプログラムが読めるようにしておかないと危険だなと思います。

リスク管理の一環としても、bot開発を学んでおいて損はなさそうです。

また、出入金に関する操作もAPIキーにおける操作ができないようにしておくと良さそうです。

私は、今のところ取引所をまたいだアービトラージをする予定がないため、今の段階では出入金のチェックは外しておきました。

新規注文を出す

次は、bitFlyer LightningのAPI仕様書を読んで新規注文を出すのに必要な情報を探します。

以下の画像が該当箇所ですね。各パラメータを入力していきます。

因みに、FX取引ですので証拠金を入れていないと注文が出せません。

あらかじめ一定額の入金が必要ですが、私はすでに何度か取引をしていたため、この点は問題なく通過しました。

コードの意味を理解する

ところが、次に示されたのは長大なコード。

な、長いっ!

import hashlib
import hmac
import requests
import datetime
import json

api_key = "APIキーを入力"
api_secret = "APIシークレットを入力"

base_url = "https://api.bitflyer.jp"
path_url = "/v1/me/sendchildorder"
method = "POST"

timestamp = str(datetime.datetime.today())

param = {
"product_code" : "FX_BTC_JPY",
"child_order_type" : "LIMIT",
"side" : "BUY",
"price" : 指値価格を入力,
"size" : 0.01,
}
body = json.dumps(param)

message = timestamp + method + path_url + body
signature = hmac.new(bytearray(api_secret.encode('utf-8')), message.encode('utf-8') , digestmod = hashlib.sha256 ).hexdigest()

headers = {
'ACCESS-KEY' : api_key,
'ACCESS-TIMESTAMP' : timestamp,
'ACCESS-SIGN' : signature,
'Content-Type' : 'application/json'
}

response = requests.post( base_url + path_url , data = body , headers = headers)
print( response.status_code )
print( response.json() )

〇〇 = ~~と書かれている部分が変数をまとめる処理をしていることは理解できるのですが、中身を詳しく見ると意味が分からないことばかり。

解説を読んでもイマイチ理解できなかったり、単語の意味が分からなかったりしたため、ここでも地道に調べる作業です!

どんなライブラリをインポートしているのか調べる

とりあえず初っ端から意味を理解できないものが出てきたので、一つずつ意味を調べていくことにしました。

import hashlib
import hmac
import requests
import datetime
import json

上記のコードでimportしているライブラリについて簡単にまとめていきます。

hashlib:Pythonで提供されるデータをハッシュ化して送るための標準モジュール。主にセキュリティ管理に用いられる。
hashlibを使ったハッシュ化ハッシュ化と暗号化の違いとは?hashlibによるハッシュ化

hmac:データの正当性を確認するためのメッセージ認証コード。メッセージの改ざんを検出する。
HMACとは?データ認証の基本概念を解説

requests:Pythonでウェブスクレイピングをするときに使われる。具体的には、データの取得→抽出→保存を行う。仮想通貨botの運用においては、データの取得と抽出が主な役割となる。
たとえば、今回のコードにおいては、response = requests.get(URL,その他の任意の引数)に当たる部分はrequestsライブラリを用いてサーバーからの情報を取得している。引数は、予めurl=〇〇のような形でしておくこともできる。
また、コードの最終段response = requests.post( )では、サーバへ情報を登録する処理をしている。
PythonのRequestsを徹底解説

datetime:日時を処理するためのライブラリ。日時と文字列を相互に変換するメソッドstrftime()strptime()が用いられる。
Pythonのdatetimeで日付や時間と文字列を変換

json:出力する情報をJSON形式に変換して読みやすくするために使う。print( response.json ())の処理がそれにあたる。より詳しい解説はbot開発3回目の記事で触れている。

システムの土台作り

この部分では、今回のプログラムで必要な情報(URL,APIキー)を設定しています。

他のプログラムでも応用が効く部分ですね。これらを設定しておくことで、大元だけ変更すればプログラム全体にその変更が反映されるわけです。

システムの土台作りと言い換えても良いかもしれませんね。

api_key = "APIキーを入力"
api_secret = "APIシークレットを入力"

base_url = "https://api.bitflyer.jp"
path_url = "/v1/me/sendchildorder"
method = "POST"

この中でよく分からなかったのがmethod = "POST"の部分だったので、これも調べることにしました。

POSTメソッド:クライアントの入力内容をウェブサーバーに送信するための方法の一つ。値を見えないところに隠してウェブサーバーに送るやり方のこと。POSTメソッドを使うと、URLにリクエスト内容が表示されなくなります。つまり、今回のプログラムでは他の人に見られて困る情報(APIキーなど)を隠すために用いられていると思われます。
POSTメソッドとはHTTP GETとPOSTの違いGETメソッドとPOSTメソッドの違いとSEO面からの使い分け

そして、path_url = "/v1/me/sendchildorder"の赤い部分はAPI仕様書から拾ってきていることがわかりました。

認証のための暗号文(署名)

message = timestamp + method + path_url + body
signature = hmac.new(bytearray(api_secret.encode('utf-8')), message.encode('utf-8') , digestmod = hashlib.sha256 ).hexdigest()

signatureとは「署名」のことですね。

2行目のこの部分(signature = ,,,)は、解説記事でも「一番難しいかも」とされていた部分です。

そのため、私も関連記事を読み漁りました。

HMAC認証とは?HMACとは 認証の仕組みと実装HMACとは−意味を分かりやすくシグネチャとは

要するに、個人のAPIシークレットを鍵にしてこのメッセージを送っているのが本人であることを証明する役割を果たしているのだと理解しました。

実行する処理

response = requests.post( base_url + path_url , data = body , headers = headers)
print( response.status_code )
print( response.json() )

response = requests.post()を使って、これまでに作成した通信データをPOSTメソッドで送信します。

残りの2行は、サーバーから帰ってきた情報を表示するためのものです。

Python, Requestsの使い方

いざ、注文を出してみる!

ここまでのことを踏まえて書いたコードがこちら。

import hashlib
import hmac
import requests
import datetime
import json

api_key = "APIキー"
api_secret = "シークレットAPI"

base_url = "https://api.bitflyer.com"
path_url = "/v1/me/sendchildorder"
method = "POST"

timestamp = str(datetime.datetime.today)

param = {
"product_code" : "FX_BTC_JPY",
"market_type" : "FX",
"child_order_type" : "LIMIT",
"side" : "BUY",
"price" : 3000000,
"size" : 0.01,
}
body = json.dumps(param)

message = timestamp + method + path_url + body
signature = hmac.new(bytearray(api_secret.encode('utf-8')), message.encode('utf-8') , digestmod = hashlib.sha256 ).hexdigest()

headers = {
'ACCESS-KEY' : api_key,
'ACCESS-TIMESTAMP' : timestamp,
'ACCESS-SIGN' : signature,
'Content-Type' : 'application/json'
}

response = requests.post( base_url + path_url , data = body , headers = headers)
print( response.status_code )
print( response.json())

赤字の部分は、APIの仕様書を見ながら修正しました。

今回はFX取引なので、"market_type" : "FX",を追記していますね。

ちなみに.comは.jpでも注文通りました。

その結果がこちら。

まとめ

さらっと注文が通ったように書いていますが、実はかなり苦戦しています。

コードを写経のように1文字ずつ打ち込んだため、「これってどういう意味なの?」と考えるたびにググることになり、作業がまるで進まないという苦しみ,,,。

しかし、そのおかげでかなりの知識が身についてきちんと説明できるようになりました。

やっぱり基礎学習って大事です!

また、長いコードはお手本のコードを1行だけコピーしてすぐ下に貼り付けて完全に一致しているかどうかをチェックしました。

今日は2記事更新できたので嬉しいですね。

明日も一歩ずつ作業を進めていきます。

-Bot