@barchart/portfolio-api-common 1.27.2 → 1.28.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.
@@ -14,6 +14,7 @@ module.exports = (() => {
14
14
  * @extends {Enum}
15
15
  * @param {String} code
16
16
  * @param {String} description
17
+ * @param {Boolean} unique
17
18
  * @param {Function} rangeCalculator
18
19
  * @param {Function} startDateCalculator
19
20
  * @param {Function} descriptionCalculator
@@ -91,7 +92,7 @@ module.exports = (() => {
91
92
  *
92
93
  * @public
93
94
  * @param {Day} date
94
- * @return {PositionSummaryRange[]}
95
+ * @returns {PositionSummaryRange[]}
95
96
  */
96
97
  getRangesFromDate(date) {
97
98
  assert.argumentIsRequired(date, 'date', Day, 'Day');
@@ -108,6 +109,7 @@ module.exports = (() => {
108
109
  * @public
109
110
  * @param {Day} date
110
111
  * @param {Number} periods
112
+ * @returns {PositionSummaryRange[]}
111
113
  */
112
114
  getPriorRanges(date, periods) {
113
115
  assert.argumentIsRequired(date, 'date', Day, 'Day');
@@ -138,6 +140,7 @@ module.exports = (() => {
138
140
  * A summary for a calendar year.
139
141
  *
140
142
  * @public
143
+ * @static
141
144
  * @returns {PositionSummaryFrame}
142
145
  */
143
146
  static get YEARLY() {
@@ -148,6 +151,7 @@ module.exports = (() => {
148
151
  * A summary for a quarter.
149
152
  *
150
153
  * @public
154
+ * @static
151
155
  * @returns {PositionSummaryFrame}
152
156
  */
153
157
  static get QUARTERLY() {
@@ -158,6 +162,7 @@ module.exports = (() => {
158
162
  * A summary for a calendar month.
159
163
  *
160
164
  * @public
165
+ * @static
161
166
  * @returns {PositionSummaryFrame}
162
167
  */
163
168
  static get MONTHLY() {
@@ -168,6 +173,7 @@ module.exports = (() => {
168
173
  * A summary the current year (to date).
169
174
  *
170
175
  * @public
176
+ * @static
171
177
  * @returns {PositionSummaryFrame}
172
178
  */
173
179
  static get YTD() {
@@ -175,6 +181,9 @@ module.exports = (() => {
175
181
  }
176
182
 
177
183
  /**
184
+ * Returns the {@link PositionSummaryFrame} instance that matches the code
185
+ * provided.
186
+ *
178
187
  * @public
179
188
  * @static
180
189
  * @param {String} code
@@ -214,10 +223,7 @@ module.exports = (() => {
214
223
  */
215
224
 
216
225
  function getRange(start, end) {
217
- return {
218
- start: start,
219
- end: end
220
- };
226
+ return { start, end };
221
227
  }
222
228
 
223
229
  function getYearlyRanges(transactions) {
@@ -87,6 +87,8 @@ module.exports = (() => {
87
87
  }, { });
88
88
 
89
89
  if (reportFrame) {
90
+ this._referenceDate = reportDate;
91
+
90
92
  this._currentSummaryFrame = reportFrame;
91
93
  this._currentSummaryRange = array.last(this._currentSummaryFrame.getPriorRanges(reportDate, 0));
92
94
 
@@ -95,6 +97,8 @@ module.exports = (() => {
95
97
 
96
98
  this._previousSummaryRanges.pop();
97
99
  } else {
100
+ this._referenceDate = Day.getToday();
101
+
98
102
  this._currentSummaryFrame = PositionSummaryFrame.YTD;
99
103
  this._currentSummaryRange = array.first(this._currentSummaryFrame.getRecentRanges(0));
100
104
 
@@ -507,7 +511,7 @@ module.exports = (() => {
507
511
  *
508
512
  * @public
509
513
  * @param {Object} position
510
- * @return {Boolean}
514
+ * @returns {Boolean}
511
515
  */
512
516
  getPositionLock(position) {
513
517
  assert.argumentIsRequired(position, 'position', Object);
@@ -542,7 +546,7 @@ module.exports = (() => {
542
546
  *
543
547
  * @public
544
548
  * @param {Object} position
545
- * @return {Boolean}
549
+ * @returns {Boolean}
546
550
  */
547
551
  getPositionCalculating(position) {
548
552
  assert.argumentIsRequired(position, 'position', Object);
@@ -615,8 +619,9 @@ module.exports = (() => {
615
619
  /**
616
620
  * Returns current price for symbol provided.
617
621
  *
622
+ * @public
618
623
  * @param {String} symbol
619
- * @return {null|Number}
624
+ * @returns {null|Number}
620
625
  */
621
626
  getCurrentPrice(symbol) {
622
627
  assert.argumentIsRequired(symbol, 'symbol', String);
@@ -1103,7 +1108,7 @@ module.exports = (() => {
1103
1108
  const previousSummaries = this._summariesPrevious[ position.position ] || getSummaryArray(this._previousSummaryRanges);
1104
1109
 
1105
1110
  if (!requireCurrentSummary || currentSummary !== null) {
1106
- returnRef = new PositionItem(portfolio, position, currentSummary, previousSummaries, this._reporting);
1111
+ returnRef = new PositionItem(portfolio, position, currentSummary, previousSummaries, this._reporting, this._referenceDate);
1107
1112
  } else {
1108
1113
  returnRef = null;
1109
1114
  }
@@ -1165,4 +1170,4 @@ module.exports = (() => {
1165
1170
  }
1166
1171
 
1167
1172
  return PositionContainer;
1168
- })();
1173
+ })();
@@ -76,6 +76,7 @@ module.exports = (() => {
76
76
  this._dataFormat.invalid = false;
77
77
  this._dataFormat.locked = false;
78
78
  this._dataFormat.calculating = false;
79
+ this._dataFormat.expired = false;
79
80
  this._dataFormat.newsExists = false;
80
81
  this._dataFormat.quantity = null;
81
82
  this._dataFormat.quantityPrevious = null;
@@ -876,6 +877,7 @@ module.exports = (() => {
876
877
  format.invalid = definition.type === PositionLevelType.POSITION && item.invalid;
877
878
  format.locked = definition.type === PositionLevelType.POSITION && item.data.locked;
878
879
  format.calculating = definition.type === PositionLevelType.POSITION && item.data.calculating;
880
+ format.expired = definition.type === PositionLevelType.POSITION && item.data.expired;
879
881
  }
880
882
 
881
883
  let portfolioType = null;
@@ -25,9 +25,10 @@ module.exports = (() => {
25
25
  * @param {Object} currentSummary
26
26
  * @param {Object[]} previousSummaries
27
27
  * @param {Boolean} reporting
28
+ * @param {Day} referenceDate
28
29
  */
29
30
  class PositionItem extends Disposable {
30
- constructor(portfolio, position, currentSummary, previousSummaries, reporting) {
31
+ constructor(portfolio, position, currentSummary, previousSummaries, reporting, referenceDate) {
31
32
  super();
32
33
 
33
34
  this._portfolio = portfolio;
@@ -107,6 +108,7 @@ module.exports = (() => {
107
108
  this._data.fundamental = { };
108
109
  this._data.calculating = getIsCalculating(position);
109
110
  this._data.locked = getIsLocked(position);
111
+ this._data.expired = getIsExpired(position, referenceDate);
110
112
 
111
113
  this._quoteChangedEvent = new Event(this);
112
114
  this._newsExistsChangedEvent = new Event(this);
@@ -505,6 +507,13 @@ module.exports = (() => {
505
507
 
506
508
  const data = item._data;
507
509
 
510
+ // 2023/11/28, BRI. Futures contracts do not have their value set to zero
511
+ // after expiration. At expiration, the contract would have been closed
512
+ // (but the price would not have been zero). On the other hand, option
513
+ // contracts can expire worthless and we attempt to represent that here.
514
+
515
+ const worthless = data.expired && (position.instrument.type === InstrumentType.EQUITY_OPTION || position.instrument.type === InstrumentType.FUTURE_OPTION);
516
+
508
517
  let market;
509
518
 
510
519
  if (position.instrument.type === InstrumentType.OTHER) {
@@ -512,7 +521,15 @@ module.exports = (() => {
512
521
  } else if (position.instrument.type === InstrumentType.CASH) {
513
522
  market = snapshot.open;
514
523
  } else {
515
- market = ValuationCalculator.calculate(position.instrument, price, snapshot.open) || snapshot.value;
524
+ let priceToUse;
525
+
526
+ if (worthless) {
527
+ priceToUse = Decimal.ZERO;
528
+ } else {
529
+ priceToUse = price;
530
+ }
531
+
532
+ market = ValuationCalculator.calculate(position.instrument, priceToUse, snapshot.open) || snapshot.value;
516
533
  }
517
534
 
518
535
  let marketChange;
@@ -565,7 +582,9 @@ module.exports = (() => {
565
582
  if (currentSummary && position.instrument.type !== InstrumentType.CASH) {
566
583
  let priceToUse;
567
584
 
568
- if (price) {
585
+ if (worthless) {
586
+ priceToUse = Decimal.ZERO;
587
+ } else if (price) {
569
588
  priceToUse = price;
570
589
  } else if (data.previousPrice) {
571
590
  priceToUse = new Decimal(data.previousPrice);
@@ -762,11 +781,29 @@ module.exports = (() => {
762
781
  }
763
782
 
764
783
  function getIsCalculating(position) {
765
- assert.argumentIsRequired(position, 'position', Object);
784
+ assert.argumentIsRequired(position, 'position');
766
785
 
767
786
  return is.object(position.system) && is.object(position.system.calculate) && is.number(position.system.calculate.processors) && position.system.calculate.processors > 0;
768
787
  }
769
788
 
789
+ function getIsExpired(position, day) {
790
+ assert.argumentIsRequired(position, 'position');
791
+
792
+ const type = position.instrument.type;
793
+
794
+ let expiration;
795
+
796
+ if (type === InstrumentType.FUTURE) {
797
+ expiration = position.instrument.future.expiration;
798
+ } else if (type === InstrumentType.FUTURE_OPTION || type === InstrumentType.EQUITY_OPTION) {
799
+ expiration = position.instrument.option.expiration;
800
+ } else {
801
+ expiration = null;
802
+ }
803
+
804
+ return expiration !== null && expiration.getIsBefore(day);
805
+ }
806
+
770
807
  function getSnapshot(position, currentSummary, reporting) {
771
808
  let snapshot;
772
809
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.27.2",
3
+ "version": "1.28.0",
4
4
  "description": "Common JavaScript code used by Barchart's Portfolio Service",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",