どのような表示が効果的なのかが分からないのでとにかくアイデアを実装してみる。
vue-chart.jsが投資情報の可視化に役立つかどうかも確認していきたい。
次のような実装となった(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を参照。よく使うので覚えておくと良い。
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.datacollection
に push
で直接追加しても更新されないのだ。理由は不明。このような方法を取ると覚える。
オプションは次のようにした。
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軸が入れ替わるからだ。
Chart.jsではなくvue-chart.js側で実装されているであろう機能があった。APIというページの存在に気づいていなかった(しかも日本語解説)
コーディングリファレンスのページより
// テンプレートを読み込む時に横幅、縦幅を設定できるらしい。
<BarChart :chart-data="datacollection" :options="options" width="1000"/>
width="1000"
の箇所。もちろん height
も指定可能。
いろいろな使い方ができそうだ。