diff options
author | Alan Pearce | 2017-09-16 17:11:01 +0200 |
---|---|---|
committer | Alan Pearce | 2017-09-16 17:31:00 +0200 |
commit | 269e7b208e5d20bdc3f9cb2bdd178fbbecb046a6 (patch) | |
tree | f10e4670eb5335e35cbe99bc0b57ab821b59eb72 | |
download | bitcoincharts-beancount-269e7b208e5d20bdc3f9cb2bdd178fbbecb046a6.tar.xz bitcoincharts-beancount-269e7b208e5d20bdc3f9cb2bdd178fbbecb046a6.zip |
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | LICENSE | 21 | ||||
-rw-r--r-- | README.org | 40 | ||||
-rw-r--r-- | index.js | 68 | ||||
-rw-r--r-- | package-lock.json | 31 | ||||
-rw-r--r-- | package.json | 25 |
6 files changed, 186 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1 @@ | |||
/node_modules | |||
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a53abb1 --- /dev/null +++ b/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | MIT License | ||
2 | |||
3 | Copyright (c) 2017 Alan Pearce | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in all | ||
13 | copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | SOFTWARE. | ||
diff --git a/README.org b/README.org new file mode 100644 index 0000000..f0ff157 --- /dev/null +++ b/README.org | |||
@@ -0,0 +1,40 @@ | |||
1 | * Bitcoincharts Beancount converter | ||
2 | |||
3 | This is a quick tool I hacked together to convert historic bitcoin | ||
4 | prices from [[http://api.bitcoincharts.com/v1/csv/][bitcoincharts CSVs]] into beancount price directives. | ||
5 | |||
6 | The files are gzipped CSVs of (unixtime, price, tradeamount) | ||
7 | |||
8 | For each month with trades on the 1st, the tool calculates a weighted | ||
9 | average of trades on that day and outputs a beancount price directive. | ||
10 | |||
11 | ** Running | ||
12 | |||
13 | The tool does not download files on its own. Download the files | ||
14 | before running. | ||
15 | |||
16 | #+BEGIN_SRC shell | ||
17 | $ node index.js some.csv.gz | ||
18 | # or | ||
19 | $ node index.js some.csv.gz EUR | ||
20 | # or | ||
21 | $ node index.js some.csv.gz EUR BTC | ||
22 | #+END_SRC | ||
23 | |||
24 | *** Parameters | ||
25 | |||
26 | - filename (gzipped CSV) | ||
27 | - currency [optional] (currency code used in beancount {USD,EUR, etc}) | ||
28 | - commodity [optional] (currency code of commodity) {BTC,BCH,LTC, etc} | ||
29 | |||
30 | *** Status | ||
31 | |||
32 | It works. I don't plan on working on it much further. | ||
33 | |||
34 | It's not very efficent. I suspect the main problem is the group | ||
35 | function probably doesn't assume that the input is sorted and | ||
36 | therefore buffers its entire input. Patches welcome. | ||
37 | |||
38 | ** License | ||
39 | |||
40 | MIT | ||
diff --git a/index.js b/index.js new file mode 100644 index 0000000..6152685 --- /dev/null +++ b/index.js | |||
@@ -0,0 +1,68 @@ | |||
1 | const r = require('ramda') | ||
2 | const h = require('highland') | ||
3 | const fs = require('fs') | ||
4 | const path = require('path') | ||
5 | const zlib = require('zlib') | ||
6 | const BigNumber = require('bignumber.js') | ||
7 | |||
8 | BigNumber.config({ | ||
9 | DECIMAL_PLACES: 8 | ||
10 | }) | ||
11 | |||
12 | if (process.argv.length < 3) { | ||
13 | console.error(`${path.basename(process.argv[1])} | ||
14 | |||
15 | bitcoincharts historic price conversion | ||
16 | |||
17 | Input: gzipped csv of (unixtime, price, tradeamount) | ||
18 | |||
19 | Outputs beancount price directives for the weighted average price | ||
20 | of all trades executed on the first of each month in the provided file | ||
21 | |||
22 | Download files from http://api.bitcoincharts.com/v1/csv/ | ||
23 | |||
24 | usage: ${path.basename(process.argv[1])} FILENAME [CURRENCY] [COMMODITY]`) | ||
25 | process.exit(1) | ||
26 | } | ||
27 | |||
28 | const [ | ||
29 | ,, | ||
30 | filename, | ||
31 | currency = 'EUR', | ||
32 | commodity = 'BTC' | ||
33 | ] = process.argv | ||
34 | |||
35 | h( | ||
36 | fs.createReadStream(filename) | ||
37 | .pipe(zlib.createGunzip()) | ||
38 | ) | ||
39 | .split() | ||
40 | .filter(line => line.length > 1) | ||
41 | .map(line => line.split(',', 3)) | ||
42 | .map(([time, price, amount]) => [ | ||
43 | new Date(parseInt(time, 10) * 1000), | ||
44 | new BigNumber(price), | ||
45 | new BigNumber(amount) | ||
46 | ]) | ||
47 | .filter(([date]) => date.getDate() === 1) | ||
48 | .group(([date]) => date.toDateString()) | ||
49 | .map(group => Object.values(group)) | ||
50 | .sequence() | ||
51 | .map(group => group | ||
52 | .map( | ||
53 | ([date, price, amount]) => [date, price.times(amount), amount] | ||
54 | ) | ||
55 | .reduce( | ||
56 | ([date, sumPrice, sumAmount], [,weightPrice, amount]) => [ | ||
57 | date, | ||
58 | sumPrice.plus(weightPrice), | ||
59 | sumAmount.plus(amount) | ||
60 | ] | ||
61 | )) | ||
62 | .map(([date, sumprice, sumamount]) => [date, sumprice.dividedBy(sumamount)]) | ||
63 | .map(([date, avg]) => | ||
64 | `${date.toISOString().substr(0, 10)} price ${commodity} ${avg.toFixed(2)} ${currency}` | ||
65 | ) | ||
66 | .intersperse("\n") | ||
67 | .pipe(process.stdout) | ||
68 | |||
diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7ee272f --- /dev/null +++ b/package-lock.json | |||
@@ -0,0 +1,31 @@ | |||
1 | { | ||
2 | "name": "bitcoincharts-beancount", | ||
3 | "version": "1.0.0", | ||
4 | "lockfileVersion": 1, | ||
5 | "requires": true, | ||
6 | "dependencies": { | ||
7 | "bignumber.js": { | ||
8 | "version": "4.0.4", | ||
9 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz", | ||
10 | "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg==" | ||
11 | }, | ||
12 | "highland": { | ||
13 | "version": "2.11.1", | ||
14 | "resolved": "https://registry.npmjs.org/highland/-/highland-2.11.1.tgz", | ||
15 | "integrity": "sha1-ObTZKZtuB9o9FeeveypvEnUirK8=", | ||
16 | "requires": { | ||
17 | "util-deprecate": "1.0.2" | ||
18 | } | ||
19 | }, | ||
20 | "ramda": { | ||
21 | "version": "0.24.1", | ||
22 | "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz", | ||
23 | "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc=" | ||
24 | }, | ||
25 | "util-deprecate": { | ||
26 | "version": "1.0.2", | ||
27 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", | ||
28 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" | ||
29 | } | ||
30 | } | ||
31 | } | ||
diff --git a/package.json b/package.json new file mode 100644 index 0000000..20e849f --- /dev/null +++ b/package.json | |||
@@ -0,0 +1,25 @@ | |||
1 | { | ||
2 | "name": "bitcoincharts-beancount", | ||
3 | "version": "1.0.0", | ||
4 | "description": "bitcoincharts historic price conversion", | ||
5 | "main": "index.js", | ||
6 | "scripts": { | ||
7 | "test": "echo \"Error: no test specified\" && exit 1" | ||
8 | }, | ||
9 | "repository": { | ||
10 | "type": "git", | ||
11 | "url": "https://git.alanpearce.eu/bitcoincharts-beancount" | ||
12 | }, | ||
13 | "keywords": [ | ||
14 | "bitcoin", | ||
15 | "beancount", | ||
16 | "accounting" | ||
17 | ], | ||
18 | "author": "Alan Pearce <alan@alanpearce.eu>", | ||
19 | "license": "MIT", | ||
20 | "dependencies": { | ||
21 | "bignumber.js": "^4.0.4", | ||
22 | "highland": "^2.11.1", | ||
23 | "ramda": "^0.24.1" | ||
24 | } | ||
25 | } | ||