@barchart/portfolio-api-common 1.2.88 → 1.2.92

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.
@@ -86,6 +86,19 @@ 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
+ const transaction = { date: date, snapshot: { open: Decimal.ONE } };
98
+
99
+ return this.getRanges([ transaction ]);
100
+ }
101
+
89
102
  /**
90
103
  * Returns the start date for a frame, a given number of periods ago.
91
104
  *
@@ -158,6 +171,16 @@ module.exports = (() => {
158
171
  * @property {Day} end
159
172
  */
160
173
 
174
+ /**
175
+ * The start and and date for a {@link PositionSummaryFrame} along with the frame type.
176
+ *
177
+ * @typedef PositionSummaryDefinition
178
+ * @type {Object}
179
+ * @property {Day} start
180
+ * @property {Day} end
181
+ * @property {PositionSummaryFrame} frame
182
+ */
183
+
161
184
  function getRange(start, end) {
162
185
  return {
163
186
  start: start,
@@ -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) {
@@ -284,12 +284,12 @@ module.exports = (() => {
284
284
 
285
285
  const existingBarchartSymbols = this.getPositionSymbols(false);
286
286
 
287
- let similiarPositionItem;
287
+ let similarPositionItem;
288
288
 
289
- if (is.object(position.instrument.symbol) && is.string(position.instrument.symbol.barchart)) {
290
- similiarPositionItem = this._items.find(item => is.object(item.position.instrument.symbol) && item.position.instrument.symbol.barchart === position.instrument.symbol.barchart) || null;
289
+ if (extractSymbolForBarchart(position)) {
290
+ similarPositionItem = this._items.find(item => extractSymbolForBarchart(item.position) === extractSymbolForBarchart(position)) || null;
291
291
  } else {
292
- similiarPositionItem = null;
292
+ similarPositionItem = null;
293
293
  }
294
294
 
295
295
  removePositionItem.call(this, this._items.find(item => item.position.position === position.position));
@@ -339,13 +339,13 @@ module.exports = (() => {
339
339
  this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
340
340
  }
341
341
 
342
- if (similiarPositionItem !== null) {
343
- if (similiarPositionItem.previousQuote) {
344
- item.setQuote(similiarPositionItem.previousQuote);
342
+ if (similarPositionItem !== null) {
343
+ if (similarPositionItem.previousQuote) {
344
+ item.setQuote(similarPositionItem.previousQuote);
345
345
  }
346
346
 
347
- if (similiarPositionItem.quote) {
348
- item.setQuote(similiarPositionItem.quote);
347
+ if (similarPositionItem.quote) {
348
+ item.setQuote(similarPositionItem.quote);
349
349
  }
350
350
  }
351
351
 
@@ -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
- data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary, getPreviousSummary(previousSummaries, 1));
384
- data.summaryTotalPrevious = calculateSummaryTotal(getPreviousSummary(previousSummaries, 1), getPreviousSummary(previousSummaries, 2));
385
- data.summaryTotalPrevious2 = calculateSummaryTotal(getPreviousSummary(previousSummaries, 2), getPreviousSummary(previousSummaries, 3));
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 Currency = require('@barchart/common-js/lang/Currency'),
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.88",
3
+ "version": "1.2.92",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -477,6 +477,19 @@ 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
+ const transaction = { date: date, snapshot: { open: Decimal.ONE } };
489
+
490
+ return this.getRanges([ transaction ]);
491
+ }
492
+
480
493
  /**
481
494
  * Returns the start date for a frame, a given number of periods ago.
482
495
  *
@@ -549,6 +562,16 @@ module.exports = (() => {
549
562
  * @property {Day} end
550
563
  */
551
564
 
565
+ /**
566
+ * The start and and date for a {@link PositionSummaryFrame} along with the frame type.
567
+ *
568
+ * @typedef PositionSummaryDefinition
569
+ * @type {Object}
570
+ * @property {Day} start
571
+ * @property {Day} end
572
+ * @property {PositionSummaryFrame} frame
573
+ */
574
+
552
575
  function getRange(start, end) {
553
576
  return {
554
577
  start: start,
@@ -1421,7 +1444,7 @@ module.exports = (() => {
1421
1444
  * @param {Array.<Object>} portfolios - The portfolios.
1422
1445
  * @param {Array.<Object>} positions - The positions (for all of the portfolios).
1423
1446
  * @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.
1447
+ * @param {PositionSummaryFrame=} - If specified, locks the current (and previous) periods to a specific frame, use for reporting.
1425
1448
  */
1426
1449
  class PositionContainer {
1427
1450
  constructor(definitions, portfolios, positions, summaries, frame) {
@@ -1663,12 +1686,12 @@ module.exports = (() => {
1663
1686
 
1664
1687
  const existingBarchartSymbols = this.getPositionSymbols(false);
1665
1688
 
1666
- let similiarPositionItem;
1689
+ let similarPositionItem;
1667
1690
 
1668
- if (is.object(position.instrument.symbol) && is.string(position.instrument.symbol.barchart)) {
1669
- similiarPositionItem = this._items.find(item => is.object(item.position.instrument.symbol) && item.position.instrument.symbol.barchart === position.instrument.symbol.barchart) || null;
1691
+ if (extractSymbolForBarchart(position)) {
1692
+ similarPositionItem = this._items.find(item => extractSymbolForBarchart(item.position) === extractSymbolForBarchart(position)) || null;
1670
1693
  } else {
1671
- similiarPositionItem = null;
1694
+ similarPositionItem = null;
1672
1695
  }
1673
1696
 
1674
1697
  removePositionItem.call(this, this._items.find(item => item.position.position === position.position));
@@ -1718,13 +1741,13 @@ module.exports = (() => {
1718
1741
  this._positionSymbolAddedEvent.fire(addedBarchartSymbol);
1719
1742
  }
1720
1743
 
1721
- if (similiarPositionItem !== null) {
1722
- if (similiarPositionItem.previousQuote) {
1723
- item.setQuote(similiarPositionItem.previousQuote);
1744
+ if (similarPositionItem !== null) {
1745
+ if (similarPositionItem.previousQuote) {
1746
+ item.setQuote(similarPositionItem.previousQuote);
1724
1747
  }
1725
1748
 
1726
- if (similiarPositionItem.quote) {
1727
- item.setQuote(similiarPositionItem.quote);
1749
+ if (similarPositionItem.quote) {
1750
+ item.setQuote(similarPositionItem.quote);
1728
1751
  }
1729
1752
  }
1730
1753
 
@@ -2515,6 +2538,10 @@ module.exports = (() => {
2515
2538
  this._dataActual.summaryTotalCurrent = null;
2516
2539
  this._dataActual.summaryTotalPrevious = null;
2517
2540
  this._dataActual.summaryTotalPrevious2 = null;
2541
+ this._dataActual.endingPrevious = null;
2542
+ this._dataActual.endingPrevious2 = null;
2543
+ this._dataActual.endingChange = null;
2544
+ this._dataActual.endingChangePercent = null;
2518
2545
  this._dataActual.cashTotal = null;
2519
2546
 
2520
2547
  this._dataFormat.currentPrice = null;
@@ -2538,6 +2565,10 @@ module.exports = (() => {
2538
2565
  this._dataFormat.summaryTotalPreviousNegative = false;
2539
2566
  this._dataFormat.summaryTotalPrevious2 = null;
2540
2567
  this._dataFormat.summaryTotalPrevious2Negative = false;
2568
+ this._dataFormat.endingPrevious = null;
2569
+ this._dataFormat.endingPrevious2 = null;
2570
+ this._dataFormat.endingChange = null;
2571
+ this._dataFormat.endingChangePercent = null;
2541
2572
  this._dataFormat.cashTotal = null;
2542
2573
  this._dataFormat.portfolioType = null;
2543
2574
 
@@ -2773,8 +2804,6 @@ module.exports = (() => {
2773
2804
  return;
2774
2805
  }
2775
2806
 
2776
- const descriptionSelector = this._definition.descriptionSelector;
2777
-
2778
2807
  this._description = PositionLevelDefinition.getDescriptionForPortfolioGroup(portfolio);
2779
2808
 
2780
2809
  this._dataActual.description = this._description;
@@ -3019,7 +3048,7 @@ module.exports = (() => {
3019
3048
  const translate = (item, value) => {
3020
3049
  let translated;
3021
3050
 
3022
- if (item.currency !== currency) {
3051
+ if (item.currency !== currency && !value.getIsZero()) {
3023
3052
  translated = Rate.convert(value, item.currency, currency, ...rates);
3024
3053
  } else {
3025
3054
  translated = value;
@@ -3036,6 +3065,8 @@ module.exports = (() => {
3036
3065
  updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
3037
3066
  updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
3038
3067
  updates.summaryTotalPrevious2 = updates.summaryTotalPrevious2.add(translate(item, item.data.summaryTotalPrevious2));
3068
+ updates.endingPrevious = updates.endingPrevious.add(translate(item, item.data.endingPrevious));
3069
+ updates.endingPrevious2 = updates.endingPrevious2.add(translate(item, item.data.endingPrevious2));
3039
3070
 
3040
3071
  if (item.position.instrument.type === InstrumentType.CASH) {
3041
3072
  updates.cashTotal = updates.cashTotal.add(translate(item, item.data.market));
@@ -3050,6 +3081,8 @@ module.exports = (() => {
3050
3081
  summaryTotalCurrent: Decimal.ZERO,
3051
3082
  summaryTotalPrevious: Decimal.ZERO,
3052
3083
  summaryTotalPrevious2: Decimal.ZERO,
3084
+ endingPrevious: Decimal.ZERO,
3085
+ endingPrevious2: Decimal.ZERO,
3053
3086
  cashTotal: Decimal.ZERO
3054
3087
  });
3055
3088
 
@@ -3060,6 +3093,8 @@ module.exports = (() => {
3060
3093
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
3061
3094
  actual.summaryTotalPrevious = updates.summaryTotalPrevious;
3062
3095
  actual.summaryTotalPrevious2 = updates.summaryTotalPrevious2;
3096
+ actual.endingPrevious = updates.endingPrevious;
3097
+ actual.endingPrevious2 = updates.endingPrevious2;
3063
3098
  actual.cashTotal = updates.cashTotal;
3064
3099
 
3065
3100
  format.basis = formatCurrency(actual.basis, currency);
@@ -3071,6 +3106,8 @@ module.exports = (() => {
3071
3106
  format.summaryTotalPreviousNegative = updates.summaryTotalPrevious.getIsNegative();
3072
3107
  format.summaryTotalPrevious2 = formatCurrency(updates.summaryTotalPrevious2, currency);
3073
3108
  format.summaryTotalPrevious2Negative = updates.summaryTotalPrevious2.getIsNegative();
3109
+ format.endingPrevious = formatCurrency(updates.endingPrevious, currency);
3110
+ format.endingPrevious2 = formatCurrency(updates.endingPrevious2, currency);
3074
3111
  format.cashTotal = formatCurrency(updates.cashTotal, currency);
3075
3112
 
3076
3113
  calculateUnrealizedPercent(group);
@@ -3120,7 +3157,7 @@ module.exports = (() => {
3120
3157
  const translate = (item, value) => {
3121
3158
  let translated;
3122
3159
 
3123
- if (item.currency !== currency) {
3160
+ if (item.currency !== currency && !value.getIsZero()) {
3124
3161
  translated = Rate.convert(value, item.currency, currency, ...rates);
3125
3162
  } else {
3126
3163
  translated = value;
@@ -3167,7 +3204,25 @@ module.exports = (() => {
3167
3204
  actual.unrealizedToday = updates.unrealizedToday;
3168
3205
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
3169
3206
  actual.total = updates.unrealized.add(actual.realized).add(actual.income);
3170
-
3207
+
3208
+ let endingChange = updates.market.subtract(actual.endingPrevious);
3209
+ let endingChangePercent;
3210
+
3211
+ if (actual.endingPrevious.getIsZero()) {
3212
+ if (endingChange.getIsPositive()) {
3213
+ endingChangePercent = Decimal.ONE;
3214
+ } else if (endingChange.getIsNegative()) {
3215
+ endingChangePercent = Decimal.NEGATIVE_ONE;
3216
+ } else {
3217
+ endingChangePercent = Decimal.ZERO;
3218
+ }
3219
+ } else {
3220
+ endingChangePercent = endingChange.divide(actual.endingPrevious);
3221
+ }
3222
+
3223
+ actual.endingChange = endingChange;
3224
+ actual.endingChangePercent = endingChangePercent;
3225
+
3171
3226
  format.market = formatCurrency(actual.market, currency);
3172
3227
 
3173
3228
  if (updates.marketDirection.up || updates.marketDirection.down) {
@@ -3187,6 +3242,9 @@ module.exports = (() => {
3187
3242
  format.total = formatCurrency(actual.total, currency);
3188
3243
  format.totalNegative = actual.total.getIsNegative();
3189
3244
 
3245
+ format.endingChange = formatCurrency(actual.endingChange, currency);
3246
+ format.endingChangePercent = formatPercent(actual.endingChangePercent, 2);
3247
+
3190
3248
  calculateUnrealizedPercent(group);
3191
3249
  }
3192
3250
 
@@ -3319,6 +3377,9 @@ module.exports = (() => {
3319
3377
  this._data.summaryTotalPrevious = null;
3320
3378
  this._data.summaryTotalPrevious2 = null;
3321
3379
 
3380
+ this._data.endingPrevious = null;
3381
+ this._data.endingPrevious2 = null;
3382
+
3322
3383
  this._data.realized = null;
3323
3384
  this._data.income = null;
3324
3385
  this._data.basisPrice = null;
@@ -3634,9 +3695,16 @@ module.exports = (() => {
3634
3695
 
3635
3696
  data.income = snapshot.income;
3636
3697
 
3637
- data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary, getPreviousSummary(previousSummaries, 1));
3638
- data.summaryTotalPrevious = calculateSummaryTotal(getPreviousSummary(previousSummaries, 1), getPreviousSummary(previousSummaries, 2));
3639
- data.summaryTotalPrevious2 = calculateSummaryTotal(getPreviousSummary(previousSummaries, 2), getPreviousSummary(previousSummaries, 3));
3698
+ const previousSummary1 = getPreviousSummary(previousSummaries, 1);
3699
+ const previousSummary2 = getPreviousSummary(previousSummaries, 2);
3700
+ const previousSummary3 = getPreviousSummary(previousSummaries, 3);
3701
+
3702
+ data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary, previousSummary1);
3703
+ data.summaryTotalPrevious = calculateSummaryTotal(previousSummary1, previousSummary2);
3704
+ data.summaryTotalPrevious2 = calculateSummaryTotal(previousSummary2, previousSummary3);
3705
+
3706
+ data.endingPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.value;
3707
+ data.endingPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
3640
3708
 
3641
3709
  if (snapshot.open.getIsZero()) {
3642
3710
  data.basisPrice = Decimal.ZERO;