初心者が一攫千金を目指してBitcoin自動取引botを作るよ！ その３【ローカルBot】

[初心者が一攫千金を目指してBitcoin自動取引botを作るよ！ その１](http://qiita.com/speedkingg/items/2d874beee26106ce9f9a)
[初心者が一攫千金を目指してBitcoin自動取引botを作るよ！ その２](http://qiita.com/speedkingg/items/c589d34d507f0b160373)の続きになります。

今回はついに、自分で情報を取得し売買を行う**bitcoin自動取引Botもどき**を作成します！

# 仕様
組み合わせて動くかの実験として、
**安くなったら買う、そして、高くなったら売る！**みたいな愚直なBotを作ってみました。

> ①前回の取引額を渡す（この金額が判断の基準となる）
> ②Bitcoinを持っていてかつ値上がりした場合、売る！（そして、前回取引額を更新する）
> ③日本円を持っていてかつ値下がりした場合、買う！（そして、前回取引額を更新する）
> ④取引が処理されない場合、１分待って、待っても処理されない場合、キャンセルする（そして、前回取引額を元に戻す）

【参考】
・取引後のResponseの「order_id」が0でない（order_idが発行されている）場合、取引が保留となっている。

# 実装
今回より、keyとsecretをjsonにして別ファイルで保管するように変えました。
［］・・・フォルダ
[zaif]
 　|- *main.py*
 　|- [config] - *zaif_keys.json*
 　|- ...<略>


```python:main.py
# -*- coding: utf-8 -*-

import json
import time
from zaifapi import ZaifPublicApi  # Zaifが公開している認証情報が要らないAPIを実行するクラス
from zaifapi import ZaifPrivateApi  # Zaifが公開している認証情報が必要なAPIを実行するクラス
from pprint import pprint  # 表示用(jsonをきれいに表示してくれる)

zaif_keys_json = open('config/zaif_keys.json', 'r')
zaif_keys = json.load(zaif_keys_json)

KEY = zaif_keys["key"]
SECRET = zaif_keys["secret"]

if __name__ == '__main__':
    zaif_public = ZaifPublicApi()
    zaif_private = ZaifPrivateApi(KEY, SECRET)

    # 前回の取引額
    Last_transaction_amount = 122210

    # 情報取得
    last_price = int(zaif_public.last_price('btc_jpy')["last_price"])
    trade_info = zaif_private.get_info2()
    funds_btc = trade_info["funds"]["btc"]
    funds_jpy = trade_info["funds"]["jpy"]
    print('■ 現在の情報です。')
    print('last_price: ' + str(last_price))
    print('funds_btc: ' + str(funds_btc))
    print('funds_jpy: ' + str(funds_jpy))
    cancel_flag = False
    order_id = 0
    last_price_old = 0

    # btcを持っていて値上がりしたとき
    if funds_btc != 0 and last_price > Last_transaction_amount:
        # Bitcoinを売る
        trade_result = zaif_private.trade(currency_pair="btc_jpy", action="ask", price=last_price, amount=funds_btc)
        print('■ Bitcoinの売却申請を行いました。')
        pprint(trade_result)
        last_price_old = Last_transaction_amount
        Last_transaction_amount = last_price
        if trade_result["order_id"] != 0:
            cancel_flag = True
            order_id = trade_result["order_id"]
        else:
            print('■ 取引が完了しました。')

    # jpyを持っていて値下がりしたとき
    # （最小単位（0.0001btc分）の日本円以上を持っていたとき）
    elif funds_jpy > Last_transaction_amount / 10000 and last_price < Last_transaction_amount:
        # APIが小数点以下４桁までの対応なのでround()
        # 小数点第５位が繰り上げの場合、資産不足になるため(- 0.0001)
        amount = round(float(funds_jpy) / last_price, 4) - 0.0001

        # Bitcoinを買う
        trade_result = zaif_private.trade(currency_pair="btc_jpy", action="bid", price=last_price, amount=amount)
        print('■ Bitcoinの購入申請を行いました')
        pprint(trade_result)
        last_price_old = Last_transaction_amount
        Last_transaction_amount = last_price
        if trade_result["order_id"] != 0:
            cancel_flag = True
            order_id = trade_result["order_id"]
        else:
            print('■ 取引が完了しました。')

    # 取引が保留となった場合、60秒待ってまだ保留の場合はキャンセルを行う
    if cancel_flag:
        print('■ 60秒間待機します。')
        time.sleep(60)
        trade_info = zaif_private.get_info2()
        if trade_info["open_orders"] > 0:
            print('■ キャンセルしました。')
            pprint(zaif_private.cancel_order(order_id=order_id))
            Last_transaction_amount = last_price_old
        else:
            print('■ 取引が完了しました。')
            pprint(trade_info)
    
```

main.pyと同じ階層にフォルダ「config」を作成し、下記jsonファイルに保存します。

```json:zaif_keys.json
{
  "key" : "【作成したKey】",
  "secret" : "【作成したsecret】"
}
```


■実行結果
btcを持ってて値上がりしたとき

```console:
■ 現在の情報です。
last_price: 126725
funds_btc: 0.0075
funds_jpy: 7.9355
■ Bitcoinの売却申請を行いました。
{u'funds': {u'btc': 0.0, u'jpy': 7.9355, u'mona': 0.0, u'xem': 0.0},
 u'order_id': 156957485,
 u'received': 0.0,
 u'remains': 0.0075}
■ 60秒間待機します。
■ 取引が完了しました。
{u'deposit': {u'btc': 0.0, u'jpy': 958.373, u'mona': 0.0, u'xem': 0.0},
 u'funds': {u'btc': 0.0, u'jpy': 958.373, u'mona': 0.0, u'xem': 0.0},
 u'open_orders': 0,
 u'rights': {u'info': 1, u'personal_info': 0, u'trade': 1, u'withdraw': 0},
 u'server_time': 1491323133}
```

■実行結果
jpyを持ってて値下がりした時

```console:
■ 現在の情報です。
last_price: 126815
funds_btc: 0.0
funds_jpy: 959.048
■ Bitcoinの購入申請を行いました
{u'funds': {u'btc': 0.0, u'jpy': 7.9355, u'mona': 0.0, u'xem': 0.0},
 u'order_id': 156951488,
 u'received': 0.0,
 u'remains': 0.0075}
■ 60秒間待機します。
■ 取引が完了しました。
{u'deposit': {u'btc': 0.0, u'jpy': 959.048, u'mona': 0.0, u'xem': 0.0},
 u'funds': {u'btc': 0.0, u'jpy': 7.9355, u'mona': 0.0, u'xem': 0.0},
 u'open_orders': 1,
 u'rights': {u'info': 1, u'personal_info': 0, u'trade': 1, u'withdraw': 0},
 u'server_time': 1491322779}
```

# １日無限ループで動かしてみた結果
上記コードを加工し、１分ごとに１回実行し、１日動かしてみました。
>①「# 情報取得」の手前に無限ループ「while True:」を挿入
>②コードの一番後ろに「time.sleep(60)」を挿入

その結果は・・・！

昨晩の１回目の取引の金額：*￥957.8495*

```console:
■ 取引が完了しました。
{u'deposit': {u'btc': 0.0, u'jpy': 957.8495, u'mona': 0.0, u'xem': 0.0},
 u'funds': {u'btc': 0.0, u'jpy': 957.8495, u'mona': 0.0, u'xem': 0.0},
 u'open_orders': 0,
 u'rights': {u'info': 1, u'personal_info': 0, u'trade': 1, u'withdraw': 0},
 u'server_time': 1491324869}
```

只今の所持金：*￥958.8245*

```console:
■ 現在の情報です。
last_price: 127740
funds_btc: 0.0
funds_jpy: 958.8245
```

計算してみると。。。
*￥957.8495*▶*￥958.8245*なので、*￥0.975*の利益・・・！
(´◉◞౪◟◉)うん…
反省点をまとめようか。

# 反省点というか問題点
・１分ごとの瞬間の値しか見れない（変動がわからない）
・取引額を変数に格納しているだけなので、エラーで落ちると飛ぶ
・自宅PCのコンソールで動かし続けるの美しくない（寝るときPCのファンがうるさい）
・以下の場合（条件から外れて帰ってこない場合）、取引が一切できなくなる
　・Bitcoinを持っていてかつ値下がりした場合
　・日本円を持っていてかつ値上がりした場合
・0.0001でも値上がりした場合でも売るってだめなのでは（利益でない・・・）

# おわりに
なにはともあれ1日落ちずに動いたのは良かったです。
次回は反省点を活かし、**AWS Lambda上で実行**してみたいと思います！
Lambdaだと都度実行になるので、データが飛ばないようにDBにもデータを格納しないといけませんね。

※Lambdaとは、簡単に言うとコードをアップすると実行してくれるやつです。[[参考]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html)
　サーバーを立てなくていい、環境を構築しなくていい優しいフレンズです(\*´ω｀\*)

お疲れ様でした～

# 更新履歴
2017/04/06：keyとsecretをjsonにして別ファイルで保存した旨の記載が抜けてました。。。