@barchart/portfolio-api-common 1.2.125 → 1.2.126
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.
|
@@ -243,27 +243,25 @@ module.exports = (() => {
|
|
|
243
243
|
function getMonthlyRanges(transactions) {
|
|
244
244
|
const ranges = [ ];
|
|
245
245
|
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const first = array.first(transactions);
|
|
251
|
-
const last = array.last(transactions);
|
|
246
|
+
if (transactions.length !== 0) {
|
|
247
|
+
const first = array.first(transactions);
|
|
248
|
+
const last = array.last(transactions);
|
|
252
249
|
|
|
253
|
-
|
|
250
|
+
const firstDate = first.date;
|
|
254
251
|
|
|
255
|
-
|
|
252
|
+
let lastDate;
|
|
256
253
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
if (last.snapshot.open.getIsZero()) {
|
|
255
|
+
lastDate = last.date;
|
|
256
|
+
} else {
|
|
257
|
+
lastDate = Day.getToday();
|
|
258
|
+
}
|
|
262
259
|
|
|
263
|
-
|
|
260
|
+
lastDate = lastDate.getEndOfMonth();
|
|
264
261
|
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
for (let end = firstDate.getEndOfMonth(); !end.getIsAfter(lastDate); end = end.addMonths(1).getEndOfMonth()) {
|
|
263
|
+
ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
|
|
264
|
+
}
|
|
267
265
|
}
|
|
268
266
|
|
|
269
267
|
return ranges;
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -634,27 +634,25 @@ module.exports = (() => {
|
|
|
634
634
|
function getMonthlyRanges(transactions) {
|
|
635
635
|
const ranges = [ ];
|
|
636
636
|
|
|
637
|
-
if (
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const first = array.first(transactions);
|
|
642
|
-
const last = array.last(transactions);
|
|
637
|
+
if (transactions.length !== 0) {
|
|
638
|
+
const first = array.first(transactions);
|
|
639
|
+
const last = array.last(transactions);
|
|
643
640
|
|
|
644
|
-
|
|
641
|
+
const firstDate = first.date;
|
|
645
642
|
|
|
646
|
-
|
|
643
|
+
let lastDate;
|
|
647
644
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
645
|
+
if (last.snapshot.open.getIsZero()) {
|
|
646
|
+
lastDate = last.date;
|
|
647
|
+
} else {
|
|
648
|
+
lastDate = Day.getToday();
|
|
649
|
+
}
|
|
653
650
|
|
|
654
|
-
|
|
651
|
+
lastDate = lastDate.getEndOfMonth();
|
|
655
652
|
|
|
656
|
-
|
|
657
|
-
|
|
653
|
+
for (let end = firstDate.getEndOfMonth(); !end.getIsAfter(lastDate); end = end.addMonths(1).getEndOfMonth()) {
|
|
654
|
+
ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
|
|
655
|
+
}
|
|
658
656
|
}
|
|
659
657
|
|
|
660
658
|
return ranges;
|
|
@@ -17860,7 +17858,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
17860
17858
|
});
|
|
17861
17859
|
});
|
|
17862
17860
|
|
|
17863
|
-
describe('and yearly position summary ranges are processed for a transaction set that opens in
|
|
17861
|
+
describe('and yearly position summary ranges are processed for a transaction set that opens in 2015 and closes in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
|
|
17864
17862
|
let ranges;
|
|
17865
17863
|
|
|
17866
17864
|
beforeEach(() => {
|
|
@@ -17913,6 +17911,120 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
17913
17911
|
});
|
|
17914
17912
|
});
|
|
17915
17913
|
|
|
17914
|
+
describe('and monthly position summary ranges are processed for a transaction set that does not close', () => {
|
|
17915
|
+
let ranges;
|
|
17916
|
+
|
|
17917
|
+
beforeEach(() => {
|
|
17918
|
+
const transactions = [
|
|
17919
|
+
{
|
|
17920
|
+
date: new Day(2019, 1, 20),
|
|
17921
|
+
snapshot: {
|
|
17922
|
+
open: new Decimal(1)
|
|
17923
|
+
},
|
|
17924
|
+
type: TransactionType.BUY
|
|
17925
|
+
},
|
|
17926
|
+
{
|
|
17927
|
+
date: new Day(2019, 2, 21),
|
|
17928
|
+
snapshot: {
|
|
17929
|
+
open: new Decimal(1)
|
|
17930
|
+
},
|
|
17931
|
+
type: TransactionType.BUY
|
|
17932
|
+
}
|
|
17933
|
+
];
|
|
17934
|
+
|
|
17935
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
17936
|
+
});
|
|
17937
|
+
|
|
17938
|
+
it('should have at least two ranges', () => {
|
|
17939
|
+
expect(ranges.length > 1).toEqual(true);
|
|
17940
|
+
});
|
|
17941
|
+
|
|
17942
|
+
it('the first range should be from 12-31-2018 to 01-31-2019', () => {
|
|
17943
|
+
expect(ranges[0].start.format()).toEqual('2018-12-31');
|
|
17944
|
+
expect(ranges[0].end.format()).toEqual('2019-01-31');
|
|
17945
|
+
});
|
|
17946
|
+
|
|
17947
|
+
it('the last range should be for the current month', () => {
|
|
17948
|
+
const today = Day.getToday();
|
|
17949
|
+
|
|
17950
|
+
expect(ranges[ranges.length - 1].start.format()).toEqual(today.getEndOfMonth().subtractMonths(1).getEndOfMonth().format());
|
|
17951
|
+
expect(ranges[ranges.length - 1].end.format()).toEqual(today.getEndOfMonth().format());
|
|
17952
|
+
});
|
|
17953
|
+
});
|
|
17954
|
+
|
|
17955
|
+
describe('and monthly position summary ranges are processed for a transaction set closes the same month', () => {
|
|
17956
|
+
let ranges;
|
|
17957
|
+
|
|
17958
|
+
beforeEach(() => {
|
|
17959
|
+
const transactions = [
|
|
17960
|
+
{
|
|
17961
|
+
date: new Day(2018, 12, 1),
|
|
17962
|
+
snapshot: {
|
|
17963
|
+
open: new Decimal(1)
|
|
17964
|
+
},
|
|
17965
|
+
type: TransactionType.BUY
|
|
17966
|
+
},
|
|
17967
|
+
{
|
|
17968
|
+
date: new Day(2018, 12, 31),
|
|
17969
|
+
snapshot: {
|
|
17970
|
+
open: new Decimal(0)
|
|
17971
|
+
},
|
|
17972
|
+
type: TransactionType.SELL
|
|
17973
|
+
}
|
|
17974
|
+
];
|
|
17975
|
+
|
|
17976
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
17977
|
+
});
|
|
17978
|
+
|
|
17979
|
+
it('should have one range', () => {
|
|
17980
|
+
expect(ranges.length).toEqual(1);
|
|
17981
|
+
});
|
|
17982
|
+
|
|
17983
|
+
it('the first range should be from 11-30-2018 to 12-31-2018', () => {
|
|
17984
|
+
expect(ranges[0].start.format()).toEqual('2018-11-30');
|
|
17985
|
+
expect(ranges[0].end.format()).toEqual('2018-12-31');
|
|
17986
|
+
});
|
|
17987
|
+
});
|
|
17988
|
+
|
|
17989
|
+
describe('and monthly position summary ranges are processed for a transaction set closes the next month', () => {
|
|
17990
|
+
let ranges;
|
|
17991
|
+
|
|
17992
|
+
beforeEach(() => {
|
|
17993
|
+
const transactions = [
|
|
17994
|
+
{
|
|
17995
|
+
date: new Day(2015, 10, 20),
|
|
17996
|
+
snapshot: {
|
|
17997
|
+
open: new Decimal(1)
|
|
17998
|
+
},
|
|
17999
|
+
type: TransactionType.BUY
|
|
18000
|
+
},
|
|
18001
|
+
{
|
|
18002
|
+
date: new Day(2015, 11, 20),
|
|
18003
|
+
snapshot: {
|
|
18004
|
+
open: new Decimal(0)
|
|
18005
|
+
},
|
|
18006
|
+
type: TransactionType.SELL
|
|
18007
|
+
}
|
|
18008
|
+
];
|
|
18009
|
+
|
|
18010
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
18011
|
+
});
|
|
18012
|
+
|
|
18013
|
+
it('should have two ranges', () => {
|
|
18014
|
+
expect(ranges.length).toEqual(2);
|
|
18015
|
+
});
|
|
18016
|
+
|
|
18017
|
+
it('the first range should be from 09-30-2015 to 10-31-2015', () => {
|
|
18018
|
+
expect(ranges[0].start.format()).toEqual('2015-09-30');
|
|
18019
|
+
expect(ranges[0].end.format()).toEqual('2015-10-31');
|
|
18020
|
+
});
|
|
18021
|
+
|
|
18022
|
+
it('the second range should be from 10-31-2015 to 11-30-2015', () => {
|
|
18023
|
+
expect(ranges[1].start.format()).toEqual('2015-10-31');
|
|
18024
|
+
expect(ranges[1].end.format()).toEqual('2015-11-30');
|
|
18025
|
+
});
|
|
18026
|
+
});
|
|
18027
|
+
|
|
17916
18028
|
describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
|
|
17917
18029
|
let ranges;
|
|
17918
18030
|
|
|
@@ -173,7 +173,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
-
describe('and yearly position summary ranges are processed for a transaction set that opens in
|
|
176
|
+
describe('and yearly position summary ranges are processed for a transaction set that opens in 2015 and closes in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
|
|
177
177
|
let ranges;
|
|
178
178
|
|
|
179
179
|
beforeEach(() => {
|
|
@@ -226,6 +226,120 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
226
226
|
});
|
|
227
227
|
});
|
|
228
228
|
|
|
229
|
+
describe('and monthly position summary ranges are processed for a transaction set that does not close', () => {
|
|
230
|
+
let ranges;
|
|
231
|
+
|
|
232
|
+
beforeEach(() => {
|
|
233
|
+
const transactions = [
|
|
234
|
+
{
|
|
235
|
+
date: new Day(2019, 1, 20),
|
|
236
|
+
snapshot: {
|
|
237
|
+
open: new Decimal(1)
|
|
238
|
+
},
|
|
239
|
+
type: TransactionType.BUY
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
date: new Day(2019, 2, 21),
|
|
243
|
+
snapshot: {
|
|
244
|
+
open: new Decimal(1)
|
|
245
|
+
},
|
|
246
|
+
type: TransactionType.BUY
|
|
247
|
+
}
|
|
248
|
+
];
|
|
249
|
+
|
|
250
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should have at least two ranges', () => {
|
|
254
|
+
expect(ranges.length > 1).toEqual(true);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('the first range should be from 12-31-2018 to 01-31-2019', () => {
|
|
258
|
+
expect(ranges[0].start.format()).toEqual('2018-12-31');
|
|
259
|
+
expect(ranges[0].end.format()).toEqual('2019-01-31');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('the last range should be for the current month', () => {
|
|
263
|
+
const today = Day.getToday();
|
|
264
|
+
|
|
265
|
+
expect(ranges[ranges.length - 1].start.format()).toEqual(today.getEndOfMonth().subtractMonths(1).getEndOfMonth().format());
|
|
266
|
+
expect(ranges[ranges.length - 1].end.format()).toEqual(today.getEndOfMonth().format());
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('and monthly position summary ranges are processed for a transaction set closes the same month', () => {
|
|
271
|
+
let ranges;
|
|
272
|
+
|
|
273
|
+
beforeEach(() => {
|
|
274
|
+
const transactions = [
|
|
275
|
+
{
|
|
276
|
+
date: new Day(2018, 12, 1),
|
|
277
|
+
snapshot: {
|
|
278
|
+
open: new Decimal(1)
|
|
279
|
+
},
|
|
280
|
+
type: TransactionType.BUY
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
date: new Day(2018, 12, 31),
|
|
284
|
+
snapshot: {
|
|
285
|
+
open: new Decimal(0)
|
|
286
|
+
},
|
|
287
|
+
type: TransactionType.SELL
|
|
288
|
+
}
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('should have one range', () => {
|
|
295
|
+
expect(ranges.length).toEqual(1);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('the first range should be from 11-30-2018 to 12-31-2018', () => {
|
|
299
|
+
expect(ranges[0].start.format()).toEqual('2018-11-30');
|
|
300
|
+
expect(ranges[0].end.format()).toEqual('2018-12-31');
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('and monthly position summary ranges are processed for a transaction set closes the next month', () => {
|
|
305
|
+
let ranges;
|
|
306
|
+
|
|
307
|
+
beforeEach(() => {
|
|
308
|
+
const transactions = [
|
|
309
|
+
{
|
|
310
|
+
date: new Day(2015, 10, 20),
|
|
311
|
+
snapshot: {
|
|
312
|
+
open: new Decimal(1)
|
|
313
|
+
},
|
|
314
|
+
type: TransactionType.BUY
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
date: new Day(2015, 11, 20),
|
|
318
|
+
snapshot: {
|
|
319
|
+
open: new Decimal(0)
|
|
320
|
+
},
|
|
321
|
+
type: TransactionType.SELL
|
|
322
|
+
}
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('should have two ranges', () => {
|
|
329
|
+
expect(ranges.length).toEqual(2);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('the first range should be from 09-30-2015 to 10-31-2015', () => {
|
|
333
|
+
expect(ranges[0].start.format()).toEqual('2015-09-30');
|
|
334
|
+
expect(ranges[0].end.format()).toEqual('2015-10-31');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('the second range should be from 10-31-2015 to 11-30-2015', () => {
|
|
338
|
+
expect(ranges[1].start.format()).toEqual('2015-10-31');
|
|
339
|
+
expect(ranges[1].end.format()).toEqual('2015-11-30');
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
229
343
|
describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
|
|
230
344
|
let ranges;
|
|
231
345
|
|