@barchart/portfolio-api-common 1.2.111 → 1.2.115
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 +31 -2
- package/lib/data/TransactionType.js +12 -0
- package/lib/data/TransactionValidator.js +2 -0
- package/lib/formatters/TransactionFormatter.js +6 -2
- package/lib/processing/PositionGroup.js +59 -3
- package/lib/processing/PositionItem.js +72 -10
- package/lib/serialization/TransactionSchema.js +17 -2
- package/package.json +1 -1
- package/test/SpecRunner.js +307 -19
- package/test/specs/data/PositionSummaryFrameSpec.js +93 -0
|
@@ -241,7 +241,32 @@ module.exports = (() => {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
function getMonthlyRanges(transactions) {
|
|
244
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -352,6 +352,17 @@ module.exports = (() => {
|
|
|
352
352
|
static get DEBIT() {
|
|
353
353
|
return debit;
|
|
354
354
|
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* A system-generated transaction, indicating the security has stopped active trading.
|
|
358
|
+
*
|
|
359
|
+
* @public
|
|
360
|
+
* @static
|
|
361
|
+
* @returns {TransactionType}
|
|
362
|
+
*/
|
|
363
|
+
static get DELIST() {
|
|
364
|
+
return delist;
|
|
365
|
+
}
|
|
355
366
|
|
|
356
367
|
/**
|
|
357
368
|
* A system-generated deposit, arising from another transaction.
|
|
@@ -401,6 +412,7 @@ module.exports = (() => {
|
|
|
401
412
|
const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
|
|
402
413
|
const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
|
|
403
414
|
const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false);
|
|
415
|
+
const delist = new TransactionType('DL', 'Delist', 'Delist', 0, false, false, false, false, false, false, false, false, false);
|
|
404
416
|
|
|
405
417
|
const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
|
|
406
418
|
const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
|
|
@@ -244,6 +244,7 @@ module.exports = (() => {
|
|
|
244
244
|
associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_REINVEST, false);
|
|
245
245
|
associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_STOCK, false);
|
|
246
246
|
associateTypes(InstrumentType.EQUITY, TransactionType.SPLIT, false);
|
|
247
|
+
associateTypes(InstrumentType.EQUITY, TransactionType.DELIST, false);
|
|
247
248
|
|
|
248
249
|
associateTypes(InstrumentType.FUND, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
|
|
249
250
|
associateTypes(InstrumentType.FUND, TransactionType.SELL, true, [ PositionDirection.LONG ]);
|
|
@@ -252,6 +253,7 @@ module.exports = (() => {
|
|
|
252
253
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_CASH, false);
|
|
253
254
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_REINVEST, false);
|
|
254
255
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
|
|
256
|
+
associateTypes(InstrumentType.FUND, TransactionType.DELIST, false);
|
|
255
257
|
|
|
256
258
|
associateTypes(InstrumentType.OTHER, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
|
|
257
259
|
associateTypes(InstrumentType.OTHER, TransactionType.SELL, true, [ PositionDirection.LONG ]);
|
|
@@ -216,7 +216,7 @@ module.exports = (() => {
|
|
|
216
216
|
formatters.set(TransactionType.INCOME, (t) => {
|
|
217
217
|
return {
|
|
218
218
|
total: t.income.amount
|
|
219
|
-
};
|
|
219
|
+
};
|
|
220
220
|
});
|
|
221
221
|
|
|
222
222
|
formatters.set(TransactionType.FEE, (t) => {
|
|
@@ -254,6 +254,10 @@ module.exports = (() => {
|
|
|
254
254
|
price: rate
|
|
255
255
|
};
|
|
256
256
|
});
|
|
257
|
+
|
|
258
|
+
formatters.set(TransactionType.DELIST, () => {
|
|
259
|
+
return { };
|
|
260
|
+
});
|
|
257
261
|
|
|
258
262
|
const cashFormatter = (t) => {
|
|
259
263
|
return {
|
|
@@ -298,4 +302,4 @@ module.exports = (() => {
|
|
|
298
302
|
.toComparator();
|
|
299
303
|
|
|
300
304
|
return TransactionFormatter;
|
|
301
|
-
})();
|
|
305
|
+
})();
|
|
@@ -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
|
-
|
|
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 =
|
|
415
|
-
data.
|
|
416
|
-
data.
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
661
|
+
function calculatePeriodIncome(currentSummary, previousSummary) {
|
|
600
662
|
let returnRef;
|
|
601
663
|
|
|
602
664
|
if (currentSummary) {
|
|
@@ -113,6 +113,10 @@ module.exports = (() => {
|
|
|
113
113
|
static get VALUATION() {
|
|
114
114
|
return valuation;
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
static get DELIST() {
|
|
118
|
+
return delist;
|
|
119
|
+
}
|
|
116
120
|
|
|
117
121
|
static get INCOME() {
|
|
118
122
|
return income;
|
|
@@ -322,8 +326,18 @@ module.exports = (() => {
|
|
|
322
326
|
.withField('force', DataType.BOOLEAN, true)
|
|
323
327
|
.schema
|
|
324
328
|
);
|
|
325
|
-
|
|
326
|
-
const
|
|
329
|
+
|
|
330
|
+
const delist = new TransactionSchema(SchemaBuilder.withName(TransactionType.DELIST.code)
|
|
331
|
+
.withField('portfolio', DataType.STRING)
|
|
332
|
+
.withField('position', DataType.STRING)
|
|
333
|
+
.withField('sequence', DataType.NUMBER, true)
|
|
334
|
+
.withField('type', DataType.forEnum(TransactionType, 'TransactionType'))
|
|
335
|
+
.withField('date', DataType.DAY)
|
|
336
|
+
.withField('force', DataType.BOOLEAN, true)
|
|
337
|
+
.schema
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
const income = new TransactionSchema(SchemaBuilder.withName(TransactionType.INCOME.code)
|
|
327
341
|
.withField('portfolio', DataType.STRING)
|
|
328
342
|
.withField('position', DataType.STRING)
|
|
329
343
|
.withField('sequence', DataType.NUMBER, true)
|
|
@@ -349,6 +363,7 @@ module.exports = (() => {
|
|
|
349
363
|
addSchemaToMap(TransactionType.DEPOSIT, deposit);
|
|
350
364
|
addSchemaToMap(TransactionType.WITHDRAWAL, withdrawal);
|
|
351
365
|
addSchemaToMap(TransactionType.VALUATION, valuation);
|
|
366
|
+
addSchemaToMap(TransactionType.DELIST, delist);
|
|
352
367
|
addSchemaToMap(TransactionType.INCOME, income);
|
|
353
368
|
|
|
354
369
|
return TransactionSchema;
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -632,7 +632,32 @@ module.exports = (() => {
|
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
function getMonthlyRanges(transactions) {
|
|
635
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -1060,6 +1089,17 @@ module.exports = (() => {
|
|
|
1060
1089
|
static get DEBIT() {
|
|
1061
1090
|
return debit;
|
|
1062
1091
|
}
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* A system-generated transaction, indicating the security has stopped active trading.
|
|
1095
|
+
*
|
|
1096
|
+
* @public
|
|
1097
|
+
* @static
|
|
1098
|
+
* @returns {TransactionType}
|
|
1099
|
+
*/
|
|
1100
|
+
static get DELIST() {
|
|
1101
|
+
return delist;
|
|
1102
|
+
}
|
|
1063
1103
|
|
|
1064
1104
|
/**
|
|
1065
1105
|
* A system-generated deposit, arising from another transaction.
|
|
@@ -1109,6 +1149,7 @@ module.exports = (() => {
|
|
|
1109
1149
|
const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
|
|
1110
1150
|
const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
|
|
1111
1151
|
const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false);
|
|
1152
|
+
const delist = new TransactionType('DL', 'Delist', 'Delist', 0, false, false, false, false, false, false, false, false, false);
|
|
1112
1153
|
|
|
1113
1154
|
const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
|
|
1114
1155
|
const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
|
|
@@ -1372,6 +1413,7 @@ module.exports = (() => {
|
|
|
1372
1413
|
associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_REINVEST, false);
|
|
1373
1414
|
associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_STOCK, false);
|
|
1374
1415
|
associateTypes(InstrumentType.EQUITY, TransactionType.SPLIT, false);
|
|
1416
|
+
associateTypes(InstrumentType.EQUITY, TransactionType.DELIST, false);
|
|
1375
1417
|
|
|
1376
1418
|
associateTypes(InstrumentType.FUND, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
|
|
1377
1419
|
associateTypes(InstrumentType.FUND, TransactionType.SELL, true, [ PositionDirection.LONG ]);
|
|
@@ -1380,6 +1422,7 @@ module.exports = (() => {
|
|
|
1380
1422
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_CASH, false);
|
|
1381
1423
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_REINVEST, false);
|
|
1382
1424
|
associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
|
|
1425
|
+
associateTypes(InstrumentType.FUND, TransactionType.DELIST, false);
|
|
1383
1426
|
|
|
1384
1427
|
associateTypes(InstrumentType.OTHER, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
|
|
1385
1428
|
associateTypes(InstrumentType.OTHER, TransactionType.SELL, true, [ PositionDirection.LONG ]);
|
|
@@ -2629,7 +2672,17 @@ module.exports = (() => {
|
|
|
2629
2672
|
this._dataActual.periodPrice = null;
|
|
2630
2673
|
this._dataActual.periodPricePrevious = null;
|
|
2631
2674
|
this._dataActual.periodRealized = null;
|
|
2675
|
+
this._dataActual.periodRealizedPrevious = null;
|
|
2676
|
+
this._dataActual.periodRealizedPrevious2 = null;
|
|
2677
|
+
this._dataActual.periodRealizedBasis = null;
|
|
2678
|
+
this._dataActual.periodRealizedBasisPrevious = null;
|
|
2679
|
+
this._dataActual.periodRealizedBasisPrevious2 = null;
|
|
2632
2680
|
this._dataActual.periodUnrealized = null;
|
|
2681
|
+
this._dataActual.periodUnrealizedPrevious = null;
|
|
2682
|
+
this._dataActual.periodUnrealizedPrevious2 = null;
|
|
2683
|
+
this._dataActual.periodUnrealizedBasis = null;
|
|
2684
|
+
this._dataActual.periodUnrealizedBasisPrevious = null;
|
|
2685
|
+
this._dataActual.periodUnrealizedBasisPrevious2 = null;
|
|
2633
2686
|
this._dataActual.periodIncome = null;
|
|
2634
2687
|
|
|
2635
2688
|
this._dataFormat.periodPrice = null;
|
|
@@ -2638,6 +2691,14 @@ module.exports = (() => {
|
|
|
2638
2691
|
this._dataFormat.periodUnrealized = null;
|
|
2639
2692
|
this._dataFormat.periodIncome = null;
|
|
2640
2693
|
|
|
2694
|
+
this._dataActual.periodPercent = null;
|
|
2695
|
+
this._dataActual.periodPreviousPercent = null;
|
|
2696
|
+
this._dataActual.periodPrevious2Percent = null;
|
|
2697
|
+
|
|
2698
|
+
this._dataFormat.periodPercent = null;
|
|
2699
|
+
this._dataFormat.periodPreviousPercent = null;
|
|
2700
|
+
this._dataFormat.periodPrevious2Percent = null;
|
|
2701
|
+
|
|
2641
2702
|
this._items.forEach((item) => {
|
|
2642
2703
|
bindItem.call(this, item);
|
|
2643
2704
|
});
|
|
@@ -3191,7 +3252,9 @@ module.exports = (() => {
|
|
|
3191
3252
|
|
|
3192
3253
|
calculateUnrealizedPercent(group);
|
|
3193
3254
|
|
|
3194
|
-
|
|
3255
|
+
const groupItems = group._items;
|
|
3256
|
+
|
|
3257
|
+
if (group.single && groupItems.length === 1) {
|
|
3195
3258
|
const item = group._items[0];
|
|
3196
3259
|
|
|
3197
3260
|
actual.quantity = item.data.quantity;
|
|
@@ -3210,12 +3273,34 @@ module.exports = (() => {
|
|
|
3210
3273
|
format.periodPrice = formatCurrency(actual.periodPrice, currency);
|
|
3211
3274
|
format.periodPricePrevious = formatCurrency(actual.periodPricePrevious, currency);
|
|
3212
3275
|
|
|
3276
|
+
actual.periodRealized = item.data.periodRealized;
|
|
3277
|
+
actual.periodRealizedPrevious = item.data.periodRealizedPrevious;
|
|
3278
|
+
actual.periodRealizedPrevious2 = item.data.periodRealizedPrevious2;
|
|
3279
|
+
|
|
3280
|
+
actual.periodRealizedBasis = item.data.periodRealizedBasis;
|
|
3281
|
+
actual.periodRealizedBasisPrevious = item.data.periodRealizedBasisPrevious;
|
|
3282
|
+
actual.periodRealizedBasisPrevious2 = item.data.periodRealizedBasisPrevious2;
|
|
3283
|
+
|
|
3284
|
+
actual.periodUnrealized = item.data.periodUnrealized;
|
|
3285
|
+
actual.periodUnrealizedPrevious = item.data.periodUnrealizedPrevious;
|
|
3286
|
+
actual.periodUnrealizedPrevious2 = item.data.periodUnrealizedPrevious2;
|
|
3287
|
+
|
|
3288
|
+
actual.periodUnrealizedBasis = item.data.periodUnrealizedBasis;
|
|
3289
|
+
actual.periodUnrealizedBasisPrevious = item.data.periodUnrealizedBasisPrevious;
|
|
3290
|
+
actual.periodUnrealizedBasisPrevious2 = item.data.periodUnrealizedBasisPrevious2;
|
|
3291
|
+
|
|
3292
|
+
actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
|
|
3293
|
+
actual.periodPercentPrevious = calculatePeriodPercent(actual.periodRealizedPrevious, actual.periodRealizedBasisPrevious, actual.periodUnrealizedPrevious, actual.periodUnrealizedBasisPrevious);
|
|
3294
|
+
actual.periodPercentPrevious2 = calculatePeriodPercent(actual.periodRealizedPrevious2, actual.periodRealizedBasisPrevious2, actual.periodUnrealizedPrevious2, actual.periodUnrealizedBasisPrevious2);
|
|
3295
|
+
|
|
3296
|
+
format.periodPercent = formatPercent(actual.periodPercent, 2);
|
|
3297
|
+
format.periodPercentPrevious = formatPercent(actual.periodPercentPrevious, 2);
|
|
3298
|
+
format.periodPercentPrevious2 = formatPercent(actual.periodPercentPrevious2, 2);
|
|
3299
|
+
|
|
3213
3300
|
format.invalid = definition.type === PositionLevelType.POSITION && item.invalid;
|
|
3214
3301
|
format.locked = definition.type === PositionLevelType.POSITION && item.data.locked;
|
|
3215
3302
|
}
|
|
3216
3303
|
|
|
3217
|
-
const groupItems = group._items;
|
|
3218
|
-
|
|
3219
3304
|
let portfolioType = null;
|
|
3220
3305
|
|
|
3221
3306
|
if (groupItems.length > 0) {
|
|
@@ -3335,6 +3420,13 @@ module.exports = (() => {
|
|
|
3335
3420
|
format.marketChangePercent = formatPercent(actual.marketChangePercent, 2);
|
|
3336
3421
|
|
|
3337
3422
|
calculateUnrealizedPercent(group);
|
|
3423
|
+
|
|
3424
|
+
if (group.single && item) {
|
|
3425
|
+
actual.periodUnrealized = item.data.periodUnrealized;
|
|
3426
|
+
|
|
3427
|
+
actual.periodPercent = calculatePeriodPercent(actual.periodRealized, actual.periodRealizedBasis, actual.periodUnrealized, actual.periodUnrealizedBasis);
|
|
3428
|
+
format.periodPercent = formatPercent(actual.periodPercent, 2);
|
|
3429
|
+
}
|
|
3338
3430
|
}
|
|
3339
3431
|
|
|
3340
3432
|
function calculateMarketPercent(group, rates, parentGroup, portfolioGroup) {
|
|
@@ -3393,6 +3485,13 @@ module.exports = (() => {
|
|
|
3393
3485
|
}
|
|
3394
3486
|
}
|
|
3395
3487
|
|
|
3488
|
+
function calculatePeriodPercent(realized, realizedBasis, unrealized, unrealizedBasis) {
|
|
3489
|
+
const numerator = realized.add(unrealized);
|
|
3490
|
+
const denominator = realizedBasis.add(unrealizedBasis);
|
|
3491
|
+
|
|
3492
|
+
return denominator.getIsZero() ? Decimal.ZERO : numerator.divide(denominator);
|
|
3493
|
+
}
|
|
3494
|
+
|
|
3396
3495
|
const unchanged = { up: false, down: false };
|
|
3397
3496
|
|
|
3398
3497
|
return PositionGroup;
|
|
@@ -3480,7 +3579,21 @@ module.exports = (() => {
|
|
|
3480
3579
|
this._data.basisPrice = null;
|
|
3481
3580
|
|
|
3482
3581
|
this._data.periodRealized = null;
|
|
3582
|
+
this._data.periodRealizedPrevious = null;
|
|
3583
|
+
this._data.periodRealizedPrevious2 = null;
|
|
3584
|
+
|
|
3585
|
+
this._data.periodRealizedBasis = null;
|
|
3586
|
+
this._data.periodRealizedBasisPrevious = null;
|
|
3587
|
+
this._data.periodRealizedBasisPrevious2 = null;
|
|
3588
|
+
|
|
3483
3589
|
this._data.periodUnrealized = null;
|
|
3590
|
+
this._data.periodUnrealizedPrevious = null;
|
|
3591
|
+
this._data.periodUnrealizedPrevious2 = null;
|
|
3592
|
+
|
|
3593
|
+
this._data.periodUnrealizedBasis = null;
|
|
3594
|
+
this._data.periodUnrealizedBasisPrevious = null;
|
|
3595
|
+
this._data.periodUnrealizedBasisPrevious2 = null;
|
|
3596
|
+
|
|
3484
3597
|
this._data.periodIncome = null;
|
|
3485
3598
|
|
|
3486
3599
|
this._data.periodPrice = null;
|
|
@@ -3490,15 +3603,15 @@ module.exports = (() => {
|
|
|
3490
3603
|
this._data.fundamental = { };
|
|
3491
3604
|
this._data.locked = getIsLocked(position);
|
|
3492
3605
|
|
|
3493
|
-
calculateStaticData(this);
|
|
3494
|
-
calculatePriceData(this, null);
|
|
3495
|
-
|
|
3496
3606
|
this._quoteChangedEvent = new Event(this);
|
|
3497
3607
|
this._newsExistsChangedEvent = new Event(this);
|
|
3498
3608
|
this._fundamentalDataChangedEvent = new Event(this);
|
|
3499
3609
|
this._lockChangedEvent = new Event(this);
|
|
3500
3610
|
this._portfolioChangedEvent = new Event(this);
|
|
3501
3611
|
this._positionItemDisposeEvent = new Event(this);
|
|
3612
|
+
|
|
3613
|
+
calculateStaticData(this);
|
|
3614
|
+
calculatePriceData(this, null);
|
|
3502
3615
|
}
|
|
3503
3616
|
|
|
3504
3617
|
/**
|
|
@@ -3812,9 +3925,23 @@ module.exports = (() => {
|
|
|
3812
3925
|
data.marketPrevious2 = previousSummary2 === null ? Decimal.ZERO : previousSummary2.end.value;
|
|
3813
3926
|
data.quantityPrevious = previousSummary1 === null ? Decimal.ZERO : previousSummary1.end.open;
|
|
3814
3927
|
|
|
3815
|
-
data.periodRealized =
|
|
3816
|
-
data.
|
|
3817
|
-
data.
|
|
3928
|
+
data.periodRealized = calculatePeriodRealized(item.currentSummary, previousSummary1);
|
|
3929
|
+
data.periodRealizedPrevious = calculatePeriodRealized(previousSummary1, previousSummary2);
|
|
3930
|
+
data.periodRealizedPrevious2 = calculatePeriodRealized(previousSummary2, previousSummary3);
|
|
3931
|
+
|
|
3932
|
+
data.periodRealizedBasis = calculatePeriodRealizedBasis(item.currentSummary, previousSummary1);
|
|
3933
|
+
data.periodRealizedBasisPrevious = calculatePeriodRealizedBasis(previousSummary1, previousSummary2);
|
|
3934
|
+
data.periodRealizedBasisPrevious2 = calculatePeriodRealizedBasis(previousSummary2, previousSummary3);
|
|
3935
|
+
|
|
3936
|
+
data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary1);
|
|
3937
|
+
data.periodUnrealizedPrevious = calculatePeriodUnrealized(previousSummary1, previousSummary2);
|
|
3938
|
+
data.periodUnrealizedPrevious2 = calculatePeriodUnrealized(previousSummary2, previousSummary3);
|
|
3939
|
+
|
|
3940
|
+
data.periodUnrealizedBasis = calculatePeriodUnrealizedBasis(item.currentSummary, previousSummary1);
|
|
3941
|
+
data.periodUnrealizedBasisPrevious = calculatePeriodUnrealizedBasis(previousSummary1, previousSummary2);
|
|
3942
|
+
data.periodUnrealizedBasisPrevious2 = calculatePeriodUnrealizedBasis(previousSummary2, previousSummary3);
|
|
3943
|
+
|
|
3944
|
+
data.periodIncome = calculatePeriodIncome(item.currentSummary, previousSummary1);
|
|
3818
3945
|
|
|
3819
3946
|
if (snapshot.open.getIsZero()) {
|
|
3820
3947
|
data.basisPrice = Decimal.ZERO;
|
|
@@ -3941,11 +4068,16 @@ module.exports = (() => {
|
|
|
3941
4068
|
|
|
3942
4069
|
data.unrealized = unrealized;
|
|
3943
4070
|
data.unrealizedChange = unrealizedChange;
|
|
4071
|
+
|
|
4072
|
+
data.periodUnrealized = calculatePeriodUnrealized(item.currentSummary, previousSummary, data.unrealized);
|
|
4073
|
+
data.periodUnrealizedChange = unrealizedChange;
|
|
3944
4074
|
} else {
|
|
3945
4075
|
data.summaryTotalCurrentChange = Decimal.ZERO;
|
|
3946
4076
|
|
|
3947
4077
|
data.unrealized = Decimal.ZERO;
|
|
3948
4078
|
data.unrealizedChange = Decimal.ZERO;
|
|
4079
|
+
|
|
4080
|
+
data.periodUnrealizedChange = Decimal.ZERO;
|
|
3949
4081
|
}
|
|
3950
4082
|
} else {
|
|
3951
4083
|
data.summaryTotalCurrentChange = Decimal.ZERO;
|
|
@@ -3969,7 +4101,7 @@ module.exports = (() => {
|
|
|
3969
4101
|
return returnRef;
|
|
3970
4102
|
}
|
|
3971
4103
|
|
|
3972
|
-
function
|
|
4104
|
+
function calculatePeriodRealized(currentSummary, previousSummary) {
|
|
3973
4105
|
let returnRef;
|
|
3974
4106
|
|
|
3975
4107
|
if (currentSummary) {
|
|
@@ -3983,21 +4115,50 @@ module.exports = (() => {
|
|
|
3983
4115
|
return returnRef;
|
|
3984
4116
|
}
|
|
3985
4117
|
|
|
3986
|
-
function
|
|
4118
|
+
function calculatePeriodRealizedBasis(currentSummary, previousSummary) {
|
|
3987
4119
|
let returnRef;
|
|
3988
4120
|
|
|
3989
4121
|
if (currentSummary) {
|
|
3990
4122
|
const period = currentSummary.period;
|
|
3991
4123
|
|
|
3992
|
-
returnRef = period.
|
|
4124
|
+
returnRef = period.sells.subtract(calculatePeriodRealized(currentSummary, previousSummary));
|
|
3993
4125
|
} else {
|
|
3994
4126
|
returnRef = Decimal.ZERO;
|
|
3995
4127
|
}
|
|
3996
4128
|
|
|
3997
4129
|
return returnRef;
|
|
3998
4130
|
}
|
|
4131
|
+
|
|
4132
|
+
function calculatePeriodUnrealized(currentSummary, previousSummary, override) {
|
|
4133
|
+
let returnRef;
|
|
3999
4134
|
|
|
4000
|
-
|
|
4135
|
+
if (currentSummary) {
|
|
4136
|
+
const period = currentSummary.period;
|
|
4137
|
+
const unrealized = override || period.unrealized;
|
|
4138
|
+
|
|
4139
|
+
returnRef = unrealized.subtract(previousSummary !== null ? previousSummary.period.unrealized : Decimal.ZERO);
|
|
4140
|
+
} else {
|
|
4141
|
+
returnRef = Decimal.ZERO;
|
|
4142
|
+
}
|
|
4143
|
+
|
|
4144
|
+
return returnRef;
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
function calculatePeriodUnrealizedBasis(currentSummary, previousSummary) {
|
|
4148
|
+
let returnRef;
|
|
4149
|
+
|
|
4150
|
+
if (currentSummary) {
|
|
4151
|
+
const period = currentSummary.period;
|
|
4152
|
+
|
|
4153
|
+
returnRef = currentSummary.end.basis.absolute();
|
|
4154
|
+
} else {
|
|
4155
|
+
returnRef = Decimal.ZERO;
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
return returnRef;
|
|
4159
|
+
}
|
|
4160
|
+
|
|
4161
|
+
function calculatePeriodIncome(currentSummary, previousSummary) {
|
|
4001
4162
|
let returnRef;
|
|
4002
4163
|
|
|
4003
4164
|
if (currentSummary) {
|
|
@@ -4554,6 +4715,10 @@ module.exports = (() => {
|
|
|
4554
4715
|
static get VALUATION() {
|
|
4555
4716
|
return valuation;
|
|
4556
4717
|
}
|
|
4718
|
+
|
|
4719
|
+
static get DELIST() {
|
|
4720
|
+
return delist;
|
|
4721
|
+
}
|
|
4557
4722
|
|
|
4558
4723
|
static get INCOME() {
|
|
4559
4724
|
return income;
|
|
@@ -4763,8 +4928,18 @@ module.exports = (() => {
|
|
|
4763
4928
|
.withField('force', DataType.BOOLEAN, true)
|
|
4764
4929
|
.schema
|
|
4765
4930
|
);
|
|
4766
|
-
|
|
4767
|
-
const
|
|
4931
|
+
|
|
4932
|
+
const delist = new TransactionSchema(SchemaBuilder.withName(TransactionType.DELIST.code)
|
|
4933
|
+
.withField('portfolio', DataType.STRING)
|
|
4934
|
+
.withField('position', DataType.STRING)
|
|
4935
|
+
.withField('sequence', DataType.NUMBER, true)
|
|
4936
|
+
.withField('type', DataType.forEnum(TransactionType, 'TransactionType'))
|
|
4937
|
+
.withField('date', DataType.DAY)
|
|
4938
|
+
.withField('force', DataType.BOOLEAN, true)
|
|
4939
|
+
.schema
|
|
4940
|
+
);
|
|
4941
|
+
|
|
4942
|
+
const income = new TransactionSchema(SchemaBuilder.withName(TransactionType.INCOME.code)
|
|
4768
4943
|
.withField('portfolio', DataType.STRING)
|
|
4769
4944
|
.withField('position', DataType.STRING)
|
|
4770
4945
|
.withField('sequence', DataType.NUMBER, true)
|
|
@@ -4790,6 +4965,7 @@ module.exports = (() => {
|
|
|
4790
4965
|
addSchemaToMap(TransactionType.DEPOSIT, deposit);
|
|
4791
4966
|
addSchemaToMap(TransactionType.WITHDRAWAL, withdrawal);
|
|
4792
4967
|
addSchemaToMap(TransactionType.VALUATION, valuation);
|
|
4968
|
+
addSchemaToMap(TransactionType.DELIST, delist);
|
|
4793
4969
|
addSchemaToMap(TransactionType.INCOME, income);
|
|
4794
4970
|
|
|
4795
4971
|
return TransactionSchema;
|
|
@@ -6193,6 +6369,19 @@ module.exports = function () {
|
|
|
6193
6369
|
return this.addYears(years, true);
|
|
6194
6370
|
}
|
|
6195
6371
|
|
|
6372
|
+
/**
|
|
6373
|
+
* Returns a new Day instance for the end of the month of the current instance.
|
|
6374
|
+
*
|
|
6375
|
+
* @public
|
|
6376
|
+
* @returns {Day}
|
|
6377
|
+
*/
|
|
6378
|
+
|
|
6379
|
+
}, {
|
|
6380
|
+
key: 'getEndOfMonth',
|
|
6381
|
+
value: function getEndOfMonth() {
|
|
6382
|
+
return new Day(this.year, this.month, Day.getDaysInMonth(this.year, this.month));
|
|
6383
|
+
}
|
|
6384
|
+
|
|
6196
6385
|
/**
|
|
6197
6386
|
* Indicates if another {@link Day} occurs before the current instance.
|
|
6198
6387
|
*
|
|
@@ -9985,7 +10174,7 @@ module.exports = function () {
|
|
|
9985
10174
|
* the schema.
|
|
9986
10175
|
*
|
|
9987
10176
|
* @public
|
|
9988
|
-
* @param {
|
|
10177
|
+
* @param {Object} data
|
|
9989
10178
|
* @returns {Object}
|
|
9990
10179
|
*/
|
|
9991
10180
|
|
|
@@ -10067,7 +10256,13 @@ module.exports = function () {
|
|
|
10067
10256
|
};
|
|
10068
10257
|
|
|
10069
10258
|
return function (key, value) {
|
|
10070
|
-
|
|
10259
|
+
var item = advance(key);
|
|
10260
|
+
|
|
10261
|
+
if (key === '') {
|
|
10262
|
+
return value;
|
|
10263
|
+
} else {
|
|
10264
|
+
return item.reviver(value);
|
|
10265
|
+
}
|
|
10071
10266
|
};
|
|
10072
10267
|
}
|
|
10073
10268
|
|
|
@@ -17709,6 +17904,50 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
17709
17904
|
});
|
|
17710
17905
|
});
|
|
17711
17906
|
|
|
17907
|
+
describe('and month position summary ranges are processed for a transaction set that does not close', () => {
|
|
17908
|
+
let ranges;
|
|
17909
|
+
|
|
17910
|
+
beforeEach(() => {
|
|
17911
|
+
const transactions = [
|
|
17912
|
+
{
|
|
17913
|
+
date: new Day(2018, 10, 20),
|
|
17914
|
+
snapshot: {
|
|
17915
|
+
open: new Decimal(1)
|
|
17916
|
+
},
|
|
17917
|
+
type: TransactionType.BUY
|
|
17918
|
+
},
|
|
17919
|
+
{
|
|
17920
|
+
date: new Day(2018, 11, 21),
|
|
17921
|
+
snapshot: {
|
|
17922
|
+
open: new Decimal(1)
|
|
17923
|
+
},
|
|
17924
|
+
type: TransactionType.BUY
|
|
17925
|
+
}
|
|
17926
|
+
];
|
|
17927
|
+
|
|
17928
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
17929
|
+
});
|
|
17930
|
+
|
|
17931
|
+
it('should have three ranges (assuming the current year is 2018 and the current month is December)', () => {
|
|
17932
|
+
expect(ranges.length).toEqual(3);
|
|
17933
|
+
});
|
|
17934
|
+
|
|
17935
|
+
it('the first range should be from 2018-09-30 to 2018-10-31', () => {
|
|
17936
|
+
expect(ranges[0].start.format()).toEqual('2018-09-30');
|
|
17937
|
+
expect(ranges[0].end.format()).toEqual('2018-10-31');
|
|
17938
|
+
});
|
|
17939
|
+
|
|
17940
|
+
it('the second range should be from 2018-10-31 to 2018-11-30', () => {
|
|
17941
|
+
expect(ranges[1].start.format()).toEqual('2018-10-31');
|
|
17942
|
+
expect(ranges[1].end.format()).toEqual('2018-11-30');
|
|
17943
|
+
});
|
|
17944
|
+
|
|
17945
|
+
it('the third range should be from 2018-10-31 to 2018-11-30', () => {
|
|
17946
|
+
expect(ranges[2].start.format()).toEqual('2018-11-30');
|
|
17947
|
+
expect(ranges[2].end.format()).toEqual('2018-12-31');
|
|
17948
|
+
});
|
|
17949
|
+
});
|
|
17950
|
+
|
|
17712
17951
|
describe('and getting the start date for yearly frames', () => {
|
|
17713
17952
|
describe('for one year ago', function() {
|
|
17714
17953
|
let start;
|
|
@@ -17751,6 +17990,55 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
17751
17990
|
});
|
|
17752
17991
|
});
|
|
17753
17992
|
|
|
17993
|
+
|
|
17994
|
+
|
|
17995
|
+
|
|
17996
|
+
////
|
|
17997
|
+
|
|
17998
|
+
describe('and getting the start date for monthly frames', () => {
|
|
17999
|
+
describe('for one month ago', function () {
|
|
18000
|
+
let start;
|
|
18001
|
+
|
|
18002
|
+
beforeEach(() => {
|
|
18003
|
+
start = PositionSummaryFrame.MONTHLY.getStartDate(1);
|
|
18004
|
+
});
|
|
18005
|
+
|
|
18006
|
+
it('should be on the last day of month', () => {
|
|
18007
|
+
const today = Day.getToday();
|
|
18008
|
+
|
|
18009
|
+
expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 2));
|
|
18010
|
+
});
|
|
18011
|
+
|
|
18012
|
+
it('should be month ago', () => {
|
|
18013
|
+
expect(start.month).toEqual(Day.getToday().month - 2);
|
|
18014
|
+
});
|
|
18015
|
+
});
|
|
18016
|
+
|
|
18017
|
+
describe('for three months ago', function () {
|
|
18018
|
+
let start;
|
|
18019
|
+
|
|
18020
|
+
beforeEach(() => {
|
|
18021
|
+
start = PositionSummaryFrame.MONTHLY.getStartDate(3);
|
|
18022
|
+
});
|
|
18023
|
+
|
|
18024
|
+
it('should be on the last day of month', () => {
|
|
18025
|
+
const today = Day.getToday();
|
|
18026
|
+
|
|
18027
|
+
expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 4));
|
|
18028
|
+
});
|
|
18029
|
+
|
|
18030
|
+
it('should be 3 month ago', () => {
|
|
18031
|
+
expect(start.month).toEqual(Day.getToday().month - 4);
|
|
18032
|
+
});
|
|
18033
|
+
});
|
|
18034
|
+
});
|
|
18035
|
+
|
|
18036
|
+
////
|
|
18037
|
+
|
|
18038
|
+
|
|
18039
|
+
|
|
18040
|
+
|
|
18041
|
+
|
|
17754
18042
|
describe('and recent ranges are calculated', () => {
|
|
17755
18043
|
let todayYear;
|
|
17756
18044
|
let todayMonth;
|
|
@@ -311,6 +311,50 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
311
311
|
});
|
|
312
312
|
});
|
|
313
313
|
|
|
314
|
+
describe('and month position summary ranges are processed for a transaction set that does not close', () => {
|
|
315
|
+
let ranges;
|
|
316
|
+
|
|
317
|
+
beforeEach(() => {
|
|
318
|
+
const transactions = [
|
|
319
|
+
{
|
|
320
|
+
date: new Day(2018, 10, 20),
|
|
321
|
+
snapshot: {
|
|
322
|
+
open: new Decimal(1)
|
|
323
|
+
},
|
|
324
|
+
type: TransactionType.BUY
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
date: new Day(2018, 11, 21),
|
|
328
|
+
snapshot: {
|
|
329
|
+
open: new Decimal(1)
|
|
330
|
+
},
|
|
331
|
+
type: TransactionType.BUY
|
|
332
|
+
}
|
|
333
|
+
];
|
|
334
|
+
|
|
335
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should have three ranges (assuming the current year is 2018 and the current month is December)', () => {
|
|
339
|
+
expect(ranges.length).toEqual(3);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('the first range should be from 2018-09-30 to 2018-10-31', () => {
|
|
343
|
+
expect(ranges[0].start.format()).toEqual('2018-09-30');
|
|
344
|
+
expect(ranges[0].end.format()).toEqual('2018-10-31');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('the second range should be from 2018-10-31 to 2018-11-30', () => {
|
|
348
|
+
expect(ranges[1].start.format()).toEqual('2018-10-31');
|
|
349
|
+
expect(ranges[1].end.format()).toEqual('2018-11-30');
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('the third range should be from 2018-10-31 to 2018-11-30', () => {
|
|
353
|
+
expect(ranges[2].start.format()).toEqual('2018-11-30');
|
|
354
|
+
expect(ranges[2].end.format()).toEqual('2018-12-31');
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
314
358
|
describe('and getting the start date for yearly frames', () => {
|
|
315
359
|
describe('for one year ago', function() {
|
|
316
360
|
let start;
|
|
@@ -353,6 +397,55 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
353
397
|
});
|
|
354
398
|
});
|
|
355
399
|
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
////
|
|
404
|
+
|
|
405
|
+
describe('and getting the start date for monthly frames', () => {
|
|
406
|
+
describe('for one month ago', function () {
|
|
407
|
+
let start;
|
|
408
|
+
|
|
409
|
+
beforeEach(() => {
|
|
410
|
+
start = PositionSummaryFrame.MONTHLY.getStartDate(1);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('should be on the last day of month', () => {
|
|
414
|
+
const today = Day.getToday();
|
|
415
|
+
|
|
416
|
+
expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 2));
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should be month ago', () => {
|
|
420
|
+
expect(start.month).toEqual(Day.getToday().month - 2);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
describe('for three months ago', function () {
|
|
425
|
+
let start;
|
|
426
|
+
|
|
427
|
+
beforeEach(() => {
|
|
428
|
+
start = PositionSummaryFrame.MONTHLY.getStartDate(3);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should be on the last day of month', () => {
|
|
432
|
+
const today = Day.getToday();
|
|
433
|
+
|
|
434
|
+
expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 4));
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('should be 3 month ago', () => {
|
|
438
|
+
expect(start.month).toEqual(Day.getToday().month - 4);
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
////
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
356
449
|
describe('and recent ranges are calculated', () => {
|
|
357
450
|
let todayYear;
|
|
358
451
|
let todayMonth;
|