UNPKG

tlab-trading-toolkit

Version:

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

197 lines (196 loc) 9.02 kB
'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); /*************************************************************************************************************************** * @license * * Copyright 2017 Coinbase, Inc. * * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * * with the License. You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * * License for the specific language governing permissions and limitations under the License. * ***************************************************************************************************************************/ const ExchangeFeed_1 = require("../ExchangeFeed"); const Orderbook_1 = require("../../lib/Orderbook"); const ProductMap_1 = require("../ProductMap"); class HitbtcMarketFeed extends ExchangeFeed_1.ExchangeFeed { constructor(config) { super(config); this.requestId = 0; this.counters = {}; this.owner = 'Hitbtc'; this.url = `wss://api.hitbtc.com/api/2/ws`; this.seq = 0; this.connect(); setInterval(() => { this.ping(); }, 25 * 1000); } static product(genericProduct) { return ProductMap_1.ProductMap.ExchangeMap.get('Hitbtc').getExchangeProduct(genericProduct) || genericProduct; } static genericProduct(exchangeProduct) { return ProductMap_1.ProductMap.ExchangeMap.get('Hitbtc').getGenericProduct(exchangeProduct) || exchangeProduct; } static getMarket(genericProduct) { return ProductMap_1.ProductMap.ExchangeMap.get('Hitbtc').getMarket(genericProduct); } static getMarketForExchangeProduct(exchangeProduct) { return ProductMap_1.ProductMap.ExchangeMap.get('Hitbtc').getMarket(HitbtcMarketFeed.genericProduct(exchangeProduct)); } nextSequence(product) { let counter = this.counters[product]; if (!counter) { counter = this.counters[product] = { base: -1, offset: 0 }; } if (counter.base < 1) { console.warn(`Requesting next sequence without setting snapshot sequence for product ${product}, current counter offset ${counter.offset}`); return -1; } counter.offset += 1; return counter.base + counter.offset; } setSnapshotSequence(product, sequence) { let counter = this.counters[product]; if (!counter) { counter = this.counters[product] = { base: -1, offset: 0 }; } counter.base = sequence; } getSnapshotSequence(product) { const counter = this.counters[product]; return counter ? counter.base : -1; } subscribe(productIds) { return __awaiter(this, void 0, void 0, function* () { this.logger.log('debug', `Subscribing to the following symbols: ${JSON.stringify(productIds)}`); var totalCount = productIds.length; var count = 0; for (const productId of productIds) { this.counters[productId] = { base: -1, offset: 0 }; const subscribeOrderbookMessage = { method: "subscribeOrderbook", id: this.requestId++, params: { symbol: productId } }; const subscribeTradebookMessage = { method: "subscribeTrades", id: this.requestId++, params: { limit: 100, symbol: productId } }; this.send(JSON.stringify(subscribeOrderbookMessage)); this.send(JSON.stringify(subscribeTradebookMessage)); yield new Promise((resolve, reject) => { setTimeout(resolve, 750); }); this.logger.log('debug', `completed ${count++} of ${totalCount}`); } return true; }); } onOpen() { // Nothing for now } handleMessage(rawMsg) { const msg = JSON.parse(rawMsg); switch (msg.method) { case "snapshotOrderbook": this.handleSnapshot(msg); break; case "updateOrderbook": this.handleOrderbookUpdate(msg); break; case "snapshotTrades": case "updateTrades": this.handleTrade(msg); break; } } handleSnapshot(snapshot) { // (re)initialize our order id map let sequence = snapshot.params.sequence; let exchangeSymbol = snapshot.params.symbol; let genericProduct = HitbtcMarketFeed.genericProduct(exchangeSymbol); this.setSnapshotSequence(exchangeSymbol, sequence); var asks = snapshot.params.ask.map((info) => { return Orderbook_1.PriceLevelFactory(parseFloat(info.price), parseFloat(info.size), 'sell'); }); var bids = snapshot.params.bid.map((info) => { return Orderbook_1.PriceLevelFactory(parseFloat(info.price), parseFloat(info.size), 'buy'); }); const snapshotMsg = { time: new Date(snapshot.params.timestamp), sequence: sequence, type: 'snapshot', productId: genericProduct, asks, bids, orderPool: null }; this.push(snapshotMsg); } handleOrderbookUpdate(updates) { let sequence = updates.params.sequence; let exchangeSymbol = updates.params.symbol; let genericProduct = HitbtcMarketFeed.genericProduct(updates.params.symbol); updates.params.ask.map((info) => { const seq = this.nextSequence(exchangeSymbol); const message = { time: new Date(updates.params.timestamp), sourceSequence: sequence, sequence: seq, type: 'level', productId: genericProduct, price: (info.price).toString(), size: info.size ? info.size.toString() : '0', side: 'sell', count: 1, }; this.push(message); }); updates.params.bid.map((info) => { const seq = this.nextSequence(exchangeSymbol); const message = { time: new Date(updates.params.timestamp), sourceSequence: sequence, sequence: seq, type: 'level', productId: genericProduct, price: (info.price).toString(), size: info.size ? info.size.toString() : '0', side: 'buy', count: 1, }; this.push(message); }); } handleTrade(trades) { trades.params.data.forEach((trade) => { const message = { type: 'trade', productId: HitbtcMarketFeed.genericProduct(trades.params.symbol), time: new Date(trade.timestamp), tradeId: trade.id.toString(), price: trade.price.toString(), size: trade.quantity.toString(), side: trade.side.toLowerCase(), }; this.push(message); }); } } exports.HitbtcMarketFeed = HitbtcMarketFeed;