こんにちは、はやたす(@hayatasuuu )です。
第12回目の本記事では、コードを読みやすくするためにクラスを作成していきます。
前回の記事 : #11 Python×ビットコイン自動売買 | Pythonを使ってビットコインを売却しよう!
これまで記事では、すべてのコードを1つのファイルに書いていました。
このように、1つのファイルですべてのコードを書くと非常に読みづらいです。
また複数のAPIにアクセスするとき、毎回URLを編集する必要が出てきます。
そこでクラスを活用することで、コインチェックAPIを扱いやすくしていきましょう。
クラスを苦手としている人は多いですが、これを機に慣れていきましょう!
クラスを作成してコードを読みやすくしよう!
ここからは新しいファイルcoincheck.py
にクラスを作成していきます。
STEP① : ライブラリのインポート
まずはcoincheck.py
を開いて、main.py
で使っていたライブラリをインポートしましょう。
import hmac
import hashlib
import json
import time
import requests
上記のライブラリは、PrivateAPIの利用で必要になるんでしたね。
STEP② : __init__()の設定
ライブラリのインポートが完了したら、Coincheck
という名前でクラスを作成していきましょう。
class Coincheck(object):
pass
まずはインスタンスを生成したとき、どのメソッドでも共通で使う変数を設定するために__init__()
を書いていきます。
具体的にいうと、API Keyのように「どんな操作をする上でも使う変数」を、以下のように__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 Keyだけでなく、URLも設定しておきます。
このように設定すると、これまでと同じようにアクセス先の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'
}
if method == 'GET':
r = requests.get(endpoint, headers=headers, params=params)
else:
r = requests.post(endpoint, headers=headers, data=body)
return r.json()
上記のように_request()
を準備しておくと、メソッドを呼び出すだけでAPIにアクセスできるので、認証用のコードを何度も書かずに済みます。
ちなみに_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
では、複数あるKeyのなかでlast
しか使っていませんでした。
今回の自動売買では他のKeyが不要なので、last
だけ取得できるように以下のプロパティを作成しましょう。
class Coincheck(object):
"""
中略
"""
@property
def last(self):
return self.ticker()['last']
これでlast
プロパティを使えば、ビットコインの最新価格だけ取得できます。
以下のようにmain.py
を編集して、last
プロパティを使ってみましょう。
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)
ターミナルの出力を見ると、ビットコインの最新価格だけが取得できていることが分かります。
その他メソッドの作成
残りのAPIについても、同じ要領で作成してきます。
最終的にコード全体としては以下のようになります。
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'
}
if method == 'GET':
r = requests.get(endpoint, headers=headers, params=params)
else:
r = requests.post(endpoint, headers=headers, data=body)
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
プロパティを追加しました。
これで今まで使ってきたAPIを操作できるメソッドを持つ、Coincheck専用のクラスを作成できました。
まとめ : クラスを作成してコードを読みやすくしよう!
というわけで、この記事ではビットコインの自動売買で使うクラスを作成しました。
今回のようにクラスを作成すると、コードの見通しが良くなります。
これから自動売買のロジックを組んでいきますが、コードが錯綜していると、自分でプログラムを組んでいて訳が分からなくなってしまいます。
このチュートリアルに限らず、クラスや関数を上手く活用して、繰り返し使う処理はまとめるようにしましょう。
次回の記事では、実際に自動売買ロジックを組んでみたいと思います。
いよいよ本格的になっていくので、難しいと感じる部分があったら復習しながら学習するようにしてください。