noteのタイトル画像

[オープンソース] python製仮想通貨自動売買bot開発フレームワーク「Puppeteer」(傀儡師)

[更新] 2019-04-12 sampleプログラムを拡張しました。
[広告] 2019-04-17 Puppeteerのbot「HAL900」を掲載しました。
[追記] 2019-07-31 GitHubにも公開しました。

前回のnoteにて、NeoDuelBotという仮想通貨トレードbot開発フレームワークの無償配布が終了し、今後はクローズドな環境に移行することが告知されたことをお伝えしました。

個人的には「ありゃー、残念だけど仕方ないかぁ」って言う気持ちでした。
NeoDuelBot上で動作するストラテジを作成中であり、順調に仕上がってきたところだったので、作成中のストラテジをどうしようか?と悩んでいました。
(この記事を書いている最中に、NeoDuelBotがnoteにて販売されるという記事が投稿されましたね。)

で、思い立ったのが

いやいや、俺もSWエンジニアなんだし、以前に似たようなbot開発フレームワークをnode.jsで作ったこともあるんだから、今度はpythonで新しく作れば良いんじゃない?

ってものでした。
最近は仕事でpythonを使わざるを得ない状況にあり、MeCab, gensim, tensorflow, keras等と格闘する毎日。
だんだんとpythonにも慣れてきたこの頃です。

いきなり大規模なものは作れないけど、オープンソースソフトウェア(OSS)にして誰でもアクセスでき、利用できるようにすることで、他の人の賛同が得られたら徐々に拡張していけば良いや、と。

でもって、サクッと作ったのが「puppeteer」(傀儡師)と命名したbot開発フレームワークです。ソースコードを見てもらうと機能も貧弱で、かなり恥ずかしい作りなんですが、とりあえず動きます。(pythonのバージョンは3.6以上が必要)

ライセンスはオースンソースの人たちが良く利用する「MITライセンス」にしました。
MITライセンスについてはこちらを参照ください。

現在対応している取引所はbitmexのみ。
bitmexを採用したのはAPIの挙動を確認することができるTestNetというサイトが使用できるからです。ここで試運転することでポカミスを減らすことができます。
取引所を操作するためにbot開発者の間では定番のccxtを内部で利用しています。

ccxtのAPIを呼び出してtickerとorderbookを取得して、自分で作ったロジック(ストラテジ)に渡すというだけの作りです。

例えば、sample.pyというストラテジと、sample.jsonという定義ファイルをユーザさんが用意して、botを動作させようと思えば、 コンソールで「puppeteer」フォルダしたに移動して、そこで次のコマンドを

python3 puppeteer.py puppets/sample/sample.py puppets/sample/sample.json

と実行してもらえれば動きます。
実行周期や取引所のapiKey,secret、諸々のパラメータはJSONファイルに記述します。

sample.py

# -*- coding: utf-8 -*-
# ==========================================
# サンプル・ストラテジ
# ==========================================
import datetime

from puppeteer import Puppeteer

# ==========================================
# Puppet(傀儡) クラス
#   param:
#       puppeteer: Puppeteerオブジェクト
# ==========================================
class Puppet(Puppeteer):
    _exchange = None    # 取引所オブジェクト(ccxt.bitmex)
    _logger = None      # logger
    _config = None      # 定義ファイル

    # ==========================================================
    # 初期化
    #   param:
    #       puppeteer: Puppeteerオブジェクト
    # ==========================================================
    def __init__(self, Puppeteer):
        self._exchange = Puppeteer._exchange
        self._logger = Puppeteer._logger
        self._config = Puppeteer._config
        
    # ==========================================================
    # 売買実行
    #   param:
    #       ticker: Tick情報
    #       orderbook: 板情報
    #       position: ポジション情報
    #       balance: 資産情報
    #       candle: ローソク足
    # ==========================================================
    def run(self, ticker, orderbook, position, balance, candle):

        print('last={}'.format(ticker['last']))
        print('bid={}, ask={}'.format(orderbook['bids'][0][0], orderbook['asks'][0][0]))
        # --------------------------
        # ここに処理を記述します
        # --------------------------

sample.json

{
    "//" : "===============================================",
    "//" : " システムで利用",
    "//" : "===============================================",
    "//" : "取引所のapiKey, secretを設定します",
    "APIKEY" : "YOUR_APIKEY",
    "SECRET" : "YOUR_SECRET",

    "//" : "bitmex取引所で対応する通貨ペア等を記述",
    "SYMBOL" : "BTC/USD",
    "INFO_SYMBOL" : "XBTUSD",
    "COIN_BASE" : "BTC",
    "COIN_QUOTE" : "USD",
    "//" : "bitmex取引所の価格の最小幅(0.5ドル)",
    "PRICE_UNIT" : 0.5,

    "//" : "TestNetを使うか?(使う: true, 使わない: false)",
    "USE_TESTNET" : true,

    "//" : "ticker, orderbook, position, balance, candle のどれを利用するかを指定する。Falseを指定した場合はそのデータは取得しない",
    "USE" : {
        "TICKER" : true,
        "ORDERBOOK" : true,
        "POSITION" : true,
        "BALANCE" : true,
        "CANDLE" : true
    },

    "//" : "ローソク足の収集定義。",
    "CANDLE" : {
        "//" : "ローソク足の足幅を設定する。設定値= 1m, 5m, 1h, 1d",
        "TIMEFRAME" : "1m",
        "//" : "データ取得開始時刻(UNIXTIME:1ミリ秒)、使用しない場合 もしくは自動の場合は null(None) を指定",
        "SINCE" : null,
        "//" : "取得件数(未指定:100、MAX:500)",
        "LIMIT" : null,
        "//" : "True(New->Old)、False(Old->New) 未指定時はFlase",
        "REVERSE" : false,
        "//" : "True(最新の未確定足を含む)、False(含まない) 未指定はTrue",
        "PARTIAL" : false
    },

    "//" : "板情報の収集定義。",
    "ORDERBOOK" : {
        "//" : "取得件数(未指定:25、MAX:取引所による?)",
        "LIMIT" : null
    },

    "//" : "インターバルを秒で設定",
    "INTERVAL" :30,

    "//" : "discord通知用URL",
    "DISCORD_WEBHOOK_URL" : "",

    "//" : "===============================================",
    "//" : " ユーザで自由に定義",
    "//" : "===============================================",
    "//" : "売買するサイズ",
    "LOT_SIZE" :50
}

上記のサンプルを動作させた結果は、30秒周期でtickの最終価格と、板情報から取得したbid/askの値をログに吐くだけのものです。

last=5187.0
bid=5187, ask=5187.5
last=5187.0
bid=5187, ask=5187.5
last=5187.5
bid=5187, ask=5187.5
last=5187.5
bid=5187, ask=5187.5
last=5187.5
bid=5187, ask=5187.5
・・・
・・・

ohlcvデータを取得してローソク足を作るなどの機能追加は今後随時行なっていきたいと思います。

Puppeteer(傀儡師)のソースコード等は、GitLabにて公開中です。

要望等あればどうぞお気軽にご連絡ください。

追記:

2019-07-31 GitHubにも公開しました。


ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。