前回に引き続き、各取引所のAPIの利用方法を紹介します。今回はZaifです。
前提・条件
開発実行環境は、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 を有効化する方法
Zaif APIの使い方
Zaifは仮想通貨の現物と信用取引で同じ価格板を利用することができます。信用取引ではレバレッジを掛けて資金の数倍の取引を行うことができます。ZaifではAPIを利用すると最大7.77倍まで任意の値でのレバレッジ取引が可能となっています。通常のWebの取引画面では x1 x2.5 x5 x7.77 の4種類のみとなっています。
また、Webの取引画面では注文方法として、「指値」と「成行」のいずれかを選択することができますが、APIを利用した場合、注文方法は指値のみ利用可能となっています。Zaifでも現物取引と信用取引でAPIが共通する部分と異なる部分があるので、現物取引を「Zaif」、信用取引を「ZaifFX」として紹介します。
まずはコードの一覧です。
Function Get-Price($SiteName){
Switch ($SiteName)
{
"bitFlyer"{$Url = "https://api.bitflyer.jp/v1/getboard?product_code=BTC_JPY"}
"bitFlyerFX"{$Url = "https://api.bitflyer.jp/v1/getboard?product_code=FX_BTC_JPY"}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{$Url = "https://api.zaif.jp/api/1/depth/btc_jpy"}
}
$res = Invoke-RestMethod $Url -Method GET
Switch ($SiteName)
{
{($_ -eq "bitFlyer") -Or ($_ -eq "bitFlyerFX")}{
$AskPrice = $res.asks[0].price
$BidPrice = $res.bids[0].price
$AskSize = $res.asks[0].size
$BidSize = $res.bids[0].size
}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{
$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 = $SiteName}
$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")}
$objPs | FT
}
Function Get-Keys($SiteName){
Return (Get-Content (".\Keys.json") -Encoding UTF8 -Raw | ConvertFrom-Json) | Where Site -eq $SiteName
}
Function Get-Header($SiteName, $Query){
$Keys = Get-Keys $SiteName
$APIKey = $Keys.APIKey
$SecretKey = $Keys.SecretKey
Switch ($SiteName)
{
{($_ -eq "bitFlyer") -Or ($_ -eq "bitFlyerFX")}{
$Nonce = ([DateTimeOffset](Get-Date)).ToUnixTimeMilliseconds()
$Query = $Nonce.ToString() + $Query
$KeyData = [System.Text.Encoding]::UTF8.GetBytes($SecretKey)
$QueryData = [System.Text.Encoding]::UTF8.GetBytes($Query)
Add-Type -AssemblyName System.Security
$HMAC = New-Object System.Security.Cryptography.HMACSHA256
$HMAC.Key = $KeyData
$HMACHash = $HMAC.ComputeHash($QueryData)
$Sign = [System.BitConverter]::ToString($HMACHash).ToLower().Replace("-", "")
$Header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Header.Add("ACCESS-KEY", "$APIKey")
$Header.Add("ACCESS-TIMESTAMP", "$Nonce")
$Header.Add("ACCESS-SIGN", "$Sign")
Return $Header
}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{
Add-Type -AssemblyName System.Net.Http
$Content = New-Object System.Net.Http.FormUrlEncodedContent($Query)
$Query = $Content.ReadAsStringAsync().Result
$KeyData = [System.Text.Encoding]::UTF8.GetBytes($SecretKey)
$QueryData = [System.Text.Encoding]::UTF8.GetBytes($Query)
Add-Type -AssemblyName System.Security
$HMAC = New-Object System.Security.Cryptography.HMACSHA512
$HMAC.Key = $KeyData
$HMACHash = $HMAC.ComputeHash($QueryData)
$Sign = [System.BitConverter]::ToString($HMACHash).ToLower().Replace("-", "")
$Header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Header.Add("key", "$APIKey")
$Header.Add("Sign", "$Sign")
Return $Header
}
}
}
Function Get-Asset($SiteName, $AssetName){
Switch ($SiteName){
"bitFlyer"{
$Url ="https://api.bitflyer.jp/v1/me/getbalance"
$Query = "GET/v1/me/getbalance"
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method GET -Headers $Header
$Asset = ($res | Where currency_code -eq "$AssetName").amount
}
"bitFlyerFX"{
$Url ="https://api.bitflyer.jp/v1/me/getcollateral"
$Query = "GET/v1/me/getcollateral"
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method GET -Headers $Header
If($AssetName -eq "jpy"){$Asset = $res.collateral}Else{$Asset = 0}
}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "get_info")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
$Asset = $res.return.funds.($AssetName)
}
}
If($AssetName -eq "jpy"){
Return $Asset.ToString("#,0")
}Else{
Return $Asset.ToString("#,0.00000000")
}
Return $Asset
}
Function Set-Order($SiteName, $Side, $Type, $Price, $Amount){
Switch ($SiteName)
{
"bitFlyer"{
$Url ="https://api.bitflyer.jp/v1/me/sendchildorder"
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("product_code", "BTC_JPY")
$Body.Add("side", $Side.ToUpper())
$Body.Add("child_order_type", $Type.ToUpper())
$Body.Add("price", "$Price")
$Body.Add("size", "$Amount")
$Body = ConvertTo-JSON $Body
$Query = "POST/v1/me/sendchildorder" + $Body
$Header = Get-Header $SiteName $Query
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body -ContentType "application/json"
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
Return $res.child_order_acceptance_id
}
"bitFlyerFX"{
$Url ="https://api.bitflyer.jp/v1/me/sendchildorder"
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("product_code", "FX_BTC_JPY")
$Body.Add("side", $Side.ToUpper())
$Body.Add("child_order_type", $Type.ToUpper())
$Body.Add("price", "$Price")
$Body.Add("size", "$Amount")
$Body = ConvertTo-JSON $Body
$Query = "POST/v1/me/sendchildorder" + $Body
$Header = Get-Header $SiteName $Query
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body -ContentType "application/json"
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
Return $res.child_order_acceptance_id
}
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "trade")
$Body.Add("currency_pair", "btc_jpy")
If($Side -eq "sell"){$Side = "ask"}ElseIf($Side -eq "buy"){$Side = "bid"}
$Body.Add("action", "$Side")
$Body.Add("price", "$Price")
$Body.Add("amount", "$Amount")
$Header = Get-Header $SiteName $Body
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
If($res.success -eq 0){
Write-Host "Oder Error! " $res.error -ForegroundColor Red
Return 0
}Else{
Return 1
}
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "create_position")
$Body.Add("type", "margin")
$Body.Add("currency_pair", "btc_jpy")
If($Side -eq "sell"){$Side = "ask"}ElseIf($Side -eq "buy"){$Side = "bid"}
$Body.Add("action", "$Side")
$Body.Add("price", "$Price")
$Body.Add("amount", "$Amount")
$Body.Add("leverage", "2")
$Header = Get-Header $SiteName $Body
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
If($res.success -eq 0){
Write-Host "Oder Error! " $res.error -ForegroundColor Red
Return 0
}Else{
Return $res.return.leverage_id
}
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
}
}
}
Function Get-Order($SiteName){
Switch ($SiteName)
{
"bitFlyer"{
$Url ="https://api.bitflyer.jp/v1/me/getchildorders?product_code=BTC_JPY&child_order_state=ACTIVE"
$Query = "GET/v1/me/getchildorders?product_code=BTC_JPY&child_order_state=ACTIVE"
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method GET -Headers $Header
}
"bitFlyerFX"{
$Url ="https://api.bitflyer.jp/v1/me/getchildorders?product_code=FX_BTC_JPY&child_order_state=ACTIVE"
$Query = "GET/v1/me/getchildorders?product_code=FX_BTC_JPY&child_order_state=ACTIVE"
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method GET -Headers $Header
}
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "active_orders")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "active_positions")
$Body.Add("type", "margin")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
}
Return $res
}
Function Cancel-Order($SiteName, $OrderID){
Switch ($SiteName)
{
"bitFlyer"{
$Url ="https://api.bitflyer.jp/v1/me/cancelchildorder"
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("product_code", "BTC_JPY")
$Body.Add("child_order_acceptance_id", "$OrderID")
$Body = ConvertTo-JSON $Body
$Query = "POST/v1/me/cancelchildorder" + $Body
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body -ContentType "application/json"
}
"bitFlyerFX"{
$Url ="https://api.bitflyer.jp/v1/me/cancelchildorder"
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("product_code", "FX_BTC_JPY")
$Body.Add("child_order_acceptance_id", "$OrderID")
$Body = ConvertTo-JSON $Body
$Query = "POST/v1/me/cancelchildorder" + $Body
$Header = Get-Header $SiteName $Query
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body -ContentType "application/json"
}
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "cancel_order")
$Body.Add("order_id", "$OrderID")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "cancel_position")
$Body.Add("leverage_id", "$OrderID")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
}
Return $res
}
Function Close-FX($SiteName, $CloseOrderID, $BtcPrice){
Switch ($SiteName)
{
"bitFlyerFX"{
#反対売買を行うことでポジションをクローズ
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$res = Get-Order $SiteName
ForEach($item In $res.return | Get-Member | ? MemberType -eq NoteProperty){
$OrderID =$item.Name
If($CloseOrderID -eq $OrderID){
$Price = $res.return.$OrderID.price
$Amount = $res.return.$OrderID.amount
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "change_position")
$Body.Add("type", "margin")
$Body.Add("leverage_id", "$OrderID")
If($Price -ge $BtcPrice){$Body.Add("limit", "$BtcPrice")}Else{$Body.Add("stop", "$BtcPrice")}
$Header = Get-Header Zaif $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
}
}
}
Return $res
}
#取引所 (bitFlyer, bitFlyerFX, Zaif, ZaifFX)
$SiteName = "Zaif"
#資産 (jpy, btc)
$AssetName = "jpy"
#売買 (sell, buy)
$Side = "buy"
#指値・成行 (limit, market)
$Type = "limit"
#価格
$Price = 700000
#注文量 (bitFlyer>0.001, Zaif>0.0001)
$Amount = 0.001
#ビットコイン価格
$BtcPrice = 700000
#価格情報
#Get-Price $SiteName
#資産情報
#Get-Asset $SiteName $AssetName
#売買注文
#$OrderID = Set-Order $SiteName $Side $Type $Price $Amount
#注文情報
#Get-Order $SiteName
#注文取消し
#Cancel-Order $SiteName $OrderID
#FXポジションクローズ
#Close-FX $SiteName $OrderID $BtcPrice
価格情報の取得:Get-Price
Function Get-Price($SiteName){
Switch ($SiteName)
{
"bitFlyer"{$Url = "https://api.bitflyer.jp/v1/getboard?product_code=BTC_JPY"}
"bitFlyerFX"{$Url = "https://api.bitflyer.jp/v1/getboard?product_code=FX_BTC_JPY"}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{$Url = "https://api.zaif.jp/api/1/depth/btc_jpy"}
}
$res = Invoke-RestMethod $Url -Method GET
Switch ($SiteName)
{
{($_ -eq "bitFlyer") -Or ($_ -eq "bitFlyerFX")}{
$AskPrice = $res.asks[0].price
$BidPrice = $res.bids[0].price
$AskSize = $res.asks[0].size
$BidSize = $res.bids[0].size
}
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{
$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 = $SiteName}
$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")}
$objPs | FT
}
Public APIを使ってまずは板情報から売値(Ask)と買値(Bid)を取得してみましょう。Zaifの場合はhttps://api.zaif.jp/api/1/depth/btc_jpyこのURLからGetメソッドで直接ビットコインの価格情報が取得可能です。他の仮想通貨の場合はhttps://api.zaif.jp/api/1/depth/mona_jpyのように通過ペアを変更するだけです。
8: Invoke-RestMethodの単純なGetメソッドなので、組み立てたURLを直接ブラウザで参照してもjson形式板情報を参照することができます。24-30: PSCustomObjectに売値の最安値と買値の最高値の情報を格納してテーブル形式で表示しています。
Get-Price "Zaif"Name AskPrice AskSize BidPrice BidSize---- -------- ------- -------- -------Zaif 840175.0 0.35660 840100.0 0.11150
API KeyとSecret Keyの取得:Get-Keys
Private APIを利用するための「API Key」と「Secret Key」を取得します。Web取引画面の「アカウント」-「開発者向けAPI」を選択します。https://zaif.jp/api_keysこちらからAPIキーとシークレットキーを作成、取得します。
APIキーの取得
Function Get-Keys($SiteName){
Return (Get-Content (".\Keys.json") -Encoding UTF8 -Raw | ConvertFrom-Json) | Where Site -eq $SiteName
}
キーを直接コード内に記述するのは避けたいので、Keys.jsonファイルとして別途保存しておきます。ZaifとZaifFXは、キー自体は同じものが利用できるので同様のキーを保存しておきます。
[ { "SiteName": "bitFlyer", "APIKey": "取得したAPIキー", "SecretKey": "取得したシークレットキー" }, { "SiteName": "bitFlyerFX", "APIKey": "取得したAPIキー", "SecretKey": "取得したシークレットキー" }, { "SiteName": "Zaif", "APIKey": "取得したAPIキー", "SecretKey": "取得したシークレットキー" }, { "SiteName": "ZaifFX", "APIKey": "取得したAPIキー", "SecretKey": "取得したシークレットキー" }]
(Keys.json)
Header情報の作成:Get-Header
取得したキーを使ってAPIの認証を行うためには、Invoke-RestMethodコマンドにHeaderとして認証情報を作成して渡す必要があります。Zaifの場合は必要な情報を文字列として連結して、SHA512ハッシュ関数を使ってシークレットキーで署名したものが認証に必要な情報となります。難しい話は読み飛ばしてもコードをそのまま再利用すれば使えるものを紹介します。
必要なHeader情報
項目値keyAPIキーsign署名値 ※1
※1:クエリー値(Nonce、メソッド、パラメーター等)を文字列として連結してシークレットキーを使ってSHA512ハッシュ関数で署名したもの。
{($_ -eq "Zaif") -Or ($_ -eq "ZaifFX")}{
Add-Type -AssemblyName System.Net.Http
$Content = New-Object System.Net.Http.FormUrlEncodedContent($Query)
$Query = $Content.ReadAsStringAsync().Result
$KeyData = [System.Text.Encoding]::UTF8.GetBytes($SecretKey)
$QueryData = [System.Text.Encoding]::UTF8.GetBytes($Query)
Add-Type -AssemblyName System.Security
$HMAC = New-Object System.Security.Cryptography.HMACSHA512
$HMAC.Key = $KeyData
$HMACHash = $HMAC.ComputeHash($QueryData)
$Sign = [System.BitConverter]::ToString($HMACHash).ToLower().Replace("-", "")
$Header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Header.Add("key", "$APIKey")
$Header.Add("Sign", "$Sign")
Return $Header
}
作成したGet-KeysコマンドでAPIキーを読み込みます。1: ZaifとZaifFXではHeader情報は同じものを利用できます。2-10: Queryとして渡されたデータをシークレットキーを使ってハッシュ関数で署名します。11: ハイフンを省いた文字列として取得します。12-15: Header情報を作成します。
売買注文:Set-Order
売買注文はInvoke-RestMethodコマンドのPostメソッドで発注することができます。このときHeader情報に認証データ、Bodyに注文内容と、合わせて送信することになります。ZaifとZaifFXではAPIのエンドポイントが異なります。また、Zaifでは現物、信用取引ともにすべて指値注文のみとなります。
まずは現物取引です。
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "trade")
$Body.Add("currency_pair", "btc_jpy")
If($Side -eq "sell"){$Side = "ask"}ElseIf($Side -eq "buy"){$Side = "bid"}
$Body.Add("action", "$Side")
$Body.Add("price", "$Price")
$Body.Add("amount", "$Amount")
$Header = Get-Header $SiteName $Body
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
If($res.success -eq 0){
Write-Host "Oder Error! " $res.error -ForegroundColor Red
Return 0
}Else{
Return 1
}
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
}
2: 現物取引のエンドポイントはhttps://api.zaif.jp/tapiとなります。6: methodとしてtradeを指定します。8:売り注文の場合は”Ask”、買い注文の場合は”bid”となります。11: 最小注文単位は0.0001btcとなります。13-24: ZaifのAPIでは取引注文が集中するとAPIエラーが頻繁に発生するため、エラー処理Try~Catchで行います。15-17: 注文がエラーとなると、”success”のプロパティ値が0となるので、この場合エラーメッセージを表示して戻り値を0としています。19: 現物取引の場合、注文が成功するとOrderIDは全て0となってしまうので、注文成功したという意味で1を戻り値とします。22-23: その他エラーとなった場合もエラーメッセージを表示して戻り値を0とします。
Set-Order "Zaif" "buy" "limit" "700000" "0.001"1
次に信用取引です。
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "create_position")
$Body.Add("type", "margin")
$Body.Add("currency_pair", "btc_jpy")
If($Side -eq "sell"){$Side = "ask"}ElseIf($Side -eq "buy"){$Side = "bid"}
$Body.Add("action", "$Side")
$Body.Add("price", "$Price")
$Body.Add("amount", "$Amount")
$Body.Add("leverage", "2")
$Header = Get-Header $SiteName $Body
Try{
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
If($res.success -eq 0){
Write-Host "Oder Error! " $res.error -ForegroundColor Red
Return 0
}Else{
Return $res.return.leverage_id
}
}Catch{
Write-Host "Oder Error! " $_.ErrorDetails.Message -ForegroundColor Red
Return 0
}
}
2: 信用取引のエンドポイントはhttps://api.zaif.jp/tlapiとなります。6: methodとしてcreate_positionを指定します。7: typeとしてmarginを指定します。9: 売り注文の場合は”Ask”、買い注文の場合は”bid”となります。12: 最小注文単位は0.0001btcとなります。13: bitFlyerFXではレバレッジはWebの取引ツールから指定しましたが、ZaifFXの場合は注文時に指定します。0.01単位で1~7.77倍まで指定することが可能です。15-26: エラー処理Try~Catchで行います。17-19: 注文がエラーとなると、”success”のプロパティ値が0となるので、この場合エラーメッセージを表示して戻り値を0としています。21: 信用取引の場合、注文が成功するとOrderIDが取得できるので、戻り値とします。24-25: その他エラーとなった場合もエラーメッセージを表示して戻り値を0とします。
Set-Order "ZaifFX" "sell" "limit" "700000" "0.001"12345678
注文の確認:Get-Order
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "active_orders")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "active_positions")
$Body.Add("type", "margin")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
6: 現在有効となっている注文一覧を取得します。8: すべての注文情報がjson形式のデータとして確認できます。15: 現在オープンしている信用取引の注文一覧を取得します。18: すべての注文情報がjson形式のデータとして確認できます。
注文のキャンセル:Cancel-Order
"Zaif"{
$Url = "https://api.zaif.jp/tapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "cancel_order")
$Body.Add("order_id", "$OrderID")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "cancel_position")
$Body.Add("leverage_id", "$OrderID")
$Header = Get-Header $SiteName $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
現物取引の場合、注文時にオーダーIDが確認できないので、Get-Orderコマンドで取引注文IDを確認した後キャンセル時に指定します。
Cancel-Order "ZaifFX" 12345678
信用取引のポジションクローズ:Close-FX
bitFlyerFXではポジションの解消は反対売買を行うことで完了しましたが、Zaifの信用取引の場合は、オープンしているポジションにクローズ条件を追加して完了します。現在オープンしている注文のリミット注文価格、もしくはストップ注文価格を設定し、その価格に現在のビットコイン価格が達することでポジションクローズとなります。リミット注文価格は売り、もしくは買いの注文で利益となる方向のビットコイン価格、ストップ注文価格は損益となる方向のビットコイン価格となります。
Function Close-FX($SiteName, $CloseOrderID, $BtcPrice){
Switch ($SiteName)
{
"bitFlyerFX"{
#反対売買を行うことでポジションをクローズ
}
"ZaifFX"{
$Url = "https://api.zaif.jp/tlapi"
$res = Get-Order $SiteName
ForEach($item In $res.return | Get-Member | ? MemberType -eq NoteProperty){
$OrderID =$item.Name
If($CloseOrderID -eq $OrderID){
$Price = $res.return.$OrderID.price
$Amount = $res.return.$OrderID.amount
$Nonce = ([System.DateTime]::UtcNow - (Get-Date("1970, 1, 1"))).TotalSeconds
$Body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Body.Add("nonce", "$Nonce")
$Body.Add("method", "change_position")
$Body.Add("type", "margin")
$Body.Add("leverage_id", "$OrderID")
If($Price -ge $BtcPrice){$Body.Add("limit", "$BtcPrice")}Else{$Body.Add("stop", "$BtcPrice")}
$Header = Get-Header Zaif $Body
$res = Invoke-RestMethod $Url -Method POST -Headers $Header -Body $Body
}
}
}
}
Return $res
}
9:Get-Orderコマンドでオープンしている注文一覧を取得します。10-12:クローズする注文IDと一致する場合クローズ条件を追加します。18: methodとしてchange_positionを指定し、注文情報を変更します。21: リミット注文価格とストップ注文価格を設定することでポジションをクローズします。現在のビットコイン価格を指定することで即時クローズとなります。※ビットコイン価格は常に変動しているため、必ずしも指定した価格でクローズするとは限りません。また、クローズできない場合もあります。
コマンドサンプル
以降は作成した各コマンドのサンプルとなります。
#取引所 (bitFlyer, bitFlyerFX)
$SiteName = "bitFlyer"
#資産 (jpy, btc)
$AssetName = "jpy"
#売買 (sell, buy)
$Side = "buy"
#指値・成行 (limit, market)
$Type = "limit"
#価格
$Price = 700000
#注文量 (>0.001)
$Amount = 0.001
#価格情報
#Get-Price $SiteName
#資産情報
#Get-Asset $SiteName $AssetName
#売買注文
#$OrderID = Set-Order $SiteName $Side $Type $Price $Amount
#注文情報
#Get-Order $SiteName
#注文取消し
#Cancel-Order $SiteName $OrderID
以上がbitFlyerの基本的なAPIの利用方法となります。この他にもAPIを利用して様々な情報の取得や、取引管理などが可能となっています。これらのサンプルコードについても必要となる折にその都度追加していく予定です。参考:Zaif(https://zaif.jp/)APIリファレンス(https://corp.zaif.jp/api-docs/)