Binance完結する3通貨アービトラージを探る

![ab3-2.png](https://qiita-image-store.s3.amazonaws.com/0/253878/ecb574bf-7501-96ae-3288-e811b722091e.png)

#環境
- Windows10 64bit
- Python 3.6
- PyCharm
- [CCTX](https://github.com/ccxt/ccxt/wiki/Manual)
- [pandas](https://pandas.pydata.org/pandas-docs/stable/api.html)

#ググって目に入った情報
[binance 3 アービトラージ - Google検索](https://www.google.co.jp/search?q=binance+3+アービトラージ)

- [binanceの3点アビトラを行ってみました。 - Bitcoin 裁定取引と自動取引 abitra.netのブログ](http://abitra.hatenablog.com/entry/2018/02/02/042419)
- [Binanceで3通貨アービトラージの価格差を取得 · GitHub](https://gist.github.com/koheso/02118464e81db10f8e05254c1e2e292c)
- [3通貨間アービトラージで稼ぐことはできるのか？｜かかってコアラ](http://koaland.xyz/3%E9%80%9A%E8%B2%A8%E9%96%93%E3%82%A2%E3%83%BC%E3%83%93%E3%83%88%E3%83%A9%E3%83%BC%E3%82%B8%E3%81%A7%E7%A8%BC%E3%81%90%E3%81%93%E3%81%A8%E3%81%AF%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%AE%E3%81%8B%EF%BC%9F/)

辺りを目に入れつつ。あまり上手く利益が出てる例は無かったですが…
結局先人の成果物を理解することが難しかったので自分で組んでみました。

#やりたいこと/大まかな流れ
1. Binance内の通貨取引ペア**全840種**を得る
2. Binance内の取引通貨種**全238種**を得る
3. 3通貨ぐるっと回せるルート**全3880種**を得る
4. 3で得たルートで3回取引したときに元手がどう変わるか

**アルゴリズムは含みません**。まず市場の観測。勝機の有無を知りたかったので。解析とか判定はもっと先の話。

#全コード#
```python

import ccxt
from datetime import datetime
from datetime import timedelta
import pandas as pd
import numpy as np

print(str(datetime.today())[0:19] +' プログラム開始')
print()

# 初期準備
pd.set_option('display.max_rows', 1500)  # 省略させない
binance = ccxt.binance()
binance.load_markets()


# 取引ペア取得
print(str(datetime.today())[0:19] + ' 全ての取引種を取得')
Pairlists = list(binance.markets.keys())
Pl_sum = len(Pairlists)

print(str(datetime.today())[0:19] + ' ' +  str(Pl_sum) + '種')
print()

print(str(datetime.today())[0:19] + ' 全ての取引値を取得')
cp = datetime.today()
s = []
for i in range(Pl_sum):
    name = str(Pairlists[i])
    c1 = name.split("/")[0]
    c2 = name.split("/")[1]
    ask = ccxt.binance().fetch_ticker(Pairlists[i])['ask']
    bid = ccxt.binance().fetch_ticker(Pairlists[i])['bid']

    s.append([name, c1, c2, ask, bid, str(datetime.today())[0:19]])

    price = pd.DataFrame(s, columns=["name", "c1", "c2", "ask", "bid", "time"])

    t = datetime.today() - cp
    if i == 0 or i < 10:
        nj = 0
        nji = 0
    else:
        nj = (Pl_sum - i) * (t.seconds / i)
        if nj > nji != 0:
            nj = nji
        nji = nj
    print('\r  └  ' + str(i)+ '/' + str(Pl_sum) + '  残り ' +'{:,.0f}'.format(nj) + '秒  ' + c1 + '/' + c2 + '  ask:' + '{:.5f}'.format(ask) + '  bid:' + '{:.5f}'.format(bid), end='')

price = price.set_index("name")

print()

# 通貨リスト取得
print(str(datetime.today())[0:19] + ' 全ての通貨種を取得')
c = []
c = price['c1'].tolist() + price['c2'].tolist()

l = set(c)
l = sorted(l)

print(str(datetime.today())[0:19] + ' ' + str(len(l)) + '種')
print()


# ルート探索
# 基礎通貨宣言
print(str(datetime.today())[0:19] + ' 組み合わせ探索と計算')
AbiPair = []
BaseCurrency = ["BTC", "ETH", "USDT", "BNB"]
mk = 0

for i0 in range(len(BaseCurrency)):
    T0 = BaseCurrency[i0]
    for i1 in range(len(l)):
        T1 = l[i1]
        if T0 + "/" + T1 in Pairlists or T1 + "/" + T0 in Pairlists:
            # T1確定

            for i2 in range(len(l)):
                T2 = l[i2]
                if T2 + "/" + T1 in Pairlists or T1 + "/" + T2 in Pairlists:
                    # T2確定

                    if T2 + "/" + T0 in Pairlists or T0 + "/" + T2 in Pairlists:
                        # ルート確定
                        # 1st buy
                        if T1 + "/" + T0 in price.index.values:
                            buyT1 = 1 / price.at[str(T1 + "/" + T0), 'ask']
                        else:
                            buyT1 = price.at[str(T0 + "/" + T1), 'bid']

                        # 2nd buy
                        if T2 + "/" + T1 in price.index.values:
                            buyT2 = buyT1 / price.at[str(T2 + "/" + T1), 'ask']
                        else:
                            buyT2 = buyT1 * price.at[str(T1 + "/" + T2), 'bid']

                        # 3rd buy
                        if T0 + "/" + T2 in price.index.values:
                            buyT0 = buyT2 / price.at[str(T0 + "/" + T2), 'ask'] - 1
                        else:
                            buyT0 = buyT2 * price.at[str(T2 + "/" + T0), 'bid'] - 1

                        if float('inf') in [buyT1, buyT2, buyT0] or 0 in [buyT1, buyT2, buyT0] :
                            print(str(datetime.today())[0:19] + '  └ 無効 ' + '  ' + T0 + '/' + T1 + '/' + T2)
                            mk += 1
                        else:
                            print(str(datetime.today())[0:19] + '  └ calc ' + '  ' + T0 + '/' + T1 + '/' + T2)
                            AbiPair.append([T0, T1, T2, buyT1, buyT2, '{:.5f}'.format(buyT0)])

AbiPair = pd.DataFrame(AbiPair, columns=["T0", "T1", "T2", "BuyT1", "BuyT2", "BuyT0"])
AbiPair = AbiPair.sort_values('BuyT0', ascending=False)

print()
print('3通貨ルートの総数は ' + str(len(AbiPair)) + ' 種')
print('(無効値 ' + str(mk) + '種')
print()
print()

pd.set_option('display.max_rows', None) # すべての行を表示
print(AbiPair.dropna(subset=['BuyT1', 'BuyT2', 'BuyT0']))
print()
print()
print(str(datetime.today())[0:19] +' プログラム終了')

```
#以下コード詳細
##1.準備
```python

import ccxt
from datetime import datetime
import pandas as pd

pd.set_option('display.max_rows', 1500) # 省略させない
binance = ccxt.binance()
binance.load_markets()
```

各ライブラリを呼び出します。[load_markets](https://github.com/ccxt/ccxt/wiki/Manual#loading-markets)はとりあえず呼んどけみたいな感じ。

##2.取引ペア取得
```python

Pairlists = list(binance.markets.keys())
Pl_sum = len(Pairlists)
```
keysの中身はこんな感じ。[シンボル](https://github.com/ccxt/ccxt/wiki/Manual#symbols-and-market-ids)って言うんですかね。取引出来る通貨ペア全種が得られます。

```python:print(Pairlists)
['ETH/BTC', 'LTC/BTC', 'BNB/BTC', 'NEO/BTC', 'QTUM/ETH', 'EOS/ETH', 'SNT/ETH', 'BNT/ETH', 'BCH/BTC', 'GAS/BTC', 'BNB/ETH', 'BTC/USDT', 'ETH/USDT', 'HSR/BTC', 'OAX/ETH', 'DNT/ETH', 'MCO/ETH', 'ICN/ETH', 'MCO/BTC', 'WTC/BTC', 'WTC/ETH', 'LRC/BTC', 'LRC/ETH', 'QTUM/BTC', 'YOYOW/BTC', 'OMG/BTC', 'OMG/ETH', 'ZRX/BTC', 'ZRX/ETH', 'STRAT/BTC', 'STRAT/ETH', 'SNGLS/BTC', 'SNGLS/ETH', 'BQX/BTC', 'BQX/ETH', 'KNC/BTC', 'KNC/ETH', 'FUN/BTC', 'FUN/ETH', 'SNM/BTC', 'SNM/ETH', 'NEO/ETH', 'IOTA/BTC', 'IOTA/ETH', 'LINK/BTC', 'LINK/ETH', 'XVG/BTC', 'XVG/ETH', 'SALT/BTC', 'SALT/ETH', 'MDA/BTC', 'MDA/ETH', 'MTL/BTC', 'MTL/ETH', 'SUB/BTC', 'SUB/ETH', 'EOS/BTC', 'SNT/BTC', 'ETC/ETH', 'ETC/BTC', 'MTH/BTC', 'MTH/ETH', 'ENG/BTC', 'ENG/ETH', 'DNT/BTC', 'ZEC/BTC', 'ZEC/ETH', 'BNT/BTC', 'AST/BTC', 'AST/ETH', 'DASH/BTC', 'DASH/ETH', 'OAX/BTC', 'ICN/BTC', 'BTG/BTC', 'BTG/ETH', 'EVX/BTC', 'EVX/ETH', 'REQ/BTC', 'REQ/ETH', 'VIB/BTC', 'VIB/ETH', 'HSR/ETH', 'TRX/BTC', 'TRX/ETH', 'POWR/BTC', 'POWR/ETH', 'ARK/BTC', 'ARK/ETH', 'YOYOW/ETH', 'XRP/BTC', 'XRP/ETH', 'MOD/BTC', 'MOD/ETH', 'ENJ/BTC', 'ENJ/ETH', 'STORJ/BTC', 'STORJ/ETH', 'BNB/USDT', 'VEN/BNB', 'YOYOW/BNB', 'POWR/BNB', 'VEN/BTC', 'VEN/ETH', 'KMD/BTC', 'KMD/ETH', 'NULS/BNB', 'RCN/BTC', 'RCN/ETH', 'RCN/BNB', 'NULS/BTC', 'NULS/ETH', 'RDN/BTC', 'RDN/ETH', 'RDN/BNB', 'XMR/BTC', 'XMR/ETH', 'DLT/BNB', 'WTC/BNB', 'DLT/BTC', 'DLT/ETH', 'AMB/BTC', 'AMB/ETH', 'AMB/BNB', 'BCH/ETH', 'BCH/USDT', 'BCH/BNB', 'BAT/BTC', 'BAT/ETH', 'BAT/BNB', 'BCPT/BTC', 'BCPT/ETH', 'BCPT/BNB', 'ARN/BTC', 'ARN/ETH', 'GVT/BTC', 'GVT/ETH', 'CDT/BTC', 'CDT/ETH', 'GXS/BTC', 'GXS/ETH', 'NEO/USDT', 'NEO/BNB', 'POE/BTC', 'POE/ETH', 'QSP/BTC', 'QSP/ETH', 'QSP/BNB', 'BTS/BTC', 'BTS/ETH', 'BTS/BNB', 'XZC/BTC', 'XZC/ETH', 'XZC/BNB', 'LSK/BTC', 'LSK/ETH', 'LSK/BNB', 'TNT/BTC', 'TNT/ETH', 'FUEL/BTC', 'FUEL/ETH', 'MANA/BTC', 'MANA/ETH', 'BCD/BTC', 'BCD/ETH', 'DGD/BTC', 'DGD/ETH', 'IOTA/BNB', 'ADX/BTC', 'ADX/ETH', 'ADX/BNB', 'ADA/BTC', 'ADA/ETH', 'PPT/BTC', 'PPT/ETH', 'CMT/BTC', 'CMT/ETH', 'CMT/BNB', 'XLM/BTC', 'XLM/ETH', 'XLM/BNB', 'CND/BTC', 'CND/ETH', 'CND/BNB', 'LEND/BTC', 'LEND/ETH', 'WABI/BTC', 'WABI/ETH', 'WABI/BNB', 'LTC/ETH', 'LTC/USDT', 'LTC/BNB', 'TNB/BTC', 'TNB/ETH', 'WAVES/BTC', 'WAVES/ETH', 'WAVES/BNB', 'GTO/BTC', 'GTO/ETH', 'GTO/BNB', 'ICX/BTC', 'ICX/ETH', 'ICX/BNB', 'OST/BTC', 'OST/ETH', 'OST/BNB', 'ELF/BTC', 'ELF/ETH', 'AION/BTC', 'AION/ETH', 'AION/BNB', 'NEBL/BTC', 'NEBL/ETH', 'NEBL/BNB', 'BRD/BTC', 'BRD/ETH', 'BRD/BNB', 'MCO/BNB', 'EDO/BTC', 'EDO/ETH', 'WINGS/BTC', 'WINGS/ETH', 'NAV/BTC', 'NAV/ETH', 'NAV/BNB', 'LUN/BTC', 'LUN/ETH', 'TRIG/BTC', 'TRIG/ETH', 'TRIG/BNB', 'APPC/BTC', 'APPC/ETH', 'APPC/BNB', 'VIBE/BTC', 'VIBE/ETH', 'RLC/BTC', 'RLC/ETH', 'RLC/BNB', 'INS/BTC', 'INS/ETH', 'PIVX/BTC', 'PIVX/ETH', 'PIVX/BNB', 'IOST/BTC', 'IOST/ETH', 'CHAT/BTC', 'CHAT/ETH', 'STEEM/BTC', 'STEEM/ETH', 'STEEM/BNB', 'XRB/BTC', 'XRB/ETH', 'XRB/BNB', 'VIA/BTC', 'VIA/ETH', 'VIA/BNB', 'BLZ/BTC', 'BLZ/ETH', 'BLZ/BNB', 'AE/BTC', 'AE/ETH', 'AE/BNB', 'RPX/BTC', 'RPX/ETH', 'RPX/BNB', 'NCASH/BTC', 'NCASH/ETH', 'NCASH/BNB', 'POA/BTC', 'POA/ETH', 'POA/BNB', 'ZIL/BTC', 'ZIL/ETH', 'ZIL/BNB', 'ONT/BTC', 'ONT/ETH', 'ONT/BNB', 'STORM/BTC', 'STORM/ETH', 'STORM/BNB', 'QTUM/BNB', 'QTUM/USDT', 'XEM/BTC', 'XEM/ETH', 'XEM/BNB', 'WAN/BTC', 'WAN/ETH', 'WAN/BNB', 'WPR/BTC', 'WPR/ETH', 'QLC/BTC', 'QLC/ETH', 'SYS/BTC', 'SYS/ETH', 'SYS/BNB', 'QLC/BNB', 'GRS/BTC', 'GRS/ETH', 'ADA/USDT', 'ADA/BNB', 'CLOAK/BTC', 'CLOAK/ETH', 'GNT/BTC', 'GNT/ETH', 'GNT/BNB', 'LOOM/BTC', 'LOOM/ETH', 'LOOM/BNB', 'XRP/USDT', 'BCN/BTC', 'BCN/ETH', 'BCN/BNB', 'REP/BTC', 'REP/ETH', 'REP/BNB', 'TUSD/BTC', 'TUSD/ETH', 'TUSD/BNB', 'ZEN/BTC', 'ZEN/ETH', 'ZEN/BNB', 'SKY/BTC', 'SKY/ETH', 'SKY/BNB', 'EOS/USDT', 'EOS/BNB', 'CVC/BTC', 'CVC/ETH', 'CVC/BNB', 'THETA/BTC', 'THETA/ETH', 'THETA/BNB', 'XRP/BNB', 'TUSD/USDT', 'IOTA/USDT', 'XLM/USDT', 'IOTX/BTC', 'IOTX/ETH', 'QKC/BTC', 'QKC/ETH', 'AGI/BTC', 'AGI/ETH', 'AGI/BNB', 'NXS/BTC', 'NXS/ETH', 'NXS/BNB', 'ENJ/BNB', 'DATA/BTC', 'DATA/ETH', 'ONT/USDT', 'TRX/USDT', 'ETC/USDT', 'ETC/BNB', 'ICX/USDT', 'SC/BTC', 'SC/ETH', 'SC/BNB', 'NPXS/BTC', 'NPXS/ETH', 'VEN/USDT', 'KEY/BTC', 'KEY/ETH', 'NAS/BTC', 'NAS/ETH', 'NAS/BNB', 'MFT/BTC', 'MFT/ETH', 'MFT/BNB', 'DENT/BTC', 'DENT/ETH']
```

本執筆時で370種でした。ｵｵｽｷﾞｨ!
Pl_sumに種類数を突っ込んでおきます。

##3.各ペアのレート取得
```python
s = []

for i in range(Pl_sum):
    name = str(Pairlists[i])
    c1 = name.split("/")[0]
    c2 = name.split("/")[1]
    ask = ccxt.binance().fetch_ticker(Pairlists[i])['ask']
    bid = ccxt.binance().fetch_ticker(Pairlists[i])['bid']

    s.append([name, c1, c2, ask, bid, str(datetime.today())[0:19]])

    price = pd.DataFrame(s, columns=["name", "c1", "c2", "ask", "bid", "time"])

price = price.set_index("name")
```
ask,bidの取得に合わせて、シンボル名称がスラッシュで区切られているのを前提に分割しておきます。後で使います。
またこの量だと時間差がかなり出てくるので、時刻を併記しておきます。これは使い道は無いですが、気になったので。

```python:print(price)
              c1    c2           ask           bid                 time
name                                                                   
ETH/BTC      ETH   BTC  7.183900e-02  7.181400e-02  2018-07-08 10:45:34
LTC/BTC      LTC   BTC  1.248900e-02  1.247800e-02  2018-07-08 10:45:34
BNB/BTC      BNB   BTC  2.074200e-03  2.070500e-03  2018-07-08 10:45:36
NEO/BTC      NEO   BTC  5.784000e-03  5.779000e-03  2018-07-08 10:45:36
QTUM/ETH    QTUM   ETH  1.884000e-02  1.878900e-02  2018-07-08 10:45:36
EOS/ETH      EOS   ETH  1.830000e-02  1.828000e-02  2018-07-08 10:45:36
SNT/ETH      SNT   ETH  1.683800e-04  1.672600e-04  2018-07-08 10:45:37
BNT/ETH      BNT   ETH  6.478000e-03  6.450000e-03  2018-07-08 10:45:37
--------(中略)--------
NAS/ETH      NAS   ETH  9.493000e-03  9.477000e-03  2018-07-08 10:47:12
NAS/BNB      NAS   BNB  3.294900e-01  3.248100e-01  2018-07-08 10:47:13
MFT/BTC      MFT   BTC  2.380000e-06  2.370000e-06  2018-07-08 10:47:14
MFT/ETH      MFT   ETH  3.322000e-05  3.310000e-05  2018-07-08 10:47:14
MFT/BNB      MFT   BNB  1.160000e-03  1.134000e-03  2018-07-08 10:47:14
DENT/BTC    DENT   BTC  9.000000e-07  8.900000e-07  2018-07-08 10:47:15
DENT/ETH    DENT   ETH  1.247000e-05  1.240000e-05  2018-07-08 10:47:15
```
だんだん見える化が進んできました。

##4.通貨種を取得
```python
c = []
c = price['c1'].tolist() + price['c2'].tolist()

l = set(c)
l = sorted(l)
```
前述のペアの通貨を全てリストに連結。setで重複除いて、昇順で並べます。

```python:print(l)

['ADA', 'ADX', 'AE', 'AGI', 'AION', 'AMB', 'APPC', 'ARK', 'ARN', 'AST', 'BAT', 'BCD', 'BCH', 'BCN', 'BCPT', 'BLZ', 'BNB', 'BNT', 'BQX', 'BRD', 'BTC', 'BTG', 'BTS', 'CDT', 'CHAT', 'CLOAK', 'CMT', 'CND', 'CVC', 'DASH', 'DATA', 'DENT', 'DGD', 'DLT', 'DNT', 'EDO', 'ELF', 'ENG', 'ENJ', 'EOS', 'ETC', 'ETH', 'EVX', 'FUEL', 'FUN', 'GAS', 'GNT', 'GRS', 'GTO', 'GVT', 'GXS', 'HSR', 'ICN', 'ICX', 'INS', 'IOST', 'IOTA', 'IOTX', 'KEY', 'KMD', 'KNC', 'LEND', 'LINK', 'LOOM', 'LRC', 'LSK', 'LTC', 'LUN', 'MANA', 'MCO', 'MDA', 'MFT', 'MOD', 'MTH', 'MTL', 'NAS', 'NAV', 'NCASH', 'NEBL', 'NEO', 'NPXS', 'NULS', 'NXS', 'OAX', 'OMG', 'ONT', 'OST', 'PIVX', 'POA', 'POE', 'POWR', 'PPT', 'QKC', 'QLC', 'QSP', 'QTUM', 'RCN', 'RDN', 'REP', 'REQ', 'RLC', 'RPX', 'SALT', 'SC', 'SKY', 'SNGLS', 'SNM', 'SNT', 'STEEM', 'STORJ', 'STORM', 'STRAT', 'SUB', 'SYS', 'THETA', 'TNB', 'TNT', 'TRIG', 'TRX', 'TUSD', 'USDT', 'VEN', 'VIA', 'VIB', 'VIBE', 'WABI', 'WAN', 'WAVES', 'WINGS', 'WPR', 'WTC', 'XEM', 'XLM', 'XMR', 'XRB', 'XRP', 'XVG', 'XZC', 'YOYOW', 'ZEC', 'ZEN', 'ZIL', 'ZRX']
```
全143種が得られました。

##5.ルート探索
###1.基礎通貨宣言

```python
BaseCurrency = ["BTC", "ETH", "USDT", "BNB"]
```
![hwrt.png](https://qiita-image-store.s3.amazonaws.com/0/253878/a599c619-7ed3-9591-a4e4-62c59d7f0f18.png)
アルトコイン同士の取引は出来るわけ無く、ベースとなる支払いに使える通貨が限られています。BTCでしかやるつもり無いですが、4種宣言してリストに入れておきます。
###2.ループ処理開始
```python
for i0 in range(len(BaseCurrency)):
    T0 = BaseCurrency[i0]
```

これからT0、T1、T2と言う変数に3種の通貨を割り当てて行きます。
T0でT1を買う、T1でT2を買う、T2でT0を買い戻す　というルートを導くために処理をつなげます。

###3.第1購入通貨決定
```python
    for i1 in range(len(l)):
        T1 = l[i1]
        if ((T0 + "/" + T1 in Pairlists) == True) or ((T1 + "/" + T0 in Pairlists) == True):
```
最初のT0は”BTC"です。
最初のl[i1]は通貨名昇順第1番目”ADA"です。
keysのリスト内に、**"BTC/ADA" or "ADA/BTC"** が居ることを確認して次に行きます。

###3.第2購入通貨決定
```python
            for i2 in range(len(l)):
                T2 = l[i2]
                if ((T2 + "/" + T1 in Pairlists) == True) or ((T1 + "/" + T2 in Pairlists) == True):
```
最初のT1は”ADA"です。
最初のl[i2]は通貨名昇順第1番目”ADA"です。
keysのリスト内に、**"ADA/ADA" or "ADA/ADA"** が居ないので行けませんね。

次のl[i2]は通貨名昇順第**2**番目”ADX"です。
keysのリスト内に、**"ADA/ADX" or "ADX/ADA"** が居ないので行けませんね。
(中略)

X番目のl[i2]は”BNB"です。
keysのリスト内に、**"ADA/BNB" or "BNB/ADA"** が居るので次に行きます。

###4.ルート確定
```python
                    if ((T2 + "/" + T0 in Pairlists) == True) or ((T0 + "/" + T2 in Pairlists) == True):
```

T0は”BTC"です。
T2は"BNB"です。

keysのリスト内に、**"BTC/BNB" or "BNB/BTC"** が居るので次に行きます。

###5.レート収集
```python

                        # 1st buy
                        if (T1 + "/" + T0 in price.index.values) == True:
                            buyT1 = 1 / price.at[str(T1 + "/" + T0), 'ask']
                        else:
                            buyT1 = price.at[str(T0 + "/" + T1), 'bid']

                        # 2nd buy
                        if (T2 + "/" + T1 in price.index.values) == True:
                            buyT2 = buyT1 / price.at[str(T2 + "/" + T1), 'ask']
                        else:
                            buyT2 = buyT1 * price.at[str(T1 + "/" + T2), 'bid']

                        # 3rd buy
                        if (T0 + "/" + T2 in price.index.values) == True:
                            buyT0 = buyT2 / price.at[str(T0 + "/" + T2), 'ask'] - 1
                        else:
                            buyT0 = buyT2 * price.at[str(T2 + "/" + T0), 'bid'] - 1
```
基礎通貨(T0)、第1購入通貨(T1)、第2購入通貨(T2)の定義が出来たので、それぞれの購入時のレートを出します。
3rd buy時に最初の通貨に戻ります。
最後の -1 は好みが分かれるかも。97%/101%って形で考えるか、-3%/+1%って形で考えるか。私は後者にしました。

###6.リストへ格納
```python
                        AbiPair.append([T0, T1, T2, buyT1, buyT2, '{:.5f}'.format(buyT0)])
```
得られたレートを格納します。ここまでをループします。

###7.DataFrameへ格納
```python

AbiPair = pd.DataFrame(AbiPair, columns=["T0", "T1", "T2", "BuyT1", "BuyT2", "BuyT0"])
AbiPair = AbiPair.sort_values('BuyT0', ascending=False)
print(AbiPair)
```

利益率の高い順にソートして調理完了。printすると以下が得られます。

```python:print(AbiPair)

        T0     T1     T2         BuyT1         BuyT2     BuyT0
913   USDT    ADA    BTC  6.802721e+00  1.488435e-04   0.00049
400    BTC   USDT    ADA  6.721730e+03  4.572605e+04   0.00049
113    BTC  CLOAK    ETH  1.543925e+03  1.392157e+01   0.00038
588    ETH    BTC  CLOAK  7.185800e-02  1.109433e+02   0.00038
265    BTC    ETH    WTC  1.391304e+01  9.246390e+02   0.00018
889    ETH    WTC    BTC  6.645843e+01  7.188808e-02   0.00018
962   USDT    ETH    ETC  2.069536e-03  5.377794e-02   0.00002
733    ETH    ETC   USDT  2.598550e+01  4.832082e+02   0.00002
518    ETH    BNB    NAV  3.457456e+01  1.026561e+03  -0.02990
1224   BNB    NAV    ETH  2.969121e+01  2.805819e-02  -0.02990
1203   BNB    GTO    ETH  8.453085e+01  2.806762e-02  -0.02957
509    ETH    BNB    GTO  3.457456e+01  2.922617e+03  -0.02957
69     BTC    BNB    OST  4.808617e+02  7.591754e+04  -0.02901
1239   BNB    OST    BTC  1.578781e+02  2.019261e-03  -0.02901
502    ETH    BNB    CND  3.457456e+01  1.415830e+04  -0.02888
1113   BNB    CND    ETH  4.095004e+02  2.808763e-02  -0.02888
1223   BNB    NAV    BTC  2.969121e+01  2.021971e-03  -0.02771
62     BTC    BNB    NAV  4.808617e+02  1.427737e+04  -0.02771
(後略)
```

##6.まとめ
目的である市場の観察は果たせました。

実際中身見てみると、利益が出るのはこの瞬間で1328組中 **上位8組のみ**、とかなり厳しい戦いな模様。さらにここには**手数料が入っていない**ので実利はもっと薄まります。。。

勝ち目が薄いのは分かりましたが、ゼロではないかなと。もう少しデータ集めて見てみたいところです。

## 2020.7.4 更新
珍しくこの記事でレスを受けて見直しました。5分くらい待つコードなのですが、待ち時間に何も出ないのは不安になるので、進捗をprint。全コードってとこ以外はメンテしてないので、ちょっと差分あるのはご容赦。

特に長く待つBinanceに問い合わせしまくるところは残り秒数を出す仕込みも入れてみたり。

![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/6b05b976-934f-080f-69af-824d05c34138.gif)

あと取引として存在してるけど値が0のが居るのか、値が無限大になってしまうやつがノイジーなので除去。

[上手にビジュアライズされてる方](https://note.com/cryptocurrency2/n/nca643b43557b)まで。取引ペアを固定したあとはこーゆーこと出来ますよね。すばらしや。

[Binanceは日本取引塞いじゃうみたい](https://crypto.watch.impress.co.jp/docs/news/1229808.html)なのが残念ですねー。