2020-03-20

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

本日より板データの可視化を開発してみる。

Article Image

今回から新しい試みを行う

サーバ<>クライアント型でデータの可視化を行う。

少し難しくなるがコードの解説を詳しくやっていくと終わらないので割愛させて頂く。

アーキテクチャ図のような物

# アーキテクト図のような物

バックエンドとフロントエンドを分ける理由

実はsocket.io-clientVue.jsから直接呼び出せるのでNode.jsサーバは省略できる。

しかし、将来的に中央のNode.jsサーバは24h稼働にして自動取引やデータ保存用としたいのでこの構成でスタートする。

余談:本来ならNode.jsの自前サーバ内からexpressVue.jsのHTTPサーバを兼任できるが、今回はコードをとにかく短く+サーバ軽量化もできるのでHTTPサーバはVue.jsの開発サーバ機能を使っていく。

Node.jsサーバ側のコード

まずはメインとなるindex.js

const bF = require('./bitFlyer.js')
const PORT = process.env.PORT || 7000;
const io = require('socket.io')(PORT)

const socket_bF_client = bF()

io.on('connection', function (socket) {
    console.log(`a user connected[id:${socket.id}]`)
    socket_bF_client.on("lightning_board_snapshot_FX_BTC_JPY", (message) => {
        socket.emit("lightning_board_snapshot_FX_BTC_JPY",message)
    })
})

このコードで注意するのはioはサーバ用のオブジェクト。socket_bF_clientは板情報を受ける側のクライアント。更にsocketとなっているのはユーザ側のVue.jsが繋げてくる箇所。ここを「io.emit」にしてしまうと送信データが何個も送信されるバグになる(クライアント別ではなくクライアントの数を全chに配信している?)

続いて1行目で現れるbitFlyer.jsは公式コードをパブリックchに限定した簡易バージョンが入っている

//モジュール化
module.exports = function () {
    // Node.js (JavaScript)
    const crypto = require("crypto");
    const io = require("socket.io-client");

    // 約定情報ではなく板情報(スナップショット)に設定
    //const publicChannels = ["lightning_executions_FX_BTC_JPY"];
    const publicChannels = ["lightning_board_snapshot_FX_BTC_JPY"];

    const socket = io("https://io.lightstream.bitflyer.com", {
        transports: ["websocket"] // specify explicitly
    });

    // connection handling
    socket.on("connect", () => {
        // subscribe to the Public Channels
        for (const ch of publicChannels) {
            socket.emit("subscribe", ch, err => {
                if (err) {
                    console.error(ch, "Subscribe Error:", err);
                    return;
                }
                console.log(ch, "Subscribed.");
            });
        }
      
       // 公式はここにプライベートチャンネルのコードがあったが削除
      
    });

    // 重要! index.jsで.onメソッドを受けるためにsocketごとreturnする
    return socket;
}

publicChannelsの配列に入れる文字列(板情報を指定)は公式に表記があるので参照のこと。

keysecretは必要ないので消去してある。合わせてプライベートチャンネル用のコードも削除。

socketreturnしてindex.jsで利用している点に注意。

コード的にエラーになりそうな箇所ではあるがなんの問題もなく動作している。

画面上は接続情報しか表示されないが裏で板情報を定期的に取得し続ける。

Vue.jsクライアントサイドのコード

長くなるので必要な箇所のみ記述。将来的に外観を美しく揃えたいのでVuetifyを予めaddしてあるが今回のコードに影響はない。

<script> //参考
  
//スクリプトタグの下にインポート
import io from "socket.io-client";

export default { //参考

mounted部。Vue.jsに関しての説明は他サイトを参照。

  mounted() {
    //今回はNode.jsサーバもローカルで動いている
    this.socket = io("http://localhost:7000");

    //Node.jsサーバに接続
    this.socket.on("connect", () => {
      //Node.jsサーバが板情報を受け取り次第Vue.js側にも同じメッセージをemitする
      this.socket.on("lightning_board_snapshot_FX_BTC_JPY", message => {
        // Vue.jsのdataに生のまま格納
        this.board_data = message
      });
    });
  },

テンプレート部。生で board_data を表示する。

<template>
  <v-container>
    <v-row class="text-center">
      {{board_data}}
    </v-row>
  </v-container>
</template>

実行結果

Node.jsサーバー側を起動

node index.js

別のターミナルにてVue.jsの開発サーバで起動

npm run serve

ブラウザにて http://localhost:8080/ (環境によってポートは変わる)にて動作確認。

動作確認

JSONがそのままテキストで表示されれば今回は完了だ。

次回から

このデータを加工し棒グラフのような表示にしていきたい。chart.jsの導入を考えているがこのあたりは実験も兼ねながらとなるが少しづつ記事にしていきたい。



この記事をシェア


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