仮想通貨の自動売買API開発 使用言語と方向性
目次/もくじ
公開:2017/6/21
今ならAPIの仕様の改良により、
CoinCheck、ZAIF、bitFlyer、POLONIEXの現物取引、信用取引のアービトラージ、スキャルピング、コピートレードシステムなどが作れると思いますが、基本的にはアービトラージの開発を想定しています。
それぞれの取引所で仕様やプログラミングがまったく変わってくるので、アービトラージをやるなら2社以上のAPIの理解が必要です。スキャルピングだけであれば一社をマスターすればOKです。
前提としては、
・トレードの知識がある(成行注文、指値注文、現物、信用、約定拒否、スリップ、板などが分かる)
・PHPが分かる(連想配列、変数、関数などの基本)
方を想定しています。
「WEB API? JSON? Hash? 何それおいしいの?」という方は安心してください。何とかなると思います。
仮想通貨の自動売買プログラムを書く前に、そもそもどうやってプログラムと取引を連動させるのか、という問題があります。
その問題は知っているか知らないかだけの話で、最近のイケてるWEBサービスはWeb APIというものを出しています。これを使えば、そのWEBサービスの機能を一部間借りすることができます。
基本的に出力はJSONで吐き出されますが、簡単に言えばRSSやXMLのようなやつで、何かのリクエストに対して特定の形式でレスポンスを返してくれます。
JavaScriptが一番相性がいいらしいですが、基本的にはどの言語でもいじりやすいようなフォーマットとして新しく登場しました。
JSONを処理する言語としては、個人的にはPHPが一番慣れているので、(Javascriptは何となくいけ好かないので)、PHPでWEB APIを触ってみようと思います。
さて、
コインチェックのWEB APIにはPUBLIC APIとPRIVATE APIというものがあります。その名の通り、PUBLICの方は、現在のレートや最新の約定情報などで、PRIVATEの方は、自分の残高や実際の取引などを扱えます。
コインチェックのドキュメントを見ると、サンプルのような例のようなものがあるのですが、
https://coincheck.com/ja/documents/exchange/api
PHP単体で完結できるようには書いてありません。
PHPのサンプルはなぜかハッシュを生成するところで終わっていて、
HTTPのリクエストのPHPのサンプルは掲載されていません。(「それぐらいエンジニアならできるでしょ?」ってことなのかな)
そこで、「コインチェック API サンプル」とかで検索する人が多いと思いますが、GithubにPHPのコインチェック専用ライブラリ(オブジェクト指向)があります。しかし、これもところどころ不備があって、正常に動きません。
というわけで、仕方なく自力でWEB API x PHPをいじります。
流れとしては、
PUBLIC APIでレートを取得して、PRIVATE APIで取引を行う、というシンプルなモデルです。業者間アービトラージを想定しているので、コインチェックだったり、ZAIFだったり、bitFlyerだったりすると思いますが、勉強のためと思ってください。
必要な知識としては、PHPの基本的な記述方法とトレード系プログラミングに関する注意すべきことが頭にあれば良いです。(リクオートとか約定拒否とか指値・逆指値とか)
サーバー系言語(PHP)で仮想通貨APIを処理するメリット,デメリット
Web APIは基本的にJavascriptで処理させることを想定していますが、これまでのようにPHPで処理することもできます。
一般的なツイッターAPIやGoogleAPIの場合、サーバー上で処理ができるPHPの方が有利そうですが、仮想通貨のトレード系APIの場合、ちょっとした問題が発生します。
PHPで書くことのデメリット
サーバーが連続アクセスに対して拒絶反応をする
一般的なサーバーはDos対策がされているので、同一IPからのアクセスは一定時間の間に上限があります。それ以上アクセスしようとすると503エラーかアクセス拒否になります。
自動売買の場合、しょっちゅう計算フラグを立てる必要があるため、ここら辺がネックになります。
MT4のティックのように更新しようとするとここらへんで引っかかります。
MT4からDosした場合、セッション、クッキーの挙動がおかしくなる
MT4から自サーバーにウェブリクエスト -> 自サーバーから取引所に送信
という方法を試しにとったのですが、この方法をとるとPHPのスーパーグローバル変数の挙動がおかしくなることがあることがわかりました。
今までMT4とセッション処理を組み合わせたことがなかったので気づきませんでしたが、MT4からウェブリクエストするとサーバー側はブラウザではないと認識して(当たり前ですが)セッションの挙動がおかしくなるようです。
セッションは別として、クッキーはブラウザに保存されるので、
当たり前と言えば当たり前ですよね。
これが何が問題なのかというと、セッション、クッキーが使えないことによって
「前にトレードした時間から何秒以内はトレードしない」
という条件文が使えなくなります。
サーバー側に値を保存したまま、ページを更新するには、セッションかクッキーかデータベースが必要です。
しかし、たったこれだけのためにデータベースを使うというのも汎用性が失われるだけだと思います。
解決策
せっかくここまで作ったので、メール送信が簡単にできるPHPを捨てるというのは比較的もったいないと感じたりします。(配布するときにはやっぱりJavascriptの方が楽なんですけどね)
そこでDosのようになってしまう解決策をかるーく考察しました。
ローカルPCでPHPを動かす
これで99割解決です。(99割はネタですよ、もちろん)
自ローカルPCでPHPを動かす環境(XAMPPとか)を整えて、そこから直接取引所にアクセスすればいいのです。
長期的な自動売買をする場合はVPS上にPHP動作環境を入れるという、ホスティング会社に誤解されかねないような
方法もありだと思います。(最近はVPSでWEBサーバーとかもあるからね、多少はね。)
まぁ、しかし、開発者=利用者のときは良いですが、ソフトを配布する際にはハードルが高くなりそうですね。
MT4によるフラグをやめてブラウザでF5を自動化する
MT4によるアクセスでPHPを連続稼働させるというのが、普通じゃないといえば普通じゃないので、
ローカルPCからブラウザ経由で処理します。
これならセッションもクッキーも使えますし、自動化もUWSCを使えばそんなに難しくありません。
欠点は、自動売買している間はそのブラウザが使えなくなるということくらいでしょうか。
(UWSC使いはIEを使うことしか頭にないですが、ChromeやFirefoxの拡張機能にはF5アタックに近いツールがあるので、それを使う方が早いですね。)
Dosツールをお持ちの方はそちらを使ってどうぞ。(なんで持ってるんですかね~)
PHPで書くことのメリット
PHPだからメールで取引状況を確認できる!
これ、比較的メリットだと思います。JavascriptやC#でもできないことはないでしょうが、やっぱりサーバーサイド専用の言語であるPHPにはかなわないと思います。
コーディングしているとき、「Javascriptで書いて、HTA化すれば良かったんじゃね?」と頭をよぎりましたが、このメール機能の実装によりPHPの方が良いような気がしてきました。
これで、「取引が発生したらメール送信する」といったことができるので、外出先でも確認できます。
コピートレードはサーバー系言語の方が有利
中にはビットコイントレードをコピートレードするシステムを開発するケースもあるかと思います。その場合は、サーバー系プログラミングの方が有利です。
というかそれ以外では開発が困難だと思います。
もちろん、すべての処理をサーバーでする訳ではありませんが、コピーするデータのやり取りはデータベースが必要になるので、その際にPHPなりPerlなりのプログラミングが必要になると思います。
MQLではHashの処理ができないのでプライベートAPIは叩けない
ビットコインの自動売買システム構築のトピックに関して、
「・・・hash_hmac(‘sha256’,…)辺りをMQLで何とかすることが出来れば、MT4からAPIで注文もできると思うのですが、可能でしょうか?」
というお便りをいただいたので、そのお話をします。
結論から言うとMQL単体では困難です。
そもそもハッシュとは暗号化の一種で、第三者に見られたくない通信内容を隠すために使われるものです。
純粋な暗号化と違う点は、暗号化であれば鍵を元にしてもとのメッセージを復元できるのに対し、ハッシュの場合は復元することがそもそもできません。
そのため、データを送る側と受け取る側であらかじめ同じハッシュの取り決めを共有し、送受信されたデータが一致することによって認証を行います。
ちなみにこれは余談ですが、一般的な暗号化はRSA暗号という素数同士の掛け算による暗号を使っています。これは極端に大きな数字が素数である可能性が高く、その数字の掛け算の結果から、もとの因数を導き出すことが困難という数学上の性質から来ています。
サーマーウォーズの主人公がやっていたアレです。
それに対してブロックチェーンで使われる暗号化は楕円曲線の対数化の復号の難読性を使っています。簡単に言うと、ある数字aとnを与えられて、aをn乗してkという結果を出すのは簡単だけど、kという数字からnを導き出すのは難しいよ、っていう話を楕円曲線上でやるヤツです。
話を戻すと、
WEB APIのprivateメソッドでは、認証を行うためにハッシュ化が必要になります。PHPではハッシュ化の関数があるので、その関数にメッセージとキーとハッシュ方式を入れれば良いだけですが、MQLにはハッシュ関数がありません。
そのため、MQLから無理やりハッシュを扱うなら、
I ハッシュ化だけしてくれるサイトに投げる
II ハッシュ化をDLLに投げる
III ハッシュ化する箇所だけ他の言語体にする
しかありません。
I
技術的には超簡単です。ハッシュ化する内容をサイトに投げればいいだけなので… ただ、セキュリティは完全に失われるので、家の鍵をかけていない状態になります。トレードするには危険ですが、残高照会や取引履歴の参照だけができるAPIキーなら良いと思います。
II
C++が使えるならDLLにその処理を投げるのもありだと思います。2015年にMQL5でその依頼が$40でやっているので、誰か数学系に強い人に頼んで作ってもらった方が早いですね。
ハッシュ化の際に(うろ覚えですが)16進数表記に変換する必要があるため、それができないMQLではMQL内で独自関数を作るのはかなり長い道のりになると思います。(進数変換の関数から作らないといけない)
III
今はPHPやっている方法ですが、これが一番簡単だと思います。bitFlyer,CoinCheck,ZAIFでハッシュ化方式がSHA512だったりSHA256だったりするので、すでに組み込みの関数がある言語は便利です。
JAVAにもあったような気がします。Javascriptは標準ではなかったかな、確か。
現時点ではこれまでにやってきた方法が最善手だと思います。PHPがもし苦手であればJAVAでもC++でもその他高級言語でも良いと思いますが、MQL単体ではやっぱり難しいです。
APIでアービトラージのためのレートの比較&トレード
PUBLIC APIで取得したデータからbidとaskを抽出し、それぞれを比較します。
Private APIに比べると超簡単です。
WEB APIで取得したデータはJSON形式で返ってくるので、(いらない情報てんこ盛りで)、必要な情報だけを連想配列に格納します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
FUNCTION GetTickCC() { global $CC; $Url = "https://coincheck.com/api/ticker"; $file = file_get_contents($Url); $file = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $CC = json_decode($file,true); } FUNCTION GetTickZF() { global $ZF; $Url = "https://api.zaif.jp/api/1/ticker/btc_jpy"; $file = file_get_contents($Url); $file = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $ZF = json_decode($file,true); } FUNCTION GetTickBF() { global $BF; $Url = "https://api.bitflyer.jp/v1/getticker"; $file = file_get_contents($Url); $file = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $BF = json_decode($file,true); $BF["ask"] = $BF["best_ask"]; $BF["bid"] = $BF["best_bid"]; } |
あとはこれをPHP上で比較するだけです。
1 2 3 4 5 6 7 8 9 10 |
if( $CC["bid"] != 0 && $BF["bid"] != 0 && $ZF["bid"] != 0 ) { if( $ZF["bid"] - $CC["ask"] > 500 ) { if( $AllowTrade ) TradeCC("buy",$CC["ask"]); if( $AllowTrade ) TradeZF("sell",$ZF["bid"]); $message = ($ZF["bid"]-$CC["ask"]).",zaif bid,".$ZF["bid"].",>,coincheck ask,".$CC["ask"]; echo $message; } } ......... |
ひとつ注意しなければならないのは、PUBLIC APIの取得に失敗すると、それぞれの値が0になってしまう可能性があるということです。
比較する場合は、その前に0ではないこと(取得に成功していること)を条件に入れましょう。
また、例ではメッセージを表示するだけですが、PHPなのでメール送信が可能です。
単位時間当たりの大量取引を防ぐ
お察しの通り、これだけの条件文では、ある一定時間に大量にトレードする可能性が発生します。
EA(為替の自動売買プログラム)の場合、public変数やグローバル変数で、「前にトレードした時刻」を記録することが可能ですが、PHPの場合、基本的にアクセスする度にデータは消えてしまいます。
ではどうするかというと、会員制サイトでよく使う”セッション”を使います。
アクセスする元のIPが常に一緒であるからこそ、できる方法です。もしPHPの起動方法がDDosチックなやり方の場合、この手法は使えません。(そんな人いないか)
つまり、
ローカルPCのブラウザ → PHPサーバー → 各取引所APIサーバー
という図式です。
PHPをXAMPPなどでローカルで稼働させ、UWSCか何かで連打する方法もありだと思います。
私は海外VPS(仮想デスクトップ)が一つ余っているので、上の方法をとりますが、将来的に自動売買させて放置するのであればVPS上でやるのが一番いいと思います。
(VPSは余力がある場合にレンタルすればOKです。)
IP制限の上限を超えてアクセスするやり方(プロキシ)
APIアクセス制限には、APIキーベースのものとIPアドレスベースのものがありますが、ここではIPアドレスベースの制限を超える方法について紹介します。
基本的にはどの仮想通貨取引所も両方の制限を書けていますが、ドキュメントに記載されている数値よりも小さいアクセスでもIPアドレスの制限を受けることがあります。
下記は、bitFlyerのAPIアクセス制限に関する記載です。
各取引所APIでは一定時間の間にたたくことができる回数に上限があります。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
HTTP API は、以下のとおり呼出回数を制限いたします。Private API は 1 分間に約 200 回を上限とします。
IP アドレスごとに 1 分間に約 500 回を上限とします。1 日の平均約定単価が 0.01 未満のユーザーは、翌日の Private API 呼出回数が 1 分間に約 10 回まで制限されることがあります。
マニュアル発注は制限されません。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
(細かい情報は変更されている可能性があります)
これでも十分上限は大きいですが、どうやらこの以下の回数の場合でも
アクセス回数が多いIPはアクセス拒否されることがあるようです。(実体験)
たぶんサーバーがDosと認識して、上限に達する前に自動的に拒否しているんだと思います。
しかし、ネットワークの世界ではこういった事態もよく遭遇するもので、回避方法があります。
プロキシを使う
phpではcurlを使う際にプロキシを設定できます。IPに対するアクセス制限は串を刺せば無問題です。(APIアカウントに対する制限はさすがに無理です。)
海外IPをはじく可能性があるので、プロキシは日本のロケーションのものにしましょう。一応
記述自体は簡単でcurlのオプションに下記を足せばいいだけです。
1 2 |
$proxy = "192.168.11.1:80";//適当なプロキシを入れてね curl_setopt($curl_b, CURLOPT_PROXY, $proxy); |
プロキシの寿命と自動取得
問題は、無料プロキシの場合のプロキシの寿命です。
長時間できるものもありますが、永続的かつ自動的にプロキシのIPを回そうと思います。
手としては、
A 複数のIPをあらかじめリストで取得しておき、失敗したら次のIPを試行するループ文を使う
B プロキシのIPリストをリアルタイムで出しているサイトからスクレイピングして取得し、繰り返し試行する
があります。
Bの方が完全上位互換ですが、なかなかスクレイピングしやすい良いサイトが見つからないので、
とりあえず、Aでいきます。
プロキシ周りはあまり日常において必要性を感じていないので詳しくない関係上、もっといいプロキシIPリストの取得方法があるかもしれません。
リストを外部ファイルにすると巨大なリストも処理できますが、
とりあえずお試しなので、php本文の先頭にずらずら書きます。
1 2 3 4 5 6 7 8 9 10 11 |
$proxy[0] = '160.16.119.186:8118'; $proxy[1] = '106.184.6.128:3128'; $proxy[2] = '219.166.7.50:1024'; $proxy[3] = '219.127.253.43:80'; $proxy[4] = '121.94.173.145:80'; $proxy[5] = '103.15.187.116:3128'; $proxy[6] = '60.113.49.104:8888'; $proxy[7] = '160.202.159.254:53281'; $proxy[8] = '153.122.66.207:3128'; $proxy[9] = '153.122.66.205:3128'; ... |
(プログラマのやることとは思えない冗長さですね…)
あとはfor文でこの配列の処理をすればOKです。
プロキシの取得方法
取引所APIを使った自動売買のプロキシの設定方法ですが、
一番かんたんな方法としては、
Googleで「japan proxy list」などと検索して定期的に
手動でプロキシを更新する方法です。
一番間違いがないとは思いますが正直なところ面倒だと思います。
それが仕事なら良いですけどね。
2つ目の方法としては、
「japan proxy list」の検索結果のサイトの中で
できるだけシンプルなレイアウトのサイトを見つけ、
定期的にCRONでスクレイピングして別ファイルに保存し、
トレードファイルから呼び出す方法です。
CRONはサーバーで定期的にphpなどを呼び出す機能で
最近のレンタルサーバーならメニューの中にあると思います。
スクレイピングは自分でコーディングしなければいけないので、
正直大変だと思います。
スクレイピングに関しては「MT4のチャート上にWEBデータを表示する」際に必要になったことがあるので、
そちらの記事を参照してください。
有料プロキシサーバーサービス
妥協案としては、
長く使える有料proxyサーバーを買うのが一番良いと思います。
数百円でレンタルできますし、速度も早いです。
VPNにしてしまうと、同じIPアドレスを多くの人が使っているので、
弾かれてしまう可能性が高いです。(ZAIFでは弾かれたことがあります)
プロキシとタイムアウト設定
また、プロキシを経由するとアクセス上限は超えられますが、
取引所がレスポンスを返そうとしているタイミングでタイムアウトすると、
2重にオーダーを送信してしまう可能性があります。
かといって、タイムアウトを設定しないと
プロキシサーバーが止まった時に
自サーバーのCPUがそこで止まってしまい、サーバー会社に怒られます。
なので、取引所に止められていないのであれば、
プロキシは極力使わない方が良いと思います。
また、bitFlyerのサーバーはアメリカにあるので、
bitFlyerを使う場合は、プロキシリストは日本のロケーションでなくてもOKです。
というより、日本に限定しない方がスクレイピングに向いたサイトは見つかると思います。
プロキシとセキュリティ
あと、
無料プロキシの中には情報を抜き取っているところもあるはずなので、
プロキシサーバーを使う場合にはセキュリティと暗号化処理に気を付けてください。
間違ってもデバッグの際にAPIキーを平文で送るようなことがないようにしてください。
仮想通貨取引所のアクセス拒否との死闘と解決策
これまで取引所とさまざまな悪戦苦闘を繰り広げてきましたが、
良いアイディアが思いついたので、一回まとめたいと思います。
【これまでの経緯】
取引所にAPIのアクセス拒否される
↓
プロキシを経由してIPアドレスを分散
↓
一つのプロキシだと止まってしまうことがあるので複数のプロキシを使う
↓
プロキシサーバーで停止するとレスポンス待ちになって自サーバーのCPUがパンクして止まる
↓
プロキシ接続にタイムアウトを設定し、プロキシサーバーが止まった場合は次の別のプロキシを使う
↓
取引所でオーダーが通ってレスポンスが返ってくる途中でプロキシサーバーが止まった場合、
オーダーが2重3重で発注される
とここまで来たのですが、
実にシンプルな解決策を思いつきました。
APIにPrivateアクセスする場合、
どの取引所でも「アクセスごとに増加しなければならない数字」(通常はUNIXタイムスタンプ)を
ハッシュに含めます。
これが増加していない場合はエラーになるので、それを逆に利用します。
つまり、今までは
プロキシを繰り返し送信するfor文の中で都度タイムスタンプを発行していたのですが、
それをfor文の前に変数に入れることによって、
2重3重にオーダーが通りそうな場合はエラーを発生させることで約定を防ぐことができます。
つまり、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
for($i=0 ;$i<5;$i++) { $TimeStamp_b = time();//!!ここ!! $curl_b = curl_init(); curl_setopt($curl_b, CURLOPT_RETURNTRANSFER,true); if( $postorget == "GET" ) { $Message_b = $TimeStamp_b."GET".$Pass_b.$Body_b; $Signature_b = hash_hmac("sha256", $Message_b, $AccessSecret_b); $options_b = array( CURLOPT_HTTPHEADER => array( "ACCESS-KEY:$AccessKey_b\r\n". "ACCESS-TIMESTAMP:$TimeStamp_b\r\n". "ACCESS-SIGN:$Signature_b\r\n". "Content-Type:application/json" ), CURLOPT_GET => true, CURLOPT_BODY => $Body_b |
これを
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$TimeStamp_b_ = time(); for($i=0 ;$i<5;$i++) { $TimeStamp_b = $TimeStamp_b_; $curl_b = curl_init(); curl_setopt($curl_b, CURLOPT_RETURNTRANSFER,true); if( $postorget == "GET" ) { $Message_b = $TimeStamp_b."GET".$Pass_b.$Body_b; $Signature_b = hash_hmac("sha256", $Message_b, $AccessSecret_b); $options_b = array( CURLOPT_HTTPHEADER => array( "ACCESS-KEY:$AccessKey_b\r\n". "ACCESS-TIMESTAMP:$TimeStamp_b\r\n". "ACCESS-SIGN:$Signature_b\r\n". "Content-Type:application/json" ), CURLOPT_GET => true, CURLOPT_BODY => $Body_b |
こうすればよかっただけです。(コードについては前の投稿を見てください。)
こんな簡単なことに気付かなかったなんて、頭がいい人に見られたらバカにされても文句は言えないですね。
ちなみに今のPHPではマルチタスクもできるので、
オーダーの部分だけマルチタスクにしても良いかもしれません。
しかし、そんなモチベーションはないので、
極めたい人は試してみてください。
ちなみに、アクセス拒否は取引所側の手違いということで、
現在はプロキシを通さずに生IPでやれています。
今回のプロキシ云々が影響するのは、よっぽど大量アクセスをしている人に限られるでしょう。
仮想通貨APIでコピートレード配信システムを作るやり方
仮想通貨、暗号通貨の流行りって基本的にFXと同じ道をたどるので、
今後予想される流行の一つにコピートレードがあるんじゃないかと思います。
(日本ではコピートレードあんまりメジャーにならなかったですけど)
コピートレードというのは優秀なトレーダーのトレードをコピーさせてもらうサービスのことです。
トレーダー側がトレード配信OKと承諾して、いろいろ手順を踏むとできます。
ミラートレードとの違いは、コピートレードは複数のトレードシグナルから選択するのに対し、
ミラートレードは1対1でシグナルを選べない場合に言うこと多いような気がします。
言葉としてはコピートレードの方がより意味が広いです。
さて、
本題の仮想通貨のコピートレードですが、APIがあるので何でもやれちゃいます。
全体的な方針としては、
配信側トレーダーのAPIを「建玉のみ参照できる権限で発行」し、
受信側は配信側トレーダーと自分のAPIを使って自動売買させます。
こうすることで、配信側の資産がいじられたり見られたりすることはなく、
トレードのポジションだけを見せることができます。
APIのアクセス上限はアカウントベースではなくIPアドレスベースなので、
受信側が大人数になったとしてもIPアドレスがバラけるので大丈夫です。
もしアクセスできなくなっても、
APIキーを複数発行したり、
プロキシを刺したり、
コピー先からさらにコピーしたりすれば
だいたい対処できると思います。
細かい仕様ですが、
基本的には受信側でいろいろ演算させる方式にします。
送信側でティック更新を行って、トレード情報をデータベースに入れて
それを受信側が参照するというのも正攻法なのですが、
送信側は情報を提供する側なので、あまり煩わしい手間をかけない仕様にしたいと思います。
という訳で、
受信側でシグナルを参照し、自動売買までさせます。
送信側のシグナルは、例えばbitFlyerの場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
FUNCTION GetPositionDataBF() { $Domain_b = "https://api.bitflyer.jp"; $query = "?product_code=FX_BTC_JPY"; $Pass_b = "/v1/me/getpositions".$query; $URL_b = $Domain_b.$Pass_b; $arrQuery_b = NULL; $Body_b = NULL; $res_b = CURL_BF("GET",$Pass_b,$URL_b,$Body_b,$arrQuery_b); return $res_b; } FUNCTION CURL_BF($postorget,$Pass_b,$URL_b,$Body_b,$arrQuery_b) { global $AccessKey_b; global $AccessSecret_b; global $proxy; global $currentproxy; $TimeStamp_b = time(); $curl_b = curl_init(); curl_setopt($curl_b, CURLOPT_RETURNTRANSFER,true); if( $postorget == "GET" ) { $Message_b = $TimeStamp_b."GET".$Pass_b.$Body_b; $Signature_b = hash_hmac("sha256", $Message_b, $AccessSecret_b); $options_b = array( CURLOPT_HTTPHEADER => array( "ACCESS-KEY:$AccessKey_b\r\n". "ACCESS-TIMESTAMP:$TimeStamp_b\r\n". "ACCESS-SIGN:$Signature_b\r\n". "Content-Type:application/json" ), CURLOPT_GET => true, CURLOPT_BODY => $Body_b ); curl_setopt($curl_b, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($curl_b, CURLOPT_GETFIELDS, $arrQuery_b); } else if( $postorget == "POST" ) { $Message_b = $TimeStamp_b."POST".$Pass_b.$Body_b; $Signature_b = hash_hmac("sha256", $Message_b, $AccessSecret_b); $options_b = array( CURLOPT_HTTPHEADER => array( "ACCESS-KEY: $AccessKey_b\r\n". "ACCESS-TIMESTAMP: $TimeStamp_b\r\n". "ACCESS-SIGN: $Signature_b", "Content-Type:" => "application/json", "Content-Length:" => strlen($Body_b), ), CURLOPT_POST => true, CURLOPT_BODY => $Body_b ); curl_setopt($curl_b, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($curl_b, CURLOPT_POSTFIELDS, $Body_b); } curl_setopt($curl_b, CURLOPT_URL, $URL_b); curl_setopt_array($curl_b, $options_b); $file = curl_exec($curl_b); curl_close($curl_b); return($file); } |
こんな感じの関数を書けば取り出せます。
これで受信者側はJSONをデコードするだけでポジションデータを参照できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
FUNCTION SetPositionDataToVariablesBF($PositionDataJson) { global $positiontype_bf; global $positionamount_bf; global $positionopenrate_bf; $PositionData_bf = json_decode($PositionDataJson,true); if( $PositionData_bf[0]["side"] == "BUY" || $PositionData_bf[0]["side"] == "SELL" ) { $positiontype_bf = $PositionData_bf[0]["side"]; $positionamount_bf = $PositionData_bf[0]["size"]; $positionopenrate_bf = $PositionData_bf[0]["price"]; } } |
後は、今まで通りポジションデータに従って建玉すればいいだけです。
つまり、
信用取引で「ポジションがあればチェックして条件に合えば決済する」の箇所を「(配信側の)ポジションがなければ決済する」に書き換えればいいだけです。
エントリーも同様で、「(配信側の)ポジションがあり、かつ、自分が同じ通貨の同じ方向のポジションを持っていなければエントリー」という条件文を書けばOKです。
細かいところはこれまでの寄せ集めなので、新たに特筆する必要はないと思います。
コピートレードの場合、重要なのは
システムよりも送信側と受信側がいかに納得できるような報酬体系にするか
と
法的な問題(許認可が必要な投資業に該当しないように)
です。
正直なところ、作ったとしても上記の問題が解決しなければ誰からも見られることがない前衛的美術品にすらなることができないので、もし作るなら先にそっちを解決した方が賢明です。
サービス展開向けの仮想通貨自動売買システムを作るには
前置き
ビットコイン、仮想通貨の自動売買を作る目的として、通常は個人的に利用するというものがほとんどだと思いますが、時たまサービス展開を目的としている方もいるようです。
種銭がないとか、もともと企業家とか、理由はいろいろあると思いますが、ここのゴールが変わると開発要件も大きくガラっと変わってきてしまいます。
というのも、個人的に利用する場合は、ソフトの認証やセキュリティやAPIキーの管理やコード流出の心配はあまりしなくても大丈夫ですが、利用者が複数いる場合にはそういったものを考慮に入れる必要があります。
パターンとしては、大きく3通りあると思います。
開発パターン
ほぼすべてのコードをスタンドアロンのソフトに入れて、発行したキーで認証する。
例:UWSC有料版やBandicam有料版
管理側への負荷、負担は少ない判明、キーを共有されたり公開されたりすると制御不能になる可能性があります。また、クラックされた場合、中のコードが流出します。
開発言語:C#とか
メインとなるコードを配布ソフトに入れて、認証のみをサーバーで行う。
例:FXONのEA
認証をサーバーで行うので、ソフトの共有や公開に対しても強いが、クラックされた場合には上と同様のリスクがあります。
開発言語:C#,PHP
メインとなるコードをサーバーに置いて、配布ソフトは認証のみを行う。
例:一部のソシャゲ
共有、公開、クラックに対して強いが、各ユーザーの処理をサーバーで行うため、サーバーの負荷は大きくなる。
開発言語:PHP,C#,SQL,(HTML,Javascript)
金融系のソフトウェアの場合、特にFX業界では、2番目のパターンが多いです。株の場合も2番目のパターンが多いような気がします。が、やっぱりディープな世界では逆コンパイラーなんてものも出回っていたりするので、一長一短な面があります。
本サイトでの作り方
本ブログで紹介している作り方は、基本的には3番目での作り方になりますが、実行ファイルをローカルフォルダに入れてPHPが動く環境もセットにすれば、1番目、2番目のパターンにもできると思います。
作り方のリファレンスはこちら
ビットコイン自動売買システムの作り方 一覧
例えば、APIキーの処理部分は各ユーザーのローカル環境で動作する部分に回し、取引所へのオーダーをサーバーから行うなんてことも応用すれば可能なはずです。
C#、Javaがあまり得意でない場合は、サーバーへの処理内容をHTMLのFORMで記述し、それをHTAファイルにすると簡易的に作ることができます。
APIでビットコインのヒストリデータを取得するやり方[POLONIEX]
公開:2017/9/4
国内の取引所でもAPIを発行している取引所はいくつかありますが、
ビットコインのヒストリーデータを提供している取引所は知る限りでは海外のPOLONIEXしかありません。
ヒストリーデータ(過去のろうそく足データ)が使えると、テクニカルな自動売買が可能になります。
(逆に、ヒストリーデータが使えないということは、現在レートしか参照できないということでもあります)
POLONIEXは、現在いろいろな悪い噂がありましたが、買収されたことでマシになったんじゃないかと思います。
POLONIEXのAPIのドキュメントはこちらです。https://poloniex.com/support/api/
すべて英語なので英語がダメな方は翻訳機にかけるなどしてください。
(自動翻訳だと逆にわかりにくくなることは比較的あります)
returnChartDataという項目がヒストリーデータの取得です。
1 |
https://poloniex.com/public?command=returnChartData¤cyPair=BTC_XMR&start=1405699200&end=9999999999&period=14400 |
これでコールします。
返り値はjsonです。
通貨ペアの指定が比較的厄介で、通貨ペアのリファレンスがありません。
ビットコインドルのペアがどういった表記なのかは全部試すしかありません。
- BTC_USD エラー
- BTC_USDT エラー なんでこれじゃないの!?
- USD_BTC エラー
- USDT_BTC これが正解
- BTCUSD エラー
- BTCUSDT エラー
ここで躓いてこっから先に進めない人が多いのではないかと思います。
さて、引っ張り出してくる過去のレートですが、時間枠毎のロウソク足というものが存在しないので、レートが変化する度にデータベースに格納されているようです。
ピンポイントで欲しい時刻を指定すると、そのタイミングでレートに変化なかった場合にレートが返ってこないので、欲しい時刻の前後の時間を指定します。
参照する時刻はUNIXタイムスタンプで取得スタート時間とエンド時間を指定します。
この幅が狭いと、指定した時間幅にレートが存在しない場合に返り値が空になります。
だいたい10秒~30秒くらいの幅を持たせれば問題はないと思います。
幅を持たせると今度は別の問題が発生し、複数のレートを吐き出します。
1 2 |
{"date":1405713600,"high":0.00435,"low":0.00412,"open":0.00428012,"close":0.00412,"volume":19.12271662,"quoteVolume":4531.85801066,"weightedAverage":0.00421961},{"date":1405728000,"high":0.00435161,"low":0.00406,"open":0.00411473,"close":0.00435161,"volume":35.18169499,"quoteVolume":8430.50936646,"weightedAverage":0.00417313},{"date":1405742400,"high":0.00459,"low":0.0043418,"open":0.00435173,"close":0.00437,"volume":21.66886127,"quoteVolume":4839.66822966,"weightedAverage":0.00447734}, ... |
こんな感じで。
jsonの配列は時刻と逆向きになっているので、最初のレートだけ取得すればOKです。
1 2 3 4 5 6 7 8 9 10 |
FUNCTION GetHistoryRate($unixtime) { $Url = "https://poloniex.com/public?command=returnTradeHistory¤cyPair=USDT_BTC&start=".$unixtime."&end=".($unixtime+30); $file = file_get_contents($Url); $file = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $HistoryRate = json_decode($file,true); return($HistoryRate[0]["rate"]); } |
ただし、これで取得できるレートはUSDベースのレートになるため、
日本の取引所のレートと比較する場合には為替の変換が必要です。
方法としては、
どこかの為替データのAPIを使う
のが正攻法ですが、無料で優秀なものはなかなかないみたいです。
どこも月額有料のAPIなので、レートの計算はUSDですべて行い、
最後だけ円に変換して、日本の取引所で取引という手が一番無難だと思います。
しかし、ドル円のレート変動もあるため、
・ビットコインレートに差があるのか
・ドル円レートに差があるのか(遅いのか)
判別不能なため、ベースの法定通貨が異なる場合はアービトラージは理論的に難しんじゃないかと思います。
関連記事
-
コインチェックのAPIの使い方[PHP]
公開:2017/6/21 PHPプログラマと言っても、いろいろな分野の人がいるわけで、WEB系だか
-
[API]ビットコインスキャルピングの自動売買システムの作り方(Poloniex)
「アービトラージあるからいいじゃん」ってずっと思ってたのですが、(今でも思ってる)スキャルピングに関
-
ZAIFのAPIの使い方[PHP]
APIを使ってbitFlyerからレートを取得したり、残高を確認したり、オーダーを出す方法まとめです
-
仮想通貨アービトラージシステムを作る[Binance vs Poloniex]
この記事ではポロニエックスとバイナンスでAPIを使ったアービトラージシステムを作る具体的な方法を解説
-
APIビットコインアービトラージシステム
ここまで業者間アービトラージシステムのプログラミングの考察?をしてきましたが、 中には「中身がどう