1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
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)
|