@barchart/portfolio-api-common 1.0.268 → 1.0.269

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.
@@ -224,11 +224,9 @@ module.exports = (() => {
224
224
  assert.argumentIsRequired(portfolio, 'portfolio', Object);
225
225
  assert.argumentIsRequired(portfolio.portfolio, 'portfolio.portfolio', String);
226
226
 
227
- this.startTransaction(() => {
228
- getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => item.updatePortfolio(portfolio));
227
+ getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => item.updatePortfolio(portfolio));
229
228
 
230
- updateEmptyPortfolioGroups.call(this, portfolio);
231
- });
229
+ updateEmptyPortfolioGroups.call(this, portfolio);
232
230
  }
233
231
 
234
232
  /**
@@ -243,19 +241,19 @@ module.exports = (() => {
243
241
  assert.argumentIsRequired(portfolio, 'portfolio', Object);
244
242
  assert.argumentIsRequired(portfolio.portfolio, 'portfolio.portfolio', String);
245
243
 
246
- this.startTransaction(() => {
247
- getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => removePositionItem.call(this, item));
244
+ getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => removePositionItem.call(this, item));
248
245
 
249
- delete this._portfolios[portfolio.portfolio];
246
+ delete this._portfolios[portfolio.portfolio];
250
247
 
251
- Object.keys(this._trees).forEach((key) => {
252
- this._trees[key].walk((group, groupNode) => {
253
- if (group.definition.type === PositionLevelType.PORTFOLIO && group.key === PositionLevelDefinition.getKeyForPortfolioGroup(portfolio)) {
254
- severGroupNode.call(this, groupNode);
255
- }
256
- }, true, false);
257
- });
248
+ Object.keys(this._trees).forEach((key) => {
249
+ this._trees[key].walk((group, groupNode) => {
250
+ if (group.definition.type === PositionLevelType.PORTFOLIO && group.key === PositionLevelDefinition.getKeyForPortfolioGroup(portfolio)) {
251
+ severGroupNode.call(this, groupNode);
252
+ }
253
+ }, true, false);
258
254
  });
255
+
256
+ recalculatePercentages.call(this);
259
257
  }
260
258
 
261
259
  /**
@@ -276,56 +274,54 @@ module.exports = (() => {
276
274
  return;
277
275
  }
278
276
 
279
- this.startTransaction(() => {
280
- const existingBarchartSymbols = this.getPositionSymbols(false);
277
+ const existingBarchartSymbols = this.getPositionSymbols(false);
281
278
 
282
- removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
279
+ removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
283
280
 
284
- summaries.forEach((summary) => {
285
- addSummaryCurrent(this._summariesCurrent, summary, this._currentSummaryFrame, this._currentSummaryRange);
286
- addSummaryPrevious(this._summariesPrevious, summary, this._previousSummaryFrame, this._previousSummaryRanges);
287
- });
281
+ summaries.forEach((summary) => {
282
+ addSummaryCurrent(this._summariesCurrent, summary, this._currentSummaryFrame, this._currentSummaryRange);
283
+ addSummaryPrevious(this._summariesPrevious, summary, this._previousSummaryFrame, this._previousSummaryRanges);
284
+ });
288
285
 
289
- const item = createPositionItem.call(this, position);
286
+ const item = createPositionItem.call(this, position);
290
287
 
291
- addBarchartSymbol(this._symbols, item);
292
- addDisplaySymbol(this._symbolsDisplay, item);
288
+ addBarchartSymbol(this._symbols, item);
289
+ addDisplaySymbol(this._symbolsDisplay, item);
293
290
 
294
- this._items.push(item);
291
+ this._items.push(item);
295
292
 
296
- const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
297
- if (levelDefinitions.length === 0) {
298
- return;
299
- }
293
+ const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
294
+ if (levelDefinitions.length === 0) {
295
+ return;
296
+ }
300
297
 
301
- const levelDefinition = levelDefinitions[0];
302
- const levelKey = levelDefinition.keySelector(item);
298
+ const levelDefinition = levelDefinitions[0];
299
+ const levelKey = levelDefinition.keySelector(item);
303
300
 
304
- let groupTree;
301
+ let groupTree;
305
302
 
306
- if (parentTree.getChildren().length > 0) {
307
- groupTree = parentTree.findChild(childGroup => childGroup.key === levelKey) || null;
308
- } else {
309
- groupTree = null;
310
- }
303
+ if (parentTree.getChildren().length > 0) {
304
+ groupTree = parentTree.findChild(childGroup => childGroup.key === levelKey) || null;
305
+ } else {
306
+ groupTree = null;
307
+ }
311
308
 
312
- if (groupTree !== null) {
313
- groupTree.getValue().addItem(item);
309
+ if (groupTree !== null) {
310
+ groupTree.getValue().addItem(item);
314
311
 
315
- createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
316
- } else {
317
- createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
318
- }
319
- };
312
+ createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
313
+ } else {
314
+ createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
315
+ }
316
+ };
320
317
 
321
- this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
318
+ this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
322
319
 
323
- const addedBarchartSymbol = extractSymbolForBarchart(item.position);
320
+ const addedBarchartSymbol = extractSymbolForBarchart(item.position);
324
321
 
325
- if (addedBarchartSymbol !== null && !existingBarchartSymbols.some(existingBarchartSymbol => existingBarchartSymbol === addedBarchartSymbol)) {
326
- this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
327
- }
328
- });
322
+ if (addedBarchartSymbol !== null && !existingBarchartSymbols.some(existingBarchartSymbol => existingBarchartSymbol === addedBarchartSymbol)) {
323
+ this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
324
+ }
329
325
 
330
326
  recalculatePercentages.call(this);
331
327
  }
@@ -376,49 +372,55 @@ module.exports = (() => {
376
372
  }
377
373
 
378
374
  /**
379
- * Updates the quote for a single symbol; causing updates to any grouping
380
- * level that contains the position(s) for the symbol.
375
+ * Performs a batch update of both position quotes and forex quotes,
376
+ * triggering updates to position(s) and data aggregation(s).
381
377
  *
382
378
  * @public
383
- * @param {Object} quote
379
+ * @param {Array.<Object>} positionQuotes
380
+ * @param {Array.<Object>} forexQuotes
384
381
  */
385
- setPositionQuote(quote) {
386
- assert.argumentIsRequired(quote, 'quote', Object);
382
+ setQuotes(positionQuotes, forexQuotes) {
383
+ assert.argumentIsArray(positionQuotes, 'positionQuotes');
384
+ assert.argumentIsArray(forexQuotes, 'forexQuotes');
387
385
 
388
- const symbol = quote.symbol;
389
-
390
- if (symbol) {
391
- if (this._symbols.hasOwnProperty(symbol)) {
392
- this._symbols[symbol].forEach(item => item.setQuote(quote));
393
- }
386
+ if (positionQuotes.length !== 0) {
387
+ positionQuotes.forEach((quote) => {
388
+ const symbol = quote.symbol;
394
389
 
395
- recalculatePercentages.call(this);
390
+ if (symbol) {
391
+ if (this._symbols.hasOwnProperty(symbol)) {
392
+ this._symbols[ symbol ].forEach(item => item.setQuote(quote));
393
+ }
394
+ }
395
+ });
396
396
  }
397
- }
398
-
399
- /**
400
- * Performs a batch update of quotes; causing updates to any grouping
401
- * level that contains the position(s) for the symbol(s).
402
- *
403
- * @public
404
- * @param {Object} quote
405
- */
406
- setPositionQuotes(quotes) {
407
- assert.argumentIsArray(quotes, 'quotes');
408
397
 
409
- this.startTransaction(() => {
410
- quotes.forEach((quote) => {
398
+ if (forexQuotes.length !== 0) {
399
+ forexQuotes.forEach((quote) => {
411
400
  const symbol = quote.symbol;
412
401
 
413
402
  if (symbol) {
414
- if (this._symbols.hasOwnProperty(symbol)) {
415
- this._symbols[symbol].forEach(item => item.setQuote(quote));
403
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
404
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
405
+
406
+ if (index < 0) {
407
+ this._forexQuotes.push(rate);
408
+ } else {
409
+ this._forexQuotes[index] = rate;
416
410
  }
411
+
412
+ Object.keys(this._trees).forEach((key) => {
413
+ this._trees[key].walk(group => group.setForexRates(this._forexQuotes), true, false)
414
+ });
415
+
416
+ recalculatePercentages.call(this);
417
417
  }
418
418
  });
419
+ }
419
420
 
421
+ if (positionQuotes.length !== 0 || forexQuotes.length !== 0) {
420
422
  recalculatePercentages.call(this);
421
- });
423
+ }
422
424
  }
423
425
 
424
426
  /**
@@ -441,34 +443,6 @@ module.exports = (() => {
441
443
  return this._forexQuotes;
442
444
  }
443
445
 
444
- /**
445
- * Updates the forex quote for a single currency pair; causing updates to
446
- * any grouping level that contains that requires translation.
447
- *
448
- * @public
449
- * @param {Object} quote
450
- */
451
- setForexQuote(quote) {
452
- assert.argumentIsRequired(quote, 'quote', Object);
453
-
454
- const symbol = quote.symbol;
455
-
456
- if (symbol) {
457
- const rate = Rate.fromPair(quote.lastPrice, symbol);
458
- const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
459
-
460
- if (index < 0) {
461
- this._forexQuotes.push(rate);
462
- } else {
463
- this._forexQuotes[ index ] = rate;
464
- }
465
-
466
- Object.keys(this._trees).forEach(key => this._trees[ key ].walk(group => group.setForexRates(this._forexQuotes), true, false));
467
-
468
- recalculatePercentages.call(this);
469
- }
470
- }
471
-
472
446
  /**
473
447
  * Updates fundamental data for a single symbol.
474
448
  *
@@ -617,39 +591,6 @@ module.exports = (() => {
617
591
  return this.getPositions(portfolio).find(p => p.position === position) || null;
618
592
  }
619
593
 
620
- /**
621
- * Pauses aggregation calculations during the processing of an action.
622
- *
623
- * @public
624
- * @param {Function} executor
625
- * @param {String=|Array.<String>=} names
626
- */
627
- startTransaction(executor, names) {
628
- let namesToUse;
629
-
630
- if (is.array(names)) {
631
- assert.argumentIsArray(names, 'names', String);
632
-
633
- namesToUse = names;
634
- } else {
635
- assert.argumentIsOptional(names, 'names', String);
636
-
637
- if (names) {
638
- namesToUse = [ names ];
639
- } else {
640
- namesToUse = Object.keys(this._trees);
641
- }
642
- }
643
-
644
- assert.argumentIsRequired(executor, 'executor', Function);
645
-
646
- namesToUse.forEach((name) => this._trees[name].walk(group => group.setSuspended(true), false, false));
647
-
648
- executor(this);
649
-
650
- namesToUse.forEach((name) => this._trees[name].walk(group => group.setSuspended(false), false, false));
651
- }
652
-
653
594
  /**
654
595
  * Registers an observer for symbol addition (this occurs when a new position is added
655
596
  * for a symbol that does not already exist in the container). This event only fires
@@ -54,7 +54,6 @@ module.exports = (() => {
54
54
  this._aggregateCash = is.boolean(aggregateCash) && aggregateCash;
55
55
 
56
56
  this._excluded = false;
57
- this._suspended = false;
58
57
  this._showClosedPositions = false;
59
58
 
60
59
  this._groupExcludedChangeEvent = new Event(this);
@@ -255,10 +254,6 @@ module.exports = (() => {
255
254
  return this._single;
256
255
  }
257
256
 
258
- get suspended() {
259
- return this._suspended;
260
- }
261
-
262
257
  /**
263
258
  * Indicates if the group should be excluded from higher-level aggregations.
264
259
  *
@@ -381,24 +376,6 @@ module.exports = (() => {
381
376
  }
382
377
  }
383
378
 
384
- /**
385
- * Stops (or starts) group-level aggregation calculations.
386
- *
387
- * @public
388
- * @param {Boolean} value
389
- */
390
- setSuspended(value) {
391
- assert.argumentIsRequired(value, 'value', Boolean);
392
-
393
- if (this._suspended !== value) {
394
- this._suspended = value;
395
-
396
- if (!this._suspended) {
397
- this.refresh();
398
- }
399
- }
400
- }
401
-
402
379
  /**
403
380
  * Updates the portfolio data. For example, a portfolio's name might change. This
404
381
  * function only affects {@link PositionLevelType.PORTFOLIO} groups.
@@ -430,16 +407,11 @@ module.exports = (() => {
430
407
  }
431
408
 
432
409
  /**
433
- * Causes all aggregated data to be recalculated (assuming the group has not
434
- * been suspended).
410
+ * Causes all aggregated data to be recalculated.
435
411
  *
436
412
  * @public
437
413
  */
438
414
  refresh() {
439
- if (this._suspended) {
440
- return;
441
- }
442
-
443
415
  calculateStaticData(this, this._rates);
444
416
  calculatePriceData(this, this._rates, null, true);
445
417
  }
@@ -643,10 +615,6 @@ module.exports = (() => {
643
615
  }
644
616
 
645
617
  function calculateStaticData(group, rates) {
646
- if (group.suspended) {
647
- return;
648
- }
649
-
650
618
  const actual = group._dataActual;
651
619
  const format = group._dataFormat;
652
620
 
@@ -743,10 +711,6 @@ module.exports = (() => {
743
711
  }
744
712
 
745
713
  function calculatePriceData(group, rates, item, forceRefresh) {
746
- if (group.suspended) {
747
- return;
748
- }
749
-
750
714
  const currency = group.currency;
751
715
 
752
716
  const actual = group._dataActual;
@@ -832,10 +796,6 @@ module.exports = (() => {
832
796
  }
833
797
 
834
798
  function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
835
- if (group.suspended) {
836
- return;
837
- }
838
-
839
799
  const actual = group._dataActual;
840
800
  const format = group._dataFormat;
841
801
  const excluded = group._excluded;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.268",
3
+ "version": "1.0.269",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -1380,11 +1380,9 @@ module.exports = (() => {
1380
1380
  assert.argumentIsRequired(portfolio, 'portfolio', Object);
1381
1381
  assert.argumentIsRequired(portfolio.portfolio, 'portfolio.portfolio', String);
1382
1382
 
1383
- this.startTransaction(() => {
1384
- getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => item.updatePortfolio(portfolio));
1383
+ getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => item.updatePortfolio(portfolio));
1385
1384
 
1386
- updateEmptyPortfolioGroups.call(this, portfolio);
1387
- });
1385
+ updateEmptyPortfolioGroups.call(this, portfolio);
1388
1386
  }
1389
1387
 
1390
1388
  /**
@@ -1399,19 +1397,19 @@ module.exports = (() => {
1399
1397
  assert.argumentIsRequired(portfolio, 'portfolio', Object);
1400
1398
  assert.argumentIsRequired(portfolio.portfolio, 'portfolio.portfolio', String);
1401
1399
 
1402
- this.startTransaction(() => {
1403
- getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => removePositionItem.call(this, item));
1400
+ getPositionItemsForPortfolio(this._items, portfolio.portfolio).forEach(item => removePositionItem.call(this, item));
1404
1401
 
1405
- delete this._portfolios[portfolio.portfolio];
1402
+ delete this._portfolios[portfolio.portfolio];
1406
1403
 
1407
- Object.keys(this._trees).forEach((key) => {
1408
- this._trees[key].walk((group, groupNode) => {
1409
- if (group.definition.type === PositionLevelType.PORTFOLIO && group.key === PositionLevelDefinition.getKeyForPortfolioGroup(portfolio)) {
1410
- severGroupNode.call(this, groupNode);
1411
- }
1412
- }, true, false);
1413
- });
1404
+ Object.keys(this._trees).forEach((key) => {
1405
+ this._trees[key].walk((group, groupNode) => {
1406
+ if (group.definition.type === PositionLevelType.PORTFOLIO && group.key === PositionLevelDefinition.getKeyForPortfolioGroup(portfolio)) {
1407
+ severGroupNode.call(this, groupNode);
1408
+ }
1409
+ }, true, false);
1414
1410
  });
1411
+
1412
+ recalculatePercentages.call(this);
1415
1413
  }
1416
1414
 
1417
1415
  /**
@@ -1432,56 +1430,54 @@ module.exports = (() => {
1432
1430
  return;
1433
1431
  }
1434
1432
 
1435
- this.startTransaction(() => {
1436
- const existingBarchartSymbols = this.getPositionSymbols(false);
1433
+ const existingBarchartSymbols = this.getPositionSymbols(false);
1437
1434
 
1438
- removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
1435
+ removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
1439
1436
 
1440
- summaries.forEach((summary) => {
1441
- addSummaryCurrent(this._summariesCurrent, summary, this._currentSummaryFrame, this._currentSummaryRange);
1442
- addSummaryPrevious(this._summariesPrevious, summary, this._previousSummaryFrame, this._previousSummaryRanges);
1443
- });
1437
+ summaries.forEach((summary) => {
1438
+ addSummaryCurrent(this._summariesCurrent, summary, this._currentSummaryFrame, this._currentSummaryRange);
1439
+ addSummaryPrevious(this._summariesPrevious, summary, this._previousSummaryFrame, this._previousSummaryRanges);
1440
+ });
1444
1441
 
1445
- const item = createPositionItem.call(this, position);
1442
+ const item = createPositionItem.call(this, position);
1446
1443
 
1447
- addBarchartSymbol(this._symbols, item);
1448
- addDisplaySymbol(this._symbolsDisplay, item);
1444
+ addBarchartSymbol(this._symbols, item);
1445
+ addDisplaySymbol(this._symbolsDisplay, item);
1449
1446
 
1450
- this._items.push(item);
1447
+ this._items.push(item);
1451
1448
 
1452
- const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
1453
- if (levelDefinitions.length === 0) {
1454
- return;
1455
- }
1449
+ const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
1450
+ if (levelDefinitions.length === 0) {
1451
+ return;
1452
+ }
1456
1453
 
1457
- const levelDefinition = levelDefinitions[0];
1458
- const levelKey = levelDefinition.keySelector(item);
1454
+ const levelDefinition = levelDefinitions[0];
1455
+ const levelKey = levelDefinition.keySelector(item);
1459
1456
 
1460
- let groupTree;
1457
+ let groupTree;
1461
1458
 
1462
- if (parentTree.getChildren().length > 0) {
1463
- groupTree = parentTree.findChild(childGroup => childGroup.key === levelKey) || null;
1464
- } else {
1465
- groupTree = null;
1466
- }
1459
+ if (parentTree.getChildren().length > 0) {
1460
+ groupTree = parentTree.findChild(childGroup => childGroup.key === levelKey) || null;
1461
+ } else {
1462
+ groupTree = null;
1463
+ }
1467
1464
 
1468
- if (groupTree !== null) {
1469
- groupTree.getValue().addItem(item);
1465
+ if (groupTree !== null) {
1466
+ groupTree.getValue().addItem(item);
1470
1467
 
1471
- createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
1472
- } else {
1473
- createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
1474
- }
1475
- };
1468
+ createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
1469
+ } else {
1470
+ createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
1471
+ }
1472
+ };
1476
1473
 
1477
- this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
1474
+ this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
1478
1475
 
1479
- const addedBarchartSymbol = extractSymbolForBarchart(item.position);
1476
+ const addedBarchartSymbol = extractSymbolForBarchart(item.position);
1480
1477
 
1481
- if (addedBarchartSymbol !== null && !existingBarchartSymbols.some(existingBarchartSymbol => existingBarchartSymbol === addedBarchartSymbol)) {
1482
- this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
1483
- }
1484
- });
1478
+ if (addedBarchartSymbol !== null && !existingBarchartSymbols.some(existingBarchartSymbol => existingBarchartSymbol === addedBarchartSymbol)) {
1479
+ this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
1480
+ }
1485
1481
 
1486
1482
  recalculatePercentages.call(this);
1487
1483
  }
@@ -1532,49 +1528,55 @@ module.exports = (() => {
1532
1528
  }
1533
1529
 
1534
1530
  /**
1535
- * Updates the quote for a single symbol; causing updates to any grouping
1536
- * level that contains the position(s) for the symbol.
1531
+ * Performs a batch update of both position quotes and forex quotes,
1532
+ * triggering updates to position(s) and data aggregation(s).
1537
1533
  *
1538
1534
  * @public
1539
- * @param {Object} quote
1535
+ * @param {Array.<Object>} positionQuotes
1536
+ * @param {Array.<Object>} forexQuotes
1540
1537
  */
1541
- setPositionQuote(quote) {
1542
- assert.argumentIsRequired(quote, 'quote', Object);
1538
+ setQuotes(positionQuotes, forexQuotes) {
1539
+ assert.argumentIsArray(positionQuotes, 'positionQuotes');
1540
+ assert.argumentIsArray(forexQuotes, 'forexQuotes');
1543
1541
 
1544
- const symbol = quote.symbol;
1545
-
1546
- if (symbol) {
1547
- if (this._symbols.hasOwnProperty(symbol)) {
1548
- this._symbols[symbol].forEach(item => item.setQuote(quote));
1549
- }
1542
+ if (positionQuotes.length !== 0) {
1543
+ positionQuotes.forEach((quote) => {
1544
+ const symbol = quote.symbol;
1550
1545
 
1551
- recalculatePercentages.call(this);
1546
+ if (symbol) {
1547
+ if (this._symbols.hasOwnProperty(symbol)) {
1548
+ this._symbols[ symbol ].forEach(item => item.setQuote(quote));
1549
+ }
1550
+ }
1551
+ });
1552
1552
  }
1553
- }
1554
1553
 
1555
- /**
1556
- * Performs a batch update of quotes; causing updates to any grouping
1557
- * level that contains the position(s) for the symbol(s).
1558
- *
1559
- * @public
1560
- * @param {Object} quote
1561
- */
1562
- setPositionQuotes(quotes) {
1563
- assert.argumentIsArray(quotes, 'quotes');
1564
-
1565
- this.startTransaction(() => {
1566
- quotes.forEach((quote) => {
1554
+ if (forexQuotes.length !== 0) {
1555
+ forexQuotes.forEach((quote) => {
1567
1556
  const symbol = quote.symbol;
1568
1557
 
1569
1558
  if (symbol) {
1570
- if (this._symbols.hasOwnProperty(symbol)) {
1571
- this._symbols[symbol].forEach(item => item.setQuote(quote));
1559
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
1560
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
1561
+
1562
+ if (index < 0) {
1563
+ this._forexQuotes.push(rate);
1564
+ } else {
1565
+ this._forexQuotes[index] = rate;
1572
1566
  }
1567
+
1568
+ Object.keys(this._trees).forEach((key) => {
1569
+ this._trees[key].walk(group => group.setForexRates(this._forexQuotes), true, false)
1570
+ });
1571
+
1572
+ recalculatePercentages.call(this);
1573
1573
  }
1574
1574
  });
1575
+ }
1575
1576
 
1577
+ if (positionQuotes.length !== 0 || forexQuotes.length !== 0) {
1576
1578
  recalculatePercentages.call(this);
1577
- });
1579
+ }
1578
1580
  }
1579
1581
 
1580
1582
  /**
@@ -1597,34 +1599,6 @@ module.exports = (() => {
1597
1599
  return this._forexQuotes;
1598
1600
  }
1599
1601
 
1600
- /**
1601
- * Updates the forex quote for a single currency pair; causing updates to
1602
- * any grouping level that contains that requires translation.
1603
- *
1604
- * @public
1605
- * @param {Object} quote
1606
- */
1607
- setForexQuote(quote) {
1608
- assert.argumentIsRequired(quote, 'quote', Object);
1609
-
1610
- const symbol = quote.symbol;
1611
-
1612
- if (symbol) {
1613
- const rate = Rate.fromPair(quote.lastPrice, symbol);
1614
- const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
1615
-
1616
- if (index < 0) {
1617
- this._forexQuotes.push(rate);
1618
- } else {
1619
- this._forexQuotes[ index ] = rate;
1620
- }
1621
-
1622
- Object.keys(this._trees).forEach(key => this._trees[ key ].walk(group => group.setForexRates(this._forexQuotes), true, false));
1623
-
1624
- recalculatePercentages.call(this);
1625
- }
1626
- }
1627
-
1628
1602
  /**
1629
1603
  * Updates fundamental data for a single symbol.
1630
1604
  *
@@ -1773,39 +1747,6 @@ module.exports = (() => {
1773
1747
  return this.getPositions(portfolio).find(p => p.position === position) || null;
1774
1748
  }
1775
1749
 
1776
- /**
1777
- * Pauses aggregation calculations during the processing of an action.
1778
- *
1779
- * @public
1780
- * @param {Function} executor
1781
- * @param {String=|Array.<String>=} names
1782
- */
1783
- startTransaction(executor, names) {
1784
- let namesToUse;
1785
-
1786
- if (is.array(names)) {
1787
- assert.argumentIsArray(names, 'names', String);
1788
-
1789
- namesToUse = names;
1790
- } else {
1791
- assert.argumentIsOptional(names, 'names', String);
1792
-
1793
- if (names) {
1794
- namesToUse = [ names ];
1795
- } else {
1796
- namesToUse = Object.keys(this._trees);
1797
- }
1798
- }
1799
-
1800
- assert.argumentIsRequired(executor, 'executor', Function);
1801
-
1802
- namesToUse.forEach((name) => this._trees[name].walk(group => group.setSuspended(true), false, false));
1803
-
1804
- executor(this);
1805
-
1806
- namesToUse.forEach((name) => this._trees[name].walk(group => group.setSuspended(false), false, false));
1807
- }
1808
-
1809
1750
  /**
1810
1751
  * Registers an observer for symbol addition (this occurs when a new position is added
1811
1752
  * for a symbol that does not already exist in the container). This event only fires
@@ -2212,7 +2153,6 @@ module.exports = (() => {
2212
2153
  this._aggregateCash = is.boolean(aggregateCash) && aggregateCash;
2213
2154
 
2214
2155
  this._excluded = false;
2215
- this._suspended = false;
2216
2156
  this._showClosedPositions = false;
2217
2157
 
2218
2158
  this._groupExcludedChangeEvent = new Event(this);
@@ -2413,10 +2353,6 @@ module.exports = (() => {
2413
2353
  return this._single;
2414
2354
  }
2415
2355
 
2416
- get suspended() {
2417
- return this._suspended;
2418
- }
2419
-
2420
2356
  /**
2421
2357
  * Indicates if the group should be excluded from higher-level aggregations.
2422
2358
  *
@@ -2539,24 +2475,6 @@ module.exports = (() => {
2539
2475
  }
2540
2476
  }
2541
2477
 
2542
- /**
2543
- * Stops (or starts) group-level aggregation calculations.
2544
- *
2545
- * @public
2546
- * @param {Boolean} value
2547
- */
2548
- setSuspended(value) {
2549
- assert.argumentIsRequired(value, 'value', Boolean);
2550
-
2551
- if (this._suspended !== value) {
2552
- this._suspended = value;
2553
-
2554
- if (!this._suspended) {
2555
- this.refresh();
2556
- }
2557
- }
2558
- }
2559
-
2560
2478
  /**
2561
2479
  * Updates the portfolio data. For example, a portfolio's name might change. This
2562
2480
  * function only affects {@link PositionLevelType.PORTFOLIO} groups.
@@ -2588,16 +2506,11 @@ module.exports = (() => {
2588
2506
  }
2589
2507
 
2590
2508
  /**
2591
- * Causes all aggregated data to be recalculated (assuming the group has not
2592
- * been suspended).
2509
+ * Causes all aggregated data to be recalculated.
2593
2510
  *
2594
2511
  * @public
2595
2512
  */
2596
2513
  refresh() {
2597
- if (this._suspended) {
2598
- return;
2599
- }
2600
-
2601
2514
  calculateStaticData(this, this._rates);
2602
2515
  calculatePriceData(this, this._rates, null, true);
2603
2516
  }
@@ -2801,10 +2714,6 @@ module.exports = (() => {
2801
2714
  }
2802
2715
 
2803
2716
  function calculateStaticData(group, rates) {
2804
- if (group.suspended) {
2805
- return;
2806
- }
2807
-
2808
2717
  const actual = group._dataActual;
2809
2718
  const format = group._dataFormat;
2810
2719
 
@@ -2901,10 +2810,6 @@ module.exports = (() => {
2901
2810
  }
2902
2811
 
2903
2812
  function calculatePriceData(group, rates, item, forceRefresh) {
2904
- if (group.suspended) {
2905
- return;
2906
- }
2907
-
2908
2813
  const currency = group.currency;
2909
2814
 
2910
2815
  const actual = group._dataActual;
@@ -2990,10 +2895,6 @@ module.exports = (() => {
2990
2895
  }
2991
2896
 
2992
2897
  function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
2993
- if (group.suspended) {
2994
- return;
2995
- }
2996
-
2997
2898
  const actual = group._dataActual;
2998
2899
  const format = group._dataFormat;
2999
2900
  const excluded = group._excluded;