Angularで可視化しながら、３通貨アービトーラージ（内部アービトラージ）の自動化実験をしてみた

[2019/02/24 大幅にコードをリファクタリングしたため、記事も修正しました。]

こんにちわ、Angular好きフロントエンジニアです。今回は今流行りの仮想通貨で億り人を目指して、3通貨アービトラージの実験をしてみました。結論から言えばいい結果が得られなかったのですが、色々気づいた点もあったので、実際に開発したコードと共にメモを残します。
↓開発したコード
- フロント
    - https://github.com/hedrall/internal-arbitrage
- (プロキシ用)API
    - https://github.com/hedrall/internal-arbitrage-api

※私のコードを使用、改変使用することで発生するいかなる損害も保証しません。全ては自己責任で扱ってください。

# 1. 背景（知っている人は読み飛ばしてください）
## 1.1 アービトラージ（裁定取引）とは？
仮想通貨は（株、先物含め）、取引所間に価格差が生まれます。例えばある「通貨C」が取引所Aで100円, 取引所Bで200円で取引されているとした場合、取引所Aで通貨Cを購入すると同時に取引所Bで通貨Cを売れば差額の100円を利益として得ることができます。A, B両取引所に同時に資産を持っていた場合は同時に売り注文と買い注文を出すことができるため、理論上は100%利益をあげることができます。デメリットとしては、裁定２以上の取引所に資産を持っておく必要がるし、取引所間の送金手数料がかかるため、潤沢な資産が必要になります。
↓詳しく面白おかしく書いている記事
http://xn--eck3a9bu7culw30roe4arcdo69l1ja456a.xyz/post-2384/

## 1.2 ３通貨（内部）アービトラージとは？
上記の裁定取引を取引所内で通貨間で行う取引。例えばJPYとBTCでXEM（ネムコイン）を買える取引所があります。仮に次のような状況だったとしたらどうでしょう。
1BTC -> 10000円
日本円で買った場合、1XEM -> 100円
BTCで買った場合、1XEM   -> 0.002BTC
この場合は、①100JPYで1XEMを買って、②0.002BTCで 1XEMを売却します。最後に③0.002BTCを日本円に換金すると(200円)、XEM, BTCの総量は変わらず、日本円は100円増えた状態になれります。上記の通り、理論上は100%利益の出る取引を1取引所内で行うことが出来ます。
↓まさに３通貨アービトラージをやりたくなる記事

## 1.3 ３通貨アービトラージの魅力
３通貨アービトラージでは1取引所内に資産があれば良いので、資本金は少額でも大丈夫です。また、実際は一取引あたりの利益は**非常に小さい**ことが多いのですが、短時間で繰り返し利益をあげることができるため、結果的に大きな利益をあげることが期待できます。例えば秒給1円を実現すれば、月給260万円を実現できますwただ、全く非現実的な数字ではなく、利益幅を0.2%取ることができれば、１分間に3万円相当を移動させることで実現できます。

## 1.4 今回やったこと
日本の仮想通貨取引所「Zaif」でJPY, BTC, **XEM**の３通貨間アービトラージを自動化すべく開発を行いました。Zaifを選んだ理由として、アービトラージは既に多くの方が関心を持っているため競合が多い領域なのですが、Zaifは日本の取引所なので、海外のハッカーには扱いづらいかな？とか、日本には正味スプレッドが0の取引所が少ないのでその中では老舗のZaifを選びました。また、ZaifのXEMの取引量は実際少なく、例えば1000万円の資本を持っている人が３通貨アービトラージを行おうと思っても、瞬時に**1000万円分をJPYで購入して、1000万円分をBTCで売り切って、JPYで1000万円分のBTCを買い戻して、、、、**というのは至難の技です。個人単位ではまだ人が手をつけていない（利幅が大きくない）領域を狙うのが正攻法だと思います。XEMを選んだもの同様の理由で、1オルトコインでしかないXEMはETH, BCHなどに対して競合が少ないことを期待した結果です。

# 2 開発
## 2.1 構成
コンソール画面にAngular, APIにPHPを使用しました。一般的にアービトラージはどれだけ早く価格差を算出し一番乗りできるかが勝負の世界です。が、今回は実験から始めたこともあり、可視化を重視しながら開発をするために愚策とわかりつつAngularで情報取得->演算->可視化->注文を行なうこととしました。ただし、ZaifのAPIはCORSが許可されておらずブラウザから叩けないため、node/expressで構成した APIでプロキシするようにしました。
※このAPIには```http://localhost:4400```でアクセスできる前提になっています。
Angularというと全く知らない方からするとハードルが高そうに感じるかもしれませんが、Typescriptのコード自体はJAVAやC++のような一般的なオブジェクト思考言語と同じような書き方ができるので簡単にアレンジできると思います。具体的には以下の2ファイルを編集することで、改修が可能です。

```
src/app/coin/chart/chart.component.ts
src/app/coin/chart/chart.component.html
```

## 2.2 実行方法

Angularの実行方法は非常に簡単です。

```
git clone https://github.com/hedrall/internal-arbitrage.git
cd ダウンロードしたレポジトリ
npm install
ng serve --port 4300 <- 好きなポートで
// APIも起動
git clone https://github.com/hedrall/internal-arbitrage.git
cd ダウンロードしたレポジトリ
npm install
npm start <- 好きなポートで
```
これだけ

## 2.3 実際に動かした所
<img width="1642" alt="スクリーンショット 2018-02-12 23.17.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/194978/44220500-53f7-1348-61fc-d848d2b57be2.png">
左上のセレクトボックスから取引したいペアを選ぶと自動的に板情報の取得が開始されます。（と言っても端数計算の関係から、今回はXEM/JPYにのみ対応しました）。取得した板情報から限度額を元に購入・売却可能量と購入・売却価格を自動的に算出します。算出した結果利益が出る取引方法の実行ボタンが有効になります。理由は後述しますが、今回は自動化には至っていません。手動で裁定取引を実行することができます。

## 2.4 計算の流れ
1.BTCの取引履歴を取得
2. x秒間のBTC/JPYの平均価格を算出する(デフォルトは10秒間)
3. XEM/JPYとXEM/BTCの板情報を取得する
4. それぞれの板から購入可能量（端数は切る）とその時の平均価格を算出する
5. 先ほど求めた購入可能量を元に、各板情報から、売却する場合の平均価格を算出する。
6. 「JPY買い・BTC売り」、「BTC買いJPY売り」の価格差（利益）、利益率を計算する
7. 利益率が0%を超える取引方法の実行ボタンを有効にする
※売り買いともにmakerとして注文するため、手数料は合計0.2%程度かかりますが、手数料による金額調整は行なっておりません。

# 3 結果・結論
今回は自動取引まで実装することはありませんでした。理由は以下の通りです。
1. 意外と利幅が小さい
まずはこれです。実行して画面を眺めているとわかりますが、利益を出せるタイミングはさほど多くありません。確実に利益を出すにはもう少し安定して価格差を期待したい所です。長期戦でレンジを絞るのか、別の取引所を使用するのか検討する余地があります。
2. ZaifのAPIの質が悪い
これは意外とクリティカルな問題でした（勝手に使用して勝手に批判してZaifさんすみません、、）。取引系の注文はセキュリティーの関係からリクエスト毎にインクリメントした数値を添える必要がある（詰まりシリアルにリクエストを出す必要がある）のですが、一回一回のリクエストにそれなりの時間がかかるため、価格が変動してします恐れが高くなっています。また、zaifを普段から使用している方ならわかるとい思いますが、出来高の大きい時期は注文がかなり通りにくくなります。APIリクエストも失敗が多発します。価格変動を考慮するとリトライを実装するのは得策とは思えませんので、対応は難しいと考えられます。APIの質の高い取引所を使用するか、zaifのサーバー強化を期待する必要があります。
3. 板計算の難しさ
購入量が大きくなると、買い・売りごとに複数のリクエストを出さなければなりませんが、上記のAPI速度の制約から難しい部分ではあります。じゃあ、成行的に注文を入れて最低額から順に購入すれば良いのでは？とも考えましたが、そもそもアビトラは小さな利幅を確実に回収する取引なので少々危険です。

# 4 総評
結局煮え切れない記事になってしまい申し訳ございませんでした。が、今回は真剣にアービトラージについて考え実装をしてみました。結果として、基本的には資金を準備して取引所間の純粋なアービトラージを行った方が確実に大きな利幅が得られることが予想されました。オルトコイン系は取引所間の送金手数料が安いことも多いので、今度試してみようと思います。しかしながら、３通貨アービトラージも確実に利益の出る時間帯は存在しますので、APIの品質を評価しながら、より高品質な取引所に舞台を写すことも一つの方策と考えられます。
しいて今回開発したコンソールの唯一の利点を上げると、画面下の方にひっそりと手動注文ボタンがあります。 Zaifの注文が通りにくい時はこちらを利用して注文すると、公式サイトからより少しは注文を入れやすいです。

普段記事を書くことは少ない私ですが、今回は実装の記録として長々と記事を書かせていただきました。もし興味を持たれた方がいましたら、ご意見ご感想ご指摘をいただけると嬉しいです。記事の改善をしていきます。