-
Notifications
You must be signed in to change notification settings - Fork 0
/
profit.js
127 lines (125 loc) · 3.17 KB
/
profit.js
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Calculate profit in LIFO manner.
const _ = require('lodash');
const fs = require('fs');
const csv = require('csv')
const BigNumber = require('bignumber.js');
const Line = require('./line.js');
const argv = require('yargs')
.option('input', {
demandOption: true,
describe: 'The path of the input file'
})
.option('year', {
describe: 'Export sales for this year only',
type: 'integer'
})
.option('source', {
describe: 'Export sales for this source only',
type: 'string'
})
.option('exclude_source', {
describe: 'Exclude sales for this source only',
type: 'string'
})
.option('easytxf', {
describe: 'If true, export in easytxf.com format',
type: 'boolean'
})
.option('combine', {
describe: 'If true, combine sales for the same symbol, bought and sold in the same day',
type: 'boolean'
})
.conflicts('source', 'exclude_source')
.help()
.strict()
.argv
output = [];
symbols = {};
fs.createReadStream(argv.input)
.pipe(csv.parse())
.on('data', (row) => {
if (row === null) {
return;
}
let l = new Line(...row);
l.mergeFee()
if (!symbols.hasOwnProperty(l.symbol)) {
symbols[l.symbol] = [];
}
let lines = symbols[l.symbol];
if (lines.length == 0) {
lines.push(l);
return;
}
let last = lines[lines.length-1];
if (l.date < last.date) {
throw 'going backwards!'
}
if (!last.canMerge(l)) {
lines.push(l);
return;
}
var sales = [];
while (last && l.volume.gte(last.volume)) {
sales.push(l.merge(last));
lines.pop();
last = lines[lines.length-1]
}
if (last) {
sales.push(last.merge(l));
}
if (l.action !== 'SELL') {
return;
}
if (argv.source && l.source !== argv.source) {
return;
}
if (argv.exclude_source && l.source === argv.exclude_source) {
return;
}
if (argv.year && l.date.getUTCFullYear() !== argv.year) {
return;
}
while (sales.length > 0) {
let t = sales.pop();
if (t.profit.toFixed(2) === '0.00' ||
t.profit.toFixed(2) === '-0.00') {
continue;
}
let lastT = output[output.length-1]
if (argv.combine &&lastT &&
t.symbol === lastT.symbol &&
t.openingDate === lastT.openingDate &&
t.closingDate === lastT.closingDate
) {
lastT.volume = lastT.volume.plus(t.volume);
lastT.cost = lastT.cost.plus(t.cost);
lastT.proceeds = lastT.proceeds.plus(t.proceeds);
lastT.profit = lastT.proceeds.minus(lastT.cost);
} else {
output.push(t);
}
}
})
.on('end', () => {
output.forEach(t => {
if (argv.easytxf) {
console.log(t.symbol + ',' +
t.volume.toFixed(6) + ',' +
t.openingDate + ',' +
t.cost.toFixed(2) + ',' +
t.closingDate + ',' +
t.proceeds.toFixed(2)
);
} else {
console.log(t.symbol + ',' +
t.volume.toFixed(6) + ',' +
t.openingDate + ',' +
t.cost.toFixed(2) + ',' +
t.closingDate + ',' +
t.proceeds.toFixed(2) + ',' +
t.profit.toFixed(2)
);
}
});
});