@barchart/portfolio-api-common 1.0.265 → 1.0.266
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/lib/processing/PositionContainer.js +22 -9
- package/lib/processing/PositionGroup.js +61 -39
- package/package.json +1 -1
- package/test/SpecRunner.js +83 -48
|
@@ -324,6 +324,8 @@ module.exports = (() => {
|
|
|
324
324
|
this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
|
|
325
325
|
}
|
|
326
326
|
});
|
|
327
|
+
|
|
328
|
+
recalculatePercentages.call(this);
|
|
327
329
|
}
|
|
328
330
|
|
|
329
331
|
/**
|
|
@@ -337,6 +339,8 @@ module.exports = (() => {
|
|
|
337
339
|
assert.argumentIsRequired(position.position, 'position.position', String);
|
|
338
340
|
|
|
339
341
|
removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
|
|
342
|
+
|
|
343
|
+
recalculatePercentages.call(this);
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
/**
|
|
@@ -384,6 +388,8 @@ module.exports = (() => {
|
|
|
384
388
|
if (this._symbols.hasOwnProperty(symbol)) {
|
|
385
389
|
this._symbols[symbol].forEach(item => item.setQuote(quote));
|
|
386
390
|
}
|
|
391
|
+
|
|
392
|
+
recalculatePercentages.call(this);
|
|
387
393
|
}
|
|
388
394
|
|
|
389
395
|
/**
|
|
@@ -427,7 +433,9 @@ module.exports = (() => {
|
|
|
427
433
|
this._forexQuotes[index] = rate;
|
|
428
434
|
}
|
|
429
435
|
|
|
430
|
-
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.
|
|
436
|
+
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.setForexRates(this._forexQuotes), true, false));
|
|
437
|
+
|
|
438
|
+
recalculatePercentages.call(this);
|
|
431
439
|
}
|
|
432
440
|
|
|
433
441
|
/**
|
|
@@ -739,12 +747,6 @@ module.exports = (() => {
|
|
|
739
747
|
}
|
|
740
748
|
}
|
|
741
749
|
}));
|
|
742
|
-
|
|
743
|
-
addGroupBinding.call(this, group, group.registerMarketPercentChangeHandler(() => {
|
|
744
|
-
if (!groupTree.getIsRoot()) {
|
|
745
|
-
groupTree.getParent().walk((childGroup) => childGroup.refreshMarketPercent());
|
|
746
|
-
}
|
|
747
|
-
}));
|
|
748
750
|
}
|
|
749
751
|
|
|
750
752
|
function createGroups(parentTree, items, treeDefinition, levelDefinitions, overrideRequiredGroups) {
|
|
@@ -752,6 +754,8 @@ module.exports = (() => {
|
|
|
752
754
|
return;
|
|
753
755
|
}
|
|
754
756
|
|
|
757
|
+
const rates = this._forexQuotes;
|
|
758
|
+
|
|
755
759
|
const levelDefinition = levelDefinitions[0];
|
|
756
760
|
|
|
757
761
|
const populatedObjects = array.groupBy(items, levelDefinition.keySelector);
|
|
@@ -759,7 +763,7 @@ module.exports = (() => {
|
|
|
759
763
|
const items = populatedObjects[key];
|
|
760
764
|
const first = items[0];
|
|
761
765
|
|
|
762
|
-
list.push(new PositionGroup(
|
|
766
|
+
list.push(new PositionGroup(levelDefinition, items, rates, levelDefinition.currencySelector(first), key, levelDefinition.descriptionSelector(first), levelDefinition.aggregateCash));
|
|
763
767
|
|
|
764
768
|
return list;
|
|
765
769
|
}, [ ]);
|
|
@@ -772,7 +776,7 @@ module.exports = (() => {
|
|
|
772
776
|
});
|
|
773
777
|
|
|
774
778
|
const empty = missingGroups.map((group) => {
|
|
775
|
-
return new PositionGroup(
|
|
779
|
+
return new PositionGroup(levelDefinition, [ ], rates, group.currency, group.key, group.description);
|
|
776
780
|
});
|
|
777
781
|
|
|
778
782
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -812,6 +816,9 @@ module.exports = (() => {
|
|
|
812
816
|
|
|
813
817
|
this._nodes[group.id] = childTree;
|
|
814
818
|
|
|
819
|
+
group.setParentGroup(this.getParentGroup(group));
|
|
820
|
+
group.setPortfolioGroup(this.getParentGroupForPortfolio(group));
|
|
821
|
+
|
|
815
822
|
initializeGroupObservers.call(this, childTree, treeDefinition);
|
|
816
823
|
|
|
817
824
|
createGroups.call(this, childTree, group.items, treeDefinition, array.dropLeft(levelDefinitions));
|
|
@@ -952,5 +959,11 @@ module.exports = (() => {
|
|
|
952
959
|
groupNodeToSever.walk(group => delete this._nodes[group.id], false, true);
|
|
953
960
|
}
|
|
954
961
|
|
|
962
|
+
function recalculatePercentages() {
|
|
963
|
+
Object.keys(this._trees).forEach((key) => {
|
|
964
|
+
this._trees[key].walk(group => group.refreshMarketPercent(), false, false);
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
|
|
955
968
|
return PositionContainer;
|
|
956
969
|
})();
|
|
@@ -33,13 +33,17 @@ module.exports = (() => {
|
|
|
33
33
|
* @param {Boolean=} aggregateCash
|
|
34
34
|
*/
|
|
35
35
|
class PositionGroup {
|
|
36
|
-
constructor(
|
|
36
|
+
constructor(definition, items, rates, currency, key, description, aggregateCash) {
|
|
37
37
|
this._id = counter++;
|
|
38
38
|
|
|
39
39
|
this._definition = definition;
|
|
40
|
-
this._container = container;
|
|
41
40
|
|
|
42
41
|
this._items = items;
|
|
42
|
+
this._rates = rates;
|
|
43
|
+
|
|
44
|
+
this._parentGroup = null;
|
|
45
|
+
this._portfolioGroup = null;
|
|
46
|
+
|
|
43
47
|
this._currency = currency || Currency.CAD;
|
|
44
48
|
this._bypassCurrencyTranslation = false;
|
|
45
49
|
|
|
@@ -53,7 +57,6 @@ module.exports = (() => {
|
|
|
53
57
|
this._suspended = false;
|
|
54
58
|
this._showClosedPositions = false;
|
|
55
59
|
|
|
56
|
-
this._marketPercentChangeEvent = new Event(this);
|
|
57
60
|
this._groupExcludedChangeEvent = new Event(this);
|
|
58
61
|
this._showClosedPositionsChangeEvent = new Event(this);
|
|
59
62
|
|
|
@@ -266,6 +269,40 @@ module.exports = (() => {
|
|
|
266
269
|
return this._excluded;
|
|
267
270
|
}
|
|
268
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Sets the immediate parent group (allowing for calculation of relative
|
|
274
|
+
* percentages).
|
|
275
|
+
*
|
|
276
|
+
* @public
|
|
277
|
+
* @param {PortfolioGroup} group
|
|
278
|
+
*/
|
|
279
|
+
setParentGroup(group) {
|
|
280
|
+
assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
|
|
281
|
+
|
|
282
|
+
if (this._parentGroup !== null) {
|
|
283
|
+
throw new Error('The parent group has already been set.');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this._parentGroup = group;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Sets the nearest parent group for a portfolio (allowing for calculation
|
|
291
|
+
* of relative percentages).
|
|
292
|
+
*
|
|
293
|
+
* @public
|
|
294
|
+
* @param {PortfolioGroup} group
|
|
295
|
+
*/
|
|
296
|
+
setPortfolioGroup(group) {
|
|
297
|
+
assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
|
|
298
|
+
|
|
299
|
+
if (this._portfolioGroup !== null) {
|
|
300
|
+
throw new Error('The portfolio group has already been set.');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this._portfolioGroup = group;
|
|
304
|
+
}
|
|
305
|
+
|
|
269
306
|
/**
|
|
270
307
|
* Adds a new {@link PositionItem} to the group.
|
|
271
308
|
*
|
|
@@ -311,9 +348,11 @@ module.exports = (() => {
|
|
|
311
348
|
* Causes aggregated data to be recalculated using a new exchange rate.
|
|
312
349
|
*
|
|
313
350
|
* @public
|
|
314
|
-
* @param {Rate} rate
|
|
351
|
+
* @param {Array.<Rate>} rate
|
|
315
352
|
*/
|
|
316
|
-
|
|
353
|
+
setForexRates(rates) {
|
|
354
|
+
this._rates = rates;
|
|
355
|
+
|
|
317
356
|
if (!this._bypassCurrencyTranslation) {
|
|
318
357
|
this.refresh();
|
|
319
358
|
}
|
|
@@ -401,10 +440,8 @@ module.exports = (() => {
|
|
|
401
440
|
return;
|
|
402
441
|
}
|
|
403
442
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
calculateStaticData(this, rates);
|
|
407
|
-
calculatePriceData(this, rates, null, true);
|
|
443
|
+
calculateStaticData(this, this._rates);
|
|
444
|
+
calculatePriceData(this, this._rates, null, true);
|
|
408
445
|
}
|
|
409
446
|
|
|
410
447
|
/**
|
|
@@ -414,7 +451,7 @@ module.exports = (() => {
|
|
|
414
451
|
* @public
|
|
415
452
|
*/
|
|
416
453
|
refreshMarketPercent() {
|
|
417
|
-
calculateMarketPercent(this, this.
|
|
454
|
+
calculateMarketPercent(this, this._rates, this._parentGroup, this._portfolioGroup);
|
|
418
455
|
}
|
|
419
456
|
|
|
420
457
|
/**
|
|
@@ -427,17 +464,6 @@ module.exports = (() => {
|
|
|
427
464
|
return this._items.length === 0;
|
|
428
465
|
}
|
|
429
466
|
|
|
430
|
-
/**
|
|
431
|
-
* Adds an observer for change in the market percentage of the group.
|
|
432
|
-
*
|
|
433
|
-
* @public
|
|
434
|
-
* @param {Function} handler
|
|
435
|
-
* @return {Disposable}
|
|
436
|
-
*/
|
|
437
|
-
registerMarketPercentChangeHandler(handler) {
|
|
438
|
-
return this._marketPercentChangeEvent.register(handler);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
467
|
/**
|
|
442
468
|
* Adds an observer for changes to the exclusion of the group
|
|
443
469
|
* from higher level aggregations.
|
|
@@ -492,10 +518,10 @@ module.exports = (() => {
|
|
|
492
518
|
this._dataFormat.currentPrice = null;
|
|
493
519
|
}
|
|
494
520
|
|
|
495
|
-
calculatePriceData(this, this.
|
|
521
|
+
calculatePriceData(this, this._rates, sender, false);
|
|
496
522
|
});
|
|
497
523
|
|
|
498
|
-
let fundamentalBinding = item.registerFundamentalDataChangeHandler((data
|
|
524
|
+
let fundamentalBinding = item.registerFundamentalDataChangeHandler((data) => {
|
|
499
525
|
if (this._single) {
|
|
500
526
|
this._dataFormat.fundamental = data;
|
|
501
527
|
} else {
|
|
@@ -546,13 +572,13 @@ module.exports = (() => {
|
|
|
546
572
|
let newsBinding = Disposable.getEmpty();
|
|
547
573
|
|
|
548
574
|
if (this._single) {
|
|
549
|
-
newsBinding = item.registerNewsExistsChangeHandler((exists
|
|
575
|
+
newsBinding = item.registerNewsExistsChangeHandler((exists) => {
|
|
550
576
|
this._dataActual.newsExists = exists;
|
|
551
577
|
this._dataFormat.newsExists = exists;
|
|
552
578
|
});
|
|
553
579
|
}
|
|
554
580
|
|
|
555
|
-
this._disposeStack.push(item.registerPortfolioChangeHandler((portfolio
|
|
581
|
+
this._disposeStack.push(item.registerPortfolioChangeHandler((portfolio) => {
|
|
556
582
|
const descriptionSelector = this._definition.descriptionSelector;
|
|
557
583
|
|
|
558
584
|
this._description = descriptionSelector(this._items[0]);
|
|
@@ -801,14 +827,11 @@ module.exports = (() => {
|
|
|
801
827
|
|
|
802
828
|
format.total = formatCurrency(actual.total, currency);
|
|
803
829
|
format.totalNegative = actual.total.getIsNegative();
|
|
804
|
-
|
|
805
|
-
calculateMarketPercent(group, rates, false);
|
|
830
|
+
|
|
806
831
|
calculateUnrealizedPercent(group);
|
|
807
832
|
}
|
|
808
833
|
|
|
809
|
-
function calculateMarketPercent(group, rates,
|
|
810
|
-
return;
|
|
811
|
-
|
|
834
|
+
function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
|
|
812
835
|
if (group.suspended) {
|
|
813
836
|
return;
|
|
814
837
|
}
|
|
@@ -817,12 +840,10 @@ module.exports = (() => {
|
|
|
817
840
|
const format = group._dataFormat;
|
|
818
841
|
const excluded = group._excluded;
|
|
819
842
|
|
|
820
|
-
const portfolioParent = group._container.getParentGroupForPortfolio(group);
|
|
821
|
-
|
|
822
843
|
const calculatePercent = (parent) => {
|
|
823
844
|
let marketPercent;
|
|
824
845
|
|
|
825
|
-
if (parent
|
|
846
|
+
if (parent && !excluded) {
|
|
826
847
|
const parentData = parent._dataActual;
|
|
827
848
|
|
|
828
849
|
if (parentData.marketAbsolute !== null && !parentData.marketAbsolute.getIsZero()) {
|
|
@@ -845,14 +866,15 @@ module.exports = (() => {
|
|
|
845
866
|
return marketPercent;
|
|
846
867
|
};
|
|
847
868
|
|
|
848
|
-
actual.marketPercent = calculatePercent(
|
|
869
|
+
actual.marketPercent = calculatePercent(parentGroup);
|
|
849
870
|
format.marketPercent = formatPercent(actual.marketPercent, 2);
|
|
850
871
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
872
|
+
if (parentGroup === portfolioGroup) {
|
|
873
|
+
actual.marketPercentPortfolio = actual.marketPercent;
|
|
874
|
+
format.marketPercentPortfolio = format.marketPercent;
|
|
875
|
+
} else {
|
|
876
|
+
actual.marketPercentPortfolio = calculatePercent(portfolioGroup);
|
|
877
|
+
format.marketPercentPortfolio = formatPercent(actual.marketPercentPortfolio, 2);
|
|
856
878
|
}
|
|
857
879
|
}
|
|
858
880
|
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -1480,6 +1480,8 @@ module.exports = (() => {
|
|
|
1480
1480
|
this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
|
|
1481
1481
|
}
|
|
1482
1482
|
});
|
|
1483
|
+
|
|
1484
|
+
recalculatePercentages.call(this);
|
|
1483
1485
|
}
|
|
1484
1486
|
|
|
1485
1487
|
/**
|
|
@@ -1493,6 +1495,8 @@ module.exports = (() => {
|
|
|
1493
1495
|
assert.argumentIsRequired(position.position, 'position.position', String);
|
|
1494
1496
|
|
|
1495
1497
|
removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
|
|
1498
|
+
|
|
1499
|
+
recalculatePercentages.call(this);
|
|
1496
1500
|
}
|
|
1497
1501
|
|
|
1498
1502
|
/**
|
|
@@ -1540,6 +1544,8 @@ module.exports = (() => {
|
|
|
1540
1544
|
if (this._symbols.hasOwnProperty(symbol)) {
|
|
1541
1545
|
this._symbols[symbol].forEach(item => item.setQuote(quote));
|
|
1542
1546
|
}
|
|
1547
|
+
|
|
1548
|
+
recalculatePercentages.call(this);
|
|
1543
1549
|
}
|
|
1544
1550
|
|
|
1545
1551
|
/**
|
|
@@ -1583,7 +1589,9 @@ module.exports = (() => {
|
|
|
1583
1589
|
this._forexQuotes[index] = rate;
|
|
1584
1590
|
}
|
|
1585
1591
|
|
|
1586
|
-
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.
|
|
1592
|
+
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.setForexRates(this._forexQuotes), true, false));
|
|
1593
|
+
|
|
1594
|
+
recalculatePercentages.call(this);
|
|
1587
1595
|
}
|
|
1588
1596
|
|
|
1589
1597
|
/**
|
|
@@ -1895,12 +1903,6 @@ module.exports = (() => {
|
|
|
1895
1903
|
}
|
|
1896
1904
|
}
|
|
1897
1905
|
}));
|
|
1898
|
-
|
|
1899
|
-
addGroupBinding.call(this, group, group.registerMarketPercentChangeHandler(() => {
|
|
1900
|
-
if (!groupTree.getIsRoot()) {
|
|
1901
|
-
groupTree.getParent().walk((childGroup) => childGroup.refreshMarketPercent());
|
|
1902
|
-
}
|
|
1903
|
-
}));
|
|
1904
1906
|
}
|
|
1905
1907
|
|
|
1906
1908
|
function createGroups(parentTree, items, treeDefinition, levelDefinitions, overrideRequiredGroups) {
|
|
@@ -1908,6 +1910,8 @@ module.exports = (() => {
|
|
|
1908
1910
|
return;
|
|
1909
1911
|
}
|
|
1910
1912
|
|
|
1913
|
+
const rates = this._forexQuotes;
|
|
1914
|
+
|
|
1911
1915
|
const levelDefinition = levelDefinitions[0];
|
|
1912
1916
|
|
|
1913
1917
|
const populatedObjects = array.groupBy(items, levelDefinition.keySelector);
|
|
@@ -1915,7 +1919,7 @@ module.exports = (() => {
|
|
|
1915
1919
|
const items = populatedObjects[key];
|
|
1916
1920
|
const first = items[0];
|
|
1917
1921
|
|
|
1918
|
-
list.push(new PositionGroup(
|
|
1922
|
+
list.push(new PositionGroup(levelDefinition, items, rates, levelDefinition.currencySelector(first), key, levelDefinition.descriptionSelector(first), levelDefinition.aggregateCash));
|
|
1919
1923
|
|
|
1920
1924
|
return list;
|
|
1921
1925
|
}, [ ]);
|
|
@@ -1928,7 +1932,7 @@ module.exports = (() => {
|
|
|
1928
1932
|
});
|
|
1929
1933
|
|
|
1930
1934
|
const empty = missingGroups.map((group) => {
|
|
1931
|
-
return new PositionGroup(
|
|
1935
|
+
return new PositionGroup(levelDefinition, [ ], rates, group.currency, group.key, group.description);
|
|
1932
1936
|
});
|
|
1933
1937
|
|
|
1934
1938
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -1968,6 +1972,9 @@ module.exports = (() => {
|
|
|
1968
1972
|
|
|
1969
1973
|
this._nodes[group.id] = childTree;
|
|
1970
1974
|
|
|
1975
|
+
group.setParentGroup(this.getParentGroup(group));
|
|
1976
|
+
group.setPortfolioGroup(this.getParentGroupForPortfolio(group));
|
|
1977
|
+
|
|
1971
1978
|
initializeGroupObservers.call(this, childTree, treeDefinition);
|
|
1972
1979
|
|
|
1973
1980
|
createGroups.call(this, childTree, group.items, treeDefinition, array.dropLeft(levelDefinitions));
|
|
@@ -2108,6 +2115,12 @@ module.exports = (() => {
|
|
|
2108
2115
|
groupNodeToSever.walk(group => delete this._nodes[group.id], false, true);
|
|
2109
2116
|
}
|
|
2110
2117
|
|
|
2118
|
+
function recalculatePercentages() {
|
|
2119
|
+
Object.keys(this._trees).forEach((key) => {
|
|
2120
|
+
this._trees[key].walk(group => group.refreshMarketPercent(), false, false);
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2111
2124
|
return PositionContainer;
|
|
2112
2125
|
})();
|
|
2113
2126
|
|
|
@@ -2147,13 +2160,17 @@ module.exports = (() => {
|
|
|
2147
2160
|
* @param {Boolean=} aggregateCash
|
|
2148
2161
|
*/
|
|
2149
2162
|
class PositionGroup {
|
|
2150
|
-
constructor(
|
|
2163
|
+
constructor(definition, items, rates, currency, key, description, aggregateCash) {
|
|
2151
2164
|
this._id = counter++;
|
|
2152
2165
|
|
|
2153
2166
|
this._definition = definition;
|
|
2154
|
-
this._container = container;
|
|
2155
2167
|
|
|
2156
2168
|
this._items = items;
|
|
2169
|
+
this._rates = rates;
|
|
2170
|
+
|
|
2171
|
+
this._parentGroup = null;
|
|
2172
|
+
this._portfolioGroup = null;
|
|
2173
|
+
|
|
2157
2174
|
this._currency = currency || Currency.CAD;
|
|
2158
2175
|
this._bypassCurrencyTranslation = false;
|
|
2159
2176
|
|
|
@@ -2167,7 +2184,6 @@ module.exports = (() => {
|
|
|
2167
2184
|
this._suspended = false;
|
|
2168
2185
|
this._showClosedPositions = false;
|
|
2169
2186
|
|
|
2170
|
-
this._marketPercentChangeEvent = new Event(this);
|
|
2171
2187
|
this._groupExcludedChangeEvent = new Event(this);
|
|
2172
2188
|
this._showClosedPositionsChangeEvent = new Event(this);
|
|
2173
2189
|
|
|
@@ -2380,6 +2396,40 @@ module.exports = (() => {
|
|
|
2380
2396
|
return this._excluded;
|
|
2381
2397
|
}
|
|
2382
2398
|
|
|
2399
|
+
/**
|
|
2400
|
+
* Sets the immediate parent group (allowing for calculation of relative
|
|
2401
|
+
* percentages).
|
|
2402
|
+
*
|
|
2403
|
+
* @public
|
|
2404
|
+
* @param {PortfolioGroup} group
|
|
2405
|
+
*/
|
|
2406
|
+
setParentGroup(group) {
|
|
2407
|
+
assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
|
|
2408
|
+
|
|
2409
|
+
if (this._parentGroup !== null) {
|
|
2410
|
+
throw new Error('The parent group has already been set.');
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
this._parentGroup = group;
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
/**
|
|
2417
|
+
* Sets the nearest parent group for a portfolio (allowing for calculation
|
|
2418
|
+
* of relative percentages).
|
|
2419
|
+
*
|
|
2420
|
+
* @public
|
|
2421
|
+
* @param {PortfolioGroup} group
|
|
2422
|
+
*/
|
|
2423
|
+
setPortfolioGroup(group) {
|
|
2424
|
+
assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
|
|
2425
|
+
|
|
2426
|
+
if (this._portfolioGroup !== null) {
|
|
2427
|
+
throw new Error('The portfolio group has already been set.');
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
this._portfolioGroup = group;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2383
2433
|
/**
|
|
2384
2434
|
* Adds a new {@link PositionItem} to the group.
|
|
2385
2435
|
*
|
|
@@ -2425,9 +2475,11 @@ module.exports = (() => {
|
|
|
2425
2475
|
* Causes aggregated data to be recalculated using a new exchange rate.
|
|
2426
2476
|
*
|
|
2427
2477
|
* @public
|
|
2428
|
-
* @param {Rate} rate
|
|
2478
|
+
* @param {Array.<Rate>} rate
|
|
2429
2479
|
*/
|
|
2430
|
-
|
|
2480
|
+
setForexRates(rates) {
|
|
2481
|
+
this._rates = rates;
|
|
2482
|
+
|
|
2431
2483
|
if (!this._bypassCurrencyTranslation) {
|
|
2432
2484
|
this.refresh();
|
|
2433
2485
|
}
|
|
@@ -2515,10 +2567,8 @@ module.exports = (() => {
|
|
|
2515
2567
|
return;
|
|
2516
2568
|
}
|
|
2517
2569
|
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
calculateStaticData(this, rates);
|
|
2521
|
-
calculatePriceData(this, rates, null, true);
|
|
2570
|
+
calculateStaticData(this, this._rates);
|
|
2571
|
+
calculatePriceData(this, this._rates, null, true);
|
|
2522
2572
|
}
|
|
2523
2573
|
|
|
2524
2574
|
/**
|
|
@@ -2528,7 +2578,7 @@ module.exports = (() => {
|
|
|
2528
2578
|
* @public
|
|
2529
2579
|
*/
|
|
2530
2580
|
refreshMarketPercent() {
|
|
2531
|
-
calculateMarketPercent(this, this.
|
|
2581
|
+
calculateMarketPercent(this, this._rates, this._parentGroup, this._portfolioGroup);
|
|
2532
2582
|
}
|
|
2533
2583
|
|
|
2534
2584
|
/**
|
|
@@ -2541,17 +2591,6 @@ module.exports = (() => {
|
|
|
2541
2591
|
return this._items.length === 0;
|
|
2542
2592
|
}
|
|
2543
2593
|
|
|
2544
|
-
/**
|
|
2545
|
-
* Adds an observer for change in the market percentage of the group.
|
|
2546
|
-
*
|
|
2547
|
-
* @public
|
|
2548
|
-
* @param {Function} handler
|
|
2549
|
-
* @return {Disposable}
|
|
2550
|
-
*/
|
|
2551
|
-
registerMarketPercentChangeHandler(handler) {
|
|
2552
|
-
return this._marketPercentChangeEvent.register(handler);
|
|
2553
|
-
}
|
|
2554
|
-
|
|
2555
2594
|
/**
|
|
2556
2595
|
* Adds an observer for changes to the exclusion of the group
|
|
2557
2596
|
* from higher level aggregations.
|
|
@@ -2606,10 +2645,10 @@ module.exports = (() => {
|
|
|
2606
2645
|
this._dataFormat.currentPrice = null;
|
|
2607
2646
|
}
|
|
2608
2647
|
|
|
2609
|
-
calculatePriceData(this, this.
|
|
2648
|
+
calculatePriceData(this, this._rates, sender, false);
|
|
2610
2649
|
});
|
|
2611
2650
|
|
|
2612
|
-
let fundamentalBinding = item.registerFundamentalDataChangeHandler((data
|
|
2651
|
+
let fundamentalBinding = item.registerFundamentalDataChangeHandler((data) => {
|
|
2613
2652
|
if (this._single) {
|
|
2614
2653
|
this._dataFormat.fundamental = data;
|
|
2615
2654
|
} else {
|
|
@@ -2660,13 +2699,13 @@ module.exports = (() => {
|
|
|
2660
2699
|
let newsBinding = Disposable.getEmpty();
|
|
2661
2700
|
|
|
2662
2701
|
if (this._single) {
|
|
2663
|
-
newsBinding = item.registerNewsExistsChangeHandler((exists
|
|
2702
|
+
newsBinding = item.registerNewsExistsChangeHandler((exists) => {
|
|
2664
2703
|
this._dataActual.newsExists = exists;
|
|
2665
2704
|
this._dataFormat.newsExists = exists;
|
|
2666
2705
|
});
|
|
2667
2706
|
}
|
|
2668
2707
|
|
|
2669
|
-
this._disposeStack.push(item.registerPortfolioChangeHandler((portfolio
|
|
2708
|
+
this._disposeStack.push(item.registerPortfolioChangeHandler((portfolio) => {
|
|
2670
2709
|
const descriptionSelector = this._definition.descriptionSelector;
|
|
2671
2710
|
|
|
2672
2711
|
this._description = descriptionSelector(this._items[0]);
|
|
@@ -2915,14 +2954,11 @@ module.exports = (() => {
|
|
|
2915
2954
|
|
|
2916
2955
|
format.total = formatCurrency(actual.total, currency);
|
|
2917
2956
|
format.totalNegative = actual.total.getIsNegative();
|
|
2918
|
-
|
|
2919
|
-
calculateMarketPercent(group, rates, false);
|
|
2957
|
+
|
|
2920
2958
|
calculateUnrealizedPercent(group);
|
|
2921
2959
|
}
|
|
2922
2960
|
|
|
2923
|
-
function calculateMarketPercent(group, rates,
|
|
2924
|
-
return;
|
|
2925
|
-
|
|
2961
|
+
function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
|
|
2926
2962
|
if (group.suspended) {
|
|
2927
2963
|
return;
|
|
2928
2964
|
}
|
|
@@ -2931,12 +2967,10 @@ module.exports = (() => {
|
|
|
2931
2967
|
const format = group._dataFormat;
|
|
2932
2968
|
const excluded = group._excluded;
|
|
2933
2969
|
|
|
2934
|
-
const portfolioParent = group._container.getParentGroupForPortfolio(group);
|
|
2935
|
-
|
|
2936
2970
|
const calculatePercent = (parent) => {
|
|
2937
2971
|
let marketPercent;
|
|
2938
2972
|
|
|
2939
|
-
if (parent
|
|
2973
|
+
if (parent && !excluded) {
|
|
2940
2974
|
const parentData = parent._dataActual;
|
|
2941
2975
|
|
|
2942
2976
|
if (parentData.marketAbsolute !== null && !parentData.marketAbsolute.getIsZero()) {
|
|
@@ -2959,14 +2993,15 @@ module.exports = (() => {
|
|
|
2959
2993
|
return marketPercent;
|
|
2960
2994
|
};
|
|
2961
2995
|
|
|
2962
|
-
actual.marketPercent = calculatePercent(
|
|
2996
|
+
actual.marketPercent = calculatePercent(parentGroup);
|
|
2963
2997
|
format.marketPercent = formatPercent(actual.marketPercent, 2);
|
|
2964
2998
|
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2999
|
+
if (parentGroup === portfolioGroup) {
|
|
3000
|
+
actual.marketPercentPortfolio = actual.marketPercent;
|
|
3001
|
+
format.marketPercentPortfolio = format.marketPercent;
|
|
3002
|
+
} else {
|
|
3003
|
+
actual.marketPercentPortfolio = calculatePercent(portfolioGroup);
|
|
3004
|
+
format.marketPercentPortfolio = formatPercent(actual.marketPercentPortfolio, 2);
|
|
2970
3005
|
}
|
|
2971
3006
|
}
|
|
2972
3007
|
|