-
Notifications
You must be signed in to change notification settings - Fork 0
/
tradeBatcher.js
124 lines (103 loc) · 2.69 KB
/
tradeBatcher.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
//
// Small wrapper that only propagates new trades.
//
// Expects trade batches to be written like:
// [
// {
// tid: x, // tid is preferred, but if none available date will also work
// price: x,
// date: (timestamp),
// amount: x
// },
// {
// tid: x + 1,
// price: x,
// date: (timestamp),
// amount: x
// }
// ]
//
// Emits 'new trades' event with:
// {
// amount: x,
// start: (moment),
// end: (moment),
// first: (trade),
// last: (trade)
// data: [
// // batch of new trades with
// // moments instead of timestamps
// ]
// }
var _ = require('lodash');
var moment = require('moment');
var util = require('../util');
var log = require('../log');
var TradeBatcher = function(tid) {
if(!_.isString(tid))
throw new Error('tid is not a string');
_.bindAll(this);
this.tid = tid;
this.last = -1;
}
util.makeEventEmitter(TradeBatcher);
TradeBatcher.prototype.write = function(batch) {
if(!_.isArray(batch))
throw new Error('batch is not an array');
if(_.isEmpty(batch))
return log.debug('Trade fetch came back empty.');
var filterBatch = this.filter(batch);
var amount = _.size(filterBatch);
if(!amount)
return log.debug('No new trades.');
var momentBatch = this.convertDates(filterBatch);
var last = _.last(momentBatch);
var first = _.first(momentBatch);
log.debug(
'Processing', amount, 'new trades.',
'From',
first.date.format('YYYY-MM-DD HH:mm:ss'),
'UTC to',
last.date.format('YYYY-MM-DD HH:mm:ss'),
'UTC.',
'(' + first.date.from(last.date, true) + ')'
);
this.emit('new batch', {
amount: amount,
start: first.date,
end: last.date,
last: last,
first: first,
data: momentBatch
});
this.last = last[this.tid];
// we overwrote those, get unix ts back
if(this.tid === 'date')
this.last = this.last.unix();
}
TradeBatcher.prototype.filter = function(batch) {
// make sure we're not trying to count
// beyond infinity
var lastTid = _.last(batch)[this.tid];
if(lastTid === lastTid + 1)
util.die('trade tid is max int, Gekko can\'t process..');
// remove trades that have zero amount
// see @link
// https://github.com/askmike/gekko/issues/486
batch = _.filter(batch, function(trade) {
return trade.amount > 0;
});
// weed out known trades
// TODO: optimize by stopping as soon as the
// first trade is too old (reverse first)
return _.filter(batch, function(trade) {
return this.last < trade[this.tid];
}, this);
}
TradeBatcher.prototype.convertDates = function(batch) {
return _.map(_.cloneDeep(batch), function(trade) {
trade.date = moment.unix(trade.date).utc();
return trade;
});
}
module.exports = TradeBatcher;