noteのタイトル画像

HTML一つだけでCCXTを使う

目次
・サーバサイドで有名なCCXTをブラウザだけから使いたい
・HTML内のscriptタグから直接呼び出すには制限があった
・邪の道はHeroku
・ただし、遅い

●サーバサイドで有名なCCXTをブラウザだけから使いたい

仮想通貨bot界隈で非常に人気の高いCCXT(CryptoCurrency eXchange Trading library)を「ブラウザ」だけから使って見たいと思いました。

HTMLを起動するだけで、仮想通貨取引所と簡単取引できたら楽チンだろうなぁ、というのが単純な 発想です。

で、さっそくHTML内のScriptタグにccxtを組み込んでみましょう。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <title>ccxt 試験</title>
  <!-- ccxt -->
  <script type="text/javascript" src="https://unpkg.com/ccxt"></script>
</head>

<body>
  <script>
    const bf = new ccxt.bitflyer({
      apiKey: 'xxxxx',
      secret: 'yyyyy',
    });

  </script>
</body>

</html>

上記の例はbitflyerのCCXTオブジェクトを作成しているところです。
(apiKey, secretはまだ設定していませんが、本番では設定します)

ね、簡単でしょう。

これでサクサク発注できたら素晴らしいです。

と、、、そうは問屋が卸してくれません。

このまま良い気になってCCXTのメソッドを呼び出しても色々と失敗することになります。

例えばtickerを取ってみましょう。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <title>ccxt 試験</title>
  <!-- ccxt -->
  <script type="text/javascript" src="https://unpkg.com/ccxt"></script>
</head>

<body>
  <script>
    const bf = new ccxt.bitflyer({
      apiKey: 'xxxxx',
      secret: 'yyyyy',
    });

    bf.fetchTicker('FX_BTC_JPY')
      .then(r => console.log(r));
  </script>
</body>

</html>

これを実行すると、次のようなエラーが出ます。

Failed to load https://api.bitflyer.jp/v1/getmarkets: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

ここで、

CORS disabled

って言われちゃってます。

どうやら CORS 問題に引っかかっている模様です。

CORSとは、Cross-Origin Resource Sharingの略で、ブラウザがオリジン(HTMLの呼び出し元サーバ)以外のサーバにアクセスすることです。

●HTML内のscriptタグから直接呼び出すには制限があった

通常のブラウザはCORSを基本拒否しています。

そりゃそうだ、って思いました。

もし、制限なく許していたら、あちこちからアクセスされまくって、サーバが危険に晒されることになります。

CCXTのCORS対応はどうなっているでしょうか。
hasを取って、対応状況を確認します。

console.log(bf.has);

をプログラムに書き込んで、内容をダンプすると

CORS: false
cancelOrder: true
cancelOrders: false
createDepositAddress: false
createLimitOrder: true
createMarketOrder: true
createOrder: true
deposit: false
editOrder: "emulated"
fetchBalance: true
fetchBidsAsks: false
fetchClosedOrders: "emulated"
fetchCurrencies: false
fetchDepositAddress: false
fetchDeposits: false
fetchFundingFees: false
fetchL2OrderBook: true
fetchMarkets: true
fetchMyTrades: true
fetchOHLCV: "emulated"
fetchOpenOrders: "emulated"
fetchOrder: true
fetchOrderBook: true
fetchOrderBooks: false
fetchOrders: true
fetchTicker: true
fetchTickers: false
fetchTrades: true
fetchTradingFees: false
fetchTradingLimits: false
fetchTransactions: false
fetchWithdrawals: false
privateAPI: true
publicAPI: true
withdraw: true

のように出力されました。

oh my god! 

CORS: false

となっていますね。これは簡単には行きそうにないです。

●邪の道はHeroku

色々と文献を検索しても、なかなかうまい方法が見つかりません。

と、その時、CCXTにあるサンプルが目に止まりました。

以下のURL

https://github.com/ccxt/ccxt/tree/master/examples/html

に、HTMLでCCXTを使うサンプルがいくつか掲載されているではありませんか!

灯台下暗しとはこのことを言うのでしょう。

サンプルの中の一つ

 basic-cors-proxy.html

を開けて見ます。

・・・
const proxy = 'https://cors-anywhere.herokuapp.com/'
const exchange = new ccxt.bittrex ({ 'proxy': proxy })
・・・

なる記述を発見します。

んん?Heroku?

Herokuは言わずと知れたクラウドプラットフォームです。

ここがcors-anywhereというサービスを展開しているようです。

これを真似っ子して、次のように記述してみます。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <title>ccxt 試験</title>
  <!-- ccxt -->
  <script type="text/javascript" src="https://unpkg.com/ccxt"></script>
</head>

<body>
  <script>
    const bf = new ccxt.bitflyer({
      apiKey: 'xxxxx',
      secret: 'yyyyy',
      proxy: 'https://cors-anywhere.herokuapp.com/',  // ブラウザからCCXTを使用する場合、CORS問題を回避できないので、HerokuのCORSサービスを経由する
    });

    console.log(bf.has);

    bf.fetchTicker('FX_BTC_JPY')
      .then(r => console.log(r));
  </script>
</body>

</html>

これを実行してみましょう。

結果として次のようにticker情報を得ることができました。
(fetchTickerはパブリックAPIなので、apiKeyの設定は不要です)

ask: 708145
askVolume: undefined
average: undefined
baseVolume: 364338.05446995
bid: 708124
bidVolume: undefined
change: undefined
close: 708124
datetime: "2018-10-12T12:21:54.823Z"
high: undefined
info:
 best_ask: 708145
 best_ask_size: 0.02
 best_bid: 708124
 best_bid_size: 0.1349782
 ltp: 708124
 product_code: "FX_BTC_JPY"
 tick_id: 27757798
 timestamp: "2018-10-12T12:21:54.823"
 total_ask_depth: 10814.39547986
 total_bid_depth: 13234.47816328
 volume: 370723.07781279
 volume_by_product: 364338.05446995
last: 708124
low: undefined
open: undefined
percentage: undefined
previousClose: undefined
quoteVolume: undefined
symbol: "FX_BTC_JPY"
timestamp: 1539346914823
vwap: undefined

●ただし、遅い

ですが、良いことばかりじゃありません。

とにかく応答が遅いです。

これがHerokuサービスを経由したからなのかどうかまでは計測していませんが、一瞬「あれ?」っていうくらい間(2−3秒?)があります。

秒針の間を縫うようにトレードする方にはお勧めできません。

CCXTを使わないで、直接取引所のAPIを呼び出した方が「おそらく」高速でしょう。
リクエストヘッダにCORS対応を割りこませれば良いと思います。

無理やりCCXTをHTML上で使う利点としては、

・煩わしい前処理とか不要
・多くの著名な取引所をサポート
・インターフェイスが統一されていてわかりやすい

ってことでしょうかね。

サクッとCCXTを使って証拠金残高とかを表示させる用途には良いのではないでしょうか。

今回はこの辺で。


ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。