【node.js】Socket.IOでBitFlyerのBTCFXチャートデータ生成を自作する


CSG夏休みAdventCalendar23日目です。

Dockerとか書いてみたかったのですが書けるレベルにまでは至っていなかったのでまたの機会に。

部活のイベントで書くネタとしてはどうかとも思いましたがせっかくなのでアウトプットしようという事で、今回は某LTで使ったネタの一部から、仮想通貨自動売買テクニックの一部をご紹介します。

はじめに

テクニックとは言っても唯の実装なんですが、何故わざわざ自分で収集するかといいますと。

実際、自動売買やろうと思うとCryptowatchなんていうAPIを使うのがメジャーなわけですが、1か月ほど前に1, 5分の短い時間足で数分間データが抜けてたり価格が違っていたことがありました。

裁量トレードの場合、多少値段が違うくらいならそこまで困ることもないのですが、自動売買ではチャートデータを元にエントリー基準などを決めるので、正確なデータを抜けなく取得出来る信用できる方法が必要なわけです。

という事で既にCryptowatchAPIを前提に実装しているBotに適応するため、CryptowatchのResponseと同じ形式のデータを作成したいと思います。

前提

CryptowatchReferenceなんかを見てみると以下のようなjsonが返却されます。

{
  "result":
      {
        "14400": 
          [
            [CloseTime, O, H, L, C, V],
            [CloseTime, O, H, L, C, V],
          ]
      }
}

なので最終取引時間, 始値, 高値, 安値, 終値, 出来高を足事に配列で持たせてやればいいことになりますね。

実装

今回はnode.jsでSocket.ioを用いて実装していきます。

まずはSocket.IOクライアントのとmomentのインストール。

$ npm i -S socket.io-client moment

それではコーディングを始めていきましょう。

 $ vi ohlcgenerator.js
const io = require('socket.io-client');

const moment = require('moment');

const STREAM_URI = 'https://io.lightstream.bitflyer.com';
const FX_EXECUTIONS_CHANNEL = 'lightning_executions_FX_BTC_JPY';
const minTimeinterval = 1; //min

const socket = io(STREAM_URI, { transports: ['websocket'] });
socket.on('connect', () => {
    socket.emit('subscribe', FX_EXECUTIONS_CHANNEL);
});

socket.on(FX_EXECUTIONS_CHANNEL, message => {
        updateOhlc(message[0].exec_date, message[0].price, message[0].size);
});

let ohlcv = [];

const updateOhlc = (date, price, size) => {
    currentBar = ohlcv[ohlcv.length - 1];
    if(ohlcv.length == 0 || makeTimestamp(currentBar[0]) != makeTimestamp(date)) {
            ohlcv.push([date, price, price, price, price, size]);
    } else {
            if(currentBar[2] < price) currentBar[2] = price;
            else if(currentBar[3] > price) currentBar[3] = price;
            currentBar[4] = price;
            currentBar[5] += size;
    }
    //ここでストラテジ関数を実行したり?
    //strategy.proc(ohlcv);
};

/*指定時間足*/
const makeTimestamp = (date) => {
    let time = moment(date);
    let result = -1;
    if(minTimeinterval >= 60) {
            result = time.hour() * 60 / minTimeinterval;
    } else {
            result = time.minute() / minTimeinterval;
    }
    return Math.floor(result);
};

さいごに

プログラムを起動した時点からのデータしか収集できないため、botとは別プログラムにして別途DBにOHLCデータとして格納して置いたり、botと同じプログラムに組み込むのであればohlcの初期化にはCryptowatchのAPI等を用いてもいいかもしれません。

また、StereamingAPIからのデータ流入が止まる事もあるので、その対策も必要になってきます。

(昨日今日と少し忙しかったので軽めの書き込みですが後日修正など行いたいと思います)