@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.
- package/lib/processing/PositionContainer.js +80 -139
- package/lib/processing/PositionGroup.js +1 -41
- package/package.json +1 -1
- package/test/SpecRunner.js +81 -180
|
@@ -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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
246
|
+
delete this._portfolios[portfolio.portfolio];
|
|
250
247
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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.
|
|
280
|
-
const existingBarchartSymbols = this.getPositionSymbols(false);
|
|
277
|
+
const existingBarchartSymbols = this.getPositionSymbols(false);
|
|
281
278
|
|
|
282
|
-
|
|
279
|
+
removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
|
|
283
280
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
286
|
+
const item = createPositionItem.call(this, position);
|
|
290
287
|
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
addBarchartSymbol(this._symbols, item);
|
|
289
|
+
addDisplaySymbol(this._symbolsDisplay, item);
|
|
293
290
|
|
|
294
|
-
|
|
291
|
+
this._items.push(item);
|
|
295
292
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
293
|
+
const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
|
|
294
|
+
if (levelDefinitions.length === 0) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
300
297
|
|
|
301
|
-
|
|
302
|
-
|
|
298
|
+
const levelDefinition = levelDefinitions[0];
|
|
299
|
+
const levelKey = levelDefinition.keySelector(item);
|
|
303
300
|
|
|
304
|
-
|
|
301
|
+
let groupTree;
|
|
305
302
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
313
|
-
|
|
309
|
+
if (groupTree !== null) {
|
|
310
|
+
groupTree.getValue().addItem(item);
|
|
314
311
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
312
|
+
createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
|
|
313
|
+
} else {
|
|
314
|
+
createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
320
317
|
|
|
321
|
-
|
|
318
|
+
this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
|
|
322
319
|
|
|
323
|
-
|
|
320
|
+
const addedBarchartSymbol = extractSymbolForBarchart(item.position);
|
|
324
321
|
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
*
|
|
380
|
-
*
|
|
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}
|
|
379
|
+
* @param {Array.<Object>} positionQuotes
|
|
380
|
+
* @param {Array.<Object>} forexQuotes
|
|
384
381
|
*/
|
|
385
|
-
|
|
386
|
-
assert.
|
|
382
|
+
setQuotes(positionQuotes, forexQuotes) {
|
|
383
|
+
assert.argumentIsArray(positionQuotes, 'positionQuotes');
|
|
384
|
+
assert.argumentIsArray(forexQuotes, 'forexQuotes');
|
|
387
385
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
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
|
-
|
|
410
|
-
|
|
398
|
+
if (forexQuotes.length !== 0) {
|
|
399
|
+
forexQuotes.forEach((quote) => {
|
|
411
400
|
const symbol = quote.symbol;
|
|
412
401
|
|
|
413
402
|
if (symbol) {
|
|
414
|
-
|
|
415
|
-
|
|
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
|
|
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
package/test/SpecRunner.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
1402
|
+
delete this._portfolios[portfolio.portfolio];
|
|
1406
1403
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
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.
|
|
1436
|
-
const existingBarchartSymbols = this.getPositionSymbols(false);
|
|
1433
|
+
const existingBarchartSymbols = this.getPositionSymbols(false);
|
|
1437
1434
|
|
|
1438
|
-
|
|
1435
|
+
removePositionItem.call(this, this._items.find((item) => item.position.position === position.position));
|
|
1439
1436
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
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
|
-
|
|
1442
|
+
const item = createPositionItem.call(this, position);
|
|
1446
1443
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1444
|
+
addBarchartSymbol(this._symbols, item);
|
|
1445
|
+
addDisplaySymbol(this._symbolsDisplay, item);
|
|
1449
1446
|
|
|
1450
|
-
|
|
1447
|
+
this._items.push(item);
|
|
1451
1448
|
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1449
|
+
const createGroupOrInjectItem = (parentTree, treeDefinition, levelDefinitions) => {
|
|
1450
|
+
if (levelDefinitions.length === 0) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1456
1453
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1454
|
+
const levelDefinition = levelDefinitions[0];
|
|
1455
|
+
const levelKey = levelDefinition.keySelector(item);
|
|
1459
1456
|
|
|
1460
|
-
|
|
1457
|
+
let groupTree;
|
|
1461
1458
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
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
|
-
|
|
1469
|
-
|
|
1465
|
+
if (groupTree !== null) {
|
|
1466
|
+
groupTree.getValue().addItem(item);
|
|
1470
1467
|
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1468
|
+
createGroupOrInjectItem(groupTree, treeDefinition, array.dropLeft(levelDefinitions));
|
|
1469
|
+
} else {
|
|
1470
|
+
createGroups.call(this, parentTree, [ item ], treeDefinition, levelDefinitions, [ ]);
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1476
1473
|
|
|
1477
|
-
|
|
1474
|
+
this._definitions.forEach(definition => createGroupOrInjectItem(this._trees[definition.name], definition, definition.definitions));
|
|
1478
1475
|
|
|
1479
|
-
|
|
1476
|
+
const addedBarchartSymbol = extractSymbolForBarchart(item.position);
|
|
1480
1477
|
|
|
1481
|
-
|
|
1482
|
-
|
|
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
|
-
*
|
|
1536
|
-
*
|
|
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}
|
|
1535
|
+
* @param {Array.<Object>} positionQuotes
|
|
1536
|
+
* @param {Array.<Object>} forexQuotes
|
|
1540
1537
|
*/
|
|
1541
|
-
|
|
1542
|
-
assert.
|
|
1538
|
+
setQuotes(positionQuotes, forexQuotes) {
|
|
1539
|
+
assert.argumentIsArray(positionQuotes, 'positionQuotes');
|
|
1540
|
+
assert.argumentIsArray(forexQuotes, 'forexQuotes');
|
|
1543
1541
|
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1571
|
-
|
|
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
|
|
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;
|