ビットコインが爆上がりした1年でしたね。まさか100万円を超えたことにも驚きましたが瞬く間に200万円を突破してしまいました。
1年前に戻ってまだ手放すな! と言ってやりたい...
まあ、それはさておきビットコインの面白いところはその出自からしてFinTech的なキーワードを持ってるのでエンジニアフレンドリー、つまりAPIを持ってる取引所が多いことも特徴かと思います。
なので、MetaTraderみたいなの使わなくても好きな言語でbotなりツールが書けるのも魅力的なところ。
というわけで今回はbitFlyerのAPIを使ってビットコインのFX取引をしてみます。
私はIFD取引をすることが多いのですが、bitFlyerはIFDがUI的に結構やりづらいので自分向けのカスタムUIを作るところを目指します。
bitFlyer APIでできること
bitFlyer APIでは以下のことが出来ます。
- 板情報(最終売買価格とか)などの公開情報の取得
- 売買(BTC/JPY,BTC-FX/JPY,ETH/BTCなど)
- リアルタイムAPI(PubNub)による情報の随時取得
まずはAPIキーの取得
まずはAPIキーの取得をします。開発者ページで新しいAPIキーを追加
を押すと「APIキー」と「API Secret」が生成されます。
こちらを利用することで認証を行えます。APIキー毎に利用できる権限を制御できるので不要な権限はなるべく付けない方がいろいろと便利かと思います。
ここで生成したキーは決して外部に公開しないようにしてください。githubとか要注意。
Rubyで呼び出し部分を作成
PlayGroundを利用することで、APIの振る舞いの確認が簡単にできます。
ただし、ここで実行されるprivate系の処理は実処理なので売買すると実際にも売買されるのでそこだけ注意してください。
PlayGroundでは各種の言語での実装も記載されるのでそれを参考に簡易のAPIラッパーを以下のように作ります。
class BitFlyerAPI
require "net/http"
require "uri"
require "openssl"
require 'json'
def initialize key, secret
@key = key
@secret = secret
end
def call_api(key, secret, method, uri, body="")
timestamp = Time.now.to_i.to_s
text = timestamp + method + uri.request_uri + body
sign = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, text)
options = if method == "GET"
Net::HTTP::Get.new(uri.request_uri, initheader = {
"ACCESS-KEY" => key,
"ACCESS-TIMESTAMP" => timestamp,
"ACCESS-SIGN" => sign,
});
else
Net::HTTP::Post.new(uri.request_uri, initheader = {
"ACCESS-KEY" => key,
"ACCESS-TIMESTAMP" => timestamp,
"ACCESS-SIGN" => sign,
"Content-Type" => "application/json"
});
end
options.body = body if body != ""
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
response = https.request(options)
JSON.parse(response.body)
end
def collatera
uri = URI.parse("https://api.bitflyer.jp")
uri.path = "/v1/me/getcollateral"
call_api(@key, @secret, "GET", uri)
end
def positions(product_code)
uri = URI.parse("https://api.bitflyer.jp")
uri.path = "/v1/me/getpositions"
uri.query = "product_code=" + product_code
call_api(@key, @secret, "GET", uri)
end
def executions(product_code)
uri = URI.parse("https://api.bitflyer.jp")
uri.path = '/v1/executions'
uri.query = 'product_code=FX_BTC_JPY'
call_api(@key, @secret, "GET", uri)
end
def sendparentorder size, buy_price, sell_price, trigger_price
uri = URI.parse("https://api.bitflyer.jp")
uri.path = "/v1/me/sendparentorder"
params = {
"order_method"=>"IFD",
"minute_to_expire"=>10000,
"time_in_force"=>"GTC",
"parameters"=>[
{
"product_code"=>"FX_BTC_JPY",
"condition_type"=>"LIMIT",
"side"=>"BUY",
"price"=>buy_price,
"size"=>size
},
{
"product_code"=>"FX_BTC_JPY",
"condition_type"=>"STOP_LIMIT",
"side"=>"SELL",
"price"=>sell_price,
"trigger_price"=>trigger_price,
"size"=>size
}
]
}
body = JSON.generate(params)
call_api(@key, @secret, "POST", uri, body)
end
end
下記のように利用します。
生のRESTをラッピングして板情報や保証金の状態をハッシュで取り扱える形にしました。
api = BitFlyerAPI.new "APIキー", "秘密鍵"
api.collatera
> {"collateral"=>3088.0, "open_position_pnl"=>0.0, "require_collateral"=>0.0, "keep_rate"=>0.0}
任意の含み益を目標に取引
私が売買する時は大体IDFでどのくらいの含み益を見込んで、許容する損失はどのくらいか?を考えて購入します。
なんで、買いの時の算出式は以下の感じ。これで、何枚のコインをどのくらいで買ってどのくらいで売るかを算出できます。
r = api.collatera
collateral = r["collateral"]
pnl_limit = -500 # 許容損失
target_profit = 10 # 目標利益(円)
size = 0.001 # 購入コイン数
buy_coinprice = api.executions("FX_BTC_JPY").first["price"] # 現在の1ビットコインあたりの買い価格。
buy_price = buy_coinprice * size
sell_price = buy_price + target_profit #
sell_coinprice = (sell_price / size).to_i # 目標利益を出すための1ビットコインあたりの売り価格
trigger_price = buy_price + pnl_limit
trigger_coinprice = (trigger_price / size).to_i # 許容損失に抑えるための売り価格
leverage = 3 #レバレッジ
require_collateral = buy_price / leverage # 必要書庫金
上記で計算した値をハッシュに詰め込んで、以下のようにsendparentorderメソッドでIDFでのLIMIT:BUY, LIMIT-STOP:SELLが注文されます。
この例だと現在の最新の売買価格をつっこんでるので指値だけど成行っぽい振る舞いになります。本来はbuy_coinpriceは任意の値を入れるべきです。
api.sendparentorder data[:size], data[:buy_coinprice], data[:sell_coinprice], data[:trigger_coinprice]
これを実行すると実際にbitFlyer Lightningで注文が出てるのが分かります。簡単ですね!
まとめ
とりあえず完全に「触ってみた」レベルの内容ですが、思っていた以上に簡単にAPIを叩くことが出来ました。
今後は取り急ぎWebUIを付けるのと、BOTなんかを使った自動売買を作っていきたいと思います。
ちなみに、この記事読んでるときに見つけたこのUdemyのコンテンツを購入するほうがより詳細な情報が高速に集まる気はしますが、テーマを決めた以降に気づいたから仕方ないですね!
それでは、Happy Hacking!