まず初めに、この記事はある程度VBAができる人向けに書いています。
ある程度VBAができる人にとっても、トレーディングBOTを作るというのは難易度が高い……というより、普段やらない特殊な処理が多くなっています。
この記事ではこの手の特殊な処理についてだけ扱います。具体期には下記の通りです。
※「そもそもVBAって何?」って人には過去に「LifeGameを作ろう!」っていう連載記事を書いたことがあるのでこちらをどうぞ ⇒ エクセルVBA入門(エクセルでLifeGameを作る)
そんなワケで、この記事に書いていないことのリストに書いてあることくらいは大体できる人を対象とした記事となっています。
さて具体的な話に移る前に……「御託はいいから、さっさとbasファイルをよこせや!」って方はこちらからどうぞw ⇒ bittrex_connect.txt
※セキュリティの都合上、拡張子はtxtになっていますが、そのままbasに直してインポートすれば使えます。
さて、コードを書き始める前に、下準備として、Bittrexからapi_keyとapi_secretというのを取得しておく必要があります。
まずはBittrexにログインしてください。で、まず右上のメニューの「setting」をクリックしましょう。
次に「API Keys」をクリックし、「API Key」の管理画面を表示します。
管理画面ではまず、「Add New Key」をクリックし、APIの権限を設定し、2段階認証のキーを入れ、「Update Keys」をクリックします。
ここで注意が必要なのは権限の部分です。単純に資産を表示妻帯だけであれば「READ INFO」だけを「ON」にしておけば良いでしょう。
加えて、一般的なトレーディングボットを作成するのであれば、「TRADE LIMIT」「TRADE MARKET」も「ON」にします。
「WITHDRAW」を「ON」にすると、送金までできるようになってしまうので、使うことはあまりお勧めしませんが、アービトラージ系のトレーディングボットを作成するのであれば、ここにも「ON」にする必要があります。
すると、api_keyとapi_secretが表示されるので、どこかにコピペして保管しておいてください。
ちなみにapi_secretは今後、表示されなくなってしまいますので、必ずここで保管するようにしてください。
これで下準備は完了です。ではコーディングに移ります。まずはBittrexの公式サイトにあるサンプルコードを見てみましょう。
$apisecret=’xxx’;
$nonce=time();
$uri=’https://bittrex.com/api/v1.1/market/getopenorders?apikey=’.$apikey.’&nonce=’.$nonce;
$sign=hash_hmac(‘sha512’,$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(‘apisign:’.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);
PHPでは変数の前に必ず$を付けるというルールがあります。また、文字列をつなぐときには「.」を使うというルールがあります。そこまで分かると、このコードの内容もざっくり分かるのではないでしょうか。
これを単純にVBAに置き換えていけばよいワケです。
ざっくりと解説しておくと……
Bittrexへの命令の部分となります。この文の場合、重要なのは「market/getopenorders?」の部分です。この部分が命令となっており、前後は接頭語・接尾語くらいに思ってもらえれば良いと思います。
この例では引数の渡し方が分かりにくいので、ちょっと別の例を出します。例えば、1ETHあたり0.1BTCの価格で、10ETH買いたい場合の命令文は「market/buylimit?market=BTC-ETH&quantity=10&rate=0.1」となります。
今回紹介するコードでは接尾語・接頭語部分は自動入力とし、この部分だけ引数として渡せば、処理ができるものを作ります。
なお、命令文の一覧は過去に記事を書いているので、そちらを参考にしてもらえれば良いかと思います。 ⇒ BittrexAPIの命令文一覧
きっと実際のBOTを作成する際にはこの一覧ページを参照しながら作ることになると思います。
BittrexのAPIでは、命令の整合性を取るために暗号化による署名での確認を行っています。このため、署名を作成するためのコードが必要となります。
普段、VBAで暗号系のライブラリを使うことってまずないですよね(^^;
作りましたので、使ってください。
ここで、実際に命令文を送信しています。WEB系ではお馴染みですが「httpリクエスト送る」といった言い方をします。
本当を言うと、インターネットエクスプローラーを介してやる方法がお手軽で有名です。これが出来ると、結構面白いものが色々作れるので、それ専門の本なんかも出ています。(⇒Excel VBAでIEを思いのままに操作できるプログラミング術)
ただし、今回は速度を重視してIEを使わずにhttpリクエストを送ります。
では、コーディングに移りましょう♪
さて、実際のコーディングを始める前に、この3つは定数にしてしまいます。
これは、先ほど取得したapi_keyとapi_secretと命令文の先頭の文字列です。
Public Const BITTREX_API_SECRET As String = “76e7ded647c9415e809ac93e22baf6c6”
Public Const BITTREX_API_PREFIX As String = “https://bittrex.com/api/v1.1/”
「System.Security.Cryptography.HMACSHA512」というオブジェクトを使います。
上で紹介したPHPのコードのではhash_hmacという関数では3つの引数を取れる形でしたが、今回はSHA512しか使わないので、uriとapikeyの2つの引数だけを取るようにします。
Dim keyArray(64) As Byte
Dim i As Long
Dim text As Object
Dim SHA512 As Object
Dim xml As Object
On Error Resume Next
For i = 0 To 63
keyArray(i) = Asc(Mid(apikey, i + 1, 1))
Next
On Error GoTo 0
Set text = CreateObject(“System.Text.UTF8Encoding”)
Set SHA512 = CreateObject(“System.Security.Cryptography.HMACSHA512”)
Set xml = CreateObject(“MSXML2.DOMDocument”)
SHA512.key = keyArray()
xml.loadXML “<root />”
xml.DocumentElement.DataType = “bin.Hex”
xml.DocumentElement.nodeTypedValue = SHA512.ComputeHash_2((text.GetBytes_4(uri)))
hashHmacSHA512 = Replace(xml.DocumentElement.text, vbLf, “”)
End Function
なにげにこのあたりのライブラリにはSHA256に関するものもあって……やりようによってはマイニングもできるのかもしれませんねw
エクセルでマイニングとか……ネタ的には面白いですよねwもしかしたら、そのうちやるかもしれないですw
どう作るか悩みどころでしたが、今回は命令文「例)market/buylimit?market=BTC-ETH&quantity=10&rate=0.1」をそのまま文字列の引数として受け取る関数にしました。
命令内容ごとに命令文を組み立てる関数を作った方が便利だとは思います……「marketBuylimit(“BTC-ETH”, 10, 0.1)」って感じで呼び出せる関数を作ると便利ですよね。
が、BittrexのAPIをすべて網羅するのは面倒なので、止めておきますw
On Error GoTo Err_sendCommand
Dim uri As String
Dim con As String
con = IIf(InStr(command, “?”) > 0, “&”, “?”)
uri = BITTREX_API_PREFIX & command & con & “apikey=” & BITTREX_API_KEY & “&nonce=” & CDbl(Now())
Dim oXmlHttp As Object
Set oXmlHttp = CreateObject(“MSXML2.XMLHTTP”)
oXmlHttp.Open “POST”, uri, False
oXmlHttp.setRequestHeader “Content-Type”, “application/x-www-form-urlencoded”
oXmlHttp.setRequestHeader “apisign”, hashHmacSHA512(uri, BITTREX_API_SECRET)
oXmlHttp.send (uri)
sendCommand = oXmlHttp.responseText
Exit Function
Err_sendCommand:
sendCommand = “False”
End Function
さて、上記の関数を実際に実行してみると、下記のような形のデータが返ってきます。WEB系ではお馴染みのjsonというデータの形式です。
{“success”:true,”message”:””,”result”:{“Currency”:”BTC”,”Balance”:0.00000201,”Available”:0.00000201,”Pending”:0.00000000,”CryptoAddress”:”19yqy7UKPDF9juXSUbPREfxwD5Y9ruXD8T”}}
LeftやMidやInStrやらを駆使して分けても良いのですが、「ScriptControl」を使うと比較的簡単に利用することができるので、今回はそれを使います。
ただし、現状(2018年02月24日)の段階では64bit版のOfficeでは使えないようです。OSは64bit版でも大丈夫なのですが、Officeはまだ32bit版の方がいろいろ有利みたいですね。
少数派だとは思いますが、64bit版のOfficeをご利用の方はLeftやMidやInStrやらを駆使してください。
On Error Resume Next
Dim objSC As Object
Dim strFunc As String
Set objSC = CreateObject(“ScriptControl”)
objSC.Language = “JScript”
strFunc = “function jsonParse(s) { return eval(‘(‘ + s + ‘)’); }”
objSC.AddCode strFunc
Set jsonParse = objSC.CodeObject.jsonParse(strJSON)
End Function
さて、これだけでは使い勝手が悪いので、すぐに中身が取れる関数を2つ用意しておきます。
まずはエラー確認の関数です。json形式の文字列を引数として渡すことで、エラーがなければ「True」が返ってきます。
Dim json As Object
Set json = jsonParse(jsonString)
getSuccess = CBool(CallByName(json, “success”, VbGet))
End Function
次に結果を取り出す関数です。keyを引数として渡すことで値が返ってきます。どのコマンドでどの値が返ってくるかというようなことは、以前紹介したBittrexのAPIについての詳細記事を見てください。 ⇒ BittrexAPIの命令文一覧
最後に簡単な実装例ですが、大体下記の感じで使用してもらえれば……と思います。
j = sendCommand(“account/getbalance?currency=BTC”)
If getSuccess(j) Then
getResult(j, “Available”)
End If
このコードは自由にコピペして持って行ってもらって構いませんが……
実際に儲かるプログラムができた際には僕にも下さい!!!