const r = require('ramda') const h = require('highland') const fs = require('fs') const path = require('path') const zlib = require('zlib') const BigNumber = require('bignumber.js') BigNumber.config({ DECIMAL_PLACES: 8 }) if (process.argv.length < 3) { console.error(`${path.basename(process.argv[1])} bitcoincharts historic price conversion Input: gzipped csv of (unixtime, price, tradeamount) Outputs beancount price directives for the weighted average price of all trades executed on the first of each month in the provided file Download files from http://api.bitcoincharts.com/v1/csv/ usage: ${path.basename(process.argv[1])} FILENAME [CURRENCY] [COMMODITY]`) process.exit(1) } const [ ,, filename, currency = 'EUR', commodity = 'BTC' ] = process.argv h( fs.createReadStream(filename) .pipe(zlib.createGunzip()) ) .split() .filter(line => line.length > 1) .map(line => line.split(',', 3)) .map(([time, price, amount]) => [ new Date(parseInt(time, 10) * 1000), new BigNumber(price), new BigNumber(amount) ]) .filter(([date]) => date.getDate() === 1) .group(([date]) => date.toDateString()) .map(group => Object.values(group)) .sequence() .map(group => group .map( ([date, price, amount]) => [date, price.times(amount), amount] ) .reduce( ([date, sumPrice, sumAmount], [,weightPrice, amount]) => [ date, sumPrice.plus(weightPrice), sumAmount.plus(amount) ] )) .map(([date, sumprice, sumamount]) => [date, sumprice.dividedBy(sumamount)]) .map(([date, avg]) => `${date.toISOString().substr(0, 10)} price ${commodity} ${avg.toFixed(2)} ${currency}` ) .intersperse("\n") .pipe(process.stdout)