UNPKG

tlab-trading-toolkit

Version:

A trading toolkit for building advanced trading bots on the GDAX platform

164 lines (163 loc) 5.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("./core"); const io = require("socket.io-client"); const stream_1 = require("stream"); const types_1 = require("./lib/types"); var connectionOptions = { "reconnection": true, "reconnectionDelay": 2000, "reconnectionDelayMax": 60000, "reconnectionAttempts": "Infinity", "timeout": 10000, "transports": ["websocket"], "secure": true }; var quoteSocket = io('http://localhost:15000/api/quotes', connectionOptions); var queue = {}; var queueing = {}; var socketConnected = false; var subscriptions = new Map(); function getSnapshot(product) { let book = subscriptions.get(product); book.book.clear(); quoteSocket.emit('snapshot', product); } function subscribe(product) { queueing[product] = true; queue[product] = []; quoteSocket.emit('subscribe', product); getSnapshot(product); } function unSubscribe(product) { quoteSocket.emit('unsubscribe', product); } class SocketIOReadStream extends stream_1.Readable { constructor() { super({ objectMode: true }); var self = this; quoteSocket.on('connect', () => { socketConnected = true; console.log('Connection established'); subscriptions.forEach((book, product) => { subscribe(product); }); //Join channel and request snapshot for all subscriptions quoteSocket.on('stream', function (data) { if (queueing[data.productId]) { queue[data.productId].push(data); if (queue[data.productId].length > 400) { queueing[data.productId] = false; queue[data.productId] = []; } } else { queue[data.productId].forEach(function (oldMessage) { self.push(oldMessage); }); self.push(data); } }); quoteSocket.on('snapshot', processSnaphshot); quoteSocket.on('disconnect', () => { socketConnected = false; }); }); } _read(size) { // This is not an on-demand service. For that, I refer you to Netflix. Data gets pushed to the queue as it comes // in from the websocket, so there's nothing to do here. } } exports.SocketIOReadStream = SocketIOReadStream; let Socket = new SocketIOReadStream(); function processSnaphshot(data) { try { console.info('Received snapshot '); let snapshot = {}; snapshot.sequence = parseInt(data.info.sequence); snapshot.productId = data.productId; snapshot.type = 'snapshot'; const bids = []; const asks = []; const orders = {}; data.bids.forEach((bid) => { const newOrder = { id: bid.price, price: types_1.Big(bid.price), size: types_1.Big(bid.totalSize), side: 'buy' }; orders[newOrder.id] = newOrder; const level = { price: types_1.Big(bid.price), totalSize: types_1.Big(bid.totalSize).abs(), orders: [newOrder] }; bids.push(level); }); data.asks.forEach((ask) => { const newOrder = { id: ask.price, price: types_1.Big(ask.price), size: types_1.Big(ask.totalSize), side: 'sell' }; orders[newOrder.id] = newOrder; const level = { price: types_1.Big(ask.price), totalSize: types_1.Big(ask.totalSize).abs(), orders: [newOrder] }; asks.push(level); }); snapshot.asks = asks; snapshot.bids = bids; snapshot.orderPool = orders; Socket.push(snapshot); queueing[data.productId] = false; } catch (err) { queueing[data.productId] = false; } } function subscribeBook(product) { let book = subscriptions.get(product); if (book) { return book; } let Book = new core_1.LiveOrderbook({ product: product, }); Book.on('LiveOrderbook.skippedMessage', (details) => { // On GDAX, this event should never be emitted, but we put it here for completeness if (!queueing[product]) { queueing[product] = true; queue[product] = []; console.log('SKIPPED MESSAGE', details); console.log('Requesting snapshot again'); getSnapshot(product); } }); subscriptions.set(product, Book); if (socketConnected) { subscribe(product); } Socket.pipe(Book); return Book; } exports.subscribeBook = subscribeBook; function unsubscribeBook(product) { let book = subscriptions.get(product); if (!book) { console.warn('Unsubscribe recieved for book not present'); return; } unSubscribe(product); Socket.unpipe(book); subscriptions.delete(product); } exports.unsubscribeBook = unsubscribeBook; global.subscribeBook = subscribeBook; global.unsubscribeBook = unsubscribeBook; exports.default = subscribeBook;