@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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
|
|
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 (
|
|
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'
|
|
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
|
|