forked from askmike/gekko
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcandleBatcher.js
93 lines (73 loc) · 2.03 KB
/
candleBatcher.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
// internally we only use 1m
// candles, this can easily
// convert them to any desired
// size.
// Acts as ~fake~ stream: takes
// 1m candles as input and emits
// bigger candles.
//
// input are transported candles.
var _ = require('lodash');
var util = require(__dirname + '/util');
var CandleBatcher = function(candleSize) {
if(!_.isNumber(candleSize))
throw new Error('candleSize is not a number');
this.candleSize = candleSize;
this.smallCandles = [];
this.calculatedCandles = [];
_.bindAll(this);
}
util.makeEventEmitter(CandleBatcher);
CandleBatcher.prototype.write = function(candles) {
if(!_.isArray(candles)) {
throw new Error('candles is not an array');
}
this.emitted = 0;
_.each(candles, function(candle) {
this.smallCandles.push(candle);
this.check();
}, this);
return this.emitted;
}
CandleBatcher.prototype.check = function() {
if(_.size(this.smallCandles) % this.candleSize !== 0)
return;
this.emitted++;
this.calculatedCandles.push(this.calculate());
this.smallCandles = [];
}
CandleBatcher.prototype.flush = function() {
_.each(
this.calculatedCandles,
candle => this.emit('candle', candle)
);
this.calculatedCandles = [];
}
CandleBatcher.prototype.calculate = function() {
// remove the id property of the small candle
var { id, ...first } = this.smallCandles.shift();
first.vwp = first.vwp * first.volume;
var candle = _.reduce(
this.smallCandles,
function(candle, m) {
candle.high = _.max([candle.high, m.high]);
candle.low = _.min([candle.low, m.low]);
candle.close = m.close;
candle.volume += m.volume;
candle.vwp += m.vwp * m.volume;
candle.trades += m.trades;
return candle;
},
first
);
if(candle.volume)
// we have added up all prices (relative to volume)
// now divide by volume to get the Volume Weighted Price
candle.vwp /= candle.volume;
else
// empty candle
candle.vwp = candle.open;
candle.start = first.start;
return candle;
}
module.exports = CandleBatcher;