一時は200万円以上の値段を付けたビットコインに代表される仮想通貨ブーム。様々な事件、出来事が起きた中でも今なお市場は活況です。そんな仮想通貨の世界でも、ほんの少しプログラムが書ける人が楽をできる時代となっています。いわゆる、仮想通貨のシステムトレードです。株式、FXなどでは当たり前のように行われているシステムトレードは、仮想通貨の世界においても有効な取引手段となっています。システムトレードといっても、必ずしもすべて自動的にトレードを重ねて利益を積み上げていくということだけではなく、トレードの判断となる情報をシステマチックに収集して分析を行い、トレードを優位に進めるための手助けになることもシステムトレードと考えています。この連載では、自動取引、いわゆるbotを作ることだけでなく、テクニカル分析の元となる材料や様々な情報の集め方も紹介していく予定です。仮想通貨のシステムトレードでは、Pythonという言語が主流になりつつありますが、長年Windows使いとして生業を立ててきた身としては、あえてWindowsに標準搭載されているPowerShellで仮想通貨のシステムトレードを実現するべく、いざチャレンジします!
前提・条件
開発実行環境は、24時間システムを稼働することも考慮し、「お名前.comデスクトップクラウド」の仮想マシンを使って作成~稼働まで行っています。PowerShellの基本的な文法、使い方については解説を省略しています。APIを公開している仮想通貨取引所の口座開設が完了しているものとします。口座開設方法については省略しています。システムトレードを行うことによって必ずしも利益が出るという保証はありません。.NET Framework で TLS1.1 および 1.2 を有効化する
PowerShellで使用される暗号化プロトコルは以下で確認することができます。
[Net.ServicePointManager]::SecurityProtocolSsl3, Tls
既定ではSSL3、TLS(1.0)が利用可能となっています。しかし最近では暗号化プロトコルにTLS 1.2を必須とするサイトが増えてきており、仮想通貨取引所のAPIも同様となっています。既定の設定では.NET Frameworkを利用しているInvoke-WebRequestコマンドを実行するとエラーとなる場合があります。Invoke-WebRequestコマンドでTLS 1.2を利用するようにあらかじめ設定をしておきましょう。
1つ目の方法としてはInvoke-WebRequestコマンドを呼び出す前にTLS 1.2で通信することを明記します。こちらはスクリプト毎にその都度明記する必要があります。
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body -ContentType "application/json"
もう1つの方法としては、以下のコマンドを実行して、レジストリでTLS 1.2で通信を既定値として設定しておきます。
Set-ItemProperty -Path HKLM:\\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 -Name SchUseStrongCrypto -Value 1"
いずれかの対策を事前に行うことで、Invoke-WebRequestコマンドでAPIを利用する場合のエラーを回避することが可能です。
参考:.NET Framework で TLS1.1 および 1.2 を有効化する方法
PowerShellで開発を行うことの利点
PowerShellはWindowsに標準で搭載されているシェル&開発言語で、PowerShell ISEというエディタツールもあらかじめインストールされているので手軽に開発を始めることができます。特別に開発環境を整える必要はなく、今回は「お名前.comデスクトップクラウド」のPowerShell ISEを利用して開発を進めていきます。
基本的に各取引所はREST(REpresentational State Transfer)形式のWebサービスとしてAPIを公開しています。REST APIではJSON形式のテキストデータをやりとりすることで情報を送受信する仕様となっています。PowerShellでは、文字列としてのJSON形式のデータを自動的にPSCustomObjectとし読み込んで取り扱うことのできる便利な機能が用意されています。オブジェクトとして扱えることで、変数に格納したり、汎用的なPowerShellのコマンドをそのまま再利用することも可能となるので、開発効率が格段にアップします。
デスクトップクラウド上でPowerShell ISEを使って開発開始
前置きはこのくらいとして、まずはAPIを利用したサンプルを紹介しましょう。各取引所のビットコインの板情報を取得して最新の売買値情報を表示しています。
Function Get-Prices(){
$Sites = @()
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "BTCBOX"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://www.btcbox.co.jp/api/v1/depth/"}
$Sites += $objPs
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "bitbank"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://public.bitbank.cc/btc_jpy/depth"}
$Sites += $objPs
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "bitFlyer"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://api.bitflyer.jp/v1/ticker"}
$Sites += $objPs
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "FISCO"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://api.fcce.jp/api/1/depth/btc_jpy"}
$Sites += $objPs
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "QUOINE"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://api.quoine.com/products/5/price_levels"}
$Sites += $objPs
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = "Zaif"}
$objPs | Add-Member -NotePropertyMembers @{TickerUrl = "https://api.zaif.jp/api/1/depth/btc_jpy"}
$Sites += $objPs
$Prices = @()
ForEach($Site In $Sites){
$SiteName = $Site.Name
$res = Invoke-RestMethod $Site.TickerUrl -Method GET
[int]$AskPrice = 0
[int]$BidPrice = 0
[double]$AskSize = 0
[double]$BidSize = 0
Switch ($SiteName)
{
"BTCBOX" {
$AskPrice = $res.asks[$res.asks.Count-1][0]
$BidPrice = $res.bids[0][0]
$AskSize = $res.asks[$res.asks.Count-1][1]
$BidSize = $res.bids[0][1]
}
"bitbank" {
$AskPrice = $res.data.asks[0][0]
$BidPrice = $res.data.bids[0][0]
$AskSize = $res.data.asks[0][1]
$BidSize = $res.data.bids[0][1]
}
"bitFlyer" {
$AskPrice = $res.best_ask
$BidPrice = $res.best_bid
$AskSize = $res.best_ask_size
$BidSize = $res.best_bid_size
}
"FISCO" {
$AskPrice = $res.asks[0][0]
$BidPrice = $res.bids[0][0]
$AskSize = $res.asks[0][1]
$BidSize = $res.bids[0][1]
}
"QUOINE" {
$AskPrice = $res.sell_price_levels[0][0]
$BidPrice = $res.buy_price_levels[0][0]
$AskSize = $res.sell_price_levels[0][1]
$BidSize = $res.buy_price_levels[0][1]
}
"Zaif" {
$AskPrice = $res.asks[0][0]
$BidPrice = $res.bids[0][0]
$AskSize = $res.asks[0][1]
$BidSize = $res.bids[0][1]
}
}
$objPs = New-Object PSCustomObject
$objPs | Add-Member -NotePropertyMembers @{Name = $Site.Name}
$objPs | Add-Member -NotePropertyMembers @{AskPrice = $AskPrice}
$objPs | Add-Member -NotePropertyMembers @{AskSize = $AskSize.ToString("0.00000")}
$objPs | Add-Member -NotePropertyMembers @{BidPrice = $BidPrice}
$objPs | Add-Member -NotePropertyMembers @{BidSize = $BidSize.ToString("0.00000")}
$Prices += $objPs
}
$Prices | FT
}
結果
PS > Sample_01.ps1Name AskPrice AskSize BidPrice BidSize---- -------- ------- -------- -------BTCBOX 812522 4.72090 811820 0.05000bitbank 816179 0.00710 816023 0.03530bitFlyer 814320 0.37000 813521 0.10000FISCO 814660 0.00490 814620 0.22000QUOINE 815300 0.04000 814594 0.01196Zaif 814660 0.00490 814620 0.22000
取引所ごとの細かい仕様は後述することとして、ここではポイントとなる部分を解説しておきます。
41: $res = Invoke-RestMethod $Site.TickerUrl -Method GET
各取引所のREST APIからInvoke-RestMethodコマンドの「GET」メソッドで情報を取得しています。この行の直後にブレークポイントを設定して、変数$resに格納されているデータをGetTypeコマンドで確認してみましょう。APIから取得した情報がPSCustomObjectとして格納されているのが確認できます。
PS > Sample_01.ps1ヒット 'Sample_01.ps1:43' の行のブレークポイント[DBG]: PS >> $res.GetType()IsPublic IsSerial Name BaseType-------- -------- ---- --------True False PSCustomObject System.Object
さらに変数$resの中身を確認してみると、asksとbidsの要素に分かれて値が確認できます。
[DBG]: PS >> $resasks bids---- ----{19999999 2.982, 14700000 0.05, 9580530 0.004, 8374208 0.005...} {798380 0.0...
要素名として$res.asksを指定することで、配列として格納されたビットコインの価格と注文量が確認できます。
[DBG]: PS >> $res.asks199999992.982147000000.0595805300.00483742080.00550000000.14600000242000001.5
取引所ごとに要素名は異なる部分もありますが、ほぼ同様の仕様で最新の板情報を取得することができるようになっています。PSCustomObjectとして取り扱えるので、要素名としてask値(売値)、bid値(買値)、注文量をテーブル形式で表示することも簡単に行うことができます。
仮想通貨取引の基本としては、安く買って高く売ることで利益を出すことが目的となります。同じ数量のビットコインを購入するにしても、どの取引所を選択するかによってタイミング次第では数万円の価格差が発生している場合もあります。このサンプルで取得した各取引所のビットコインの板情報は、裁定取引と呼ばれる価格差を利用して利益を出すことのできるトレード手法の重要な情報となります。売買を自動化するだけなく、このような価格情報や取引情報などをAPIを利用して情報収集し、データとして蓄積することもシステムトレードを構成する一つの重要な要素となります。PowerShellを利用することでこれらのデータをデータベースに蓄積し、普段使い慣れたExcelに読み込んで分析するといったことも簡単にできるようになります。Windowsに標準で搭載されている言語ということで、Microsoft Office製品や他のシステム製品と連携がしやすいといった点もPowerShellを利用することの利点となります。
APIを公開している国内仮想通貨取引所
システマチックに仮想通貨の取引を行うには、仮想通貨取引所が公開しているAPI(Application Programming Interface)を利用することになります。取引量の多い海外の取引所もAPIを公開しているところが数多くありますので、システムトレードを進めていく過程ではいずれ選択肢の一つになるものと考えられますが、使い方やサポートを考慮し、まずは日本国内の仮想通貨取引所を選択してシステムトレードを始めてみましょう。システムトレードを行う上で注意しなければいけないのが、仮想通貨の売買にともなう手数料です。取引所や売買する仮想通貨、現物取引かFXなのかなどによって手数料は異なります。一度の取引で大きな利益を得られる場合はそれほど気になることもありませんが、取引を繰り返して小さな利益を積み上げていくような場合は、取引手数料を十分考慮しておく必要があります。国内においてAPIを公開している金融庁登録事業者の取引所は以下となります。APIのリファレンスと取引手数料のページも併せて記載してあります。取引所ごとにアップデートが時々ありますのでチェックしておきましょう。※BITPointはAPI経由の取引はサポート対象外となるため除外しています。
APIを公開している日本国内の金融庁登録事業者
BTCBOXWebサイトAPIリファレンス手数料bitbankWebサイトAPIリファレンス手数料bitFlyerWebサイトAPIリファレンス手数料FISCOWebサイトAPIリファレンス-QUOINEXWebサイトAPIリファレンス手数料ZaifWebサイトAPIリファレンス手数料
APIの種類
取引所ごとに名称は異なりますが、APIの種類は大きく分けて2つあります。1つはアカウントの認証を必要とせず一般的に公開されている「Public API」、もう1つは取引所のアカウントに関連付けられた「Private API」です。「Public API」は主に、仮想通貨ごとの相場情報や価格情報などを取引所のアカウントの有無に関わらず取得することが可能です。「Private API」はユーザーの資産状況、注文状況を取得することが可能です。また、売買の注文も「Private API」を利用することになります。
APIの種類用途Public API仮想通貨の相場情報や価格取得。誰でも利用可能。Private API資産状況や注文状況を取得。売買の注文を行う。アカウント保有者のみ利用可能。
APIを利用することで、短時間に取引を何度も繰り返したり、独自のルールに基づいて売買を24時間自動的に行うなど、人の手では通常行えないような取引が可能となります。ただし、各取引所によってAPIのパフォーマンスにばらつきがあり、ある取引所では1分間に100回以上の注文を出せる一方で、ある取引所では市場が過熱状態となるとAPIからの注文がなかなか成立しないといった事も多々あります。システムによる取引とはいっても、取引所ごとのAPIのクセや特色がかなり影響してくるのもシステムトレードを行う上では考慮しておく必要があります。自身のトレードスタイルに最適な取引所を選択し、そこにマッチしたシステムを作成してトレードを進めていくことが重要となります。
次回以降、各取引所の主要なAPI機能を、サンプルを使いながら解説していきます。APIの使い方がある程度分かってきたところで、様々なシステムトレードのスタイルやロジックなどを紹介し、それをどのようにPowerShellのコードに落とし込んでいくか、というところまで解説する予定です。
仮想通貨のシステムトレードでなかなかPowerShellのサンプルコードが少ない中、少しでも同じ志の方々のお役に立てれば幸いです。