tlab-trading-toolkit
Version:
A trading toolkit for building advanced trading bots on the GDAX platform
164 lines (163 loc) • 5.36 kB
JavaScript
;
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;