Pythonでcoincheck APIを使ってみる。  ~自動取引プログラム作成に向けて~

# 更新
Coincheckクラスの`def get()`を更新しました。
[github](https://github.com/ti-ginkgo/coincheckAPI_TEST)に実行できるコードを置いてあります。

# coincheck API
仮想通貨が流行っていたので、自動取引の足掛かりとしてAPIの使い方を紹介します。
coincheckのサイトにPythonのサンプルが掲載されていなかったのでPythonでコードを書きます。

## 準備
1.[coincheck](https://coincheck.com/?c=ourb238FfGs)に登録
2. 登録後にライブラリで使うアクセスキーとシークレットキーを入手  

- 「ウォレット」をクリック
- 「設定」をクリック
- 「APIキー」をクリック
- 「新たにAPIキーを追加する」をクリック  

## APIを使う
APIにはPublic APIとPrivate APIの2種類あります。
Public APIは、取引所の注文状況や公開されている取引の履歴、板情報を取得などを行えます。
Private APIは、取引所での新規注文やキャンセル、自分の残高の確認などを行えます。
Private APIは、アクセスキーとシークレットキーを必要とします。

### ライブラリのインポート
紹介するサンプルファイルの実行には最初に以下のライブラリをインポートする必要があります。

```python
import requests
import json
```

requestsは外部ライブラリなので、インストールしていない人は`pip install requests`を実行してください。

### Public API
#### ティッカー **[GET]**
各種最新情報を取得できます。

```ticker.py
URL = 'https://coincheck.com/api/ticker'
coincheck = requests.get(URL).json() 
for key, item in coincheck.items():
    print("%-9s : %-10.9s " % (key, item))
```

#### 全取取引履歴 **[GET]**
最新の取引履歴を取得できます。

-  PARAMETERS
 - offset: 指定した数だけスキップ 

```trades.py
URL = 'https://coincheck.com/api/trades'
coincheck = requests.get(URL, params={"offset": 20}).json() 
print(coincheck)
```

#### 板情報 **[GET]**
板情報を取得できます。

```order_books.py
URL = 'https://coincheck.com/api/order_books'
coincheck = requests.get(URL).json() 
for key in coincheck.keys():
    print(key, ":")
    for value in coincheck[key]:
        print(value)
    print()
```

#### レート **[GET]**
取引所の注文を元にレートを算出します。

- PARAMETERS
 - order_type: 注文のタイプ("sell" or "buy")。
 - pair: 取引ペア。現在は"btc_jpy"のみ有効。
 - amount: 注文での量。
 - price: 注文での金額。

**priceまたはamountのいずれかをパラメータとして指定する必要があります。両方指定するとエラーになります。**

```rate.py
URL = 'https://coincheck.com/api/exchange/orders/rate'
params = {'order_type': 'sell', 'pair': 'btc_jpy', 'amount': 0.1}
coincheck = requests.get(URL, params=params).json() 
print(coincheck)

params = {'order_type': 'buy', 'pair': 'btc_jpy', 'price': 280000}
coincheck = requests.get(URL, params=params).json() 
print(coincheck)
```

#### 販売レート **[GET]**
販売所のレートを取得します。

- PARAMETERS
 - pair: 通貨ペア(例"btc_jpy", "bch_jpy"など)

```rate_pair.py
coins = {'BTC': 'btc_jpy', 'ETH': 'eth_jpy',
         'XEM': 'xem_jpy', 'BCH': 'bch_jpy'}

URL = 'https://coincheck.com/api/rate/'

for key, item in coins.items():
    coincheck = requests.get(URL+item).json()
    print("%-4s : %-10s" % (key, coincheck['rate']))
``` 

### Private API
Private APIは認証が必要なので、認証を簡潔に行うためのCoincheckクラスを定義しましょう。
Coincheckクラスには、GET・POST・DELETEメソッドを定義しています。
これによりPrivate APIを簡単に使うことができます。

```privateAPI.py
import json
import requests
import time
import hmac
import hashlib

class Coincheck:
    def __init__(self, access_key, secret_key, url='https://coincheck.com'):
        self.access_key = access_key
        self.secret_key = secret_key
        self.url = url

     def get(self, path, params=None):
        if params != None:
            params = json.dumps(params)
        else:
            params = ''
        nonce = str(int(time.time()))
        message = nonce + self.url + path + params

        signature = self.getSignature(message)

        return requests.get(
            self.url+path,
            headers=self.getHeader(self.access_key, nonce, signature)
        ).json()

    def post(self, path, params):
        params = json.dumps(params)
        nonce = str(int(time.time()))
        message = nonce + self.url + path + params
        
        signature = self.getSignature(message)

        return requests.post(
            self.url+path,
            data=params,
            headers=self.getHeader(self.access_key, nonce, signature)
        ).json()

    def delete(self, path):
        nonce = str(int(time.time()))
        message = nonce + self.url + path

        signature = self.getSignature(message)

        return requests.delete(
            self.url+path,
            headers=self.getHeader(self.access_key, nonce, signature)
        ).json()
    
    def getSignature(self, message):
        signature = hmac.new(
            bytes(self.secret_key.encode('ascii')),
            bytes(message.encode('ascii')),
            hashlib.sha256
        ).hexdigest()
        
        return signature
    
    def getHeader(self, access_key, nonce, signature):
        headers = {
            'ACCESS-KEY': access_key,
            'ACCESS-NONCE': nonce,
            'ACCESS-SIGNATURE': signature,
            'Content-Type': 'application/json' # 超重要。
        }
        
        return headers

access_key = '取得したアクセスキー'
secret_key = '取得したシークレットキー'

# インスタンスを作りましょう。
coincheck = Coincheck(access_key, secret_key)
```
<br>
#### 注文
注文に関する操作をできます。

##### 新規注文 **[POST]**
取引所に新規注文を発行します。

- PARAMETERS
 - pair: 取引ペア。現在は"btc_jpy"のみ有効。
 - order_type: 注文方法。8種類あります。
 - rate: 注文のレート。
 - amount: 注文での量。
 - market_buy_amount: **成行買で利用する*日本円*の金額**
 - position_id: 決済するポジションのID
 - stop_loss_rate: 逆指値レート

| order_type      | 説明 | パラメータ |
|:-----------------:|:-------------------:|:------------------:|
| "buy" | 指値注文の現物取引買い | rate, amount | 
| "sell" | 指値注文の現物取引売り | rate, amount | 
| "market_buy" | 成行注文の現物取引買い | market_buy_amount | 
| "market_sell" | 成行注文の現物取引売り | amount |   
| "leverage_buy" | 指値注文のレバレッジ取引新規買い | **rate**, amount |
| "leverage_sell"| 指値注文のレバレッジ取引新規売り | **rate**, amount |
| "close_short" | 指値注文のレバレッジ取引決済買い | **rate**, amount, position_id|
| "close_long"| 指値注文のレバレッジ取引決済売り | **rate**, amount, position_id|

**rate**を指定しなければ成行注文となります。それ以外の太字になっていないパラメータは指定が必要です。

```python3
# 100万の指値で0,01ビットコインを現物取引買い注文
path_orders = '/api/exchange/orders'
params = {
    "pair": "btc_jpy",
    "order_type": "buy",
    "rate": 100000,
    "amount": 0.01,
}
result = coincheck.post(path_orders, params)
print(result)

# Nonceは1以上大きくならないといけない
time.sleep(1)

# 10万円分のビットコインを成行買い注文
params = {
    "pair": "btc_jpy",
    "order_type": "market_buy", 
    "market_buy_amount": 100000, # 量ではなく金額
}
result = coincheck.post(path_orders, params)
print(result)
```

他の注文を同じ要領でできます。
`{'success': False, 'error': 'Nonce must be incremented'}`のようなエラーがでたらAPIキーを新規作成してみてください。
NonceはAPIキーごとに管理されるので、同じAPIキーを使い他のプログラムを実行していた場合エラーになる可能性があります。

<br>
##### 未決済の注文一覧 **[GET]**
アカウントの未決済の注文を一覧で表示。

```python3
path_orders_opens = '/api/exchange/orders/opens'
result = coincheck.get(path_orders_opens)
print(result)
```
<br>
##### 注文のキャンセル **[DELETE]**
新規注文または未決済の注文一覧のIDを指定してキャンセルできます。

- PARAMETERS
 - id キャンセルしたい**新規注文**または**未決済の注文一覧**のIDを指定。

```python
# [id]を注文を数字で置き換えます
path_orders_cancel = '/api/exchange/orders/[id]'
# path_orders_cancel = '/api/exchange/orders/12345678'など
result = coincheck.delete(path_orders_cancel)
print(result)
```

<br>
##### 取引履歴 **[GET]**
自分の最近の取引履歴を取得できます。

```python3
path_orders_transactions = '/api/exchange/orders/transactions'
result = coincheck.get(path_orders_transactions)
print(result)

path_orders_transactions_pagination = '/api/exchange/orders/transactions_pagination'
result = coincheck.get(path_orders_transactions_pagination)
print(result)
```

<br>
##### ポジション一覧 **[GET]**
レバレッジ取引のポジション一覧を表示します。

- PARAMETERS
 - status: "open", "closed"を指定できます。

```python
path_leverage_positions = '/api/exchange/leverage/positions'
result = coincheck.get(path_leverage_positions)
print(result)
```

### 補足
ここからは自動取引であまり使うことはないと思われるものですが、一応使用例を挙げておきます。
#### アカウント
##### 残高 **[GET]**
自分のアカウントの残高を確認できます。

```python3
path_balance = '/api/accounts/balance'
result = coincheck.get(path_balance)
print(result)
```

<br>
##### レバレッジアカウントの残高 **[GET]**
自分のレバレッジアカウントの残高を確認できます。

```python3
path_leverage_balance = '/api/accounts/leverage_balance'
result = coincheck.get(path_leverage_balance)
print(result)
```

<br>
##### ビットコインの送金 **[POST]**
指定のアドレスにビットコインを送ります。

- PARAMETERS
 - address: 送り先のビットコインアドレス
 - amount: 送りたいビットコインの量

```python3
path_send_money = '/api/send_money'
params = {
    "address": "1v6zFvyNPgdRvhUufkRoTtgyiw1xigncc",
    "amount": 0.1
}
result = coincheck.post(path_send_money, params)
print(result)
```

<br>
##### 送金履歴 **[GET]**
ビットコインの送金履歴を取得します。

- PARAMETERS
 - currency: 履歴を見たい通貨(現在は"BTC"のみ)

<font color="DarkRed">コードはGETメソッドを書き換える必要があります。後ほど更新します。</font>

##### 受け取り履歴 **[GET]**
ビットコインの受け取り履歴を取得します。

- PARAMETERS
 - currency: 履歴を見たい通貨(現在は"BTC"のみ) 

<font color="DarkRed">コードはGETメソッドを書き換える必要があります。後ほど更新します。</font>

<br>
##### ビットコインの高速入金 **[POST]**
受取中のビットコインを高速入金します。[高速入金とは?](https://coincheck.com/ja/documents/about/fast-bitcoin-deposit)

```python3
# [id]は数字に変換しましょう。
path_deposit_money = '/api/deposit_money/[id]/fast' 
params = {
    "id": id
}
result = coincheck.post(path_deposit_money, params)
print(result)
```

<br>
##### アカウント情報 **[GET]**
自分のアカウントの情報を表示します。

```python3
path_accounts = '/api/accounts'
result = coincheck.get(path_accounts)
print(result)
```

<br>
#### 日本円出金
日本円を銀行振込で出金できます。
コードは使う機会がほとんどないと思うので省略します。
普通に入金した方が楽です。

##### 銀行口座一覧 **[GET]**
自分のアカウントに出金用に登録された銀行口座の一覧を取得できます。

##### 銀行口座の登録 **[POST]**
自分のアカウントに出金先の銀行口座を登録できます。

##### 銀行口座の削除 **[DELETE]**
自分のアカウントの出金先の銀行口座を削除できます。

##### 出金履歴 **[GET]**
日本円出金の申請の履歴を取得できます。

##### 出金申請の作成 **[POST]**
日本円の出金申請ができます。

##### 出金申請のキャンセル **[DELETE]**
出金申請をキャンセルできます。statusが**pending**の出金申請のみキャンセルできます。

<br>
#### 信用取引 
##### 借入申請 **[POST]**
借入の申請をします。

- PARAMETERS
 - amount: 借りたい量
 - currency: 借りたい通貨("BTC", "ETH") 


```python3
path_lending_borrows = '/api/lending/borrows'
params = {
    "amount": 0.1,
    "curreny": "BTH"
}
result = coincheck.post(path_lending_borrows, params)
print(result)
```

<br>
##### 借入中一覧 **[GET]**
借入している通貨の一覧を取得できます。
返り値のidを返却に使います。

```python3
path_lending_borrows_matches = '/api/lending/borrows/matches'
result = coincheck.get(path_lending_borrows_matches)
print(result)
# {
#   "success": true,
#   "matches": [
#     {
#       "id": 12345,
#       "borrow_id": 6789,
#       "rate": "0.0005",
#       "amount": "1.3",
#       "pending_amount": "1.30065",
#       "currency": "BTC",
#       "deadline": "2017-11-30T05:55:38.000Z"
#     }
#   ]
# }
```

<br>
##### 返済 **[POST]**
idを元に返却することができる。

- PARAMETERS
 - id: 借入中一覧のID 

```python3
# [id]は数字に置き換えてください。
path_lending_borrows_replay = '/api/lending/borrows/[id]/repay'
params = {
    "id": 12345
}
result = coincheck.post(path_lending_borrows_replay, params)
print(result)
```

<br>
#### 振替
##### レバレッジアカウントへ振替 **[POST]**
現物取引アカウントからレバレッジアカウントへ振替ます。

- PARAMETERS
 - currency: 通貨(現在はJPYのみ対応)
 - amount: 移動する数量

```python3
path_to_leverage = '/api/exchange/transfers/to_leverage'
params = {
    "currency": "JPY",
    "amount": 10000
}
result = coincheck.post(path_to_leverage, params)
print(result)
```

<br>
##### レバレッジアカウントから振替 **[POST]**
レバレッジアカウントから現物取引アカウントへ振替ます。

- PARAMETERS
 - currency: 通貨(現在はJPYのみ対応)
 - amount: 移動する数量

```python3
path_from_leverage = '/api/exchange/transfers/from_leverage'
params = {
    "currency": "JPY",
    "amount": 10000
}
result = coincheck.post(path_from_leverage, params)
print(result)
```

## まとめ
APIの紹介は以上になります。これらの中の特に取引の部分を上手く使うことにより、自動取引プログラムが作成できるのではないでしょうか。何かのお役に立てば幸いです。

## 参考サイト
[取引所APIドキュメント| Coincheck](https://coincheck.com/ja/documents/exchange/api)