@barchart/portfolio-api-common 1.2.110 → 1.2.114

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.
@@ -241,7 +241,32 @@ module.exports = (() => {
241
241
  }
242
242
 
243
243
  function getMonthlyRanges(transactions) {
244
- return [ ];
244
+ const ranges = [ ];
245
+
246
+ if (!transactions.length) {
247
+ return ranges;
248
+ }
249
+
250
+ const first = array.first(transactions);
251
+ const last = array.last(transactions);
252
+
253
+ const firstDate = first.date;
254
+ let lastDate;
255
+
256
+ lastDate = last.snapshot.open.getIsZero()
257
+ ? new Day(last.date.year, last.date.month, last.date.day).addMonths(1)
258
+ : Day.getToday();
259
+ lastDate = lastDate.getEndOfMonth();
260
+
261
+ for (
262
+ let end = firstDate.getEndOfMonth();
263
+ end.format() <= lastDate.format();
264
+ end = end.addMonths(1).getEndOfMonth()
265
+ ) {
266
+ ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
267
+ }
268
+
269
+ return ranges;
245
270
  }
246
271
 
247
272
  function getYearToDateRanges(transactions) {
@@ -278,7 +303,11 @@ module.exports = (() => {
278
303
  }
279
304
 
280
305
  function getMonthlyStartDate(periods, date) {
281
- return null;
306
+ const today = date || Day.getToday();
307
+
308
+ return today
309
+ .subtractMonths(periods)
310
+ .subtractDays(today.day);
282
311
  }
283
312
 
284
313
  function getYearToDateStartDate(periods, date) {
@@ -169,7 +169,17 @@ module.exports = (() => {
169
169
  this._dataActual.periodPrice = null;
170
170
  this._dataActual.periodPricePrevious = null;
171
171
  this._dataActual.periodRealized = null;
172
+ this._dataActual.periodRealizedPrevious = null;
173
+ this._dataActual.periodRealizedPrevious2 = null;
174
+ this._dataActual.periodRealizedBasis = null;
175
+ this._dataActual.periodRealizedBasisPrevious = null;
176
+ this._dataActual.periodRealizedBasisPrevious2 = null;
172
177
  this._dataActual.periodUnrealized = null;
178
+ this._dataActual.periodUnrealizedPrevious = null;
179
+ this._dataActual.periodUnrealizedPrevious2 = null;
180
+ this._dataActual.periodUnrealizedBasis = null;
181
+ this._dataActual.periodUnrealizedBasisPrevious = null;
182
+ this._dataActual.periodUnrealizedBasisPrevious2 = null;
173
183
  this._dataActual.periodIncome = null;
174
184
 
175
185
  this._dataFormat.periodPrice = null;
@@ -178,6 +188,14 @@ module.exports = (() => {
178
188
  this._dataFormat.periodUnrealized = null;
179
189
  this._dataFormat.periodIncome = null;
180
190
 
191
+ this._dataActual.periodPercent = null;
192
+ this._dataActual.periodPreviousPercent = null;
193
+ this._dataActual.periodPrevious2Percent = null;
194
+
195
+ this._dataFormat.periodPercent = null;
196
+ this._dataFormat.periodPreviousPercent = null;
197
+ this._dataFormat.periodPrevious2Percent = null;
198
+
181
199
  this._items.forEach((item) => {
182
200
  bindItem.call(this, item);
183
201
  });
@@ -731,7 +749,9 @@ module.exports = (() => {
731
749
 
732
750
  calculateUnrealizedPercent(group);
733
751
 
734
- if (group.single && group._items.length === 1) {
752
+ const groupItems = group._items;
753
+
754
+ if (group.single && groupItems.length === 1) {
735
755
  const item = group._items[0];
736
756
 
737
757
  actual.quantity = item.data.quantity;
@@ -750,12 +770,34 @@ module.exports = (() => {
750
770
  format.periodPrice = formatCurrency(actual.periodPrice, currency);
751
771
  format.periodPricePrevious = formatCurrency(actual.periodPricePrevious, currency);
752
772
 
773
+ actual.periodRealized = item.data.periodRealized;
774
+ actual.periodRealizedPrevious = item.data.periodRealizedPrevious;
775
+ actual.periodRealizedPrevious2 = item.data.periodRealizedPrevious2;
776
+
777
+ actual.periodRealizedBasis = item.data.periodRealizedBasis;
778
+ actual.periodRealizedBasisPrevious = item.data.periodRealizedBasisPrevious;
779
+ actual.periodRealizedBasisPrevious2 = item.data.periodRealizedBasisPrevious2;
780
+
781
+ actual.periodUnrealized = item.data.periodUnrealized;
782
+ actual.periodUnrealizedPrevious = item.data.periodUnrealizedPrevious;
783
+ actual.periodUnrealizedPrevious2 = item.data.periodUnrealizedPrevious2;
784
+
785
+ actual.periodUnrealizedBasis = item.data.periodUnrealizedBasis;
786
+ actual.periodUnrealizedBasisPrevious = item.data.periodUnrealizedBasisPrevious;
787
+ actual.periodUnrealizedBasisPrevious2 = item.data.periodUnrealizedBasisPrevious2;
788
+
789
+ actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
790
+ actual.periodPercentPrevious = calculatePeriodPercent(actual.periodRealizedPrevious, actual.periodRealizedBasisPrevious, actual.periodUnrealizedPrevious, actual.periodUnrealizedBasisPrevious);
791
+ actual.periodPercentPrevious2 = calculatePeriodPercent(actual.periodRealizedPrevious2, actual.periodRealizedBasisPrevious2, actual.periodUnrealizedPrevious2, actual.periodUnrealizedBasisPrevious2);
792
+
793
+ format.periodPercent = formatPercent(actual.periodPercent, 2);
794
+ format.periodPercentPrevious = formatPercent(actual.periodPercentPrevious, 2);
795
+ format.periodPercentPrevious2 = formatPercent(actual.periodPercentPrevious2, 2);
796
+
753
797
  format.invalid = definition.type === PositionLevelType.POSITION && item.invalid;
754
798
  format.locked = definition.type === PositionLevelType.POSITION && item.data.locked;
755
799
  }
756
800
 
757
- const groupItems = group._items;
758
-
759
801
  let portfolioType = null;
760
802
 
761
803
  if (groupItems.length > 0) {
@@ -875,6 +917,13 @@ module.exports = (() => {
875
917
  format.marketChangePercent = formatPercent(actual.marketChangePercent, 2);
876
918
 
877
919
  calculateUnrealizedPercent(group);
920
+
921
+ if (group.single && item) {
922
+ actual.periodUnrealized = item.data.periodUnrealized;
923
+
924
+ actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
925
+ format.periodPercent = formatPercent(actual.periodPercent, 2);
926
+ }
878
927
  }
879
928
 
880
929
  function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
@@ -933,6 +982,13 @@ module.exports = (() => {
933
982
  }
934
983
  }
935
984
 
985
+ function calculatePeriodPercent(realized, realizedBasis, unrealized, unrealizedBasis) {
986
+ const numerator = realized.add(unrealized);
987
+ const denominator = realizedBasis.add(unrealizedBasis);
988
+
989
+ return denominator.getIsZero() ? Decimal.ZERO : numerator.divide(denominator);
990
+ }
991
+
936
992
  const unchanged = { up: false, down: false };
937
993
 
938
994
  return PositionGroup;
@@ -79,7 +79,21 @@ module.exports = (() => {
79
79
  this._data.basisPrice = null;
80
80
 
81
81
  this._data.periodRealized = null;
82
+ this._data.periodRealizedPrevious = null;
83
+ this._data.periodRealizedPrevious2 = null;
84
+
85
+ this._data.periodRealizedBasis = null;
86
+ this._data.periodRealizedBasisPrevious = null;
87
+ this._data.periodRealizedBasisPrevious2 = null;
88
+
82
89
  this._data.periodUnrealized = null;
90
+ this._data.periodUnrealizedPrevious = null;
91
+ this._data.periodUnrealizedPrevious2 = null;
92
+
93
+ this._data.periodUnrealizedBasis = null;
94
+ this._data.periodUnrealizedBasisPrevious = null;
95
+ this._data.periodUnrealizedBasisPrevious2 = null;
96
+
83
97
  this._data.periodIncome = null;
84
98
 
85
99
  this._data.periodPrice = null;
@@ -89,15 +103,15 @@ module.exports = (() => {
89
103
  this._data.fundamental = { };
90
104
  this._data.locked = getIsLocked(position);
91
105
 
92
- calculateStaticData(this);
93
- calculatePriceData(this, null);
94
-
95
106
  this._quoteChangedEvent = new Event(this);
96
107
  this._newsExistsChangedEvent = new Event(this);
97
108
  this._fundamentalDataChangedEvent = new Event(this);
98
109
  this._lockChangedEvent = new Event(this);
99
110
  this._portfolioChangedEvent = new Event(this);
100
111
  this._positionItemDisposeEvent = new Event(this);
112
+
113
+ calculateStaticData(this);
114
+ calculatePriceData(this, null);
101
115
  }
102
116
 
103
117
  /**
@@ -411,9 +425,23 @@ module.exports = (() => {
411
425
  data.marketPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
412
426
  data.quantityPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.open;
413
427
 
414
- data.periodRealized = calculateRealizedPeriod(item.currentSummary, previousSummary1);
415
- data.periodUnrealized = calculateUnrealizedPeriod(item.currentSummary, previousSummary1);
416
- data.periodIncome = calculateIncomePeriod(item.currentSummary, previousSummary1);
428
+ data.periodRealized = calculatePeriodRealized(item.currentSummary, previousSummary1);
429
+ data.periodRealizedPrevious = calculatePeriodRealized(previousSummary1, previousSummary2);
430
+ data.periodRealizedPrevious2 = calculatePeriodRealized(previousSummary2, previousSummary3);
431
+
432
+ data.periodRealizedBasis = calculatePeriodRealizedBasis(item.currentSummary, previousSummary1);
433
+ data.periodRealizedBasisPrevious = calculatePeriodRealizedBasis(previousSummary1, previousSummary2);
434
+ data.periodRealizedBasisPrevious2 = calculatePeriodRealizedBasis(previousSummary2, previousSummary3);
435
+
436
+ data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary1);
437
+ data.periodUnrealizedPrevious = calculatePeriodUnrealized(previousSummary1, previousSummary2);
438
+ data.periodUnrealizedPrevious2 = calculatePeriodUnrealized(previousSummary2, previousSummary3);
439
+
440
+ data.periodUnrealizedBasis = calculatePeriodUnrealizedBasis(item.currentSummary, previousSummary1);
441
+ data.periodUnrealizedBasisPrevious = calculatePeriodUnrealizedBasis(previousSummary1, previousSummary2);
442
+ data.periodUnrealizedBasisPrevious2 = calculatePeriodUnrealizedBasis(previousSummary2, previousSummary3);
443
+
444
+ data.periodIncome = calculatePeriodIncome(item.currentSummary, previousSummary1);
417
445
 
418
446
  if (snapshot.open.getIsZero()) {
419
447
  data.basisPrice = Decimal.ZERO;
@@ -540,11 +568,16 @@ module.exports = (() => {
540
568
 
541
569
  data.unrealized = unrealized;
542
570
  data.unrealizedChange = unrealizedChange;
571
+
572
+ data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary, data.unrealized);
573
+ data.periodUnrealizedChange = unrealizedChange;
543
574
  } else {
544
575
  data.summaryTotalCurrentChange = Decimal.ZERO;
545
576
 
546
577
  data.unrealized = Decimal.ZERO;
547
578
  data.unrealizedChange = Decimal.ZERO;
579
+
580
+ data.periodUnrealizedChange = Decimal.ZERO;
548
581
  }
549
582
  } else {
550
583
  data.summaryTotalCurrentChange = Decimal.ZERO;
@@ -568,7 +601,7 @@ module.exports = (() => {
568
601
  return returnRef;
569
602
  }
570
603
 
571
- function calculateRealizedPeriod(currentSummary, previousSummary) {
604
+ function calculatePeriodRealized(currentSummary, previousSummary) {
572
605
  let returnRef;
573
606
 
574
607
  if (currentSummary) {
@@ -582,13 +615,42 @@ module.exports = (() => {
582
615
  return returnRef;
583
616
  }
584
617
 
585
- function calculateUnrealizedPeriod(currentSummary, previousSummary) {
618
+ function calculatePeriodRealizedBasis(currentSummary, previousSummary) {
619
+ let returnRef;
620
+
621
+ if (currentSummary) {
622
+ const period = currentSummary.period;
623
+
624
+ returnRef = period.sells.subtract(calculatePeriodRealized(currentSummary, previousSummary));
625
+ } else {
626
+ returnRef = Decimal.ZERO;
627
+ }
628
+
629
+ return returnRef;
630
+ }
631
+
632
+ function calculatePeriodUnrealized(currentSummary, previousSummary, override) {
633
+ let returnRef;
634
+
635
+ if (currentSummary) {
636
+ const period = currentSummary.period;
637
+ const unrealized = override || period.unrealized;
638
+
639
+ returnRef = unrealized.subtract(previousSummary !== null ? previousSummary.period.unrealized : Decimal.ZERO);
640
+ } else {
641
+ returnRef = Decimal.ZERO;
642
+ }
643
+
644
+ return returnRef;
645
+ }
646
+
647
+ function calculatePeriodUnrealizedBasis(currentSummary, previousSummary) {
586
648
  let returnRef;
587
649
 
588
650
  if (currentSummary) {
589
651
  const period = currentSummary.period;
590
652
 
591
- returnRef = period.unrealized.subtract(previousSummary !== null ? previousSummary.period.unrealized : Decimal.ZERO);
653
+ returnRef = currentSummary.end.basis.absolute();
592
654
  } else {
593
655
  returnRef = Decimal.ZERO;
594
656
  }
@@ -596,7 +658,7 @@ module.exports = (() => {
596
658
  return returnRef;
597
659
  }
598
660
 
599
- function calculateIncomePeriod(currentSummary, previousSummary) {
661
+ function calculatePeriodIncome(currentSummary, previousSummary) {
600
662
  let returnRef;
601
663
 
602
664
  if (currentSummary) {
@@ -317,7 +317,8 @@ module.exports = (() => {
317
317
  .withField('sequence', DataType.NUMBER, true)
318
318
  .withField('type', DataType.forEnum(TransactionType, 'TransactionType'))
319
319
  .withField('date', DataType.DAY)
320
- .withField('value', DataType.DECIMAL)
320
+ .withField('rate', DataType.DECIMAL, true)
321
+ .withField('value', DataType.DECIMAL, true)
321
322
  .withField('force', DataType.BOOLEAN, true)
322
323
  .schema
323
324
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.110",
3
+ "version": "1.2.114",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -632,7 +632,32 @@ module.exports = (() => {
632
632
  }
633
633
 
634
634
  function getMonthlyRanges(transactions) {
635
- return [ ];
635
+ const ranges = [ ];
636
+
637
+ if (!transactions.length) {
638
+ return ranges;
639
+ }
640
+
641
+ const first = array.first(transactions);
642
+ const last = array.last(transactions);
643
+
644
+ const firstDate = first.date;
645
+ let lastDate;
646
+
647
+ lastDate = last.snapshot.open.getIsZero()
648
+ ? new Day(last.date.year, last.date.month, last.date.day).addMonths(1)
649
+ : Day.getToday();
650
+ lastDate = lastDate.getEndOfMonth();
651
+
652
+ for (
653
+ let end = firstDate.getEndOfMonth();
654
+ end.format() <= lastDate.format();
655
+ end = end.addMonths(1).getEndOfMonth()
656
+ ) {
657
+ ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
658
+ }
659
+
660
+ return ranges;
636
661
  }
637
662
 
638
663
  function getYearToDateRanges(transactions) {
@@ -669,7 +694,11 @@ module.exports = (() => {
669
694
  }
670
695
 
671
696
  function getMonthlyStartDate(periods, date) {
672
- return null;
697
+ const today = date || Day.getToday();
698
+
699
+ return today
700
+ .subtractMonths(periods)
701
+ .subtractDays(today.day);
673
702
  }
674
703
 
675
704
  function getYearToDateStartDate(periods, date) {
@@ -2629,7 +2658,17 @@ module.exports = (() => {
2629
2658
  this._dataActual.periodPrice = null;
2630
2659
  this._dataActual.periodPricePrevious = null;
2631
2660
  this._dataActual.periodRealized = null;
2661
+ this._dataActual.periodRealizedPrevious = null;
2662
+ this._dataActual.periodRealizedPrevious2 = null;
2663
+ this._dataActual.periodRealizedBasis = null;
2664
+ this._dataActual.periodRealizedBasisPrevious = null;
2665
+ this._dataActual.periodRealizedBasisPrevious2 = null;
2632
2666
  this._dataActual.periodUnrealized = null;
2667
+ this._dataActual.periodUnrealizedPrevious = null;
2668
+ this._dataActual.periodUnrealizedPrevious2 = null;
2669
+ this._dataActual.periodUnrealizedBasis = null;
2670
+ this._dataActual.periodUnrealizedBasisPrevious = null;
2671
+ this._dataActual.periodUnrealizedBasisPrevious2 = null;
2633
2672
  this._dataActual.periodIncome = null;
2634
2673
 
2635
2674
  this._dataFormat.periodPrice = null;
@@ -2638,6 +2677,14 @@ module.exports = (() => {
2638
2677
  this._dataFormat.periodUnrealized = null;
2639
2678
  this._dataFormat.periodIncome = null;
2640
2679
 
2680
+ this._dataActual.periodPercent = null;
2681
+ this._dataActual.periodPreviousPercent = null;
2682
+ this._dataActual.periodPrevious2Percent = null;
2683
+
2684
+ this._dataFormat.periodPercent = null;
2685
+ this._dataFormat.periodPreviousPercent = null;
2686
+ this._dataFormat.periodPrevious2Percent = null;
2687
+
2641
2688
  this._items.forEach((item) => {
2642
2689
  bindItem.call(this, item);
2643
2690
  });
@@ -3191,7 +3238,9 @@ module.exports = (() => {
3191
3238
 
3192
3239
  calculateUnrealizedPercent(group);
3193
3240
 
3194
- if (group.single && group._items.length === 1) {
3241
+ const groupItems = group._items;
3242
+
3243
+ if (group.single && groupItems.length === 1) {
3195
3244
  const item = group._items[0];
3196
3245
 
3197
3246
  actual.quantity = item.data.quantity;
@@ -3210,12 +3259,34 @@ module.exports = (() => {
3210
3259
  format.periodPrice = formatCurrency(actual.periodPrice, currency);
3211
3260
  format.periodPricePrevious = formatCurrency(actual.periodPricePrevious, currency);
3212
3261
 
3262
+ actual.periodRealized = item.data.periodRealized;
3263
+ actual.periodRealizedPrevious = item.data.periodRealizedPrevious;
3264
+ actual.periodRealizedPrevious2 = item.data.periodRealizedPrevious2;
3265
+
3266
+ actual.periodRealizedBasis = item.data.periodRealizedBasis;
3267
+ actual.periodRealizedBasisPrevious = item.data.periodRealizedBasisPrevious;
3268
+ actual.periodRealizedBasisPrevious2 = item.data.periodRealizedBasisPrevious2;
3269
+
3270
+ actual.periodUnrealized = item.data.periodUnrealized;
3271
+ actual.periodUnrealizedPrevious = item.data.periodUnrealizedPrevious;
3272
+ actual.periodUnrealizedPrevious2 = item.data.periodUnrealizedPrevious2;
3273
+
3274
+ actual.periodUnrealizedBasis = item.data.periodUnrealizedBasis;
3275
+ actual.periodUnrealizedBasisPrevious = item.data.periodUnrealizedBasisPrevious;
3276
+ actual.periodUnrealizedBasisPrevious2 = item.data.periodUnrealizedBasisPrevious2;
3277
+
3278
+ actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
3279
+ actual.periodPercentPrevious = calculatePeriodPercent(actual.periodRealizedPrevious, actual.periodRealizedBasisPrevious, actual.periodUnrealizedPrevious, actual.periodUnrealizedBasisPrevious);
3280
+ actual.periodPercentPrevious2 = calculatePeriodPercent(actual.periodRealizedPrevious2, actual.periodRealizedBasisPrevious2, actual.periodUnrealizedPrevious2, actual.periodUnrealizedBasisPrevious2);
3281
+
3282
+ format.periodPercent = formatPercent(actual.periodPercent, 2);
3283
+ format.periodPercentPrevious = formatPercent(actual.periodPercentPrevious, 2);
3284
+ format.periodPercentPrevious2 = formatPercent(actual.periodPercentPrevious2, 2);
3285
+
3213
3286
  format.invalid = definition.type === PositionLevelType.POSITION && item.invalid;
3214
3287
  format.locked = definition.type === PositionLevelType.POSITION && item.data.locked;
3215
3288
  }
3216
3289
 
3217
- const groupItems = group._items;
3218
-
3219
3290
  let portfolioType = null;
3220
3291
 
3221
3292
  if (groupItems.length > 0) {
@@ -3335,6 +3406,13 @@ module.exports = (() => {
3335
3406
  format.marketChangePercent = formatPercent(actual.marketChangePercent, 2);
3336
3407
 
3337
3408
  calculateUnrealizedPercent(group);
3409
+
3410
+ if (group.single && item) {
3411
+ actual.periodUnrealized = item.data.periodUnrealized;
3412
+
3413
+ actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
3414
+ format.periodPercent = formatPercent(actual.periodPercent, 2);
3415
+ }
3338
3416
  }
3339
3417
 
3340
3418
  function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
@@ -3393,6 +3471,13 @@ module.exports = (() => {
3393
3471
  }
3394
3472
  }
3395
3473
 
3474
+ function calculatePeriodPercent(realized, realizedBasis, unrealized, unrealizedBasis) {
3475
+ const numerator = realized.add(unrealized);
3476
+ const denominator = realizedBasis.add(unrealizedBasis);
3477
+
3478
+ return denominator.getIsZero() ? Decimal.ZERO : numerator.divide(denominator);
3479
+ }
3480
+
3396
3481
  const unchanged = { up: false, down: false };
3397
3482
 
3398
3483
  return PositionGroup;
@@ -3480,7 +3565,21 @@ module.exports = (() => {
3480
3565
  this._data.basisPrice = null;
3481
3566
 
3482
3567
  this._data.periodRealized = null;
3568
+ this._data.periodRealizedPrevious = null;
3569
+ this._data.periodRealizedPrevious2 = null;
3570
+
3571
+ this._data.periodRealizedBasis = null;
3572
+ this._data.periodRealizedBasisPrevious = null;
3573
+ this._data.periodRealizedBasisPrevious2 = null;
3574
+
3483
3575
  this._data.periodUnrealized = null;
3576
+ this._data.periodUnrealizedPrevious = null;
3577
+ this._data.periodUnrealizedPrevious2 = null;
3578
+
3579
+ this._data.periodUnrealizedBasis = null;
3580
+ this._data.periodUnrealizedBasisPrevious = null;
3581
+ this._data.periodUnrealizedBasisPrevious2 = null;
3582
+
3484
3583
  this._data.periodIncome = null;
3485
3584
 
3486
3585
  this._data.periodPrice = null;
@@ -3490,15 +3589,15 @@ module.exports = (() => {
3490
3589
  this._data.fundamental = { };
3491
3590
  this._data.locked = getIsLocked(position);
3492
3591
 
3493
- calculateStaticData(this);
3494
- calculatePriceData(this, null);
3495
-
3496
3592
  this._quoteChangedEvent = new Event(this);
3497
3593
  this._newsExistsChangedEvent = new Event(this);
3498
3594
  this._fundamentalDataChangedEvent = new Event(this);
3499
3595
  this._lockChangedEvent = new Event(this);
3500
3596
  this._portfolioChangedEvent = new Event(this);
3501
3597
  this._positionItemDisposeEvent = new Event(this);
3598
+
3599
+ calculateStaticData(this);
3600
+ calculatePriceData(this, null);
3502
3601
  }
3503
3602
 
3504
3603
  /**
@@ -3812,9 +3911,23 @@ module.exports = (() => {
3812
3911
  data.marketPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
3813
3912
  data.quantityPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.open;
3814
3913
 
3815
- data.periodRealized = calculateRealizedPeriod(item.currentSummary, previousSummary1);
3816
- data.periodUnrealized = calculateUnrealizedPeriod(item.currentSummary, previousSummary1);
3817
- data.periodIncome = calculateIncomePeriod(item.currentSummary, previousSummary1);
3914
+ data.periodRealized = calculatePeriodRealized(item.currentSummary, previousSummary1);
3915
+ data.periodRealizedPrevious = calculatePeriodRealized(previousSummary1, previousSummary2);
3916
+ data.periodRealizedPrevious2 = calculatePeriodRealized(previousSummary2, previousSummary3);
3917
+
3918
+ data.periodRealizedBasis = calculatePeriodRealizedBasis(item.currentSummary, previousSummary1);
3919
+ data.periodRealizedBasisPrevious = calculatePeriodRealizedBasis(previousSummary1, previousSummary2);
3920
+ data.periodRealizedBasisPrevious2 = calculatePeriodRealizedBasis(previousSummary2, previousSummary3);
3921
+
3922
+ data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary1);
3923
+ data.periodUnrealizedPrevious = calculatePeriodUnrealized(previousSummary1, previousSummary2);
3924
+ data.periodUnrealizedPrevious2 = calculatePeriodUnrealized(previousSummary2, previousSummary3);
3925
+
3926
+ data.periodUnrealizedBasis = calculatePeriodUnrealizedBasis(item.currentSummary, previousSummary1);
3927
+ data.periodUnrealizedBasisPrevious = calculatePeriodUnrealizedBasis(previousSummary1, previousSummary2);
3928
+ data.periodUnrealizedBasisPrevious2 = calculatePeriodUnrealizedBasis(previousSummary2, previousSummary3);
3929
+
3930
+ data.periodIncome = calculatePeriodIncome(item.currentSummary, previousSummary1);
3818
3931
 
3819
3932
  if (snapshot.open.getIsZero()) {
3820
3933
  data.basisPrice = Decimal.ZERO;
@@ -3941,11 +4054,16 @@ module.exports = (() => {
3941
4054
 
3942
4055
  data.unrealized = unrealized;
3943
4056
  data.unrealizedChange = unrealizedChange;
4057
+
4058
+ data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary, data.unrealized);
4059
+ data.periodUnrealizedChange = unrealizedChange;
3944
4060
  } else {
3945
4061
  data.summaryTotalCurrentChange = Decimal.ZERO;
3946
4062
 
3947
4063
  data.unrealized = Decimal.ZERO;
3948
4064
  data.unrealizedChange = Decimal.ZERO;
4065
+
4066
+ data.periodUnrealizedChange = Decimal.ZERO;
3949
4067
  }
3950
4068
  } else {
3951
4069
  data.summaryTotalCurrentChange = Decimal.ZERO;
@@ -3969,7 +4087,7 @@ module.exports = (() => {
3969
4087
  return returnRef;
3970
4088
  }
3971
4089
 
3972
- function calculateRealizedPeriod(currentSummary, previousSummary) {
4090
+ function calculatePeriodRealized(currentSummary, previousSummary) {
3973
4091
  let returnRef;
3974
4092
 
3975
4093
  if (currentSummary) {
@@ -3983,21 +4101,50 @@ module.exports = (() => {
3983
4101
  return returnRef;
3984
4102
  }
3985
4103
 
3986
- function calculateUnrealizedPeriod(currentSummary, previousSummary) {
4104
+ function calculatePeriodRealizedBasis(currentSummary, previousSummary) {
3987
4105
  let returnRef;
3988
4106
 
3989
4107
  if (currentSummary) {
3990
4108
  const period = currentSummary.period;
3991
4109
 
3992
- returnRef = period.unrealized.subtract(previousSummary !== null ? previousSummary.period.unrealized : Decimal.ZERO);
4110
+ returnRef = period.sells.subtract(calculatePeriodRealized(currentSummary, previousSummary));
3993
4111
  } else {
3994
4112
  returnRef = Decimal.ZERO;
3995
4113
  }
3996
4114
 
3997
4115
  return returnRef;
3998
4116
  }
4117
+
4118
+ function calculatePeriodUnrealized(currentSummary, previousSummary, override) {
4119
+ let returnRef;
4120
+
4121
+ if (currentSummary) {
4122
+ const period = currentSummary.period;
4123
+ const unrealized = override || period.unrealized;
4124
+
4125
+ returnRef = unrealized.subtract(previousSummary !== null ? previousSummary.period.unrealized : Decimal.ZERO);
4126
+ } else {
4127
+ returnRef = Decimal.ZERO;
4128
+ }
3999
4129
 
4000
- function calculateIncomePeriod(currentSummary, previousSummary) {
4130
+ return returnRef;
4131
+ }
4132
+
4133
+ function calculatePeriodUnrealizedBasis(currentSummary, previousSummary) {
4134
+ let returnRef;
4135
+
4136
+ if (currentSummary) {
4137
+ const period = currentSummary.period;
4138
+
4139
+ returnRef = currentSummary.end.basis.absolute();
4140
+ } else {
4141
+ returnRef = Decimal.ZERO;
4142
+ }
4143
+
4144
+ return returnRef;
4145
+ }
4146
+
4147
+ function calculatePeriodIncome(currentSummary, previousSummary) {
4001
4148
  let returnRef;
4002
4149
 
4003
4150
  if (currentSummary) {
@@ -4758,7 +4905,8 @@ module.exports = (() => {
4758
4905
  .withField('sequence', DataType.NUMBER, true)
4759
4906
  .withField('type', DataType.forEnum(TransactionType, 'TransactionType'))
4760
4907
  .withField('date', DataType.DAY)
4761
- .withField('value', DataType.DECIMAL)
4908
+ .withField('rate', DataType.DECIMAL, true)
4909
+ .withField('value', DataType.DECIMAL, true)
4762
4910
  .withField('force', DataType.BOOLEAN, true)
4763
4911
  .schema
4764
4912
  );
@@ -6192,6 +6340,19 @@ module.exports = function () {
6192
6340
  return this.addYears(years, true);
6193
6341
  }
6194
6342
 
6343
+ /**
6344
+ * Returns a new Day instance for the end of the month of the current instance.
6345
+ *
6346
+ * @public
6347
+ * @returns {Day}
6348
+ */
6349
+
6350
+ }, {
6351
+ key: 'getEndOfMonth',
6352
+ value: function getEndOfMonth() {
6353
+ return new Day(this.year, this.month, Day.getDaysInMonth(this.year, this.month));
6354
+ }
6355
+
6195
6356
  /**
6196
6357
  * Indicates if another {@link Day} occurs before the current instance.
6197
6358
  *
@@ -9984,7 +10145,7 @@ module.exports = function () {
9984
10145
  * the schema.
9985
10146
  *
9986
10147
  * @public
9987
- * @param {data} data
10148
+ * @param {Object} data
9988
10149
  * @returns {Object}
9989
10150
  */
9990
10151
 
@@ -10066,7 +10227,13 @@ module.exports = function () {
10066
10227
  };
10067
10228
 
10068
10229
  return function (key, value) {
10069
- return advance(key).reviver(value);
10230
+ var item = advance(key);
10231
+
10232
+ if (key === '') {
10233
+ return value;
10234
+ } else {
10235
+ return item.reviver(value);
10236
+ }
10070
10237
  };
10071
10238
  }
10072
10239
 
@@ -17708,6 +17875,53 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17708
17875
  });
17709
17876
  });
17710
17877
 
17878
+
17879
+
17880
+ /////
17881
+
17882
+ describe('and month position summary ranges are processed for a transaction set that does not close', () => {
17883
+ let ranges;
17884
+
17885
+ beforeEach(() => {
17886
+ const transactions = [
17887
+ {
17888
+ date: new Day(2018, 10, 20),
17889
+ snapshot: {
17890
+ open: new Decimal(1)
17891
+ },
17892
+ type: TransactionType.BUY
17893
+ },
17894
+ {
17895
+ date: new Day(2018, 11, 21),
17896
+ snapshot: {
17897
+ open: new Decimal(1)
17898
+ },
17899
+ type: TransactionType.BUY
17900
+ }
17901
+ ];
17902
+
17903
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
17904
+ });
17905
+
17906
+ it('should have 2 ranges (assuming the current year is 2018 and the current month is November)', () => {
17907
+ expect(ranges.length).toEqual(2);
17908
+ });
17909
+
17910
+ it('the first range should be from 2018-09-30 to 2018-10-31', () => {
17911
+ expect(ranges[0].start.format()).toEqual('2018-09-30');
17912
+ expect(ranges[0].end.format()).toEqual('2018-10-31');
17913
+ });
17914
+
17915
+ it('the second range should be from 2018-10-31 to 2018-11-30', () => {
17916
+ expect(ranges[1].start.format()).toEqual('2018-10-31');
17917
+ expect(ranges[1].end.format()).toEqual('2018-11-30');
17918
+ });
17919
+ });
17920
+
17921
+ ///////
17922
+
17923
+
17924
+
17711
17925
  describe('and getting the start date for yearly frames', () => {
17712
17926
  describe('for one year ago', function() {
17713
17927
  let start;
@@ -17750,6 +17964,55 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17750
17964
  });
17751
17965
  });
17752
17966
 
17967
+
17968
+
17969
+
17970
+ ////
17971
+
17972
+ describe('and getting the start date for monthly frames', () => {
17973
+ describe('for one month ago', function () {
17974
+ let start;
17975
+
17976
+ beforeEach(() => {
17977
+ start = PositionSummaryFrame.MONTHLY.getStartDate(1);
17978
+ });
17979
+
17980
+ it('should be on the last day of month', () => {
17981
+ const today = Day.getToday();
17982
+
17983
+ expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 2));
17984
+ });
17985
+
17986
+ it('should be month ago', () => {
17987
+ expect(start.month).toEqual(Day.getToday().month - 2);
17988
+ });
17989
+ });
17990
+
17991
+ describe('for three months ago', function () {
17992
+ let start;
17993
+
17994
+ beforeEach(() => {
17995
+ start = PositionSummaryFrame.MONTHLY.getStartDate(3);
17996
+ });
17997
+
17998
+ it('should be on the last day of month', () => {
17999
+ const today = Day.getToday();
18000
+
18001
+ expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 4));
18002
+ });
18003
+
18004
+ it('should be 3 month ago', () => {
18005
+ expect(start.month).toEqual(Day.getToday().month - 4);
18006
+ });
18007
+ });
18008
+ });
18009
+
18010
+ ////
18011
+
18012
+
18013
+
18014
+
18015
+
17753
18016
  describe('and recent ranges are calculated', () => {
17754
18017
  let todayYear;
17755
18018
  let todayMonth;
@@ -311,6 +311,53 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
311
311
  });
312
312
  });
313
313
 
314
+
315
+
316
+ /////
317
+
318
+ describe('and month position summary ranges are processed for a transaction set that does not close', () => {
319
+ let ranges;
320
+
321
+ beforeEach(() => {
322
+ const transactions = [
323
+ {
324
+ date: new Day(2018, 10, 20),
325
+ snapshot: {
326
+ open: new Decimal(1)
327
+ },
328
+ type: TransactionType.BUY
329
+ },
330
+ {
331
+ date: new Day(2018, 11, 21),
332
+ snapshot: {
333
+ open: new Decimal(1)
334
+ },
335
+ type: TransactionType.BUY
336
+ }
337
+ ];
338
+
339
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
340
+ });
341
+
342
+ it('should have 2 ranges (assuming the current year is 2018 and the current month is November)', () => {
343
+ expect(ranges.length).toEqual(2);
344
+ });
345
+
346
+ it('the first range should be from 2018-09-30 to 2018-10-31', () => {
347
+ expect(ranges[0].start.format()).toEqual('2018-09-30');
348
+ expect(ranges[0].end.format()).toEqual('2018-10-31');
349
+ });
350
+
351
+ it('the second range should be from 2018-10-31 to 2018-11-30', () => {
352
+ expect(ranges[1].start.format()).toEqual('2018-10-31');
353
+ expect(ranges[1].end.format()).toEqual('2018-11-30');
354
+ });
355
+ });
356
+
357
+ ///////
358
+
359
+
360
+
314
361
  describe('and getting the start date for yearly frames', () => {
315
362
  describe('for one year ago', function() {
316
363
  let start;
@@ -353,6 +400,55 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
353
400
  });
354
401
  });
355
402
 
403
+
404
+
405
+
406
+ ////
407
+
408
+ describe('and getting the start date for monthly frames', () => {
409
+ describe('for one month ago', function () {
410
+ let start;
411
+
412
+ beforeEach(() => {
413
+ start = PositionSummaryFrame.MONTHLY.getStartDate(1);
414
+ });
415
+
416
+ it('should be on the last day of month', () => {
417
+ const today = Day.getToday();
418
+
419
+ expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 2));
420
+ });
421
+
422
+ it('should be month ago', () => {
423
+ expect(start.month).toEqual(Day.getToday().month - 2);
424
+ });
425
+ });
426
+
427
+ describe('for three months ago', function () {
428
+ let start;
429
+
430
+ beforeEach(() => {
431
+ start = PositionSummaryFrame.MONTHLY.getStartDate(3);
432
+ });
433
+
434
+ it('should be on the last day of month', () => {
435
+ const today = Day.getToday();
436
+
437
+ expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 4));
438
+ });
439
+
440
+ it('should be 3 month ago', () => {
441
+ expect(start.month).toEqual(Day.getToday().month - 4);
442
+ });
443
+ });
444
+ });
445
+
446
+ ////
447
+
448
+
449
+
450
+
451
+
356
452
  describe('and recent ranges are calculated', () => {
357
453
  let todayYear;
358
454
  let todayMonth;