こんにちは、はやたす(@hayatasuuu )です。
今回の講義では、自動売買で使うためのクラスを作成していきたいと思います。
前回の記事はこちら

今までの講義では、以下のようにすべてのコードを1つのファイルに書いていました。
import hmac
import hashlib
import json
import time
from pprint import pprint
import configparser
import requests
conf = configparser.ConfigParser()
conf.read('config.ini')
ACCESS_KEY = conf['coincheck']['access_key']
SECRET_KEY = conf['coincheck']['secret_key']
BASE_URL = 'https://coincheck.com'
url = BASE_URL + '/api/exchange/orders'
nonce = str(int(time.time()))
params = {
'pair': 'btc_jpy',
'order_type': 'market_sell',
'amount': '0.00500736'
}
body = json.dumps(params)
# body = ''
message = nonce + url + body
signature = hmac.new(SECRET_KEY.encode(),
message.encode(),
hashlib.sha256).hexdigest()
headers = {
'ACCESS-KEY': ACCESS_KEY,
'ACCESS-NONCE': nonce,
'ACCESS-SIGNATURE': signature,
'Content-Type': 'application/json'
}
# r = requests.get(url, headers=headers)
r = requests.post(url, headers=headers, data=body)
r = r.json()
pprint(r)
ただ、このようなコードを作成しておくと、非常にコードが読みづらいです。また、毎回APIのアクセス先を編集する必要があります。
そこで当記事では、ビットコインの最新価格取得や、購入のためのクラスを作成することで、コインチェックAPIを扱いやすくしたいと思います。
この記事で紹介する内容まで学習していただけば、あとはビットコイン自動売買のロジックを組むだけです。
クラスを苦手としている人は多いですが、これを機に慣れていきましょう!
Contents
クラスを作成してコードを読みやすくしよう!
ここからは、以前のコードを使いながら、新しいファイルcoincheck.py
にクラスを作成していきます。
順を追って解説していきますね。
STEP① : ライブラリのインポート
まずはmain.py
で使っていたライブラリをインポートします。
import hmac
import hashlib
import json
import time
import requests
上記ライブラリは、PrivateAPIの利用で必要になるんでしたね。
STEP② : __init__()の設定
ライブラリのインポートが完了したら、さっそくクラスを作成していきます。今回はCoincheck
という名前で、クラスを作成していきましょう。
class Coincheck(object):
pass
そうしたら、まず書いていきたいのが__init__()
です。ここには、インスタンスの生成をしたとき、どのメソッドを使うにも共通で持たせておきたい変数を設定しておきます。
今回クラスを作成する上で、各APIごとにメソッドを作成していきたいです。
そんなとき、どのメソッドでも共通で使う変数を考えてあげると、以下のような__init__()
を作成できるかと思います。
class Coincheck(object):
def __init__(self, access_key, secret_key):
self.access_key = access_key
self.secret_key = secret_key
self.url = 'https://coincheck.com'
アクセスキーとシークレットキーについては、各種APIで必要になるので問題ないと思います。
あとはURLの設定ですが、こちらは元々BASE_URL
で設定していたものです。
クラスになっても、今までと同じようにBASE_URL + それぞれのAPIにアクセスできるURL
の形で書いていきます。
STEP③ : 共通で使う内部メソッドの作成
今まで色々なAPIにアクセスして分かったと思いますが、基本的に変更されるのはURLとパラメータだけです。
反対に、以下の内容は毎回同じものを使っています。
- 署名
- ヘッダーの作成
- リクエスト部分
こういった共通部分は、できれば一回で済ませておきたいです。
ゆえに、以下のようなリクエスト用のメソッドを追加してあげましょう。
class Coincheck(object):
def __init__(self, access_key, secret_key):
self.access_key = access_key
self.secret_key = secret_key
self.url = 'https://coincheck.com'
def _request(self, endpoint, params=None, method='GET'):
nonce = str(int(time.time()))
body = json.dumps(params) if params else ''
message = nonce + endpoint + body
signature = hmac.new(self.secret_key.encode(),
message.encode(),
hashlib.sha256).hexdigest()
headers = {
'ACCESS-KEY': self.access_key,
'ACCESS-NONCE': nonce,
'ACCESS-SIGNATURE': signature,
'Content-Type': 'application/json'
}
try:
if method == 'GET':
r = requests.get(endpoint, headers=headers, params=params)
else:
r = requests.post(endpoint, headers=headers, data=body)
except:
raise
return r.json()
上記のように_request()
を準備しておくと、どのURLにアクセスするときでも、同じメソッドを使えば認証からリクエスト結果の取得までできるようになります。
また_request()
のように、アンダースコアを1つ付けているのは、このメソッドを内部的に使うことを想定しているからです。
言い方を換えると、インスタンス.メソッド名()
の形で使うことを想定していません。あくまでもクラス内で使っていくメソッドになります。
※とはいっても、もちろん外からアクセスすることは可能です!
STEP④ : 各APIにアクセスするためのメソッドを作成
これまでの講義で、以下5つのAPIを紹介しました。
- /api/ticker
- /api/trades
- /api/order_books
- /api/exchange/orders
- /api/accounts/balance
上記の各APIごとに、メソッドを作成していきましょう。
tickerメソッド
クラスに対して、以下のメソッドを追加します。
class Coincheck(object):
"""
中略
"""
def ticker(self):
endpoint = self.url + '/api/ticker'
return self._request(endpoint=endpoint)
これで、先ほど作成しておいた_request()
を活用しつつ、メソッドの作成が完了しました。
ここまで書いたら、実際にticker()
を使ってみたいと思います。main.py
を開いて、コードを以下のように編集しましょう。
import configparser
from coincheck import Coincheck
conf = configparser.ConfigParser()
conf.read('config.ini')
ACCESS_KEY = conf['coincheck']['access_key']
SECRET_KEY = conf['coincheck']['secret_key']
coincheck = Coincheck(ACCESS_KEY, SECRET_KEY)
ticker = coincheck.ticker()
print(ticker)
クラスを使うときは「①インスタンスの生成」をして「②インスタンス名.メソッド名()」で呼び出すんでしたね。
この状態でmain.py
を実行してみましょう。

そうすると、今までどおりにティッカー情報を取得できました。ビットコインの最新価格が5,867,997円ということで、かなり高い位置にいますね^^;
lastプロパティ
いま使っていた/api/ticker
では、last
しか使っていませんでした。つまり、他のKeyは今回の自動売買では不要ということになります。
今回はlast
だけ取得できるようにしたいので、以下のようなプロパティを作成しましょう。
class Coincheck(object):
"""
中略
"""
@property
def last(self):
return self.ticker()['last']
これで、last
プロパティを使えば、ビットコインの最新価格だけを取得できるようになりました。
まずは以下のようにmain.py
を編集していきましょう。
import configparser
from coincheck import Coincheck
conf = configparser.ConfigParser()
conf.read('config.ini')
ACCESS_KEY = conf['coincheck']['access_key']
SECRET_KEY = conf['coincheck']['secret_key']
coincheck = Coincheck(ACCESS_KEY, SECRET_KEY)
# ticker = coincheck.ticker()
# print(ticker)
print(coincheck.last)
これでmain.py
を実行してみたいと思います。

そうすると、ビットコインの最新価格だけが取得されました。基本的にはticker()
メソッドではなくlast
プロパティを使っていけば良いですね。
その他メソッドの作成
残りのAPIについても、同じ要領で作成していけばOKです。
つまり、コード全体としては以下のようになります。
import hmac
import hashlib
import json
import time
import requests
class Coincheck(object):
def __init__(self, access_key, secret_key):
self.access_key = access_key
self.secret_key = secret_key
self.url = 'https://coincheck.com'
def _request(self, endpoint, params=None, method='GET'):
nonce = str(int(time.time()))
body = json.dumps(params) if params else ''
message = nonce + endpoint + body
signature = hmac.new(self.secret_key.encode(),
message.encode(),
hashlib.sha256).hexdigest()
headers = {
'ACCESS-KEY': self.access_key,
'ACCESS-NONCE': nonce,
'ACCESS-SIGNATURE': signature,
'Content-Type': 'application/json'
}
try:
if method == 'GET':
r = requests.get(endpoint, headers=headers, params=params)
else:
r = requests.post(endpoint, headers=headers, data=body)
except:
raise
return r.json()
def ticker(self):
endpoint = self.url + '/api/ticker'
return self._request(endpoint=endpoint)
@property
def last(self):
return self.ticker()['last']
def trades(self, params):
endpoint = self.url + '/api/trades'
return self._request(endpoint=endpoint, params=params)
def order_books(self, params=None):
endpoint = self.url + '/api/order_books'
return self._request(endpoint=endpoint, params=params)
def balance(self):
endpoint = self.url + '/api/accounts/balance'
return self._request(endpoint=endpoint)
@property
def position(self):
balance = self.balance()
return {k: v for k, v in balance.items()
if isinstance(v, str) and float(v)}
def order(self, params):
endpoint = self.url + '/api/exchange/orders'
return self._request(endpoint=endpoint, params=params, method='POST')
balance()
メソッドは、各通貨ごとに自分の持っているポジションが表示されます。
それゆえ、今回の自動売買と無縁なものだらけになってしまうので、ticker()
と同じ発想でpotision
プロパティを追加しました。
これでクラスの作成が完了しました。
まとめ : クラスを作成してコードを読みやすくしよう!
というわけで、ビットコインの自動売買で使うクラスを作成していきました。
このようにクラスを作成しておくと、かなりコードの見通しが良くなります。
これから自動売買のロジックを組んでいきますが、色々なコードが錯綜していると自分で書いていても訳の分からないことになってしまいます。
この講義に限らず、うまくクラスや関数を活用して、同じような処理をまとめていきましょう。
次回の講義では、実際に自動売買ロジックを組んでみたいと思います。
いよいよ本格的になっていくので、難しいと感じる部分が出てきたら、復習しながら学習を進めていきましょう!