2020-03-23

Node.js x bitFlyer API #7 板データの可視化(2)

vue-chart.jsによる板情報の可視化をテストしてみる

Article Image

実験的内容

どのような表示が効果的なのかが分からないのでとにかくアイデアを実装してみる。

vue-chart.jsが投資情報の可視化に役立つかどうかも確認していきたい。

表示結果

次のような実装となった(ask板のみ)

ask板

所感

正直微妙である。

確かに板の厚みは多少なりとも分かるが一定のチャートの描画領域のなかで価格の上下は分かりにくい。

またはBITMEX板のように積み上げる形式のほうが分かりやすいのかもしれない(手前の板の厚みを次の板に足していく方式)

またリアルタイムな板情報の差分は反映していないため反応速度は遅い。

まだ初期段階のためとにかくできることを色々やってみたい。

コード

    this.socket = io("http://localhost:7000");

    this.socket.on("connect", () => {
      this.socket.on("lightning_board_snapshot_FX_BTC_JPY", message => {

        //チャートデータをクリア
        this.resetData();

        //price順で整列し直す(bitFlyerが順番を保証していないため)
        message.asks.sort((a, b) => {
          return a.price - b.price;
        });

        // asks
        let _prev_price = 0;
        let _total = 0;
        for (let ask of message.asks) {
          const price = Math.round(ask.price / 100) * 100
          if (price > _prev_price) {
            _prev_price != 0 ? this.board_data.labels.push(_prev_price) &&
            this.board_data.datasets[0].data.push(_total) : null
            _prev_price = price
            _total = 0
          } else {
            _total = _total + ask.size;
          }
        }
        //最後の1行が残ってしまうので追加する
        _total != 0
          ? this.board_data.labels.push(_prev_price) &&
            this.board_data.datasets[0].data.push(_total)
          : null;

        //リアクティブにするためにデータを渡す
        this.datacollection = this.board_data;
      });
    });
  },

socket.ioの接続先は私が用意したサーバである。データを受信するアーキテクチャ概要は前回の記事を参照していただきたい。

board_data というグローバル変数を用意した。「リアクティブに描画する」の項で必要性を解説。

冒頭の resetData() 関数にてこれをを初期化する。

これは板情報が送られてくる度に初期状態に戻している。

nullのままでpushを行うとエラーが出るというjavaScriptの特性も理解しておく。

    resetData() {
      this.board_data = {
        labels: [],
        datasets: [
          {
            label: "ask",
            data: [],
            backgroundColor: "blue",
            barPercentage: 1
          },
        ]
      };
    },

プライスのソート

        message.asks.sort((a, b) => {
          return a.price - b.price;
        });

公式より

asks, bids の配列の順序は保証していないため、必要に応じてソートしてください。

というわけでpriceでソートした。sort方法はMDNを参照。よく使うので覚えておくと良い。

forの中身

const price = Math.round(ask.price / 100) * 100

100円単位で纏めるを実装した。

情報的には細かく見たほうがトレードには役に立ちそうだが人間の視認能力の限界をこえた量に感じたため。100円でも数字を追うのは難しく感じる。あくまでチャートの面積で判断できるレベルか。

forの中身自体はかなり強引な纏め方をしているので(例えば板がない100円空間があれば、そのグラフは非表示にされ200円飛ばしの箇所ができてしまう)もっと良い方法があると思われる。

リアクティブに描画する

今回はここだけ覚えておけばよいかと思う。

次のようにテンプレートに渡している変数に代入する形で更新してやらないとチャートが再描画されない。

//リアクティブにするためにデータを渡す
this.datacollection = this.board_data;

// 参考:テンプレート部は次のように読み込んでいるため
<BarChart :chart-data="datacollection" :options="options" />

どういうわけか this.datacollectionpushで直接追加しても更新されないのだ。理由は不明。このような方法を取ると覚える。

options(chart.js)

オプションは次のようにした。

      this.options = {
        responsive: false,
        maintainAspectRatio: false,
        legend: {
          position: "bottom"
        },
        layout: {
          padding: 20
        },
        scales: {
          xAxes: [
            {
              ticks: {
                beginAtZero: true,
                max: 10,
                min: 0
              }
            }
          ]
        }
      }

HorizontalBar チャートを使用した。

合わせてこちらの記事yAxesだった箇所を xAxesに変更している。 横表示のグラフに変更するとX軸とY軸が入れ替わるからだ。

vue-chart.js Tips

Chart.jsではなくvue-chart.js側で実装されているであろう機能があった。APIというページの存在に気づいていなかった(しかも日本語解説)

コーディングリファレンスのページより

// テンプレートを読み込む時に横幅、縦幅を設定できるらしい。
<BarChart :chart-data="datacollection" :options="options" width="1000"/>

width="1000" の箇所。もちろん heightも指定可能。

いろいろな使い方ができそうだ。



この記事をシェア


謎の技術研究部 (謎技研)