Last active
December 30, 2017 21:11
-
-
Save zhehaowang/b8eadaf07f15eeef586326a42ddbccc0 to your computer and use it in GitHub Desktop.
Example websocket reader for gdax api
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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