Skip to content

Instantly share code, notes, and snippets.

@zhehaowang
Last active December 30, 2017 21:11
Show Gist options
  • Save zhehaowang/b8eadaf07f15eeef586326a42ddbccc0 to your computer and use it in GitHub Desktop.
Save zhehaowang/b8eadaf07f15eeef586326a42ddbccc0 to your computer and use it in GitHub Desktop.
Example websocket reader for gdax api
const Gdax = require('gdax');
let fs = require('fs');
const publicClient = new Gdax.PublicClient();
// currency pairs we are interested in
const currencyPairs = ['BTC-USD', 'ETH-BTC', 'ETH-USD', 'LTC-BTC', 'LTC-USD', 'BCH-USD'];
// time range we are interested in
const startDate = "2015-01-01T00:00:00.000Z";
const endDate = "2017-12-30T00:00:00.000Z";
// sleep between each requests to not exceed gdax rate limits (3/s)
// note all products share this interval
const sleepInterval = 750;
const rateExceedSleepInterval = 1500;
// requesting data at hourly granularity
const requestGranularity = 3600;
// date enumeration
function addDays(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
function enumerateDates(startStr, endStr, daysInterval = 7)
{
let dates = [];
let start = new Date(startStr);
let end = new Date(endStr);
while (start <= end) {
let next = addDays(start, daysInterval);
dates.push([start, next]);
start = next;
}
return dates;
}
function getPricesForDates(product, idx)
{
publicClient.getProductHistoricRates(product,
{ granularity: requestGranularity,
start: dateRanges[idx][0],
end: dateRanges[idx][1] })
.then(data => {
if (data['message'] === 'Rate limit exceeded') {
console.log('Rate limit exceeded, holding off for a bit');
setTimeout(() => {
getPricesForDates(product, idx);
}, rateExceedSleepInterval);
} else {
console.log(product + " : got prices");
dump(product, data);
if (idx < dateRanges.length - 1) {
setTimeout(() => {
getPricesForDates(product, idx + 1);
}, sleepInterval);
} else {
}
}
})
.catch(err => {
console.log("Get prices error: " + err);
});
}
function dump(product, data)
{
let dataString = "";
data.forEach(entry => {
dataString += (new Date(entry[0] * 1000)).toISOString() +
"\t" + entry[1] +
"\t" + entry[2] +
"\t" + entry[3] +
"\t" + entry[4] +
"\t" + entry[5] +
"\n";
});
fs.appendFile(product + '.log', dataString, err => {
if (err) {
console.log("Dump file error: " + err);
}
});
}
let dateRanges = enumerateDates(startDate, endDate);
// main logic
publicClient.getProducts()
.then(data => {
let uninterestedProducts = [];
let products = {};
data.forEach(entry => {
if (entry['id'] && currencyPairs.indexOf(entry['id']) >= 0) {
products[entry['id']] = {'description': entry};
} else {
uninterestedProducts.push(entry);
}
});
console.log("got products, asking for historic prices");
return products;
})
.then(products => {
for (product in products) {
// could consider getting the next product after we are done with one product so that we don't run into rate limit exceeded too often
getPricesForDates(product, 0);
}
})
.catch(err => {
console.log("Get products error: " + err);
});
// npm install coinbase/gdax-node
const Gdax = require('gdax');
const websocket = new Gdax.WebsocketClient(['ETH-USD']);
let trades = {};
let startTime = new Date();
websocket.on('message', data => {
let order_id = data['order_id'];
if (data['order_id']) {
if (trades[order_id]) {
trades[order_id].push(data);
} else {
trades[order_id] = [data];
}
}
if (data['type'] == 'done' && data['reason'] != 'canceled') {
console.log(trades[order_id]);
}
});
websocket.on('error', err => { console.log(err) });
websocket.on('close', () => { console.log('close') });
process.on('SIGINT', function() {
console.log("Caught exit signal");
//console.log(trades);
let runTime = (new Date() - startTime);
let totalCompletes = 0;
let totalCancels = 0;
let totalOrderIds = 0;
let totalCompleteVolume = 0;
let completes = [];
for (orderId in trades) {
hasOpen = false;
size = 0;
totalOrderIds += 1;
trades[orderId].forEach(orderEvent => {
if (orderEvent['type'] == 'open' || orderEvent['type'] == 'received') {
hasOpen = true;
} else if (orderEvent['type'] == 'done') {
if (hasOpen) {
if (orderEvent['reason'] && orderEvent['reason'] == 'canceled') {
totalCancels += 1;
} else {
completes.push(trades[orderId]);
totalCompletes += 1;
//totalCompleteVolume +=
}
}
}
});
}
console.log("Runtime: " + runTime + "ms; Saw: " + totalOrderIds + " orders; " +
"Completes: " + totalCompletes + "; Cancels: " + totalCancels);
console.log(completes);
process.exit();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment