ブログと投資で生活 / 作者プロフィール

bitFlyer でビットコイン(仮想通貨)FXの自動売買を行うシステムトレードプログラムbotを作成してみた

過去にビットコイン(仮想通貨)のシステムトレードを coincheck API を使って行っていました。

 

システム構築手順はこちらに書きました。

Coincheck でビットコイン(仮想通貨)の自動売買を行うシステムトレードプログラムbot を作成してみた

成績はこちらに書きました。

ビットコイン投資でいくら儲かる? 自動売買プログラムでデイトレードした結果を公開

 

ビットコインのチャートは価格がよく動くうえに値幅が大きいのでデイトレに適しており、2017年は仮想通貨市場全体が盛り上がっていたこともあって、良きタイミングで買い注文を入れておけば着実に利益が積み重なっていたんですが、最近ではそんな甘いものではなくなってきました。

上げ相場だけでなく下げ相場にも対応したbotを作ってみたいと、空売りもできる ビットコインFXなるものをやってみることにしました。

 

今回、使った取引所は bitFlyer(ビットフライヤー)でAPIも提供されています。

ここでは、bitFlyer API、Ruby on Rails、Heroku を使って、ビットコイン(仮想通貨)FXの自動売買を行うシステムトレードプログラムbotを作成する手順をまとめていきます。

 

bitFlyer(ビットフライヤー)に登録

まずは仮想通貨の取引所である bitFlyer(ビットフライヤー)のサイトにアクセスしてアカウント登録します。

 

登録の詳しい手順はこちらに書きました。

bitFlyer(ビットフライヤー)の登録方法、口座開設のやり方! ビットコイン購入までの使い方、買い方をまとめる

 

bitFlyer(ビットフライヤー)でAPIキーを作成

bitFlyer(ビットフライヤー)のアカウント登録が完了していたら、続いてAPIキーを作成していきます。

 

まず bitFlyer(ビットフライヤー)にログインして、左メニューにある「bitFlyer Lightning」をクリック

「bitFlyer Lightning」は、bitFlyer が提供しているビットコインの売買を行うためのプラットフォームです。

 

「bitFlyer Lightning」の画面が現れたら、左上にあるアイコンをクリック

 

するとメニューが開くので、「API」をクリックします。

 

するとAPIの画面が現れるので、下のほうにある「新しいAPIキーを追加」ボタンをクリック

 

するとAPIキーを発行するためのウィンドウが現れます。

ラベルは自分のわかりやすい好きな名前をつけます。APIを何に使うか後からわかるようにしておくと良いでしょう。

権限はAPIを使ってなんの動作を行えるようにするか設定します。今回作るシステムでは入出金や資産は操作する予定がないのでチェックを外し、トレード関連の設定に全てチェックをつけておきました。

 

最後に一番下の「OK」ボタンをクリックします。

 

追加したAPIキーが一覧表示され、APIキーとシークレットキーが確認できるようになります。シークレットキーについては「表示」ボタンを押すと表示されます。

メモ

外部にこのキーがばれてしまうと、取引の操作が他の人でもできてしまうので、漏らさないよう取り扱いには注意してください。

 

それぞれのキーはあとで使うので、とりあえずここでの作業は終わりです。

 

Rails のアプリケーションを新規作成

ターミナルを開いて Heroku にログイン。

メモ

Heroku アカウントを持っていない方は作成する必要があります。

$ heroku login

 

Rails をインストール。

$ gem install rails --no-ri --no-rdoc

 

Rails アプリケーションを作成。

$ rails new myapp --database=postgresql

 

アプリケーションのディレクトリに移動。

$ cd myapp

 

Gem をインストール。

$ bundle install

 

ひとまず空のアプリケーションを Heroku へデプロイ

git でアプリケーションを管理させる。

$ git init
$ git add .
$ git commit -m "init"

 

Heroku 上でアプリケーションを新しく作成。

$ heroku create

 

Heroku へデプロイ。

$ git push heroku master

 

いちおうマイグレーションも実行しておく。

$ heroku run rake db:migrate

 

ひとまずこれで Heroku に空のアプリケーションがデプロイできました。

 

bitFlyer(ビットフライヤー)のAPIを使ってビットコインの売買注文を入れてみる

いよいよプログラムでビットコインの売買を行っていきます。

 

orders タスクを追加。

rails g task orders

 

すると lib/tasks/orders.rake というファイルが作成されるので、ここに注文の処理を書いていこうと思います。

 

買い注文を入れるプログラム

30,000円で0.01BTCの買い注文を入れるソースコードを以下のように書いてみました。

最初に作成したアクセスキーやシークレットキーをこのコード内で使います。

namespace :orders do
 desc "30,000円で0.01BTCの買い注文を入れる"
 task :buy => :environment do
    key = "アクセスキー"
    secret = "シークレットキー"
    timestamp = Time.now.to_i.to_s
    method = "POST"
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = "/v1/me/sendchildorder"
    body = '{
      "product_code": "FX_BTC_JPY",
      "child_order_type": "LIMIT",
      "side": "BUY",
      "price": 30000,
      "size": 0.01,
      "minute_to_expire": 10000,
      "time_in_force": "GTC"
    }'
    text = timestamp + method + uri.request_uri + body
    sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
    options = Net::HTTP::Post.new(uri.request_uri, initheader = {
      "ACCESS-KEY" => key,
      "ACCESS-TIMESTAMP" => timestamp,
      "ACCESS-SIGN" => sign,
      "Content-Type" => "application/json"
    });
    options.body = body
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.request(options)
    puts JSON.parse(response.body)
  end
end

 

成行で0.02BTCの買い注文を入れるソースコードはこちら。body の中身を変えることで注文方法を変えられます。

namespace :orders do
 desc "成行で買い注文を入れる"
 task :buy => :environment do
    key = "アクセスキー"
    secret = "シークレットキー"
    timestamp = Time.now.to_i.to_s
    method = "POST"
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = "/v1/me/sendchildorder"
    body = '{
      "product_code": "FX_BTC_JPY",
      "child_order_type": "MARKET",
      "side": "BUY",
      "size": 0.02,
      "minute_to_expire": 10000,
      "time_in_force": "GTC"
    }'
    text = timestamp + method + uri.request_uri + body
    sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
    options = Net::HTTP::Post.new(uri.request_uri, initheader = {
      "ACCESS-KEY" => key,
      "ACCESS-TIMESTAMP" => timestamp,
      "ACCESS-SIGN" => sign,
      "Content-Type" => "application/json"
    });
    options.body = body
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.request(options)
    puts JSON.parse(response.body)
  end
end

 

売り注文を入れるプログラム

今度は60,000円で0.01BTCの売り注文を入れるソースコードを以下のように書いてみました。

さきほどの買い注文と要領はほとんど同じで、body の中にある side"SELL" に変えると売り注文になります。

namespace :orders do
  desc "60,000円で0.01BTCの売り注文を入れる"
  task :sell => :environment do
    key = "アクセスキー"
    secret = "シークレットキー"
    timestamp = Time.now.to_i.to_s
    method = "POST"
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = "/v1/me/sendchildorder"
    body = '{
      "product_code": "FX_BTC_JPY",
      "child_order_type": "LIMIT",
      "side": "SELL",
      "price": 60000,
      "size": 0.01,
      "minute_to_expire": 10000,
      "time_in_force": "GTC"
    }'
    text = timestamp + method + uri.request_uri + body
    sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
    options = Net::HTTP::Post.new(uri.request_uri, initheader = {
      "ACCESS-KEY" => key,
      "ACCESS-TIMESTAMP" => timestamp,
      "ACCESS-SIGN" => sign,
      "Content-Type" => "application/json"
    });
    options.body = body
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.request(options)
    puts JSON.parse(response.body)
  end
end

 

注文を確認するプログラム

今度は注文一覧を確認するソースコードを以下のように書いてみました。

namespace :orders do
  desc "注文一覧を確認する"
  task :check => :environment do
    key = "アクセスキー"
    secret = "シークレットキー"
    timestamp = Time.now.to_i.to_s
    method = "GET"
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = "/v1/me/getchildorders"
    uri.query = "product_code=FX_BTC_JPY"
    text = timestamp + method + uri.request_uri
    sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
    options = Net::HTTP::Get.new(uri.request_uri, initheader = {
    "ACCESS-KEY" => key,
    "ACCESS-TIMESTAMP" => timestamp,
    "ACCESS-SIGN" => sign,
    });
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.request(options)
    puts JSON.parse(response.body)
  end
end

 

実行結果はこのようになります。オーダーIDや注文内容が確認できます。

$ rake orders:check

[
  {
    "id": 138398,
    "child_order_id": "JOR20150707-084555-022523",
    "product_code": "BTC_JPY",
    "side": "BUY",
    "child_order_type": "LIMIT",
    "price": 30000,
    "average_price": 30000,
    "size": 0.1,
    "child_order_state": "COMPLETED",
    "expire_date": "2015-07-14T07:25:52",
    "child_order_date": "2015-07-07T08:45:53",
    "child_order_acceptance_id": "JRF20150707-084552-031927",
    "outstanding_size": 0,
    "cancel_size": 0,
    "executed_size": 0.1,
    "total_commission": 0
  },
  {
    "id": 138397,
    "child_order_id": "JOR20150707-084549-022519",
    "product_code": "BTC_JPY",
    "side": "SELL",
    "child_order_type": "LIMIT",
    "price": 30000,
    "average_price": 0,
    "size": 0.1,
    "child_order_state": "CANCELED",
    "expire_date": "2015-07-14T07:25:47",
    "child_order_date": "2015-07-07T08:45:47",
    "child_order_acceptance_id": "JRF20150707-084547-396699",
    "outstanding_size": 0,
    "cancel_size": 0.1,
    "executed_size": 0,
    "total_commission": 0
  }
]

 

ちなみに

    uri.query = "product_code=FX_BTC_JPY"

のところを

    uri.query = "product_code=FX_BTC_JPY&child_order_state=ACTIVE"

のように変えると、オープンな注文のみの一覧を取得できます。

 

サンプルで作った自動売買システム

以下はサンプルで作った自動売買プログラム。

50,000円で買い注文、60,000円で売り注文を交互に入れるプログラムです。

1時間に1回などの頻度で定期的に実行する想定です。

namespace :orders do
  desc "実行処理の説明"
  task :update => :environment do
    key = "アクセスキー"
    secret = "シークレットキー"
    timestamp = Time.now.to_i.to_s

    # 注文一覧を取得
    method = "GET"
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = "/v1/me/getchildorders"
    uri.query = "product_code=FX_BTC_JPY&child_order_state=ACTIVE"
    text = timestamp + method + uri.request_uri
    sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
    options = Net::HTTP::Get.new(uri.request_uri, initheader = {
    "ACCESS-KEY" => key,
    "ACCESS-TIMESTAMP" => timestamp,
    "ACCESS-SIGN" => sign,
    });
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.request(options)
    result = JSON.parse(response.body)

    # 前の注文が残っている場合は何もせずに終了
    if result.count > 0
      exit
    end

    # 現在のレートを確認
    uri = URI.parse("https://api.bitflyer.jp")
    uri.path = '/v1/ticker'
    uri.query = 'product_code=FX_BTC_JPY'
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    response = https.get uri.request_uri
    result = JSON.parse(response.body)
    last_rate = result['ltp']

    if last_rate > 60000
    # 現在のレートが60000円を超えたら、50000円で買い注文を入れる
       method = "POST"
       uri = URI.parse("https://api.bitflyer.jp")
       uri.path = "/v1/me/sendchildorder"
       body = '{
        "product_code": "FX_BTC_JPY",
        "child_order_type": "LIMIT",
        "side": "BUY",
        "price": 50000,
        "size": 0.01,
        "minute_to_expire": 10000,
        "time_in_force": "GTC"
       }'
       text = timestamp + method + uri.request_uri + body
       sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
       options = Net::HTTP::Post.new(uri.request_uri, initheader = {
         "ACCESS-KEY" => key,
         "ACCESS-TIMESTAMP" => timestamp,
         "ACCESS-SIGN" => sign,
         "Content-Type" => "application/json"
       });
       options.body = body
       https = Net::HTTP.new(uri.host, uri.port)
       https.use_ssl = true
       https.request(options)
    elsif last_rate < 50000
    # 現在のレートが50000円を下回ったら60000円で売り注文を入れる
       method = "POST"
       uri = URI.parse("https://api.bitflyer.jp")
       uri.path = "/v1/me/sendchildorder"
       body = '{
        "product_code": "FX_BTC_JPY",
        "child_order_type": "LIMIT",
        "side": "SELL",
        "price": 60000,
        "size": 0.01,
        "minute_to_expire": 10000,
        "time_in_force": "GTC"
       }'
       text = timestamp + method + uri.request_uri + body
       sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
       options = Net::HTTP::Post.new(uri.request_uri, initheader = {
         "ACCESS-KEY" => key,
         "ACCESS-TIMESTAMP" => timestamp,
         "ACCESS-SIGN" => sign,
         "Content-Type" => "application/json"
       });
       options.body = body
       https = Net::HTTP.new(uri.host, uri.port)
       https.use_ssl = true
       https.request(options)
    end
  end
end

 

とりあえずAPIを組み合わせてみた例なので、実用で使う場合はもっと複雑なルールを書いていく必要があります。

 

作成したプログラムを Heroku 上で動かす

作成したプログラムを Heroku にデプロイします。

git push heroku master

 

次に、ウェブブラウザで Heroku のサイトにログインして、「Heroku Scheduler」アドオンを追加します。

このアドオンを使って、Heroku に反映した自動売買タスクを定期的に実行させることができます

 

「Heroku Scheduler」アドオンの設定ページに移動したら、タスクの実行コマンドを入力し、実行間隔を10分ごとに設定して保存します。

 

Heroku のコマンドで実行されているログを確認できます。

heroku logs -t

 

まとめ

これで自動売買を行うしくみをひととおり構築することができました。

あとは自分なりの注文条件ルールをプログラムで書いてアレンジしていくだけです。

 

ここで作成したプログラムは買いと売り注文ひとつずつしか対応していないシンプルなものですが、データベースで注文を管理することでより細かな注文に対応したシステムが構築できると思います。

あとはせっかく Ruby on Rails を使っているので、損益計算も画面で確認できるようにするなど夢が広がりますね!

 

実際にこのしくみで資産を運用しています

実際にプログラムを使ってビットコインFXの自動売買botを運用し始めたので、また Twitter やブログなどで成績を公開していけたらと思います。

 

Coincheck API を使ってコーディングした例もあります。

Coincheck でビットコイン(仮想通貨)の自動売買を行うシステムトレードプログラムbot を作成してみた

そのときの運用結果はこちらに書きました。

ビットコイン投資でいくら儲かる? 自動売買プログラムでデイトレードした結果を公開

 

リアルタイムな売買のようすは Twitter でも公開しているので、よかったらフォローしてくださいな!