@barchart/portfolio-api-common 1.2.89 → 1.2.93
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/data/PositionSummaryFrame.js +53 -8
- package/lib/processing/PositionContainer.js +1 -1
- package/lib/processing/PositionGroup.js +40 -5
- package/lib/processing/PositionItem.js +13 -3
- package/lib/serialization/PositionSummaryDefinitionSchema.js +58 -0
- package/lib/serialization/PositionSummarySchema.js +1 -2
- package/package.json +1 -1
- package/test/SpecRunner.js +139 -17
- package/test/specs/data/PositionSummaryFrameSpec.js +32 -0
|
@@ -86,17 +86,52 @@ module.exports = (() => {
|
|
|
86
86
|
return this._rangeCalculator(getFilteredTransactions(transactions));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Returns the range which contains a given date and all subsequent ranges.
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
* @param {Day} date
|
|
94
|
+
* @return {Array.<PositionSummaryRange>}
|
|
95
|
+
*/
|
|
96
|
+
getRangesFromDate(date) {
|
|
97
|
+
assert.argumentIsRequired(date, 'date', Day, 'Day');
|
|
98
|
+
|
|
99
|
+
const transaction = { date: date, snapshot: { open: Decimal.ONE } };
|
|
100
|
+
|
|
101
|
+
return this.getRanges([ transaction ]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Returns the range immediately prior to the range containing the
|
|
106
|
+
* date supplied.
|
|
107
|
+
*
|
|
108
|
+
* @public
|
|
109
|
+
* @param {Day} date
|
|
110
|
+
* @param {Number} periods
|
|
111
|
+
*/
|
|
112
|
+
getPriorRanges(date, periods) {
|
|
113
|
+
assert.argumentIsRequired(date, 'date', Day, 'Day');
|
|
114
|
+
assert.argumentIsRequired(periods, 'periods', Number, 'Number');
|
|
115
|
+
|
|
116
|
+
const transactionOne = { date: this.getStartDate((periods - 1), date), snapshot: { open: Decimal.ONE } };
|
|
117
|
+
const transactionTwo = { date: date, snapshot: { open: Decimal.ZERO } };
|
|
118
|
+
|
|
119
|
+
return this._rangeCalculator([ transactionOne, transactionTwo ]);
|
|
120
|
+
}
|
|
121
|
+
|
|
89
122
|
/**
|
|
90
123
|
* Returns the start date for a frame, a given number of periods ago.
|
|
91
124
|
*
|
|
92
125
|
* @public
|
|
93
126
|
* @param {Number} periods
|
|
127
|
+
* @param {Day=} start
|
|
94
128
|
* @returns {Day}
|
|
95
129
|
*/
|
|
96
|
-
getStartDate(periods) {
|
|
130
|
+
getStartDate(periods, start) {
|
|
97
131
|
assert.argumentIsRequired(periods, 'periods', Number);
|
|
132
|
+
assert.argumentIsOptional(start, 'start', Day, 'Day');
|
|
98
133
|
|
|
99
|
-
return this._startDateCalculator(periods);
|
|
134
|
+
return this._startDateCalculator(periods, start);
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
/**
|
|
@@ -158,6 +193,16 @@ module.exports = (() => {
|
|
|
158
193
|
* @property {Day} end
|
|
159
194
|
*/
|
|
160
195
|
|
|
196
|
+
/**
|
|
197
|
+
* The start and and date for a {@link PositionSummaryFrame} along with the frame type.
|
|
198
|
+
*
|
|
199
|
+
* @typedef PositionSummaryDefinition
|
|
200
|
+
* @type {Object}
|
|
201
|
+
* @property {Day} start
|
|
202
|
+
* @property {Day} end
|
|
203
|
+
* @property {PositionSummaryFrame} frame
|
|
204
|
+
*/
|
|
205
|
+
|
|
161
206
|
function getRange(start, end) {
|
|
162
207
|
return {
|
|
163
208
|
start: start,
|
|
@@ -219,24 +264,24 @@ module.exports = (() => {
|
|
|
219
264
|
return ranges;
|
|
220
265
|
}
|
|
221
266
|
|
|
222
|
-
function getYearlyStartDate(periods) {
|
|
223
|
-
const today = Day.getToday();
|
|
267
|
+
function getYearlyStartDate(periods, date) {
|
|
268
|
+
const today = date || Day.getToday();
|
|
224
269
|
|
|
225
|
-
return
|
|
270
|
+
return today
|
|
226
271
|
.subtractMonths(today.month - 1)
|
|
227
272
|
.subtractDays(today.day)
|
|
228
273
|
.subtractYears(periods);
|
|
229
274
|
}
|
|
230
275
|
|
|
231
|
-
function getQuarterlyStartDate(periods) {
|
|
276
|
+
function getQuarterlyStartDate(periods, date) {
|
|
232
277
|
return null;
|
|
233
278
|
}
|
|
234
279
|
|
|
235
|
-
function getMonthlyStartDate(periods) {
|
|
280
|
+
function getMonthlyStartDate(periods, date) {
|
|
236
281
|
return null;
|
|
237
282
|
}
|
|
238
283
|
|
|
239
|
-
function getYearToDateStartDate(periods) {
|
|
284
|
+
function getYearToDateStartDate(periods, date) {
|
|
240
285
|
return null;
|
|
241
286
|
}
|
|
242
287
|
|
|
@@ -42,7 +42,7 @@ module.exports = (() => {
|
|
|
42
42
|
* @param {Array.<Object>} portfolios - The portfolios.
|
|
43
43
|
* @param {Array.<Object>} positions - The positions (for all of the portfolios).
|
|
44
44
|
* @param {Array.<Object>} summaries - The positions summaries (for all of the positions).
|
|
45
|
-
* @param {PositionSummaryFrame} - If specified, locks the current (and previous) periods to a specific frame, use for reporting.
|
|
45
|
+
* @param {PositionSummaryFrame=} - If specified, locks the current (and previous) periods to a specific frame, use for reporting.
|
|
46
46
|
*/
|
|
47
47
|
class PositionContainer {
|
|
48
48
|
constructor(definitions, portfolios, positions, summaries, frame) {
|
|
@@ -130,6 +130,10 @@ module.exports = (() => {
|
|
|
130
130
|
this._dataActual.summaryTotalCurrent = null;
|
|
131
131
|
this._dataActual.summaryTotalPrevious = null;
|
|
132
132
|
this._dataActual.summaryTotalPrevious2 = null;
|
|
133
|
+
this._dataActual.endingPrevious = null;
|
|
134
|
+
this._dataActual.endingPrevious2 = null;
|
|
135
|
+
this._dataActual.endingChange = null;
|
|
136
|
+
this._dataActual.endingChangePercent = null;
|
|
133
137
|
this._dataActual.cashTotal = null;
|
|
134
138
|
|
|
135
139
|
this._dataFormat.currentPrice = null;
|
|
@@ -153,6 +157,10 @@ module.exports = (() => {
|
|
|
153
157
|
this._dataFormat.summaryTotalPreviousNegative = false;
|
|
154
158
|
this._dataFormat.summaryTotalPrevious2 = null;
|
|
155
159
|
this._dataFormat.summaryTotalPrevious2Negative = false;
|
|
160
|
+
this._dataFormat.endingPrevious = null;
|
|
161
|
+
this._dataFormat.endingPrevious2 = null;
|
|
162
|
+
this._dataFormat.endingChange = null;
|
|
163
|
+
this._dataFormat.endingChangePercent = null;
|
|
156
164
|
this._dataFormat.cashTotal = null;
|
|
157
165
|
this._dataFormat.portfolioType = null;
|
|
158
166
|
|
|
@@ -388,8 +396,6 @@ module.exports = (() => {
|
|
|
388
396
|
return;
|
|
389
397
|
}
|
|
390
398
|
|
|
391
|
-
const descriptionSelector = this._definition.descriptionSelector;
|
|
392
|
-
|
|
393
399
|
this._description = PositionLevelDefinition.getDescriptionForPortfolioGroup(portfolio);
|
|
394
400
|
|
|
395
401
|
this._dataActual.description = this._description;
|
|
@@ -634,7 +640,7 @@ module.exports = (() => {
|
|
|
634
640
|
const translate = (item, value) => {
|
|
635
641
|
let translated;
|
|
636
642
|
|
|
637
|
-
if (item.currency !== currency) {
|
|
643
|
+
if (item.currency !== currency && !value.getIsZero()) {
|
|
638
644
|
translated = Rate.convert(value, item.currency, currency, ...rates);
|
|
639
645
|
} else {
|
|
640
646
|
translated = value;
|
|
@@ -651,6 +657,8 @@ module.exports = (() => {
|
|
|
651
657
|
updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
|
|
652
658
|
updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
|
|
653
659
|
updates.summaryTotalPrevious2 = updates.summaryTotalPrevious2.add(translate(item, item.data.summaryTotalPrevious2));
|
|
660
|
+
updates.endingPrevious = updates.endingPrevious.add(translate(item, item.data.endingPrevious));
|
|
661
|
+
updates.endingPrevious2 = updates.endingPrevious2.add(translate(item, item.data.endingPrevious2));
|
|
654
662
|
|
|
655
663
|
if (item.position.instrument.type === InstrumentType.CASH) {
|
|
656
664
|
updates.cashTotal = updates.cashTotal.add(translate(item, item.data.market));
|
|
@@ -665,6 +673,8 @@ module.exports = (() => {
|
|
|
665
673
|
summaryTotalCurrent: Decimal.ZERO,
|
|
666
674
|
summaryTotalPrevious: Decimal.ZERO,
|
|
667
675
|
summaryTotalPrevious2: Decimal.ZERO,
|
|
676
|
+
endingPrevious: Decimal.ZERO,
|
|
677
|
+
endingPrevious2: Decimal.ZERO,
|
|
668
678
|
cashTotal: Decimal.ZERO
|
|
669
679
|
});
|
|
670
680
|
|
|
@@ -675,6 +685,8 @@ module.exports = (() => {
|
|
|
675
685
|
actual.summaryTotalCurrent = updates.summaryTotalCurrent;
|
|
676
686
|
actual.summaryTotalPrevious = updates.summaryTotalPrevious;
|
|
677
687
|
actual.summaryTotalPrevious2 = updates.summaryTotalPrevious2;
|
|
688
|
+
actual.endingPrevious = updates.endingPrevious;
|
|
689
|
+
actual.endingPrevious2 = updates.endingPrevious2;
|
|
678
690
|
actual.cashTotal = updates.cashTotal;
|
|
679
691
|
|
|
680
692
|
format.basis = formatCurrency(actual.basis, currency);
|
|
@@ -686,6 +698,8 @@ module.exports = (() => {
|
|
|
686
698
|
format.summaryTotalPreviousNegative = updates.summaryTotalPrevious.getIsNegative();
|
|
687
699
|
format.summaryTotalPrevious2 = formatCurrency(updates.summaryTotalPrevious2, currency);
|
|
688
700
|
format.summaryTotalPrevious2Negative = updates.summaryTotalPrevious2.getIsNegative();
|
|
701
|
+
format.endingPrevious = formatCurrency(updates.endingPrevious, currency);
|
|
702
|
+
format.endingPrevious2 = formatCurrency(updates.endingPrevious2, currency);
|
|
689
703
|
format.cashTotal = formatCurrency(updates.cashTotal, currency);
|
|
690
704
|
|
|
691
705
|
calculateUnrealizedPercent(group);
|
|
@@ -735,7 +749,7 @@ module.exports = (() => {
|
|
|
735
749
|
const translate = (item, value) => {
|
|
736
750
|
let translated;
|
|
737
751
|
|
|
738
|
-
if (item.currency !== currency) {
|
|
752
|
+
if (item.currency !== currency && !value.getIsZero()) {
|
|
739
753
|
translated = Rate.convert(value, item.currency, currency, ...rates);
|
|
740
754
|
} else {
|
|
741
755
|
translated = value;
|
|
@@ -782,7 +796,25 @@ module.exports = (() => {
|
|
|
782
796
|
actual.unrealizedToday = updates.unrealizedToday;
|
|
783
797
|
actual.summaryTotalCurrent = updates.summaryTotalCurrent;
|
|
784
798
|
actual.total = updates.unrealized.add(actual.realized).add(actual.income);
|
|
785
|
-
|
|
799
|
+
|
|
800
|
+
let endingChange = updates.market.subtract(actual.endingPrevious);
|
|
801
|
+
let endingChangePercent;
|
|
802
|
+
|
|
803
|
+
if (actual.endingPrevious.getIsZero()) {
|
|
804
|
+
if (endingChange.getIsPositive()) {
|
|
805
|
+
endingChangePercent = Decimal.ONE;
|
|
806
|
+
} else if (endingChange.getIsNegative()) {
|
|
807
|
+
endingChangePercent = Decimal.NEGATIVE_ONE;
|
|
808
|
+
} else {
|
|
809
|
+
endingChangePercent = Decimal.ZERO;
|
|
810
|
+
}
|
|
811
|
+
} else {
|
|
812
|
+
endingChangePercent = endingChange.divide(actual.endingPrevious);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
actual.endingChange = endingChange;
|
|
816
|
+
actual.endingChangePercent = endingChangePercent;
|
|
817
|
+
|
|
786
818
|
format.market = formatCurrency(actual.market, currency);
|
|
787
819
|
|
|
788
820
|
if (updates.marketDirection.up || updates.marketDirection.down) {
|
|
@@ -802,6 +834,9 @@ module.exports = (() => {
|
|
|
802
834
|
format.total = formatCurrency(actual.total, currency);
|
|
803
835
|
format.totalNegative = actual.total.getIsNegative();
|
|
804
836
|
|
|
837
|
+
format.endingChange = formatCurrency(actual.endingChange, currency);
|
|
838
|
+
format.endingChangePercent = formatPercent(actual.endingChangePercent, 2);
|
|
839
|
+
|
|
805
840
|
calculateUnrealizedPercent(group);
|
|
806
841
|
}
|
|
807
842
|
|
|
@@ -65,6 +65,9 @@ module.exports = (() => {
|
|
|
65
65
|
this._data.summaryTotalPrevious = null;
|
|
66
66
|
this._data.summaryTotalPrevious2 = null;
|
|
67
67
|
|
|
68
|
+
this._data.endingPrevious = null;
|
|
69
|
+
this._data.endingPrevious2 = null;
|
|
70
|
+
|
|
68
71
|
this._data.realized = null;
|
|
69
72
|
this._data.income = null;
|
|
70
73
|
this._data.basisPrice = null;
|
|
@@ -380,9 +383,16 @@ module.exports = (() => {
|
|
|
380
383
|
|
|
381
384
|
data.income = snapshot.income;
|
|
382
385
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
+
const previousSummary1 = getPreviousSummary(previousSummaries, 1);
|
|
387
|
+
const previousSummary2 = getPreviousSummary(previousSummaries, 2);
|
|
388
|
+
const previousSummary3 = getPreviousSummary(previousSummaries, 3);
|
|
389
|
+
|
|
390
|
+
data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary, previousSummary1);
|
|
391
|
+
data.summaryTotalPrevious = calculateSummaryTotal(previousSummary1, previousSummary2);
|
|
392
|
+
data.summaryTotalPrevious2 = calculateSummaryTotal(previousSummary2, previousSummary3);
|
|
393
|
+
|
|
394
|
+
data.endingPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.value;
|
|
395
|
+
data.endingPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
|
|
386
396
|
|
|
387
397
|
if (snapshot.open.getIsZero()) {
|
|
388
398
|
data.basisPrice = Decimal.ZERO;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const DataType = require('@barchart/common-js/serialization/json/DataType'),
|
|
2
|
+
Enum = require('@barchart/common-js/lang/Enum'),
|
|
3
|
+
Schema = require('@barchart/common-js/serialization/json/Schema'),
|
|
4
|
+
SchemaBuilder = require('@barchart/common-js/serialization/json/builders/SchemaBuilder');
|
|
5
|
+
|
|
6
|
+
const PositionSummaryFrame = require('./../data/PositionSummaryFrame');
|
|
7
|
+
|
|
8
|
+
module.exports = (() => {
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The schemas which can be used to represent position summary objects.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
* @extends {Enum}
|
|
16
|
+
*/
|
|
17
|
+
class PositionSummaryDefinitionSchema extends Enum {
|
|
18
|
+
constructor(schema) {
|
|
19
|
+
super(schema.name, schema.name);
|
|
20
|
+
|
|
21
|
+
this._schema = schema;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The actual {@link Schema}.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
* @returns {Schema}
|
|
29
|
+
*/
|
|
30
|
+
get schema() {
|
|
31
|
+
return this._schema;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The complete position summary definition schema.
|
|
36
|
+
*
|
|
37
|
+
* @static
|
|
38
|
+
* @public
|
|
39
|
+
* @returns {PositionSummaryDefinitionSchema}
|
|
40
|
+
*/
|
|
41
|
+
static get COMPLETE() {
|
|
42
|
+
return complete;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
toString() {
|
|
46
|
+
return '[PositionSummaryDefinitionSchema]';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const complete = new PositionSummaryDefinitionSchema(SchemaBuilder.withName('complete')
|
|
51
|
+
.withField('start', DataType.DAY)
|
|
52
|
+
.withField('end', DataType.DAY)
|
|
53
|
+
.withField('frame', DataType.forEnum(PositionSummaryFrame, 'PositionSummaryFrame'))
|
|
54
|
+
.schema
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return PositionSummaryDefinitionSchema;
|
|
58
|
+
})();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
DataType = require('@barchart/common-js/serialization/json/DataType'),
|
|
1
|
+
const DataType = require('@barchart/common-js/serialization/json/DataType'),
|
|
3
2
|
Enum = require('@barchart/common-js/lang/Enum'),
|
|
4
3
|
Schema = require('@barchart/common-js/serialization/json/Schema'),
|
|
5
4
|
SchemaBuilder = require('@barchart/common-js/serialization/json/builders/SchemaBuilder');
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -477,17 +477,52 @@ module.exports = (() => {
|
|
|
477
477
|
return this._rangeCalculator(getFilteredTransactions(transactions));
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Returns the range which contains a given date and all subsequent ranges.
|
|
482
|
+
*
|
|
483
|
+
* @public
|
|
484
|
+
* @param {Day} date
|
|
485
|
+
* @return {Array.<PositionSummaryRange>}
|
|
486
|
+
*/
|
|
487
|
+
getRangesFromDate(date) {
|
|
488
|
+
assert.argumentIsRequired(date, 'date', Day, 'Day');
|
|
489
|
+
|
|
490
|
+
const transaction = { date: date, snapshot: { open: Decimal.ONE } };
|
|
491
|
+
|
|
492
|
+
return this.getRanges([ transaction ]);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Returns the range immediately prior to the range containing the
|
|
497
|
+
* date supplied.
|
|
498
|
+
*
|
|
499
|
+
* @public
|
|
500
|
+
* @param {Day} date
|
|
501
|
+
* @param {Number} periods
|
|
502
|
+
*/
|
|
503
|
+
getPriorRanges(date, periods) {
|
|
504
|
+
assert.argumentIsRequired(date, 'date', Day, 'Day');
|
|
505
|
+
assert.argumentIsRequired(periods, 'periods', Number, 'Number');
|
|
506
|
+
|
|
507
|
+
const transactionOne = { date: this.getStartDate((periods - 1), date), snapshot: { open: Decimal.ONE } };
|
|
508
|
+
const transactionTwo = { date: date, snapshot: { open: Decimal.ZERO } };
|
|
509
|
+
|
|
510
|
+
return this._rangeCalculator([ transactionOne, transactionTwo ]);
|
|
511
|
+
}
|
|
512
|
+
|
|
480
513
|
/**
|
|
481
514
|
* Returns the start date for a frame, a given number of periods ago.
|
|
482
515
|
*
|
|
483
516
|
* @public
|
|
484
517
|
* @param {Number} periods
|
|
518
|
+
* @param {Day=} start
|
|
485
519
|
* @returns {Day}
|
|
486
520
|
*/
|
|
487
|
-
getStartDate(periods) {
|
|
521
|
+
getStartDate(periods, start) {
|
|
488
522
|
assert.argumentIsRequired(periods, 'periods', Number);
|
|
523
|
+
assert.argumentIsOptional(start, 'start', Day, 'Day');
|
|
489
524
|
|
|
490
|
-
return this._startDateCalculator(periods);
|
|
525
|
+
return this._startDateCalculator(periods, start);
|
|
491
526
|
}
|
|
492
527
|
|
|
493
528
|
/**
|
|
@@ -549,6 +584,16 @@ module.exports = (() => {
|
|
|
549
584
|
* @property {Day} end
|
|
550
585
|
*/
|
|
551
586
|
|
|
587
|
+
/**
|
|
588
|
+
* The start and and date for a {@link PositionSummaryFrame} along with the frame type.
|
|
589
|
+
*
|
|
590
|
+
* @typedef PositionSummaryDefinition
|
|
591
|
+
* @type {Object}
|
|
592
|
+
* @property {Day} start
|
|
593
|
+
* @property {Day} end
|
|
594
|
+
* @property {PositionSummaryFrame} frame
|
|
595
|
+
*/
|
|
596
|
+
|
|
552
597
|
function getRange(start, end) {
|
|
553
598
|
return {
|
|
554
599
|
start: start,
|
|
@@ -610,24 +655,24 @@ module.exports = (() => {
|
|
|
610
655
|
return ranges;
|
|
611
656
|
}
|
|
612
657
|
|
|
613
|
-
function getYearlyStartDate(periods) {
|
|
614
|
-
const today = Day.getToday();
|
|
658
|
+
function getYearlyStartDate(periods, date) {
|
|
659
|
+
const today = date || Day.getToday();
|
|
615
660
|
|
|
616
|
-
return
|
|
661
|
+
return today
|
|
617
662
|
.subtractMonths(today.month - 1)
|
|
618
663
|
.subtractDays(today.day)
|
|
619
664
|
.subtractYears(periods);
|
|
620
665
|
}
|
|
621
666
|
|
|
622
|
-
function getQuarterlyStartDate(periods) {
|
|
667
|
+
function getQuarterlyStartDate(periods, date) {
|
|
623
668
|
return null;
|
|
624
669
|
}
|
|
625
670
|
|
|
626
|
-
function getMonthlyStartDate(periods) {
|
|
671
|
+
function getMonthlyStartDate(periods, date) {
|
|
627
672
|
return null;
|
|
628
673
|
}
|
|
629
674
|
|
|
630
|
-
function getYearToDateStartDate(periods) {
|
|
675
|
+
function getYearToDateStartDate(periods, date) {
|
|
631
676
|
return null;
|
|
632
677
|
}
|
|
633
678
|
|
|
@@ -1421,7 +1466,7 @@ module.exports = (() => {
|
|
|
1421
1466
|
* @param {Array.<Object>} portfolios - The portfolios.
|
|
1422
1467
|
* @param {Array.<Object>} positions - The positions (for all of the portfolios).
|
|
1423
1468
|
* @param {Array.<Object>} summaries - The positions summaries (for all of the positions).
|
|
1424
|
-
* @param {PositionSummaryFrame} - If specified, locks the current (and previous) periods to a specific frame, use for reporting.
|
|
1469
|
+
* @param {PositionSummaryFrame=} - If specified, locks the current (and previous) periods to a specific frame, use for reporting.
|
|
1425
1470
|
*/
|
|
1426
1471
|
class PositionContainer {
|
|
1427
1472
|
constructor(definitions, portfolios, positions, summaries, frame) {
|
|
@@ -2515,6 +2560,10 @@ module.exports = (() => {
|
|
|
2515
2560
|
this._dataActual.summaryTotalCurrent = null;
|
|
2516
2561
|
this._dataActual.summaryTotalPrevious = null;
|
|
2517
2562
|
this._dataActual.summaryTotalPrevious2 = null;
|
|
2563
|
+
this._dataActual.endingPrevious = null;
|
|
2564
|
+
this._dataActual.endingPrevious2 = null;
|
|
2565
|
+
this._dataActual.endingChange = null;
|
|
2566
|
+
this._dataActual.endingChangePercent = null;
|
|
2518
2567
|
this._dataActual.cashTotal = null;
|
|
2519
2568
|
|
|
2520
2569
|
this._dataFormat.currentPrice = null;
|
|
@@ -2538,6 +2587,10 @@ module.exports = (() => {
|
|
|
2538
2587
|
this._dataFormat.summaryTotalPreviousNegative = false;
|
|
2539
2588
|
this._dataFormat.summaryTotalPrevious2 = null;
|
|
2540
2589
|
this._dataFormat.summaryTotalPrevious2Negative = false;
|
|
2590
|
+
this._dataFormat.endingPrevious = null;
|
|
2591
|
+
this._dataFormat.endingPrevious2 = null;
|
|
2592
|
+
this._dataFormat.endingChange = null;
|
|
2593
|
+
this._dataFormat.endingChangePercent = null;
|
|
2541
2594
|
this._dataFormat.cashTotal = null;
|
|
2542
2595
|
this._dataFormat.portfolioType = null;
|
|
2543
2596
|
|
|
@@ -2773,8 +2826,6 @@ module.exports = (() => {
|
|
|
2773
2826
|
return;
|
|
2774
2827
|
}
|
|
2775
2828
|
|
|
2776
|
-
const descriptionSelector = this._definition.descriptionSelector;
|
|
2777
|
-
|
|
2778
2829
|
this._description = PositionLevelDefinition.getDescriptionForPortfolioGroup(portfolio);
|
|
2779
2830
|
|
|
2780
2831
|
this._dataActual.description = this._description;
|
|
@@ -3019,7 +3070,7 @@ module.exports = (() => {
|
|
|
3019
3070
|
const translate = (item, value) => {
|
|
3020
3071
|
let translated;
|
|
3021
3072
|
|
|
3022
|
-
if (item.currency !== currency) {
|
|
3073
|
+
if (item.currency !== currency && !value.getIsZero()) {
|
|
3023
3074
|
translated = Rate.convert(value, item.currency, currency, ...rates);
|
|
3024
3075
|
} else {
|
|
3025
3076
|
translated = value;
|
|
@@ -3036,6 +3087,8 @@ module.exports = (() => {
|
|
|
3036
3087
|
updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
|
|
3037
3088
|
updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
|
|
3038
3089
|
updates.summaryTotalPrevious2 = updates.summaryTotalPrevious2.add(translate(item, item.data.summaryTotalPrevious2));
|
|
3090
|
+
updates.endingPrevious = updates.endingPrevious.add(translate(item, item.data.endingPrevious));
|
|
3091
|
+
updates.endingPrevious2 = updates.endingPrevious2.add(translate(item, item.data.endingPrevious2));
|
|
3039
3092
|
|
|
3040
3093
|
if (item.position.instrument.type === InstrumentType.CASH) {
|
|
3041
3094
|
updates.cashTotal = updates.cashTotal.add(translate(item, item.data.market));
|
|
@@ -3050,6 +3103,8 @@ module.exports = (() => {
|
|
|
3050
3103
|
summaryTotalCurrent: Decimal.ZERO,
|
|
3051
3104
|
summaryTotalPrevious: Decimal.ZERO,
|
|
3052
3105
|
summaryTotalPrevious2: Decimal.ZERO,
|
|
3106
|
+
endingPrevious: Decimal.ZERO,
|
|
3107
|
+
endingPrevious2: Decimal.ZERO,
|
|
3053
3108
|
cashTotal: Decimal.ZERO
|
|
3054
3109
|
});
|
|
3055
3110
|
|
|
@@ -3060,6 +3115,8 @@ module.exports = (() => {
|
|
|
3060
3115
|
actual.summaryTotalCurrent = updates.summaryTotalCurrent;
|
|
3061
3116
|
actual.summaryTotalPrevious = updates.summaryTotalPrevious;
|
|
3062
3117
|
actual.summaryTotalPrevious2 = updates.summaryTotalPrevious2;
|
|
3118
|
+
actual.endingPrevious = updates.endingPrevious;
|
|
3119
|
+
actual.endingPrevious2 = updates.endingPrevious2;
|
|
3063
3120
|
actual.cashTotal = updates.cashTotal;
|
|
3064
3121
|
|
|
3065
3122
|
format.basis = formatCurrency(actual.basis, currency);
|
|
@@ -3071,6 +3128,8 @@ module.exports = (() => {
|
|
|
3071
3128
|
format.summaryTotalPreviousNegative = updates.summaryTotalPrevious.getIsNegative();
|
|
3072
3129
|
format.summaryTotalPrevious2 = formatCurrency(updates.summaryTotalPrevious2, currency);
|
|
3073
3130
|
format.summaryTotalPrevious2Negative = updates.summaryTotalPrevious2.getIsNegative();
|
|
3131
|
+
format.endingPrevious = formatCurrency(updates.endingPrevious, currency);
|
|
3132
|
+
format.endingPrevious2 = formatCurrency(updates.endingPrevious2, currency);
|
|
3074
3133
|
format.cashTotal = formatCurrency(updates.cashTotal, currency);
|
|
3075
3134
|
|
|
3076
3135
|
calculateUnrealizedPercent(group);
|
|
@@ -3120,7 +3179,7 @@ module.exports = (() => {
|
|
|
3120
3179
|
const translate = (item, value) => {
|
|
3121
3180
|
let translated;
|
|
3122
3181
|
|
|
3123
|
-
if (item.currency !== currency) {
|
|
3182
|
+
if (item.currency !== currency && !value.getIsZero()) {
|
|
3124
3183
|
translated = Rate.convert(value, item.currency, currency, ...rates);
|
|
3125
3184
|
} else {
|
|
3126
3185
|
translated = value;
|
|
@@ -3167,7 +3226,25 @@ module.exports = (() => {
|
|
|
3167
3226
|
actual.unrealizedToday = updates.unrealizedToday;
|
|
3168
3227
|
actual.summaryTotalCurrent = updates.summaryTotalCurrent;
|
|
3169
3228
|
actual.total = updates.unrealized.add(actual.realized).add(actual.income);
|
|
3170
|
-
|
|
3229
|
+
|
|
3230
|
+
let endingChange = updates.market.subtract(actual.endingPrevious);
|
|
3231
|
+
let endingChangePercent;
|
|
3232
|
+
|
|
3233
|
+
if (actual.endingPrevious.getIsZero()) {
|
|
3234
|
+
if (endingChange.getIsPositive()) {
|
|
3235
|
+
endingChangePercent = Decimal.ONE;
|
|
3236
|
+
} else if (endingChange.getIsNegative()) {
|
|
3237
|
+
endingChangePercent = Decimal.NEGATIVE_ONE;
|
|
3238
|
+
} else {
|
|
3239
|
+
endingChangePercent = Decimal.ZERO;
|
|
3240
|
+
}
|
|
3241
|
+
} else {
|
|
3242
|
+
endingChangePercent = endingChange.divide(actual.endingPrevious);
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
actual.endingChange = endingChange;
|
|
3246
|
+
actual.endingChangePercent = endingChangePercent;
|
|
3247
|
+
|
|
3171
3248
|
format.market = formatCurrency(actual.market, currency);
|
|
3172
3249
|
|
|
3173
3250
|
if (updates.marketDirection.up || updates.marketDirection.down) {
|
|
@@ -3187,6 +3264,9 @@ module.exports = (() => {
|
|
|
3187
3264
|
format.total = formatCurrency(actual.total, currency);
|
|
3188
3265
|
format.totalNegative = actual.total.getIsNegative();
|
|
3189
3266
|
|
|
3267
|
+
format.endingChange = formatCurrency(actual.endingChange, currency);
|
|
3268
|
+
format.endingChangePercent = formatPercent(actual.endingChangePercent, 2);
|
|
3269
|
+
|
|
3190
3270
|
calculateUnrealizedPercent(group);
|
|
3191
3271
|
}
|
|
3192
3272
|
|
|
@@ -3319,6 +3399,9 @@ module.exports = (() => {
|
|
|
3319
3399
|
this._data.summaryTotalPrevious = null;
|
|
3320
3400
|
this._data.summaryTotalPrevious2 = null;
|
|
3321
3401
|
|
|
3402
|
+
this._data.endingPrevious = null;
|
|
3403
|
+
this._data.endingPrevious2 = null;
|
|
3404
|
+
|
|
3322
3405
|
this._data.realized = null;
|
|
3323
3406
|
this._data.income = null;
|
|
3324
3407
|
this._data.basisPrice = null;
|
|
@@ -3634,9 +3717,16 @@ module.exports = (() => {
|
|
|
3634
3717
|
|
|
3635
3718
|
data.income = snapshot.income;
|
|
3636
3719
|
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3720
|
+
const previousSummary1 = getPreviousSummary(previousSummaries, 1);
|
|
3721
|
+
const previousSummary2 = getPreviousSummary(previousSummaries, 2);
|
|
3722
|
+
const previousSummary3 = getPreviousSummary(previousSummaries, 3);
|
|
3723
|
+
|
|
3724
|
+
data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary, previousSummary1);
|
|
3725
|
+
data.summaryTotalPrevious = calculateSummaryTotal(previousSummary1, previousSummary2);
|
|
3726
|
+
data.summaryTotalPrevious2 = calculateSummaryTotal(previousSummary2, previousSummary3);
|
|
3727
|
+
|
|
3728
|
+
data.endingPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.value;
|
|
3729
|
+
data.endingPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
|
|
3640
3730
|
|
|
3641
3731
|
if (snapshot.open.getIsZero()) {
|
|
3642
3732
|
data.basisPrice = Decimal.ZERO;
|
|
@@ -17564,6 +17654,38 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
17564
17654
|
});
|
|
17565
17655
|
});
|
|
17566
17656
|
});
|
|
17657
|
+
|
|
17658
|
+
describe('and prior ranges are calculated', () => {
|
|
17659
|
+
describe('for YEARLY ranges', () => {
|
|
17660
|
+
describe('from 2017-10-10, including one previous ranges', () => {
|
|
17661
|
+
let ranges;
|
|
17662
|
+
|
|
17663
|
+
beforeEach(() => {
|
|
17664
|
+
ranges = PositionSummaryFrame.YEARLY.getPriorRanges(new Day(2015, 4, 20), 1);
|
|
17665
|
+
});
|
|
17666
|
+
|
|
17667
|
+
it('should return two ranges', () => {
|
|
17668
|
+
expect(ranges.length).toEqual(2);
|
|
17669
|
+
});
|
|
17670
|
+
|
|
17671
|
+
it('the first range should begin on 2013-12-31', () => {
|
|
17672
|
+
expect(ranges[0].start.getIsEqual(new Day(2013, 12, 31))).toEqual(true);
|
|
17673
|
+
});
|
|
17674
|
+
|
|
17675
|
+
it('the first range should end on 2014-12-31', () => {
|
|
17676
|
+
expect(ranges[0].end.getIsEqual(new Day(2014, 12, 31))).toEqual(true);
|
|
17677
|
+
});
|
|
17678
|
+
|
|
17679
|
+
it('the second range should begin on 2014-12-31', () => {
|
|
17680
|
+
expect(ranges[1].start.getIsEqual(new Day(2014, 12, 31))).toEqual(true);
|
|
17681
|
+
});
|
|
17682
|
+
|
|
17683
|
+
it('the second range should end on 2015-12-31', () => {
|
|
17684
|
+
expect(ranges[1].end.getIsEqual(new Day(2015, 12, 31))).toEqual(true);
|
|
17685
|
+
});
|
|
17686
|
+
});
|
|
17687
|
+
});
|
|
17688
|
+
});
|
|
17567
17689
|
});
|
|
17568
17690
|
|
|
17569
17691
|
},{"./../../../lib/data/PositionSummaryFrame":3,"./../../../lib/data/TransactionType":4,"@barchart/common-js/lang/Day":21,"@barchart/common-js/lang/Decimal":22}],53:[function(require,module,exports){
|
|
@@ -422,4 +422,36 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
422
422
|
});
|
|
423
423
|
});
|
|
424
424
|
});
|
|
425
|
+
|
|
426
|
+
describe('and prior ranges are calculated', () => {
|
|
427
|
+
describe('for YEARLY ranges', () => {
|
|
428
|
+
describe('from 2017-10-10, including one previous ranges', () => {
|
|
429
|
+
let ranges;
|
|
430
|
+
|
|
431
|
+
beforeEach(() => {
|
|
432
|
+
ranges = PositionSummaryFrame.YEARLY.getPriorRanges(new Day(2015, 4, 20), 1);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it('should return two ranges', () => {
|
|
436
|
+
expect(ranges.length).toEqual(2);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('the first range should begin on 2013-12-31', () => {
|
|
440
|
+
expect(ranges[0].start.getIsEqual(new Day(2013, 12, 31))).toEqual(true);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('the first range should end on 2014-12-31', () => {
|
|
444
|
+
expect(ranges[0].end.getIsEqual(new Day(2014, 12, 31))).toEqual(true);
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it('the second range should begin on 2014-12-31', () => {
|
|
448
|
+
expect(ranges[1].start.getIsEqual(new Day(2014, 12, 31))).toEqual(true);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('the second range should end on 2015-12-31', () => {
|
|
452
|
+
expect(ranges[1].end.getIsEqual(new Day(2015, 12, 31))).toEqual(true);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
});
|
|
425
457
|
});
|