@bitfinex/lib-js-util-math 0.7.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/test/twap.test.js CHANGED
@@ -1,224 +1,218 @@
1
1
  'use strict'
2
2
 
3
- const chai = require('chai')
4
- .use(require('dirty-chai'))
5
- const { expect } = chai
3
+ const test = require('brittle')
6
4
  const { nBN } = require('../src/bn')
7
5
  const { groupBySize, kline, typicalPrice, TWAP } = require('../src/twap')
8
6
 
9
- module.exports = () => {
10
- describe('# twap-tests', () => {
11
- it('groupBySize - it should fail with empty array', () => {
12
- return expect(
13
- groupBySize.bind(null, [], 100)
14
- ).to.throw()
7
+ test('groupBySize - it should fail with empty array', (t) => {
8
+ t.exception.all(
9
+ groupBySize.bind(null, [], 100)
10
+ )
11
+ })
12
+
13
+ test('groupBySize - it should fail with interval <= 0', (t) => {
14
+ t.exception.all(
15
+ groupBySize.bind(null, [123], 0)
16
+ )
17
+ })
18
+
19
+ test('groupBySize - it should fail with mixed positive/negative values', (t) => {
20
+ t.exception.all(
21
+ groupBySize.bind(null, [-123, 123], 100)
22
+ )
23
+ })
24
+
25
+ test('groupBySize - it should fail with invalid values', (t) => {
26
+ t.exception.all(
27
+ groupBySize.bind(null, ['-a123', 123], 100)
28
+ )
29
+ })
30
+
31
+ test('groupBySize - it should work with just one item', (t) => {
32
+ const res = groupBySize(['123'], 300)
33
+ t.ok(Array.isArray(res))
34
+ t.is(res.length, 1)
35
+ t.ok(Array.isArray(res[0]))
36
+ t.is(res[0].length, 1)
37
+ t.is(res[0][0], '123')
38
+ })
39
+
40
+ test('groupBySize - it should work with primitive types', (t) => {
41
+ const res = groupBySize([100, 200, 300, 400, 500, 600, 1000, 1100, 1200], 300)
42
+ t.ok(Array.isArray(res))
43
+ t.is(res.length, 4)
44
+ const expected = [[100, 200, 300], [400, 500, 600], [], [1000, 1100, 1200]]
45
+ res.forEach((g, i) => {
46
+ const e = expected[i]
47
+ t.is(g.length, e.length)
48
+ g.forEach((item, j) => {
49
+ t.is(item, e[j])
15
50
  })
16
-
17
- it('groupBySize - it should fail with interval <= 0', () => {
18
- return expect(
19
- groupBySize.bind(null, [123], 0)
20
- ).to.throw()
21
- })
22
-
23
- it('groupBySize - it should fail with mixed positive/negative values', () => {
24
- return expect(
25
- groupBySize.bind(null, [-123, 123], 100)
26
- ).to.throw()
27
- })
28
-
29
- it('groupBySize - it should fail with invalid values', () => {
30
- return expect(
31
- groupBySize.bind(null, ['-a123', 123], 100)
32
- ).to.throw()
33
- })
34
-
35
- it('groupBySize - it should work with just one item', () => {
36
- const res = groupBySize(['123'], 300)
37
- expect(res).to.be.an('array')
38
- expect(res.length).to.be.equal(1)
39
- expect(res[0]).to.be.an('array')
40
- expect(res[0].length).to.be.equal(1)
41
- return expect(res[0][0]).to.be.equal('123')
42
- })
43
-
44
- it('groupBySize - it should work with primitive types', () => {
45
- const res = groupBySize([100, 200, 300, 400, 500, 600, 1000, 1100, 1200], 300)
46
- expect(res).to.be.an('array')
47
- expect(res.length).to.be.equal(4)
48
- const expected = [[100, 200, 300], [400, 500, 600], [], [1000, 1100, 1200]]
49
- res.forEach((g, i) => {
50
- const e = expected[i]
51
- expect(g.length).to.be.equal(e.length)
52
- g.forEach((item, j) => {
53
- expect(item).to.be.equal(e[j])
54
- })
55
- })
56
- })
57
-
58
- it('groupBySize - it should work with negative prices', () => {
59
- const res = groupBySize([-100, -200, -300, -400, -500, -600, -1000, -1100, -1200], 300)
60
- expect(res).to.be.an('array')
61
- expect(res.length).to.be.equal(4)
62
- const expected = [[-1200, -1100, -1000], [], [-600, -500, -400], [-300, -200, -100]]
63
- res.forEach((g, i) => {
64
- const e = expected[i]
65
- expect(g.length).to.be.equal(e.length)
66
- g.forEach((item, j) => {
67
- expect(item).to.be.equal(e[j])
68
- })
69
- })
70
- })
71
-
72
- it('groupBySize - it should work with complex types', () => {
73
- const now = Date.now()
74
- const prices = [
75
- { price: '10003', ts: now - 9000 },
76
- { price: '10000', ts: now - 4000 },
77
- { price: '10003', ts: now - 6000 },
78
- { price: '10001', ts: now - 5000 },
79
- { price: '10003', ts: now - 8000 }
80
- ]
81
- const expected = [
82
- [{ price: '10003', ts: now - 9000 }, { price: '10003', ts: now - 8000 }],
83
- [{ price: '10003', ts: now - 6000 }, { price: '10001', ts: now - 5000 }, { price: '10000', ts: now - 4000 }]
84
- ]
85
-
86
- const res = groupBySize(prices, 3000, (a) => a.ts)
87
- expect(res.length).to.be.equal(2)
88
- res.forEach((g, i) => {
89
- const e = expected[i]
90
- expect(g.length).to.be.equal(e.length)
91
- g.forEach((item, j) => {
92
- expect(item.ts).to.be.equal(e[j].ts)
93
- })
94
- })
95
- })
96
-
97
- it('kline - it should fail with empty array', () => {
98
- return expect(kline.bind(null, [])).to.throw()
99
- })
100
-
101
- it('kline - it should fail with invalid numbers', () => {
102
- expect(kline.bind(null, ['abc123', 123, 333, 44])).to.throw()
103
- return expect(kline.bind(null, [123, 123, 'aaa333', 44])).to.throw()
104
- })
105
-
106
- it('kline - it should return expected value', () => {
107
- const prices = ['10001', 10002, nBN(10003)]
108
- const res = kline(prices)
109
-
110
- expect(res.open).to.be.equal('10001')
111
- expect(res.high).to.be.equal('10003')
112
- expect(res.low).to.be.equal('10001')
113
- expect(res.close).to.be.equal('10003')
114
- })
115
-
116
- it('kline - it should work with complex types', () => {
117
- const now = Date.now()
118
- const prices = [
119
- { price: 10001, ts: now - 2000 },
120
- { price: 10002, ts: now - 1000 },
121
- { price: 10003, ts: now }
122
- ]
123
- const res = kline(prices, (a) => a.price)
124
-
125
- expect(res.open).to.be.equal('10001')
126
- expect(res.high).to.be.equal('10003')
127
- expect(res.low).to.be.equal('10001')
128
- expect(res.close).to.be.equal('10003')
129
- })
130
-
131
- it('typicalPrice - it should fail with empty array', () => {
132
- return expect(typicalPrice.bind(null, [])).to.throw()
133
- })
134
-
135
- it('typicalPrice - it should fail with invalid numbers', () => {
136
- expect(typicalPrice.bind(null, ['abc123', 123, 333, 44])).to.throw()
137
- return expect(typicalPrice.bind(null, [123, 123, 'aaa333', 44])).to.throw()
138
- })
139
-
140
- it('typicalPrice - it should return expected value', () => {
141
- const prices = ['10001', 10002, nBN(10003)]
142
- const res = typicalPrice(prices)
143
- return expect(res).to.be.equal('10002')
144
- })
145
-
146
- it('typicalPrice - it should work with complex types', () => {
147
- const now = Date.now()
148
- const prices = [
149
- { price: 10001, ts: now },
150
- { price: 10002, ts: now - 1000 },
151
- { price: 10003, ts: now - 2000 }
152
- ]
153
- const res = typicalPrice(prices, (a) => a.price)
154
- return expect(res).to.be.equal('10002')
155
- })
156
-
157
- it('twap - it should fail with empty array', () => {
158
- return expect(TWAP.bind(null, [], 3000, (a) => a.ts, (a) => a.price)).to.throw()
159
- })
160
-
161
- it('twap - it should fail with interval <= 0', () => {
162
- const now = Date.now()
163
- const prices = [
164
- { price: '10001', ts: now },
165
- { price: '10000', ts: now - 1000 },
166
- { price: '10001', ts: now - 2000 },
167
- { price: 10002, ts: now - 3000 },
168
- { price: '10003', ts: now - 9000 },
169
- { price: nBN('10000'), ts: now - 4000 },
170
- { price: '10003', ts: now - 6000 },
171
- { price: '10001', ts: now - 5000 },
172
- { price: '10003', ts: now - 8000 }
173
- ]
174
- return expect(TWAP.bind(null, prices, -3000, (a) => a.ts, (a) => a.price)).to.throw()
175
- })
176
-
177
- it('twap - it should fail with invalid numbers', () => {
178
- const now = Date.now()
179
- const prices = [
180
- { price: '10001', ts: now },
181
- { price: '10000', ts: now - 1000 },
182
- { price: '10001', ts: now - 2000 },
183
- { price: 10002, ts: now - 3000 },
184
- { price: '10003', ts: now - 9000 },
185
- { price: nBN('10000'), ts: now - 4000 },
186
- { price: 'ab10003', ts: now - 6000 },
187
- { price: '10001', ts: now - 5000 },
188
- { price: '10003', ts: now - 8000 }
189
- ]
190
- return expect(TWAP.bind(null, prices, 3000, (a) => a.ts, (a) => a.price)).to.throw()
191
- })
192
-
193
- it('twap - it should return expected value', () => {
194
- const now = Date.now()
195
- const prices = [
196
- { price: '10001', ts: now },
197
- { price: '10000', ts: now - 1000 },
198
- { price: '10001', ts: now - 2000 },
199
- { price: 10002, ts: now - 3000 },
200
- { price: '10003', ts: now - 9000 },
201
- { price: nBN('10000'), ts: now - 4000 },
202
- { price: '10003', ts: now - 6000 },
203
- { price: '10001', ts: now - 5000 },
204
- { price: '10003', ts: now - 8000 }
205
- ]
206
- const res = TWAP(prices, 3000, (a) => a.ts, (a) => a.price)
207
- return expect(res).to.be.equal('10001.625')
51
+ })
52
+ })
53
+
54
+ test('groupBySize - it should work with negative prices', (t) => {
55
+ const res = groupBySize([-100, -200, -300, -400, -500, -600, -1000, -1100, -1200], 300)
56
+ t.ok(Array.isArray(res))
57
+ t.is(res.length, 4)
58
+ const expected = [[-1200, -1100, -1000], [], [-600, -500, -400], [-300, -200, -100]]
59
+ res.forEach((g, i) => {
60
+ const e = expected[i]
61
+ t.is(g.length, e.length)
62
+ g.forEach((item, j) => {
63
+ t.is(item, e[j])
208
64
  })
209
-
210
- it('twap - it should filter empty slots', () => {
211
- const now = Date.now()
212
- const prices = [
213
- { price: '10001', ts: now },
214
- { price: '10000', ts: now - 1000 },
215
- { price: '10001', ts: now - 2000 },
216
- { price: 10002, ts: now - 3000 },
217
- { price: '10003', ts: now - 12000 },
218
- { price: nBN('10000'), ts: now - 4000 }
219
- ]
220
- const res = TWAP(prices, 3000, (a) => a.ts, (a) => a.price)
221
- return expect(res).to.be.equal('10001.25')
65
+ })
66
+ })
67
+
68
+ test('groupBySize - it should work with complex types', (t) => {
69
+ const now = Date.now()
70
+ const prices = [
71
+ { price: '10003', ts: now - 9000 },
72
+ { price: '10000', ts: now - 4000 },
73
+ { price: '10003', ts: now - 6000 },
74
+ { price: '10001', ts: now - 5000 },
75
+ { price: '10003', ts: now - 8000 }
76
+ ]
77
+ const expected = [
78
+ [{ price: '10003', ts: now - 9000 }, { price: '10003', ts: now - 8000 }],
79
+ [{ price: '10003', ts: now - 6000 }, { price: '10001', ts: now - 5000 }, { price: '10000', ts: now - 4000 }]
80
+ ]
81
+
82
+ const res = groupBySize(prices, 3000, (a) => a.ts)
83
+ t.is(res.length, 2)
84
+ res.forEach((g, i) => {
85
+ const e = expected[i]
86
+ t.is(g.length, e.length)
87
+ g.forEach((item, j) => {
88
+ t.is(item.ts, e[j].ts)
222
89
  })
223
90
  })
224
- }
91
+ })
92
+
93
+ test('kline - it should fail with empty array', (t) => {
94
+ t.exception.all(kline.bind(null, []))
95
+ })
96
+
97
+ test('kline - it should fail with invalid numbers', (t) => {
98
+ t.exception.all(kline.bind(null, ['abc123', 123, 333, 44]))
99
+ t.exception.all(kline.bind(null, [123, 123, 'aaa333', 44]))
100
+ })
101
+
102
+ test('kline - it should return expected value', (t) => {
103
+ const prices = ['10001', 10002, nBN(10003)]
104
+ const res = kline(prices)
105
+
106
+ t.is(res.open, '10001')
107
+ t.is(res.high, '10003')
108
+ t.is(res.low, '10001')
109
+ t.is(res.close, '10003')
110
+ })
111
+
112
+ test('kline - it should work with complex types', (t) => {
113
+ const now = Date.now()
114
+ const prices = [
115
+ { price: 10001, ts: now - 2000 },
116
+ { price: 10002, ts: now - 1000 },
117
+ { price: 10003, ts: now }
118
+ ]
119
+ const res = kline(prices, (a) => a.price)
120
+
121
+ t.is(res.open, '10001')
122
+ t.is(res.high, '10003')
123
+ t.is(res.low, '10001')
124
+ t.is(res.close, '10003')
125
+ })
126
+
127
+ test('typicalPrice - it should fail with empty array', (t) => {
128
+ t.exception.all(typicalPrice.bind(null, []))
129
+ })
130
+
131
+ test('typicalPrice - it should fail with invalid numbers', (t) => {
132
+ t.exception.all(typicalPrice.bind(null, ['abc123', 123, 333, 44]))
133
+ t.exception.all(typicalPrice.bind(null, [123, 123, 'aaa333', 44]))
134
+ })
135
+
136
+ test('typicalPrice - it should return expected value', (t) => {
137
+ const prices = ['10001', 10002, nBN(10003)]
138
+ const res = typicalPrice(prices)
139
+ t.is(res, '10002')
140
+ })
141
+
142
+ test('typicalPrice - it should work with complex types', (t) => {
143
+ const now = Date.now()
144
+ const prices = [
145
+ { price: 10001, ts: now },
146
+ { price: 10002, ts: now - 1000 },
147
+ { price: 10003, ts: now - 2000 }
148
+ ]
149
+ const res = typicalPrice(prices, (a) => a.price)
150
+ t.is(res, '10002')
151
+ })
152
+
153
+ test('twap - it should fail with empty array', (t) => {
154
+ t.exception.all(TWAP.bind(null, [], 3000, (a) => a.ts, (a) => a.price))
155
+ })
156
+
157
+ test('twap - it should fail with interval <= 0', (t) => {
158
+ const now = Date.now()
159
+ const prices = [
160
+ { price: '10001', ts: now },
161
+ { price: '10000', ts: now - 1000 },
162
+ { price: '10001', ts: now - 2000 },
163
+ { price: 10002, ts: now - 3000 },
164
+ { price: '10003', ts: now - 9000 },
165
+ { price: nBN('10000'), ts: now - 4000 },
166
+ { price: '10003', ts: now - 6000 },
167
+ { price: '10001', ts: now - 5000 },
168
+ { price: '10003', ts: now - 8000 }
169
+ ]
170
+ t.exception.all(TWAP.bind(null, prices, -3000, (a) => a.ts, (a) => a.price))
171
+ })
172
+
173
+ test('twap - it should fail with invalid numbers', (t) => {
174
+ const now = Date.now()
175
+ const prices = [
176
+ { price: '10001', ts: now },
177
+ { price: '10000', ts: now - 1000 },
178
+ { price: '10001', ts: now - 2000 },
179
+ { price: 10002, ts: now - 3000 },
180
+ { price: '10003', ts: now - 9000 },
181
+ { price: nBN('10000'), ts: now - 4000 },
182
+ { price: 'ab10003', ts: now - 6000 },
183
+ { price: '10001', ts: now - 5000 },
184
+ { price: '10003', ts: now - 8000 }
185
+ ]
186
+ t.exception.all(TWAP.bind(null, prices, 3000, (a) => a.ts, (a) => a.price))
187
+ })
188
+
189
+ test('twap - it should return expected value', (t) => {
190
+ const now = Date.now()
191
+ const prices = [
192
+ { price: '10001', ts: now },
193
+ { price: '10000', ts: now - 1000 },
194
+ { price: '10001', ts: now - 2000 },
195
+ { price: 10002, ts: now - 3000 },
196
+ { price: '10003', ts: now - 9000 },
197
+ { price: nBN('10000'), ts: now - 4000 },
198
+ { price: '10003', ts: now - 6000 },
199
+ { price: '10001', ts: now - 5000 },
200
+ { price: '10003', ts: now - 8000 }
201
+ ]
202
+ const res = TWAP(prices, 3000, (a) => a.ts, (a) => a.price)
203
+ t.is(res, '10001.625')
204
+ })
205
+
206
+ test('twap - it should filter empty slots', (t) => {
207
+ const now = Date.now()
208
+ const prices = [
209
+ { price: '10001', ts: now },
210
+ { price: '10000', ts: now - 1000 },
211
+ { price: '10001', ts: now - 2000 },
212
+ { price: 10002, ts: now - 3000 },
213
+ { price: '10003', ts: now - 12000 },
214
+ { price: nBN('10000'), ts: now - 4000 }
215
+ ]
216
+ const res = TWAP(prices, 3000, (a) => a.ts, (a) => a.price)
217
+ t.is(res, '10001.25')
218
+ })
package/test/vwap.test.js CHANGED
@@ -1,121 +1,119 @@
1
1
  'use strict'
2
2
 
3
- const chai = require('chai')
4
- .use(require('dirty-chai'))
5
- const { expect } = chai
3
+ const test = require('brittle')
6
4
  const { VWAP, EWVWAP } = require('../src/vwap')
7
5
 
8
- module.exports = () => {
9
- describe('# vwap-tests', () => {
10
- it('VWAP - it should fail with non numeric values', () => {
11
- const values = [
12
- { price: '10161', volume: '1' },
13
- { price: 'a10261.235', volume: '1' }
14
- ]
15
-
16
- return expect(
17
- VWAP.bind(null, values)
18
- ).to.throw()
19
- })
20
-
21
- it('VWAP - it return 0 with no values', () => {
22
- return expect(VWAP([])).to.be.equal('0')
23
- })
24
-
25
- it('VWAP - it should match the expected value', () => {
26
- const values = [
27
- { price: '10161', volume: '1' },
28
- { price: '10261.235', volume: '1' },
29
- { price: '10324.2567', volume: '1' },
30
- { price: '10724', volume: '1' },
31
- { price: '10232', volume: '1' },
32
- { price: '10510.25847', volume: '1' },
33
- { price: '10261.826', volume: '1' }
34
- ]
35
-
36
- const res = VWAP(values)
37
- return expect(res).to.be.equal('10353.51088142857142857143')
38
- })
39
-
40
- it('EWVWAP - it should fail with non numeric values', () => {
41
- const values = [
42
- { price: '10161', weightType: 'bfx' },
43
- { price: 'a10261.235', weightType: 'bitstamp' },
44
- { price: '10261.826', weightType: 'kraken' }
45
- ]
46
-
47
- return expect(
48
- EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
49
- ).to.throw()
50
- })
51
-
52
- it('EWVWAP - it should fail with NaN values', () => {
53
- const values = [
54
- { price: '10161', weightType: 'bfx' },
55
- { price: NaN, weightType: 'bitstamp' },
56
- { price: '10261.826', weightType: 'kraken' }
57
- ]
58
-
59
- return expect(
60
- EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
61
- ).to.throw()
62
- })
63
-
64
- it('EWVWAP - it should fail with invalid config', () => {
65
- const values = [
66
- { price: '10161', weightType: 'bfx' },
67
- { price: '10261.235', weightType: 'bitstamp' },
68
- { price: '10261.826', weightType: 'kraken' }
69
- ]
70
-
71
- return expect(
72
- EWVWAP.bind(null, values, { bfx: 0.33, bitstamp: 0.33, kraken: 0.33 })
73
- ).to.throw('ERR_INVALID_WEIGHT_CONF')
74
- })
75
-
76
- it('EWVWAP - it should throw with wrong weightType in values', async () => {
77
- const values = [
78
- { price: '10161', weightType: 'bfx' },
79
- { price: '10232', weightType: 'bitstamp' },
80
- { price: '10510.25847', weightType: 'binance' },
81
- { price: '10261.826', weightType: 'kraken' }
82
- ]
83
-
84
- return expect(
85
- EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
86
- ).to.throw('ERR_INVALID_WEIGHT_TYPE')
87
- })
88
-
89
- it('EWVWAP - it should throw with multiple weights of same type', async () => {
90
- const values = [
91
- { price: '10161', weightType: 'bfx' },
92
- { price: '10261.235', weightType: 'bfx' },
93
- { price: '10324.2567', weightType: 'bfx' },
94
- { price: '10724', weightType: 'bfx' },
95
- { price: '10510.25847', weightType: 'bitstamp' },
96
- { price: '10261.826', weightType: 'kraken' }
97
- ]
98
-
99
- return expect(
100
- EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
101
- ).to.throw('ERR_DUP_WEIGHT_PRICES')
102
- })
103
-
104
- it('EWVWAP - it return 0 with no values', async () => {
105
- return expect(
106
- VWAP([], { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
107
- ).to.be.equal('0')
108
- })
109
-
110
- it('EWVWAP - it should match the expected value', async () => {
111
- const values = [
112
- { price: '10161', weightType: 'bfx' },
113
- { price: '10510.25847', weightType: 'bitstamp' },
114
- { price: '10261.826', weightType: 'kraken' }
115
- ]
116
-
117
- const res = EWVWAP(values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
118
- return expect(res).to.be.equal('10251.016894')
119
- })
120
- })
121
- }
6
+ test('VWAP - it should fail with non numeric values', (t) => {
7
+ const values = [
8
+ { price: '10161', volume: '1' },
9
+ { price: 'a10261.235', volume: '1' }
10
+ ]
11
+
12
+ t.exception.all(
13
+ VWAP.bind(null, values)
14
+ )
15
+ })
16
+
17
+ test('VWAP - it return 0 with no values', (t) => {
18
+ t.is(VWAP([]), '0')
19
+ })
20
+
21
+ test('VWAP - it should match the expected value', (t) => {
22
+ const values = [
23
+ { price: '10161', volume: '1' },
24
+ { price: '10261.235', volume: '1' },
25
+ { price: '10324.2567', volume: '1' },
26
+ { price: '10724', volume: '1' },
27
+ { price: '10232', volume: '1' },
28
+ { price: '10510.25847', volume: '1' },
29
+ { price: '10261.826', volume: '1' }
30
+ ]
31
+
32
+ const res = VWAP(values)
33
+ t.is(res, '10353.51088142857142857143')
34
+ })
35
+
36
+ test('EWVWAP - it should fail with non numeric values', (t) => {
37
+ const values = [
38
+ { price: '10161', weightType: 'bfx' },
39
+ { price: 'a10261.235', weightType: 'bitstamp' },
40
+ { price: '10261.826', weightType: 'kraken' }
41
+ ]
42
+
43
+ t.exception.all(
44
+ EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
45
+ )
46
+ })
47
+
48
+ test('EWVWAP - it should fail with NaN values', (t) => {
49
+ const values = [
50
+ { price: '10161', weightType: 'bfx' },
51
+ { price: NaN, weightType: 'bitstamp' },
52
+ { price: '10261.826', weightType: 'kraken' }
53
+ ]
54
+
55
+ t.exception.all(
56
+ EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
57
+ )
58
+ })
59
+
60
+ test('EWVWAP - it should fail with invalid config', (t) => {
61
+ const values = [
62
+ { price: '10161', weightType: 'bfx' },
63
+ { price: '10261.235', weightType: 'bitstamp' },
64
+ { price: '10261.826', weightType: 'kraken' }
65
+ ]
66
+
67
+ t.exception(
68
+ EWVWAP.bind(null, values, { bfx: 0.33, bitstamp: 0.33, kraken: 0.33 }),
69
+ /ERR_INVALID_WEIGHT_CONF/
70
+ )
71
+ })
72
+
73
+ test('EWVWAP - it should throw with wrong weightType in values', async (t) => {
74
+ const values = [
75
+ { price: '10161', weightType: 'bfx' },
76
+ { price: '10232', weightType: 'bitstamp' },
77
+ { price: '10510.25847', weightType: 'binance' },
78
+ { price: '10261.826', weightType: 'kraken' }
79
+ ]
80
+
81
+ t.exception(
82
+ EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 }),
83
+ /ERR_INVALID_WEIGHT_TYPE/
84
+ )
85
+ })
86
+
87
+ test('EWVWAP - it should throw with multiple weights of same type', async (t) => {
88
+ const values = [
89
+ { price: '10161', weightType: 'bfx' },
90
+ { price: '10261.235', weightType: 'bfx' },
91
+ { price: '10324.2567', weightType: 'bfx' },
92
+ { price: '10724', weightType: 'bfx' },
93
+ { price: '10510.25847', weightType: 'bitstamp' },
94
+ { price: '10261.826', weightType: 'kraken' }
95
+ ]
96
+
97
+ t.exception(
98
+ EWVWAP.bind(null, values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 }),
99
+ /ERR_DUP_WEIGHT_PRICES/
100
+ )
101
+ })
102
+
103
+ test('EWVWAP - it return 0 with no values', async (t) => {
104
+ t.is(
105
+ VWAP([], { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 }),
106
+ '0'
107
+ )
108
+ })
109
+
110
+ test('EWVWAP - it should match the expected value', async (t) => {
111
+ const values = [
112
+ { price: '10161', weightType: 'bfx' },
113
+ { price: '10510.25847', weightType: 'bitstamp' },
114
+ { price: '10261.826', weightType: 'kraken' }
115
+ ]
116
+
117
+ const res = EWVWAP(values, { bfx: 0.6, bitstamp: 0.2, kraken: 0.2 })
118
+ t.is(res, '10251.016894')
119
+ })