@barchart/portfolio-api-common 1.0.97 → 1.0.101
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.
|
@@ -136,16 +136,22 @@ module.exports = (() => {
|
|
|
136
136
|
const levelDefinition = levelDefinitions[0];
|
|
137
137
|
|
|
138
138
|
const populatedObjects = array.groupBy(items, levelDefinition.keySelector);
|
|
139
|
-
const populatedGroups = Object.keys(populatedObjects).
|
|
139
|
+
const populatedGroups = Object.keys(populatedObjects).reduce((list, key) => {
|
|
140
|
+
const items = populatedObjects[key];
|
|
140
141
|
const first = items[0];
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
list.push(new PositionGroup(this, parent, items, levelDefinition.currencySelector(first), key, levelDefinition.descriptionSelector(first), levelDefinition.single && items.length === 1));
|
|
144
|
+
|
|
145
|
+
return list;
|
|
146
|
+
}, [ ]);
|
|
144
147
|
|
|
145
|
-
const missingGroups = array.difference(levelDefinition.requiredGroups.map(group => group.
|
|
148
|
+
const missingGroups = array.difference(levelDefinition.requiredGroups.map(group => group.key), populatedGroups.map(group => group.key))
|
|
149
|
+
.map((key) => {
|
|
150
|
+
return levelDefinition.requiredGroups.find(g => g.key === key);
|
|
151
|
+
});
|
|
146
152
|
|
|
147
|
-
const empty = missingGroups.map((
|
|
148
|
-
return new PositionGroup(this, parent, [ ],
|
|
153
|
+
const empty = missingGroups.map((group) => {
|
|
154
|
+
return new PositionGroup(this, parent, [ ], group.currency, group.key, group.description);
|
|
149
155
|
});
|
|
150
156
|
|
|
151
157
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -268,11 +274,7 @@ module.exports = (() => {
|
|
|
268
274
|
}
|
|
269
275
|
|
|
270
276
|
function findNode(tree, keys) {
|
|
271
|
-
return keys.reduce((tree, key) =>
|
|
272
|
-
tree = tree.findChild(group => group.description === key);
|
|
273
|
-
|
|
274
|
-
return tree;
|
|
275
|
-
}, tree);
|
|
277
|
+
return keys.reduce((tree, key) => tree.findChild(group => group.key === key), tree);
|
|
276
278
|
}
|
|
277
279
|
|
|
278
280
|
function getSummaryArray(ranges) {
|
|
@@ -12,13 +12,14 @@ module.exports = (() => {
|
|
|
12
12
|
* @public
|
|
13
13
|
*/
|
|
14
14
|
class PositionGroup {
|
|
15
|
-
constructor(container, parent, items, currency, description, single) {
|
|
15
|
+
constructor(container, parent, items, currency, key, description, single) {
|
|
16
16
|
this._container = container;
|
|
17
17
|
this._parent = parent || null;
|
|
18
18
|
|
|
19
19
|
this._items = items;
|
|
20
|
-
this._currency = currency;
|
|
20
|
+
this._currency = currency || Currency.CAD;
|
|
21
21
|
|
|
22
|
+
this._key = key;
|
|
22
23
|
this._description = description;
|
|
23
24
|
|
|
24
25
|
this._single = is.boolean(single) && single;
|
|
@@ -30,9 +31,10 @@ module.exports = (() => {
|
|
|
30
31
|
|
|
31
32
|
this._dataFormat = { };
|
|
32
33
|
this._dataActual = { };
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
this._dataFormat.key = this._key;
|
|
34
36
|
this._dataFormat.description = this._description;
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
this._dataActual.currentPrice = null;
|
|
37
39
|
this._dataActual.previousPrice = null;
|
|
38
40
|
this._dataActual.basis = null;
|
|
@@ -66,7 +68,7 @@ module.exports = (() => {
|
|
|
66
68
|
item.registerPriceChangeHandler((data, sender) => {
|
|
67
69
|
if (this._single) {
|
|
68
70
|
this._dataActual.currentPrice = data.currentPrice;
|
|
69
|
-
this._dataFormat.currentPrice =
|
|
71
|
+
this._dataFormat.currentPrice = formatCurrency(data.currentPrice, sender.position.instrument.currency);
|
|
70
72
|
} else {
|
|
71
73
|
this._dataActual.currentPrice = null;
|
|
72
74
|
this._dataFormat.currentPrice = null;
|
|
@@ -79,16 +81,20 @@ module.exports = (() => {
|
|
|
79
81
|
this.refresh();
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
get
|
|
83
|
-
return this.
|
|
84
|
+
get key() {
|
|
85
|
+
return this._key;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get description() {
|
|
89
|
+
return this._description;
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
get currency() {
|
|
87
93
|
return this._currency;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
get
|
|
91
|
-
return this.
|
|
96
|
+
get items() {
|
|
97
|
+
return this._items;
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
get data() {
|
|
@@ -14,7 +14,7 @@ module.exports = (() => {
|
|
|
14
14
|
* @param {PositionLevelDefinition~keySelector} keySelector
|
|
15
15
|
* @param {PositionLevelDefinition~descriptionSelector} descriptionSelector
|
|
16
16
|
* @param {PositionLevelDefinition~currencySelector} currencySelector
|
|
17
|
-
* @param {Array.<
|
|
17
|
+
* @param {Array.<PositionLevelDefinition~RequiredGroup>=} requiredGroups
|
|
18
18
|
* @param {Boolean=} single
|
|
19
19
|
*/
|
|
20
20
|
class PositionLevelDefinition {
|
|
@@ -139,5 +139,16 @@ module.exports = (() => {
|
|
|
139
139
|
* @returns {Currency}
|
|
140
140
|
*/
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The data required to construct a group.
|
|
144
|
+
*
|
|
145
|
+
* @public
|
|
146
|
+
* @typedef PositionLevelDefinition~RequiredGroup
|
|
147
|
+
* @type {Object}
|
|
148
|
+
* @property {String} key
|
|
149
|
+
* @property {String} description
|
|
150
|
+
* @property {Currency} currency
|
|
151
|
+
*/
|
|
152
|
+
|
|
142
153
|
return PositionLevelDefinition;
|
|
143
154
|
})();
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -852,16 +852,22 @@ module.exports = (() => {
|
|
|
852
852
|
const levelDefinition = levelDefinitions[0];
|
|
853
853
|
|
|
854
854
|
const populatedObjects = array.groupBy(items, levelDefinition.keySelector);
|
|
855
|
-
const populatedGroups = Object.keys(populatedObjects).
|
|
855
|
+
const populatedGroups = Object.keys(populatedObjects).reduce((list, key) => {
|
|
856
|
+
const items = populatedObjects[key];
|
|
856
857
|
const first = items[0];
|
|
857
858
|
|
|
858
|
-
|
|
859
|
-
|
|
859
|
+
list.push(new PositionGroup(this, parent, items, levelDefinition.currencySelector(first), key, levelDefinition.descriptionSelector(first), levelDefinition.single && items.length === 1));
|
|
860
|
+
|
|
861
|
+
return list;
|
|
862
|
+
}, [ ]);
|
|
860
863
|
|
|
861
|
-
const missingGroups = array.difference(levelDefinition.requiredGroups.map(group => group.
|
|
864
|
+
const missingGroups = array.difference(levelDefinition.requiredGroups.map(group => group.key), populatedGroups.map(group => group.key))
|
|
865
|
+
.map((key) => {
|
|
866
|
+
return levelDefinition.requiredGroups.find(g => g.key === key);
|
|
867
|
+
});
|
|
862
868
|
|
|
863
|
-
const empty = missingGroups.map((
|
|
864
|
-
return new PositionGroup(this, parent, [ ],
|
|
869
|
+
const empty = missingGroups.map((group) => {
|
|
870
|
+
return new PositionGroup(this, parent, [ ], group.currency, group.key, group.description);
|
|
865
871
|
});
|
|
866
872
|
|
|
867
873
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -984,11 +990,7 @@ module.exports = (() => {
|
|
|
984
990
|
}
|
|
985
991
|
|
|
986
992
|
function findNode(tree, keys) {
|
|
987
|
-
return keys.reduce((tree, key) =>
|
|
988
|
-
tree = tree.findChild(group => group.description === key);
|
|
989
|
-
|
|
990
|
-
return tree;
|
|
991
|
-
}, tree);
|
|
993
|
+
return keys.reduce((tree, key) => tree.findChild(group => group.key === key), tree);
|
|
992
994
|
}
|
|
993
995
|
|
|
994
996
|
function getSummaryArray(ranges) {
|
|
@@ -1013,13 +1015,14 @@ module.exports = (() => {
|
|
|
1013
1015
|
* @public
|
|
1014
1016
|
*/
|
|
1015
1017
|
class PositionGroup {
|
|
1016
|
-
constructor(container, parent, items, currency, description, single) {
|
|
1018
|
+
constructor(container, parent, items, currency, key, description, single) {
|
|
1017
1019
|
this._container = container;
|
|
1018
1020
|
this._parent = parent || null;
|
|
1019
1021
|
|
|
1020
1022
|
this._items = items;
|
|
1021
|
-
this._currency = currency;
|
|
1023
|
+
this._currency = currency || Currency.CAD;
|
|
1022
1024
|
|
|
1025
|
+
this._key = key;
|
|
1023
1026
|
this._description = description;
|
|
1024
1027
|
|
|
1025
1028
|
this._single = is.boolean(single) && single;
|
|
@@ -1031,9 +1034,10 @@ module.exports = (() => {
|
|
|
1031
1034
|
|
|
1032
1035
|
this._dataFormat = { };
|
|
1033
1036
|
this._dataActual = { };
|
|
1034
|
-
|
|
1037
|
+
|
|
1038
|
+
this._dataFormat.key = this._key;
|
|
1035
1039
|
this._dataFormat.description = this._description;
|
|
1036
|
-
|
|
1040
|
+
|
|
1037
1041
|
this._dataActual.currentPrice = null;
|
|
1038
1042
|
this._dataActual.previousPrice = null;
|
|
1039
1043
|
this._dataActual.basis = null;
|
|
@@ -1067,7 +1071,7 @@ module.exports = (() => {
|
|
|
1067
1071
|
item.registerPriceChangeHandler((data, sender) => {
|
|
1068
1072
|
if (this._single) {
|
|
1069
1073
|
this._dataActual.currentPrice = data.currentPrice;
|
|
1070
|
-
this._dataFormat.currentPrice =
|
|
1074
|
+
this._dataFormat.currentPrice = formatCurrency(data.currentPrice, sender.position.instrument.currency);
|
|
1071
1075
|
} else {
|
|
1072
1076
|
this._dataActual.currentPrice = null;
|
|
1073
1077
|
this._dataFormat.currentPrice = null;
|
|
@@ -1080,16 +1084,20 @@ module.exports = (() => {
|
|
|
1080
1084
|
this.refresh();
|
|
1081
1085
|
}
|
|
1082
1086
|
|
|
1083
|
-
get
|
|
1084
|
-
return this.
|
|
1087
|
+
get key() {
|
|
1088
|
+
return this._key;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
get description() {
|
|
1092
|
+
return this._description;
|
|
1085
1093
|
}
|
|
1086
1094
|
|
|
1087
1095
|
get currency() {
|
|
1088
1096
|
return this._currency;
|
|
1089
1097
|
}
|
|
1090
1098
|
|
|
1091
|
-
get
|
|
1092
|
-
return this.
|
|
1099
|
+
get items() {
|
|
1100
|
+
return this._items;
|
|
1093
1101
|
}
|
|
1094
1102
|
|
|
1095
1103
|
get data() {
|
|
@@ -1570,7 +1578,7 @@ module.exports = (() => {
|
|
|
1570
1578
|
* @param {PositionLevelDefinition~keySelector} keySelector
|
|
1571
1579
|
* @param {PositionLevelDefinition~descriptionSelector} descriptionSelector
|
|
1572
1580
|
* @param {PositionLevelDefinition~currencySelector} currencySelector
|
|
1573
|
-
* @param {Array.<
|
|
1581
|
+
* @param {Array.<PositionLevelDefinition~RequiredGroup>=} requiredGroups
|
|
1574
1582
|
* @param {Boolean=} single
|
|
1575
1583
|
*/
|
|
1576
1584
|
class PositionLevelDefinition {
|
|
@@ -1695,6 +1703,17 @@ module.exports = (() => {
|
|
|
1695
1703
|
* @returns {Currency}
|
|
1696
1704
|
*/
|
|
1697
1705
|
|
|
1706
|
+
/**
|
|
1707
|
+
* The data required to construct a group.
|
|
1708
|
+
*
|
|
1709
|
+
* @public
|
|
1710
|
+
* @typedef PositionLevelDefinition~RequiredGroup
|
|
1711
|
+
* @type {Object}
|
|
1712
|
+
* @property {String} key
|
|
1713
|
+
* @property {String} description
|
|
1714
|
+
* @property {Currency} currency
|
|
1715
|
+
*/
|
|
1716
|
+
|
|
1698
1717
|
return PositionLevelDefinition;
|
|
1699
1718
|
})();
|
|
1700
1719
|
|
|
@@ -6178,18 +6197,18 @@ describe('When a position container data is gathered', () => {
|
|
|
6178
6197
|
beforeEach(() => {
|
|
6179
6198
|
portfolios = [
|
|
6180
6199
|
{
|
|
6181
|
-
portfolio: '
|
|
6200
|
+
portfolio: 'My First Portfolio',
|
|
6182
6201
|
name: 'a'
|
|
6183
6202
|
}, {
|
|
6184
|
-
portfolio: '
|
|
6203
|
+
portfolio: 'My Second Portfolio',
|
|
6185
6204
|
name: 'b'
|
|
6186
6205
|
}
|
|
6187
6206
|
];
|
|
6188
6207
|
|
|
6189
6208
|
positions = [
|
|
6190
|
-
getPosition('
|
|
6191
|
-
getPosition('
|
|
6192
|
-
getPosition('
|
|
6209
|
+
getPosition('My First Portfolio', 'AAPL'),
|
|
6210
|
+
getPosition('My Second Portfolio', 'AAPL'),
|
|
6211
|
+
getPosition('My Second Portfolio', 'TSLA')
|
|
6193
6212
|
];
|
|
6194
6213
|
|
|
6195
6214
|
summaries = [ ];
|
|
@@ -6203,7 +6222,7 @@ describe('When a position container data is gathered', () => {
|
|
|
6203
6222
|
beforeEach(() => {
|
|
6204
6223
|
definitions = [
|
|
6205
6224
|
new PositionTreeDefinition(name = 'the only tree', [
|
|
6206
|
-
new PositionLevelDefinition('Total', x =>
|
|
6225
|
+
new PositionLevelDefinition('Total', x => 'totals', x => 'Total', x => Currency.CAD),
|
|
6207
6226
|
new PositionLevelDefinition('Portfolio', x => x.portfolio.portfolio, x => x.portfolio.name, x => Currency.CAD),
|
|
6208
6227
|
new PositionLevelDefinition('Position', x => x.position.position, x => x.position.instrument.symbol.barchart, x => x.position.instrument.currency)
|
|
6209
6228
|
])
|
|
@@ -6217,27 +6236,27 @@ describe('When a position container data is gathered', () => {
|
|
|
6217
6236
|
});
|
|
6218
6237
|
|
|
6219
6238
|
it('the "Total" group should have two children groups', () => {
|
|
6220
|
-
expect(container.getGroups(name, [ '
|
|
6239
|
+
expect(container.getGroups(name, [ 'totals' ]).length).toEqual(2);
|
|
6221
6240
|
});
|
|
6222
6241
|
|
|
6223
6242
|
it('the "Total" group should have three items', () => {
|
|
6224
|
-
expect(container.getGroup(name, [ '
|
|
6243
|
+
expect(container.getGroup(name, [ 'totals' ]).items.length).toEqual(3);
|
|
6225
6244
|
});
|
|
6226
6245
|
|
|
6227
6246
|
it('The "a" portfolio group should have one child group', () => {
|
|
6228
|
-
expect(container.getGroups(name, [ '
|
|
6247
|
+
expect(container.getGroups(name, [ 'totals', 'My First Portfolio' ]).length).toEqual(1);
|
|
6229
6248
|
});
|
|
6230
6249
|
|
|
6231
6250
|
it('the "a" portfolio group should have one item', () => {
|
|
6232
|
-
expect(container.getGroup(name, [ '
|
|
6251
|
+
expect(container.getGroup(name, [ 'totals', 'My First Portfolio' ]).items.length).toEqual(1);
|
|
6233
6252
|
});
|
|
6234
6253
|
|
|
6235
6254
|
it('The "b" portfolio group should have two child groups', () => {
|
|
6236
|
-
expect(container.getGroups(name, [ '
|
|
6255
|
+
expect(container.getGroups(name, [ 'totals', 'My Second Portfolio' ]).length).toEqual(2);
|
|
6237
6256
|
});
|
|
6238
6257
|
|
|
6239
6258
|
it('the "b" portfolio group should have two items', () => {
|
|
6240
|
-
expect(container.getGroup(name, [ '
|
|
6259
|
+
expect(container.getGroup(name, [ 'totals', 'My Second Portfolio' ]).items.length).toEqual(2);
|
|
6241
6260
|
});
|
|
6242
6261
|
});
|
|
6243
6262
|
});
|
|
@@ -41,18 +41,18 @@ describe('When a position container data is gathered', () => {
|
|
|
41
41
|
beforeEach(() => {
|
|
42
42
|
portfolios = [
|
|
43
43
|
{
|
|
44
|
-
portfolio: '
|
|
44
|
+
portfolio: 'My First Portfolio',
|
|
45
45
|
name: 'a'
|
|
46
46
|
}, {
|
|
47
|
-
portfolio: '
|
|
47
|
+
portfolio: 'My Second Portfolio',
|
|
48
48
|
name: 'b'
|
|
49
49
|
}
|
|
50
50
|
];
|
|
51
51
|
|
|
52
52
|
positions = [
|
|
53
|
-
getPosition('
|
|
54
|
-
getPosition('
|
|
55
|
-
getPosition('
|
|
53
|
+
getPosition('My First Portfolio', 'AAPL'),
|
|
54
|
+
getPosition('My Second Portfolio', 'AAPL'),
|
|
55
|
+
getPosition('My Second Portfolio', 'TSLA')
|
|
56
56
|
];
|
|
57
57
|
|
|
58
58
|
summaries = [ ];
|
|
@@ -66,7 +66,7 @@ describe('When a position container data is gathered', () => {
|
|
|
66
66
|
beforeEach(() => {
|
|
67
67
|
definitions = [
|
|
68
68
|
new PositionTreeDefinition(name = 'the only tree', [
|
|
69
|
-
new PositionLevelDefinition('Total', x =>
|
|
69
|
+
new PositionLevelDefinition('Total', x => 'totals', x => 'Total', x => Currency.CAD),
|
|
70
70
|
new PositionLevelDefinition('Portfolio', x => x.portfolio.portfolio, x => x.portfolio.name, x => Currency.CAD),
|
|
71
71
|
new PositionLevelDefinition('Position', x => x.position.position, x => x.position.instrument.symbol.barchart, x => x.position.instrument.currency)
|
|
72
72
|
])
|
|
@@ -80,27 +80,27 @@ describe('When a position container data is gathered', () => {
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('the "Total" group should have two children groups', () => {
|
|
83
|
-
expect(container.getGroups(name, [ '
|
|
83
|
+
expect(container.getGroups(name, [ 'totals' ]).length).toEqual(2);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it('the "Total" group should have three items', () => {
|
|
87
|
-
expect(container.getGroup(name, [ '
|
|
87
|
+
expect(container.getGroup(name, [ 'totals' ]).items.length).toEqual(3);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
it('The "a" portfolio group should have one child group', () => {
|
|
91
|
-
expect(container.getGroups(name, [ '
|
|
91
|
+
expect(container.getGroups(name, [ 'totals', 'My First Portfolio' ]).length).toEqual(1);
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it('the "a" portfolio group should have one item', () => {
|
|
95
|
-
expect(container.getGroup(name, [ '
|
|
95
|
+
expect(container.getGroup(name, [ 'totals', 'My First Portfolio' ]).items.length).toEqual(1);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
it('The "b" portfolio group should have two child groups', () => {
|
|
99
|
-
expect(container.getGroups(name, [ '
|
|
99
|
+
expect(container.getGroups(name, [ 'totals', 'My Second Portfolio' ]).length).toEqual(2);
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
it('the "b" portfolio group should have two items', () => {
|
|
103
|
-
expect(container.getGroup(name, [ '
|
|
103
|
+
expect(container.getGroup(name, [ 'totals', 'My Second Portfolio' ]).items.length).toEqual(2);
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
106
|
});
|