@barchart/portfolio-api-common 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -213,7 +213,7 @@ module.exports = (() => {
213
213
  */
214
214
 
215
215
  /**
216
- * The start and and date for a {@link PositionSummaryFrame} along with the frame type.
216
+ * The start and end date for a {@link PositionSummaryFrame} along with the frame type.
217
217
  *
218
218
  * @typedef PositionSummaryDefinition
219
219
  * @type {Object}
@@ -623,6 +623,22 @@ module.exports = (() => {
623
623
  }
624
624
  }
625
625
 
626
+ /**
627
+ * Sets the reference date (today).
628
+ *
629
+ * @public
630
+ * @param {Day} referenceDate
631
+ */
632
+ setReferenceDate(referenceDate) {
633
+ assert.argumentIsRequired(referenceDate, 'referenceDate', Day, 'Day');
634
+
635
+ this._referenceDate = referenceDate;
636
+
637
+ this._items.forEach((item) => {
638
+ item.setReferenceDate(this._referenceDate);
639
+ });
640
+ }
641
+
626
642
  /**
627
643
  * Returns current price for symbol provided.
628
644
  *
@@ -4,7 +4,6 @@ const array = require('@barchart/common-js/lang/array'),
4
4
  CurrencyTranslator = require('@barchart/common-js/lang/CurrencyTranslator'),
5
5
  Decimal = require('@barchart/common-js/lang/Decimal'),
6
6
  Disposable = require('@barchart/common-js/lang/Disposable'),
7
- DisposableStack = require('@barchart/common-js/collections/specialized/DisposableStack'),
8
7
  Event = require('@barchart/common-js/messaging/Event'),
9
8
  formatter = require('@barchart/common-js/lang/formatter'),
10
9
  is = require('@barchart/common-js/lang/is');
@@ -63,8 +62,6 @@ module.exports = (() => {
63
62
  this._groupExcludedChangeEvent = new Event(this);
64
63
  this._showClosedPositionsChangeEvent = new Event(this);
65
64
 
66
- this._disposeStack = new DisposableStack();
67
-
68
65
  this._excludedItems = [ ];
69
66
  this._excludedItemMap = { };
70
67
  this._consideredItems = this._items.slice(0);
@@ -598,52 +595,54 @@ module.exports = (() => {
598
595
  calculatePriceData(this, sender, false);
599
596
  });
600
597
 
601
- let fundamentalBinding = item.registerFundamentalDataChangeHandler((data) => {
598
+ const fundamentalBinding = item.registerFundamentalDataChangeHandler((data) => {
602
599
  if (this._single) {
603
600
  this._dataFormat.fundamental = data;
604
- } else {
605
- const fundamentalFields = [ 'percentChange1m', 'percentChange1y', 'percentChange3m', 'percentChangeYtd' ];
606
601
 
607
- const fundamentalData = this.items.reduce((sums, item, i) => {
608
- if (item.data && item.data.fundamental && item.data.fundamental.raw) {
609
- const fundamental = item.data.fundamental.raw;
602
+ return;
603
+ }
610
604
 
611
- fundamentalFields.forEach((fieldName) => {
612
- const summary = sums[fieldName];
613
- const value = fundamental[fieldName];
605
+ const fundamentalFields = [ 'percentChange1m', 'percentChange1y', 'percentChange3m', 'percentChangeYtd' ];
614
606
 
615
- if (is.number(value)) {
616
- summary.total = sums[fieldName].total + value;
617
- summary.count = sums[fieldName].count + 1;
618
- }
607
+ const fundamentalData = this.items.reduce((sums, item, i) => {
608
+ if (item.data && item.data.fundamental && item.data.fundamental.raw) {
609
+ const fundamental = item.data.fundamental.raw;
619
610
 
620
- if ((i + 1) == this.items.length) {
621
- let averageFormat;
611
+ fundamentalFields.forEach((fieldName) => {
612
+ const summary = sums[fieldName];
613
+ const value = fundamental[fieldName];
622
614
 
623
- if (summary.count > 0) {
624
- averageFormat = formatPercent(new Decimal(summary.total / summary.count), 2, true);
625
- } else {
626
- averageFormat = '—';
627
- }
615
+ if (is.number(value)) {
616
+ summary.total = sums[fieldName].total + value;
617
+ summary.count = sums[fieldName].count + 1;
618
+ }
628
619
 
629
- summary.averageFormat = averageFormat;
620
+ if ((i + 1) == this.items.length) {
621
+ let averageFormat;
622
+
623
+ if (summary.count > 0) {
624
+ averageFormat = formatPercent(new Decimal(summary.total / summary.count), 2, true);
625
+ } else {
626
+ averageFormat = '—';
630
627
  }
631
- });
632
- }
633
628
 
634
- return sums;
635
- }, fundamentalFields.reduce((sums, fieldName) => {
636
- sums[fieldName] = { total: 0, count: 0, averageFormat: '—' };
629
+ summary.averageFormat = averageFormat;
630
+ }
631
+ });
632
+ }
637
633
 
638
- return sums;
639
- }, { }));
634
+ return sums;
635
+ }, fundamentalFields.reduce((sums, fieldName) => {
636
+ sums[fieldName] = { total: 0, count: 0, averageFormat: '—' };
640
637
 
641
- this._dataFormat.fundamental = fundamentalFields.reduce((sums, fieldName) => {
642
- sums[fieldName] = fundamentalData[fieldName].averageFormat;
638
+ return sums;
639
+ }, { }));
643
640
 
644
- return sums;
645
- }, { });
646
- }
641
+ this._dataFormat.fundamental = fundamentalFields.reduce((sums, fieldName) => {
642
+ sums[fieldName] = fundamentalData[fieldName].averageFormat;
643
+
644
+ return sums;
645
+ }, { });
647
646
  });
648
647
 
649
648
  let newsBinding = Disposable.getEmpty();
@@ -665,7 +664,7 @@ module.exports = (() => {
665
664
  });
666
665
  }
667
666
 
668
- this._disposeStack.push(item.registerPortfolioChangeHandler((portfolio) => {
667
+ const portfolioChangeBinding = item.registerPortfolioChangeHandler((portfolio) => {
669
668
  const descriptionSelector = this._definition.descriptionSelector;
670
669
 
671
670
  this._description = descriptionSelector(this._items[0]);
@@ -680,21 +679,27 @@ module.exports = (() => {
680
679
  const currencySelector = this._definition.currencySelector;
681
680
 
682
681
  this.changeCurrency(currencySelector({ portfolio }));
683
- }));
682
+ });
684
683
 
685
- this._disposeStack.push(fundamentalBinding);
686
- this._disposeStack.push(quoteBinding);
687
- this._disposeStack.push(lockedBinding);
688
- this._disposeStack.push(calculatingBinding);
689
- this._disposeStack.push(newsBinding);
684
+ const referenceDateBinding = item.registerReferenceDateChangeHandler(() => {
685
+ this.refresh();
686
+ });
690
687
 
691
- this._disposeStack.push(item.registerPositionItemDisposeHandler(() => {
692
- fundamentalBinding.dispose();
688
+ let disposalBinding = null;
689
+
690
+ disposalBinding = item.registerPositionItemDisposeHandler(() => {
693
691
  quoteBinding.dispose();
692
+ fundamentalBinding.dispose();
693
+
694
694
  newsBinding.dispose();
695
695
  lockedBinding.dispose();
696
696
  calculatingBinding.dispose();
697
697
 
698
+ portfolioChangeBinding.dispose();
699
+ referenceDateBinding.dispose();
700
+
701
+ disposalBinding.dispose();
702
+
698
703
  array.remove(this._items, i => i === item);
699
704
  array.remove(this._excludedItems, i => i === item);
700
705
  array.remove(this._consideredItems, i => i === item);
@@ -702,7 +707,7 @@ module.exports = (() => {
702
707
  delete this._excludedItemMap[item.position.position];
703
708
 
704
709
  this.refresh();
705
- }));
710
+ });
706
711
  }
707
712
 
708
713
  function formatNumber(number, precision) {
@@ -120,6 +120,7 @@ module.exports = (() => {
120
120
  this._lockChangedEvent = new Event(this);
121
121
  this._calculatingChangedEvent = new Event(this);
122
122
  this._portfolioChangedEvent = new Event(this);
123
+ this._referenceDateChangedEvent = new Event(this);
123
124
  this._positionItemDisposeEvent = new Event(this);
124
125
 
125
126
  calculateStaticData(this, this._referenceDate);
@@ -254,14 +255,13 @@ module.exports = (() => {
254
255
  return;
255
256
  }
256
257
 
257
- if (this._currentPricePrevious !== quote.lastPrice || force) {
258
+ if (this._currentPrice !== quote.lastPrice || force) {
258
259
  if (quote.previousPrice) {
259
260
  this._data.previousPrice = quote.previousPrice;
260
261
  }
261
262
 
262
- calculatePriceData(this, quote.lastPrice, quote.lastDay instanceof Day && quote.lastDay.getIsEqual(this._referenceDate));
263
+ calculatePriceData(this, quote.lastPrice, getQuoteIsToday(quote, this._referenceDate));
263
264
 
264
- this._currentPricePrevious = this._currentPrice;
265
265
  this._currentPrice = quote.lastPrice;
266
266
 
267
267
  this._previousQuote = this._currentQuote;
@@ -346,6 +346,31 @@ module.exports = (() => {
346
346
  }
347
347
  }
348
348
 
349
+ /**
350
+ * Sets the reference date (today).
351
+ *
352
+ * @public
353
+ * @param {Day} referenceDate
354
+ */
355
+ setReferenceDate(referenceDate) {
356
+ assert.argumentIsRequired(referenceDate, 'referenceDate', Day, 'Day');
357
+
358
+ if (this.getIsDisposed()) {
359
+ return;
360
+ }
361
+
362
+ if (this._referenceDate.getIsEqual(referenceDate)) {
363
+ return;
364
+ }
365
+
366
+ this._referenceDate = referenceDate;
367
+
368
+ calculateStaticData(this, this._referenceDate);
369
+ calculatePriceData(this, this._currentPrice, getQuoteIsToday(this._currentQuote, this._referenceDate));
370
+
371
+ this._referenceDateChangedEvent.fire(this._referenceDate);
372
+ }
373
+
349
374
  /**
350
375
  * Registers an observer for quote changes, which is fired after internal recalculations
351
376
  * of position data are complete.
@@ -403,7 +428,7 @@ module.exports = (() => {
403
428
  }
404
429
 
405
430
  /**
406
- * Registers an observer changes to portfolio metadata.
431
+ * Registers an observer for changes to portfolio metadata.
407
432
  *
408
433
  * @public
409
434
  * @param {Function} handler
@@ -413,6 +438,17 @@ module.exports = (() => {
413
438
  return this._portfolioChangedEvent.register(handler);
414
439
  }
415
440
 
441
+ /**
442
+ * Registers an observer for changes to the reference date (today).
443
+ *
444
+ * @public
445
+ * @param {Function} handler
446
+ * @returns {Disposable}
447
+ */
448
+ registerReferenceDateChangeHandler(handler) {
449
+ return this._referenceDateChangedEvent.register(handler);
450
+ }
451
+
416
452
  /**
417
453
  * Registers an observer for object disposal.
418
454
  *
@@ -431,7 +467,9 @@ module.exports = (() => {
431
467
  this._newsExistsChangedEvent.clear();
432
468
  this._fundamentalDataChangedEvent.clear();
433
469
  this._lockChangedEvent.clear();
470
+ this._calculatingChangedEvent.clear();
434
471
  this._portfolioChangedEvent.clear();
472
+ this._referenceDateChangedEvent.clear();
435
473
  this._positionItemDisposeEvent.clear();
436
474
  }
437
475
 
@@ -846,5 +884,9 @@ module.exports = (() => {
846
884
  return snapshot;
847
885
  }
848
886
 
887
+ function getQuoteIsToday(quote, referenceDate) {
888
+ return quote && quote.lastDay instanceof Day && referenceDate instanceof Day && quote.lastDay.getIsEqual(referenceDate);
889
+ }
890
+
849
891
  return PositionItem;
850
892
  })();
@@ -93,6 +93,7 @@ module.exports = (() => {
93
93
  .withField('instrument.type', DataType.forEnum(InstrumentType, 'InstrumentType'))
94
94
  .withField('instrument.code', DataType.forEnum(UnitCode, 'UnitCode'), true)
95
95
  .withField('instrument.currency', DataType.forEnum(Currency, 'Currency'))
96
+ .withField('instrument.exchange', DataType.STRING, true)
96
97
  .withField('instrument.delist', DataType.DAY, true)
97
98
  .withField('instrument.future.expiration', DataType.DAY, true)
98
99
  .withField('instrument.future.tick', DataType.DECIMAL, true)
@@ -142,6 +143,7 @@ module.exports = (() => {
142
143
  .withField('instrument.type', DataType.forEnum(InstrumentType, 'InstrumentType'))
143
144
  .withField('instrument.code', DataType.forEnum(UnitCode, 'UnitCode'), true)
144
145
  .withField('instrument.currency', DataType.forEnum(Currency, 'Currency'))
146
+ .withField('instrument.exchange', DataType.STRING, true)
145
147
  .withField('instrument.delist', DataType.DAY, true)
146
148
  .withField('instrument.future.expiration', DataType.DAY, true)
147
149
  .withField('instrument.future.tick', DataType.DECIMAL, true)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Common JavaScript code used by Barchart's Portfolio Service",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",