目的

bitfinexを通じて仮想通貨の取引をやってます。仮想通貨を投資家に貸して利息をもらうmargin funding(lendingとも)という取引があるのですが、投資家に期限より先に返されてしまうとそれに気づいてまた新しく入札するまでそのお金は使われないままになってしまいます。いちいち仕事中に残高をチェックしたりするのは大変なので、自動化しようと思いつきました。サーバーを立てる手段はいろいろありますが、Raspberry Piが家の倉庫にしまわれていたし、電気代もかからなくてちょうどよかったのでこれをつかって自動取引サーバーをつくることにしました。

bitfinexは素晴らしいことに仮想通貨取引をプログラムで行うためのAPIがオープンソースで公開されています。これを使えば誰でも簡単に取引の自動化ができます。やったね。私はruby版のAPIをつかっています。

https://github.com/bitfinexcom/bitfinex-api-rb

為替取引を自動化してうはうはに儲かる話を期待された方、申し訳ございませんm(_ _)m

すでにpoloniex向けにはbitseederというサービスがローンチされています。
https://bitseeder.net/
やろうとしていることはこれと同じです。あちらは手数料を取るビジネスですが、こちらはraspberry piと少々の電気代があれば実現できます。

Raspberry Piのセットアップ

基本的にはrubyとインターネット環境があればよいので何使っていただいてもよいですが、私はraspbianを使っています。

https://www.raspberrypi.org/downloads/raspbian/

このイメージをmicroSDカードに書き込むだけでRaspberry Piのセットアップができるので簡単ですね。

https://jyn.jp/raspbian-setup/#SSH

このページなどを参考にsshを有効化しておくと以下の作業はsshでできるので楽です。

ruby2.3.1を入れる

aptをつかってrubyを入れられますが、こちらのバージョンが1系になっていて、bitfinexのAPIが動きませんでした。従って、ruby2系を手動でインストールする必要があります。。

rubyのinstallはrbenvを使うととても便利です。

$ sudo apt-get install rbenv
$ rbenv install 2.3.1
$ rbenv global 2.3.1

rubyをrbenvでインストールしたものを使うようにするための環境変数も入れておきましょう。(rbenvを使うときのおきまりです。)

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

bundlerを後で使うのでinstallしておきます。

$ gem install bundler
$ rbenv rehash

gitを入れる

gitはaptで入ります。

$ sudo apt-get install git

自動化プログラムをダウンロードする

こちらで自動貸し出しプログラムを公開しています。よかったらどうぞー。
https://github.com/kackyt/auto_lender

$ git clone https://github.com/kackyt/auto_lender.git

そして必要なgemをインストールします。

$ bundle install

設定ファイルを用意する

プログラムに必要な設定ファイルを用意します。

bitfinexのAPI keyを取得する

自動化プログラムを動かすにはAPI keyを作成する必要があります。アカウントから『API』をクリックして、Create New Keyをクリックすると必要なpermissionを設定する画面にいきます。Margin FundingのWriteにチェックを入れて「Generate API Key」を押します。生成されたAPI KeyとAPI Secretをなくさないように保存します。

クリップボード02.png

.env

必要な環境変数は以下の通りです。

BFX_API_KEY=""
BFX_API_SECRET=""

こちらにbitfinexで取得したAPI_KEYとAPI_SECRETを移します。

config.yml

通貨ごとにどんな取引をさせたいかを設定します。

usd:  // 通貨のticker symbol
  rate: 0.0 // 貸し出すレート(per day) 0を指定すると自動でレートを判断する
  period: 3 // 貸し出す期間(day)
btc:
  rate: 0.1
  end: "2017-08-31" // periodでなくendが指定されていた場合、その日までの期間を自動設定する

実行する

$ bundle exec ruby auto_lender.rb

エラーが表示されなければ成功です!

自動実行させる

自動実行させるにはいろいろな手法がありますが、現状それほどリアルタイム性を求めていないため、crontabで1分ごとに実行させることにしています。daemon化して常駐させて、プロセス監視させたい方は頑張って下さい^^;

HOME=/home/pi
PATH=/home/pi/.rbenv/shims:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/bi
n

* * * * * cd $HOME/auto_lender && bundle exec ruby auto_lender.rb

ソースコード解説

bitfinexに接続

API secret、API keyをつかってbitfinexに接続します。

Bitfinex::Client.configure do |conf|
  conf.secret = ENV['BFX_API_SECRET']
  conf.api_key = ENV['BFX_API_KEY']
end

client = Bitfinex::Client.new

保有通貨数を取得

APIを使って、貸通貨口座(APIでは'deposit'と表記)にある通貨数と貸し出し可能な通貨数を取得して、statusというhash変数に入れます。

client.balances.each do |b|
  if b['type'] == 'deposit'
    if status[b['currency']]
      status[b['currency']]['amount'] = b['amount'].to_f
      status[b['currency']]['available'] = b['available'].to_f
    end
  end
end

貸出判定

status.each do |name, stat|
  if stat['available'] > stat['amount'] * 0.01
    amount = stat['available']

貸し出しは貸し出し可能数が、総数の1%を超えた場合に行います。また、貸し出しは可能な数をすべて一括で貸し出します。

レート自動算出ロジック

    if stat['rate'] == 0
      lends = client.lends(name, {limit_lends: 3})
      sum = lends.inject([0, 0]) do |memo, l|
        [memo[0] + l['rate'].to_f * l['amount_used'].to_f,
         memo[1] + l['amount_used'].to_f]
      end

      frr = sum[0] / sum[1]

      book = client.funding_book(name, {limit_bids: 0, limit_asks: 5})
      sum = book['asks'].inject([0, 0]) do |memo, b|
        [memo[0] + b['rate'].to_f * b['amount'].to_f,
         memo[1] + b['amount'].to_f]
      end

      bookrate = sum[0] / sum[1]
      rate = (frr + bookrate) / 2
    else
      book = client.funding_book(name, {limit_bids: 0, limit_asks: 1})
      toprate = book['asks'][0]['rate'].to_f
      rate = [stat['rate'] * 365, toprate].max
    end

rateが0の場合は自動でrateを算出します。

  • 過去3時間のFRR(flash return rate)の加重平均
  • 現在の入札金利の上位5つの加重平均

を算出し、これを1対1で平均をとったものをrateとしています。ただ、まだ正直うまい具合のレートになってくれてなかったりするのでチューニングの余地ありです。。過去の約定履歴とかがほしかったのですが、REST APIでは取得できなかったので断念しました。

rateがゼロ以外の場合は指定の金利が使われますが、それより高い金利しか板に並んでいない場合はそちらの金利を使うことにしています。

期間の設定

    period = 2
    if stat['period']
      period = stat['period']
    end

    if stat['end']
      today = Datetime.now
      enddate = Datetime.strptime(stat['end'], '%F')
      period = enddate - today
    end

    if period > 30
      period = 30
    end

endが指定されていた場合はその日付をparseして今日との差分をperiodとして扱います。periodは30が最大となるため、その処理も入れます。

発注

APIを使って発注を行います。

   client.new_offer(name, amount, rate, period, 'lend')

あとは寝てるだけで金利収入が入ってきますw

コスト試算

Raspberry Pi 2 model Bで行うと想定。出力は5.5Wで、24時間稼働した場合、0.132kWh。
東京電力の従量電灯Bで120kWhをこえ300kWhまで(第2段階料金)とすると、1日あたり0.132×26 = 3.432円
1ヶ月あたり、3.432×30 = 102.96円

比較として、awsにt2.nanoでサーバーを立てた場合、
east USリージョンで0.0059ドル/h 1日あたり 0.0059×24×110 = 15.576円
東京リージョンで0.008ドル/h 1日あたり 0.008×24×110 = 21.12円