投資に関係ないユーザーでも参考になるようにデータに関して少し説明する。
次のようなJSONデータを時系列DBで正しく扱えるのか、という命題だ。
// message
{
"mid_price": 33320,
"bids": [
{
"price": 30000,
"size": 0.1
},
{
"price": 25570,
"size": 3
}
],
"asks": [
{
"price": 36640,
"size": 5
},
{
"price": 36700,
"size": 1.2
}
]
}
★公式に掲載されているサンプルを引用
ここで問題なのは bid と ask が配列になっていることだ。通常データーベースでこのような一対多のデータを扱う場合はテーブルを分けて扱うはずだが、これはそういうDBではない。
1つのテーブルに複数のデータが入れられないかやってみる。次のようなスキーマを定義する。
★Node.jsのためJavaScriptの構文で進める。
const influx = new Influx.InfluxDB({
host: 'localhost',
database: 'bitFlyer_db',
schema: [
{
measurement: 'lightning_board_snapshot_FX_BTC_JPY',
fields: {
mid_price: Influx.FieldType.INTEGER,
bids: [
{
price: Influx.FieldType.INTEGER,
size: Influx.FieldType.FLOAT
}
],
asks: [
{
price: Influx.FieldType.INTEGER,
size: Influx.FieldType.FLOAT
}
]
},
tags: [
]
}
]
})
できないのである。
例えば上のような定義を行って次のコードでデータを送るとエラーだ。
なおデータはmessage
という変数に格納されて送られてくるとする
influx.writePoints([
{
measurement: 'lightning_board_snapshot_FX_BTC_JPY',
tags: {},
fields: {
mid_price: message.mid_price,
asks: [...message.asks], //asks: message.asks でももちろんだめ
bids: [...message.bids],
},
}
スプレッド構文がだめとかそういうのは関係なくだめなのだ。
英語フォーラムにも同じ質問をしているページがあり「できないよ(1個づつ分け定義してね)」と解答されている。
今回は次の方法で対応という解決策しか浮かばなかった。
schema: [
{
measurement: 'lightning_board_snapshot_FX_BTC_JPY',
fields: {
mid_price: Influx.FieldType.INTEGER,
asks: Influx.FieldType.STRING,
bids: Influx.FieldType.STRING,
},
tags: []
}
]
asks と bids を単なる string と定義する。
const asks = JSON.stringify(message.asks)
const bids = JSON.stringify(message.bids)
influx.writePoints([
{
measurement: 'lightning_board_snapshot_FX_BTC_JPY',
tags: {},
fields: {
mid_price: message.mid_price,
asks: asks,
bids: bids,
},
}
JSON.stringify
を使って強制的に文字列にした。
当然ながらChronograf等で可視化が不可能となる。またデータをリードして使用する時に JSON.parse
による復元処理が必要になる。
文字列として格納される。とりあえずは保存できている。
そもそも気づけば私自身データベースの設計などしたことがない。このあたりは実務でやってる人間とそうでないとで大きく分かれそうだ。
とりあえずデータは正しく記録さえできればそれでよいのであるが、これが最適解とは言い難い。
askとbidのテーブルに分けて { price, size }
を1件としてバラバラにしたらどうか?
確かに時系列にさえなっていれば、データがバラバラでも再現時にシーケンシャルリードしてグラフにはめていくだけで良い。
試してみる価値はあるかもしれないが、データの件数がえげつないことになりそうなのでとりあえずやってない。
板データのような秒間に200件近く入ってくるレコードの登録(writePoints)は処理速度が間に合うのかどうか。
今回は時間の都合でここまでとする。