売りと買いどちらの板が厚いかが目視しやすいというメリットを発見した。
BitMEXと違い厚みに応じて中央が左右に動くがこれはこれで分かりやすい。
前回の板表示がBitMEXと反対側だったので今回からわかりやすくBitMEXとおなじになるよう修正する。
DepthChart.js
というファイルを切ってモジュール化した。
export const depthChart = (message,range) => {
const ask = askHistogram(message,range)
const bid = bidHistogram(message,range)
const labels = bid.labels.concat(ask.labels)
const data = bid.data.concat(ask.data)
let backgroundColor = new Array(bid.labels.length + ask.labels.length )
backgroundColor.fill("green",0,bid.labels.length )
backgroundColor.fill("red",bid.labels.length,bid.labels.length + ask.labels.length )
const board_data = {
labels,
datasets: [
{
label: "Depth Chart",
data,
backgroundColor,
},
]
}
return board_data
}
ask
とbid
の定数にそれぞれ2つのヒストグラムを読み込む。
コードが冗長になるのでaskHistogram()
の中身だけ記述する。
const askHistogram = (message, range) => {
//asks(売り板)
//price順で整列し直す(bitFlyerが順番を保証していないため)
message.asks.sort((a, b) => {
// 昇順
return a.price - b.price
});
//ヒストグラムを生成(階級幅:range)
const min_price = message.asks[0].price //階級を確定するためには最大価格が必要
let data = []
for (let ask of message.asks) {
//階級=配列番号を計算
const bin = Math.floor( (ask.price - min_price) / range)
!data[bin] ? data[bin] = ask.size : data[bin] = data[bin] + ask.size
}
//ラベルを設定
let labels = []
for (let i = 0; i <= data.length - 1; i++) {
const label = min_price + (range * i)
labels.push(label)
// //累積度数化
if (!data[i]) { data[i] = 0 }
i != 0 ? data[i] = data[i - 1] + data[i] : null
}
return {labels, data}
}
concat
const labels = bid.labels.concat(ask.labels)
const data = bid.data.concat(ask.data)
配列と配列をくっつける処理にconcatを使用する。もともとそのために用意された関数。文法は調べればよいが、このような関数があることだけは知っておきたい。
これは2つのチャートを一つに纏めている。チャートは左から順にデータが入っていくで、左側にくるBid
(買い)にask
(売り)をマージするイメージだ。
fill
let backgroundColor = new Array(bid.labels.length + ask.labels.length )
backgroundColor.fill("green",0,bid.labels.length )
backgroundColor.fill("red",bid.labels.length,bid.labels.length + ask.labels.length )
datasets(Chart.js)のプロパティにbackgroundColor
がある。値を一つだけ渡してやれば全体がその色になるが、ここに配列を渡してやると棒1本が配列に指定されたそれぞれの色で描画できる。
ここでは棒1本に対して1要素生成し、左を緑、右を赤に分けている。
fillというメソッドは指定したデータで配列を埋めるコードだ。知らなければ別のコードで代用してしまいそうだがスマートな記述となるため覚えておきたい。
コード一番下の"red"の例のように数字を指定して途中から埋めることもできる。
return
return {labels, data}
ES6よりオブジェクトがreturn
できる。これにより複数の値をreturn
するとき受け取った側の変数呼び出しが楽になる。
上ではAsk(売り)側のコードを記述したが、Bid(買い)側のコードは累積度数が逆からの計算になるため参考にしていただきたい。
//ラベルを設定
let labels = []
for (let i = 0; i <= data.length - 1; i++) {
const label = (range * i) + min_price
labels.push(label)
}
// iが配列の後ろから処理している点に注意
for(let i = data.length - 1; i >= 0; i--){
//累積度数化
if (!data[i]) { data[i] = 0 }
i != data.length - 1 ? data[i] = data[i + 1] + data[i] : null
}
return {labels,data}
公開するシステムに取り込むのであればもっといろいろオプション設定など実装できそうだが、とりあえず一段落してしたのでさらなる分析の手法を考えていきたい。
ピンポイントで板が厚い箇所は分かりにくいが全体的な厚みが把握できるメリットが発見できただけでもよしとする。