Python×ビットコイン自動売買

#12 Python×ビットコイン自動売買 | クラスを作成してコードを読みやすくしよう!

create-coincheck-class-object-top

こんにちは、はやたす(@hayatasuuu )です。

今回の講義では、自動売買で使うためのクラスを作成していきたいと思います。

前回の記事はこちら

sell-bitcoin-using-api
#11 Python×ビットコイン自動売買 | Pythonを使ってビットコインを売却しよう!こんにちは、はやたす(@hayatasuuu )です。 前回の記事では、Pythonを使ってビットコインを購入してみました。 ...

今までの講義では、以下のようにすべてのコードを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にアクセスするとき、毎回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__()です。
ここには、インスタンスを生成したとき、どのメソッドでも共通で使う変数を設定しておきます。

具体的にいうなら、__init__()ではAPI Keyを設定することになります。

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も設定しておきます。
これは元々BASE_URLで設定していたものです。

クラスになっても、今までと同じようにBASE_URL + それぞれのAPIにアクセスできる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()を準備しておくと、どの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を実行してみましょう。

create-coincheck-class-object1

そうすると、今までどおりにティッカー情報を取得できました。
ビットコインの最新価格が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を実行してみたいと思います。

create-coincheck-class-object2

そうすると、ビットコインの最新価格だけが取得されました。
基本的にビットコインの最新価格だけあれば良いので、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'
        }

        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専用のクラスを作成できました。

まとめ : クラスを作成してコードを読みやすくしよう!

というわけで、ビットコインの自動売買で使うクラスを作成していきました。
このようにクラスを作成しておくと、かなりコードの見通しが良くなります。

これから自動売買のロジックを組んでいきますが、色々なコードが錯綜していると自分で書いていて訳が分からなくなってしまいます。

この講義に限らず、うまくクラスや関数を活用して、同じような処理をまとめていきましょう。

次回の講義では、実際に自動売買ロジックを組んでみたいと思います。
いよいよ本格的になっていくので、難しいと感じる部分が出てきたら、復習しながら学習を進めていきましょう!

第13回目の記事はこちら

create-automatic-trading-system
#13 Python×ビットコイン自動売買 | 自動売買に必要なロジックを作成してみよう!こんにちは、はやたす(@hayatasuuu )です。 今回の講義では、自動売買に必要なロジックを作成していきたいと思います。 ...

トップページはこちら

python-bitcoin-auto-trade
Python×ビットコイン自動売買 | 初心者でも理解できる入門講義『Pythonを使ったビットコインの自動売買って、どうやって実装するんだろう...。分かりやすく書かれている入門記事はないかな〜。』このような悩みを解決する記事になっています。Pythonを使ったビットコインの自動売買を学んでみたい人は必見です。...
ABOUT ME
はやたす
たくさんPythonを紹介するYouTuberです(登録者1.94万人) | フリーランスで機械学習/分析案件も請けています(経験業界 : 金融, 情報通信, サービス) | 元プログラミングスクール講師