@barchart/portfolio-api-common 6.3.0 → 6.4.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.
@@ -115,7 +115,7 @@ module.exports = (() => {
115
115
  * @static
116
116
  * @param {Object[]} transactions
117
117
  * @param {InstrumentType} instrumentType
118
- * @param {Object} position
118
+ * @param {Object=} position
119
119
  * @return {Number}
120
120
  */
121
121
  static getSwitchIndex(transactions, instrumentType, position) {
@@ -156,7 +156,7 @@ module.exports = (() => {
156
156
  * @static
157
157
  * @param {Object[]} transactions
158
158
  * @param {InstrumentType} instrumentType
159
- * @param {Object} position
159
+ * @param {Object=} position
160
160
  * @return {Number}
161
161
  */
162
162
  static getPositionViolationIndex(transactions, instrumentType, position) {
@@ -351,6 +351,7 @@ module.exports = (() => {
351
351
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_CASH, false);
352
352
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_REINVEST, false);
353
353
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
354
+ associateTypes(InstrumentType.FUND, TransactionType.SPLIT, false);
354
355
  associateTypes(InstrumentType.FUND, TransactionType.DELIST, false);
355
356
  associateTypes(InstrumentType.FUND, TransactionType.MERGER_OPEN, false);
356
357
  associateTypes(InstrumentType.FUND, TransactionType.MERGER_CLOSE, false);
@@ -54,6 +54,8 @@ module.exports = (() => {
54
54
  this._description = description;
55
55
 
56
56
  this._single = this._definition.single;
57
+ this._homogeneous = this._definition.homogeneous;
58
+
57
59
  this._aggregateCash = is.boolean(aggregateCash) && aggregateCash;
58
60
 
59
61
  this._excluded = false;
@@ -104,6 +106,13 @@ module.exports = (() => {
104
106
  this._dataFormat.fundamental = { };
105
107
  }
106
108
 
109
+ if (this._homogeneous && items.length !== 0) {
110
+ const item = items[0];
111
+
112
+ this._dataFormat.instrument = item.position.instrument;
113
+ this._dataFormat.fundamental = item.fundamental || { };
114
+ }
115
+
107
116
  this._dataActual.quoteLast = null;
108
117
  this._dataActual.quoteOpen = null;
109
118
  this._dataActual.quoteHigh = null;
@@ -307,6 +316,17 @@ module.exports = (() => {
307
316
  return this._single;
308
317
  }
309
318
 
319
+ /**
320
+ * Indicates if the group will only contain {@link PositionItem} instances
321
+ * that share the same instrument.
322
+ *
323
+ * @public
324
+ * @returns {Boolean}
325
+ */
326
+ get homogeneous() {
327
+ return this._homogeneous;
328
+ }
329
+
310
330
  /**
311
331
  * Indicates if the group should be excluded from higher-level aggregations.
312
332
  *
@@ -525,24 +545,26 @@ module.exports = (() => {
525
545
  setBarchartPriceFormattingRules(value) {
526
546
  assert.argumentIsRequired(value, 'value', Boolean);
527
547
 
528
- if (this._useBarchartPriceFormattingRules !== value) {
529
- this._useBarchartPriceFormattingRules = value;
548
+ if (this._useBarchartPriceFormattingRules === value) {
549
+ return;
550
+ }
530
551
 
531
- if (this._single && this._dataActual.currentPrice) {
532
- const item = this._items[0];
552
+ this._useBarchartPriceFormattingRules = value;
533
553
 
534
- const instrument = item.position.instrument;
535
- const currency = instrument.currency;
554
+ if ((this._single || this._homogeneous) && this._dataActual.currentPrice) {
555
+ const item = this._items[0];
536
556
 
537
- this._dataFormat.currentPrice = formatFraction(this._dataActual.currentPrice, currency, instrument, this._useBarchartPriceFormattingRules);
557
+ const instrument = item.position.instrument;
558
+ const currency = instrument.currency;
538
559
 
539
- this._dataFormat.quoteLast = formatFraction(this._dataActual.quoteLast, currency, instrument, this._useBarchartPriceFormattingRules);
540
- this._dataFormat.quoteOpen = formatFraction(this._dataActual.quoteOpen, currency, instrument, this._useBarchartPriceFormattingRules);
541
- this._dataFormat.quoteHigh = formatFraction(this._dataActual.quoteHigh, currency, instrument, this._useBarchartPriceFormattingRules);
542
- this._dataFormat.quoteLow = formatFraction(this._dataActual.quoteLow, currency, instrument, this._useBarchartPriceFormattingRules);
560
+ this._dataFormat.currentPrice = formatFraction(this._dataActual.currentPrice, currency, instrument, this._useBarchartPriceFormattingRules);
543
561
 
544
- this._dataFormat.quoteChange = formatFraction(this._dataActual.quoteChange, currency, instrument, this._useBarchartPriceFormattingRules);
545
- }
562
+ this._dataFormat.quoteLast = formatFraction(this._dataActual.quoteLast, currency, instrument, this._useBarchartPriceFormattingRules);
563
+ this._dataFormat.quoteOpen = formatFraction(this._dataActual.quoteOpen, currency, instrument, this._useBarchartPriceFormattingRules);
564
+ this._dataFormat.quoteHigh = formatFraction(this._dataActual.quoteHigh, currency, instrument, this._useBarchartPriceFormattingRules);
565
+ this._dataFormat.quoteLow = formatFraction(this._dataActual.quoteLow, currency, instrument, this._useBarchartPriceFormattingRules);
566
+
567
+ this._dataFormat.quoteChange = formatFraction(this._dataActual.quoteChange, currency, instrument, this._useBarchartPriceFormattingRules);
546
568
  }
547
569
  }
548
570
 
@@ -553,7 +575,7 @@ module.exports = (() => {
553
575
 
554
576
  function bindItem(item) {
555
577
  const quoteBinding = item.registerQuoteChangeHandler((quote, sender) => {
556
- if (this._single) {
578
+ if (this._single || (this._homogeneous && item === this._items[0])) {
557
579
  const instrument = sender.position.instrument;
558
580
  const currency = instrument.currency;
559
581
 
@@ -596,7 +618,7 @@ module.exports = (() => {
596
618
  });
597
619
 
598
620
  const fundamentalBinding = item.registerFundamentalDataChangeHandler((data) => {
599
- if (this._single) {
621
+ if (this._single || this._homogeneous) {
600
622
  this._dataFormat.fundamental = data;
601
623
 
602
624
  return;
@@ -649,12 +671,14 @@ module.exports = (() => {
649
671
  let lockedBinding = Disposable.getEmpty();
650
672
  let calculatingBinding = Disposable.getEmpty();
651
673
 
652
- if (this._single) {
674
+ if (this._single || this._homogeneous) {
653
675
  newsBinding = item.registerNewsExistsChangeHandler((exists) => {
654
676
  this._dataActual.newsExists = exists;
655
677
  this._dataFormat.newsExists = exists;
656
678
  });
679
+ }
657
680
 
681
+ if (this._single) {
658
682
  lockedBinding = item.registerLockChangeHandler((locked) => {
659
683
  this._dataFormat.locked = locked;
660
684
  });
@@ -847,6 +871,10 @@ module.exports = (() => {
847
871
  updates.periodDivisorPrevious = updates.periodDivisorPrevious.add(translate(item, item.data.periodDivisorPrevious));
848
872
  updates.periodDivisorPrevious2 = updates.periodDivisorPrevious2.add(translate(item, item.data.periodDivisorPrevious2));
849
873
 
874
+ if (group.homogeneous) {
875
+ updates.quantity = updates.quantity.add(item.data.quantity);
876
+ }
877
+
850
878
  return updates;
851
879
  }, {
852
880
  basis: Decimal.ZERO,
@@ -867,7 +895,8 @@ module.exports = (() => {
867
895
  totalDivisor: Decimal.ZERO,
868
896
  periodDivisorCurrent: Decimal.ZERO,
869
897
  periodDivisorPrevious: Decimal.ZERO,
870
- periodDivisorPrevious2: Decimal.ZERO
898
+ periodDivisorPrevious2: Decimal.ZERO,
899
+ quantity: Decimal.ZERO
871
900
  });
872
901
 
873
902
  actual.basis = updates.basis;
@@ -890,6 +919,10 @@ module.exports = (() => {
890
919
  actual.periodDivisorPrevious = updates.periodDivisorPrevious;
891
920
  actual.periodDivisorPrevious2 = updates.periodDivisorPrevious2;
892
921
 
922
+ if (group.homogeneous) {
923
+ actual.quantity = updates.quantity;
924
+ }
925
+
893
926
  format.basis = formatCurrency(actual.basis, currency);
894
927
  format.basis2 = formatCurrency(actual.basis2, currency);
895
928
  format.realized = formatCurrency(actual.realized, currency);
@@ -909,6 +942,10 @@ module.exports = (() => {
909
942
  format.periodUnrealized = formatCurrency(updates.periodUnrealized, currency);
910
943
  format.cashTotal = formatCurrency(updates.cashTotal, currency);
911
944
 
945
+ if (group.homogeneous) {
946
+ format.quantity = formatDecimal(actual.quantity, 2);
947
+ }
948
+
912
949
  calculateRealizedPercent(group);
913
950
  calculateUnrealizedPercent(group);
914
951
 
@@ -923,7 +960,7 @@ module.exports = (() => {
923
960
  const groupItems = group._items;
924
961
 
925
962
  if (group.single && groupItems.length === 1) {
926
- const item = group._items[0];
963
+ const item = groupItems[0];
927
964
  const instrument = item.position.instrument;
928
965
 
929
966
  actual.quantity = item.data.quantity;
@@ -950,6 +987,12 @@ module.exports = (() => {
950
987
  format.expired = definition.type === PositionLevelType.POSITION && item.data.expired;
951
988
  }
952
989
 
990
+ if (group.homogeneous && groupItems.length !== 1) {
991
+ const item = groupItems[0];
992
+
993
+ format.expired = item.data.expired;
994
+ }
995
+
953
996
  let portfolioType = null;
954
997
 
955
998
  if (groupItems.length > 0) {
@@ -49,6 +49,8 @@ module.exports = (() => {
49
49
  this._requiredGroups = requiredGroups || [ ];
50
50
 
51
51
  this._single = type === PositionLevelType.POSITION;
52
+ this._homogeneous = type === PositionLevelType.INSTRUMENT;
53
+
52
54
  this._aggregateCash = is.boolean(aggregateCash) && aggregateCash;
53
55
 
54
56
  this._requiredGroupGenerator = requiredGroupGenerator || (input => null);
@@ -128,6 +130,16 @@ module.exports = (() => {
128
130
  return this._single;
129
131
  }
130
132
 
133
+ /**
134
+ * Indicates if the grouping level only contains items for the same instrument.
135
+ *
136
+ * @public
137
+ * @return {Boolean}
138
+ */
139
+ get homogeneous() {
140
+ return this._homogeneous;
141
+ }
142
+
131
143
  /**
132
144
  * Indicates if the grouping level should aggregate cash positions.
133
145
  *
@@ -15,6 +15,17 @@ module.exports = (() => {
15
15
  super(code, code);
16
16
  }
17
17
 
18
+ /**
19
+ * A level of grouping for positions which share the same instrument.
20
+ *
21
+ * @public
22
+ * @static
23
+ * @returns {PositionLevelType}
24
+ */
25
+ static get INSTRUMENT() {
26
+ return instrument;
27
+ }
28
+
18
29
  /**
19
30
  * A level of grouping that represents an entire portfolio's contents.
20
31
  *
@@ -39,8 +50,9 @@ module.exports = (() => {
39
50
  }
40
51
 
41
52
  /**
42
- * A level of grouping that is neither a portfolio or a position. This could be an
43
- * intermediate level of grouping (e.g. an asset class within a portfolio).
53
+ * A level of grouping that doesn't fit into any other explicitly defined
54
+ * category. This could be an intermediate level of grouping (e.g. an asset
55
+ * class within a portfolio).
44
56
  *
45
57
  * @public
46
58
  * @static
@@ -51,6 +63,7 @@ module.exports = (() => {
51
63
  }
52
64
  }
53
65
 
66
+ const instrument = new PositionLevelType('INSTRUMENT');
54
67
  const portfolio = new PositionLevelType('PORTFOLIO');
55
68
  const position = new PositionLevelType('POSITION');
56
69
  const other = new PositionLevelType('OTHER');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
4
4
  "description": "Common JavaScript code used by Barchart's Portfolio Service",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",