@barchart/portfolio-api-common 1.2.119 → 1.2.124

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.
@@ -11,13 +11,10 @@ module.exports = (() => {
11
11
  * @extends {Enum}
12
12
  * @param {String} code
13
13
  * @param {String} description
14
- * @param {Boolean} internal
15
14
  */
16
15
  class CorporateActionType extends Enum {
17
- constructor(code, description, internal) {
16
+ constructor(code, description) {
18
17
  super(code, description);
19
-
20
- this._internal = is.boolean(internal) && internal;
21
18
  }
22
19
 
23
20
  /**
@@ -76,14 +73,14 @@ module.exports = (() => {
76
73
  }
77
74
 
78
75
  /**
79
- * A fictitious event, used for internal system purposes.
76
+ * A delisting.
80
77
  *
81
78
  * @public
82
79
  * @static
83
80
  * @returns {CorporateActionType}
84
81
  */
85
- static get JOB() {
86
- return job;
82
+ static get DELIST() {
83
+ return delist;
87
84
  }
88
85
  }
89
86
 
@@ -91,7 +88,7 @@ module.exports = (() => {
91
88
  const nameChange = new CorporateActionType('NAME_CHANGE', 'Name Change', false);
92
89
  const dividend = new CorporateActionType('DIVIDEND', 'Dividend', false);
93
90
  const split = new CorporateActionType('SPLIT', 'Split', false);
94
- const job = new CorporateActionType('JOB', 'Job', true);
91
+ const delist = new CorporateActionType('DELIST', 'Delist', false);
95
92
 
96
93
  return CorporateActionType;
97
94
  })();
@@ -64,7 +64,7 @@ module.exports = (() => {
64
64
  *
65
65
  * @public
66
66
  * @param {Number} periods
67
- * @returns {Array.<PositionSummaryRange>}
67
+ * @returns {PositionSummaryRange[]}
68
68
  */
69
69
  getRecentRanges(periods) {
70
70
  const startDate = this.getStartDate(periods);
@@ -77,8 +77,8 @@ module.exports = (() => {
77
77
  * Returns the ranges for the set of {@link Transaction} objects.
78
78
  *
79
79
  * @public
80
- * @param {Array.<Transaction>} transactions
81
- * @returns {Array.<PositionSummaryRange>}
80
+ * @param {Transaction[]} transactions
81
+ * @returns {PositionSummaryRange[]}
82
82
  */
83
83
  getRanges(transactions) {
84
84
  assert.argumentIsArray(transactions, 'transactions');
@@ -91,7 +91,7 @@ module.exports = (() => {
91
91
  *
92
92
  * @public
93
93
  * @param {Day} date
94
- * @return {Array.<PositionSummaryRange>}
94
+ * @return {PositionSummaryRange[]}
95
95
  */
96
96
  getRangesFromDate(date) {
97
97
  assert.argumentIsRequired(date, 'date', Day, 'Day');
@@ -180,8 +180,8 @@ module.exports = (() => {
180
180
  }
181
181
 
182
182
  const yearly = new PositionSummaryFrame('YEARLY', 'year', false, getYearlyRanges, getYearlyStartDate, getYearlyRangeDescription);
183
- const quarterly = new PositionSummaryFrame('QUARTER', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
184
- const monthly = new PositionSummaryFrame('MONTH', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
183
+ const quarterly = new PositionSummaryFrame('QUARTERLY', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
184
+ const monthly = new PositionSummaryFrame('MONTHLY', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
185
185
  const ytd = new PositionSummaryFrame('YTD', 'year-to-date', true, getYearToDateRanges, getYearToDateStartDate, getYearToDateRangeDescription);
186
186
 
187
187
  /**
@@ -241,32 +241,32 @@ module.exports = (() => {
241
241
  }
242
242
 
243
243
  function getMonthlyRanges(transactions) {
244
- const ranges = [ ];
245
-
246
- if (!transactions.length) {
247
- return ranges;
244
+ const ranges = [ ];
245
+
246
+ if (!transactions.length) {
247
+ return ranges;
248
248
  }
249
249
 
250
250
  const first = array.first(transactions);
251
251
  const last = array.last(transactions);
252
252
 
253
253
  const firstDate = first.date;
254
+
254
255
  let lastDate;
255
256
 
256
- lastDate = last.snapshot.open.getIsZero()
257
- ? new Day(last.date.year, last.date.month, last.date.day).addMonths(1)
258
- : Day.getToday();
257
+ if (last.snapshot.open.getIsZero()) {
258
+ lastDate = new Day(last.date.year, last.date.month, last.date.day).addMonths(1);
259
+ } else {
260
+ lastDate = Day.getToday();
261
+ }
262
+
259
263
  lastDate = lastDate.getEndOfMonth();
260
264
 
261
- for (
262
- let end = firstDate.getEndOfMonth();
263
- end.format() <= lastDate.format();
264
- end = end.addMonths(1).getEndOfMonth()
265
- ) {
265
+ for (let end = firstDate.getEndOfMonth(); end.format() <= lastDate.format(); end = end.addMonths(1).getEndOfMonth()) {
266
266
  ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
267
267
  }
268
-
269
- return ranges;
268
+
269
+ return ranges;
270
270
  }
271
271
 
272
272
  function getYearToDateRanges(transactions) {
@@ -303,8 +303,8 @@ module.exports = (() => {
303
303
  }
304
304
 
305
305
  function getMonthlyStartDate(periods, date) {
306
- const today = date || Day.getToday();
307
-
306
+ const today = date || Day.getToday();
307
+
308
308
  return today
309
309
  .subtractMonths(periods)
310
310
  .subtractDays(today.day);
@@ -323,7 +323,7 @@ module.exports = (() => {
323
323
  }
324
324
 
325
325
  function getMonthlyRangeDescription(start, end) {
326
- return '';
326
+ return `Month ended ${end.format()}`;
327
327
  }
328
328
 
329
329
  function getYearToDateRangeDescription(start, end) {
@@ -46,32 +46,33 @@ module.exports = (() => {
46
46
  return map;
47
47
  }, { });
48
48
 
49
- const a = transactions.reduce((list, transaction) => {
49
+ const list = transactions.reduce((accumulator, transaction) => {
50
50
  const position = transaction.position;
51
51
 
52
52
  if (instruments.hasOwnProperty(position)) {
53
53
  let instrument = instruments[position];
54
- let formatted = getBasicTransaction(transaction, instrument);
54
+ let formatted = { instrument: instrument };
55
55
 
56
- if (formatters.has(transaction.type)) {
57
- const formatterFunction = formatters.get(transaction.type);
58
- const formattedTransaction = formatterFunction(transaction);
56
+ const formatterFunctions = formatters.get(transaction.type);
59
57
 
60
- Object.keys(formattedTransaction).map((key) => {
61
- if (!is.undefined(formattedTransaction[key]) && formattedTransaction[key] instanceof Decimal) {
62
- const precision = instrument.currency.precision;
58
+ formatterFunctions.forEach((formatterFunction) => {
59
+ formatterFunction(transaction, formatted);
60
+ });
63
61
 
64
- formattedTransaction[key] = formatter.numberToString(formattedTransaction[key].toFloat(), precision, ',');
65
- }
66
- });
62
+ Object.keys(formatted).forEach((key) => {
63
+ const value = formatted[key];
67
64
 
68
- formatted = Object.assign({}, formatted, formattedTransaction);
69
- }
65
+ if (value instanceof Decimal) {
66
+ const precision = instrument.currency.precision;
70
67
 
71
- list.push(formatted);
68
+ formatted[key] = formatter.numberToString(value.toFloat(), precision, ',');
69
+ }
70
+ });
71
+
72
+ accumulator.push(formatted);
72
73
  }
73
74
 
74
- return list;
75
+ return accumulator;
75
76
  }, [ ]);
76
77
 
77
78
  let comparator;
@@ -82,13 +83,13 @@ module.exports = (() => {
82
83
  comparator = comparatorAscending;
83
84
  }
84
85
 
85
- a.sort(comparator);
86
+ list.sort(comparator);
86
87
 
87
- a.forEach((t) => {
88
+ list.forEach((t) => {
88
89
  delete t.instrument.id;
89
90
  });
90
91
 
91
- return a;
92
+ return list;
92
93
  }
93
94
 
94
95
  /**
@@ -120,126 +121,105 @@ module.exports = (() => {
120
121
  }
121
122
  }
122
123
 
123
- const getBasicTransaction = (t, i) => {
124
- return {
125
- date: t.date,
126
- type: t.type.display,
127
- code: t.type.code,
128
- sequence: t.sequence,
129
- instrument: i,
130
- position: t.position
131
- };
124
+ const basicFormatter = (t, f) => {
125
+ f.date = t.date;
126
+ f.type = t.type.display;
127
+ f.code = t.type.code;
128
+ f.sequence = t.sequence;
129
+ f.position = t.position;
132
130
  };
133
131
 
134
- const formatters = new Map();
135
-
136
- const buySellFormatter = (t) => {
137
- return {
138
- boughtSold: t.quantity,
139
- price: t.trade.price,
140
- fee: t.fee,
141
- total: t.amount
142
- };
132
+ const averageCostFormatter = (t, f) => {
133
+ const basis = t.snapshot.basis;
134
+ const open = t.snapshot.open;
135
+
136
+ let average;
137
+
138
+ if (basis && open && !open.getIsZero()) {
139
+ average = basis.divide(open).absolute();
140
+ } else {
141
+ average = '';
142
+ }
143
+
144
+ f.average = average;
143
145
  };
144
146
 
145
- formatters.set(TransactionType.BUY, buySellFormatter);
146
- formatters.set(TransactionType.SELL, buySellFormatter);
147
- formatters.set(TransactionType.BUY_SHORT, buySellFormatter);
148
- formatters.set(TransactionType.SELL_SHORT, buySellFormatter);
149
-
150
- formatters.set(TransactionType.DIVIDEND, (t) => {
151
- return {
152
- shares: t.snapshot.open,
153
- total: t.dividend.amount,
154
- rate: t.dividend.rate
155
- };
156
- });
157
-
158
- formatters.set(TransactionType.DIVIDEND_STOCK, (t) => {
159
- const data = {
160
- boughtSold: t.quantity,
161
- fee: t.fee
162
- };
147
+ const buySellFormatter = (t, f) => {
148
+ f.boughtSold = t.quantity;
149
+ f.price = t.trade.price;
150
+ f.fee = t.fee;
151
+ f.total = t.amount;
152
+ };
153
+
154
+ const dividendFormatter = (t, f) => {
155
+ f.shares = t.snapshot.open;
156
+ f.total = t.dividend.amount;
157
+ f.rate = t.dividend.rate;
158
+ };
159
+
160
+ const dividendStockFormatter = (t, f) => {
161
+ f.boughtSold = t.quantity;
162
+ f.fee = t.fee;
163
163
 
164
164
  if (t.dividend && t.dividend.rate && t.dividend.price) {
165
- data.shares = t.snapshot.open.subtract(t.quantity);
166
- data.price = t.dividend.price;
167
- data.rate = t.dividend.rate;
165
+ f.shares = t.snapshot.open.subtract(t.quantity);
166
+ f.price = t.dividend.price;
167
+ f.rate = t.dividend.rate;
168
168
  }
169
+ };
170
+
171
+ const dividendReinvestFormatter = (t, f) => {
172
+ f.boughtSold = t.quantity;
173
+ f.shares = t.snapshot.open.subtract(t.quantity);
174
+ f.price = t.dividend.price;
175
+ f.fee = t.fee;
176
+ f.rate = t.dividend.rate;
177
+ };
178
+
179
+ const distributionCashFormatter = (t, f) => {
180
+ f.shares = t.snapshot.open;
181
+ f.total = t.dividend.amount;
182
+ f.rate = t.dividend.rate;
183
+ };
169
184
 
170
- return data;
171
- });
172
-
173
- formatters.set(TransactionType.DIVIDEND_REINVEST, (t) => {
174
- return {
175
- boughtSold: t.quantity,
176
- shares: t.snapshot.open.subtract(t.quantity),
177
- price: t.dividend.price,
178
- fee: t.fee,
179
- rate: t.dividend.rate
180
- };
181
- });
182
-
183
- formatters.set(TransactionType.DISTRIBUTION_CASH, (t) => {
184
- return {
185
- shares: t.snapshot.open,
186
- total: t.dividend.amount,
187
- rate: t.dividend.rate
188
- };
189
- });
190
-
191
- formatters.set(TransactionType.DISTRIBUTION_FUND, (t) => {
192
- const data = {
193
- boughtSold: t.quantity,
194
- fee: t.fee
195
- };
185
+ const distributionFundFormatter = (t, f) => {
186
+ f.boughtSold =t.quantity;
187
+ f.fee = t.fee;
196
188
 
197
189
  if (t.dividend && t.dividend.rate && t.dividend.price) {
198
- data.shares = t.snapshot.open.subtract(t.quantity);
199
- data.price = t.dividend.price;
200
- data.rate = t.dividend.rate;
190
+ f.shares = t.snapshot.open.subtract(t.quantity);
191
+ f.price = t.dividend.price;
192
+ f.rate = t.dividend.rate;
201
193
  }
194
+ };
202
195
 
203
- return data;
204
- });
205
-
206
- formatters.set(TransactionType.DISTRIBUTION_REINVEST, (t) => {
207
- return {
208
- boughtSold: t.quantity,
209
- shares: t.snapshot.open.subtract(t.quantity),
210
- price: t.dividend.price,
211
- fee: t.fee,
212
- rate: t.dividend.rate
213
- };
214
- });
215
-
216
- formatters.set(TransactionType.INCOME, (t) => {
217
- return {
218
- total: t.income.amount
219
- };
220
- });
221
-
222
- formatters.set(TransactionType.FEE, (t) => {
223
- return {
224
- fee: t.charge.amount,
225
- total: t.charge.amount
226
- };
227
- });
228
-
229
- formatters.set(TransactionType.FEE_UNITS, (t) => {
230
- return {
231
- boughtSold: t.quantity
232
- };
233
- });
234
-
235
- formatters.set(TransactionType.SPLIT, (t) => {
236
- return {
237
- shares: t.quantity,
238
- rate: t.split.numerator.divide(t.split.denominator)
239
- };
240
- });
241
-
242
- formatters.set(TransactionType.VALUATION, (t) => {
196
+ const distributionReinvestFormatter = (t, f) => {
197
+ f.boughtSold = t.quantity;
198
+ f.shares = t.snapshot.open.subtract(t.quantity);
199
+ f.price = t.dividend.price;
200
+ f.fee = t.fee;
201
+ f.rate = t.dividend.rate;
202
+ };
203
+
204
+ const incomeFormatter = (t, f) => {
205
+ f.total = t.income.amount;
206
+ };
207
+
208
+ const feeFormatter = (t, f) => {
209
+ f.fee = t.charge.amount;
210
+ f.total = t.charge.amount;
211
+ };
212
+
213
+ const feeUnitsFormatter = (t, f) => {
214
+ f.boughtSold = t.quantity;
215
+ };
216
+
217
+ const splitFormatter = (t, f) => {
218
+ f.shares = t.quantity;
219
+ f.rate = t.split.numerator.divide(t.split.denominator);
220
+ };
221
+
222
+ const valuationFormatter = (t, f) => {
243
223
  let rate;
244
224
 
245
225
  if (t.valuation.rate) {
@@ -250,39 +230,43 @@ module.exports = (() => {
250
230
  rate = t.valuation.value.divide(t.snapshot.open);
251
231
  }
252
232
 
253
- return {
254
- price: rate
255
- };
256
- });
257
-
258
- formatters.set(TransactionType.DELIST, () => {
259
- return { };
260
- });
261
-
262
- const cashFormatter = (t) => {
263
- return {
264
- total: t.quantity
265
- };
233
+ f.price = rate;
266
234
  };
267
235
 
268
- formatters.set(TransactionType.DEPOSIT, cashFormatter);
269
- formatters.set(TransactionType.WITHDRAWAL, cashFormatter);
270
-
271
- formatters.set(TransactionType.DEBIT, (t) => {
272
- const formatted = cashFormatter(t);
273
-
274
- formatted.description = t.description;
236
+ const cashFormatter = (t, f) => {
237
+ f.total = t.quantity;
238
+ };
275
239
 
276
- return formatted;
277
- });
240
+ const debitFormatter = (t, f) => {
241
+ f.description = t.description;
242
+ };
278
243
 
279
- formatters.set(TransactionType.CREDIT, (t) => {
280
- const formatted = cashFormatter(t);
244
+ const creditFormatter = (t, f) => {
245
+ f.description = t.description;
246
+ };
281
247
 
282
- formatted.description = t.description;
248
+ const formatters = new Map();
283
249
 
284
- return formatted;
285
- });
250
+ formatters.set(TransactionType.BUY, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
251
+ formatters.set(TransactionType.SELL, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
252
+ formatters.set(TransactionType.BUY_SHORT, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
253
+ formatters.set(TransactionType.SELL_SHORT, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
254
+ formatters.set(TransactionType.DIVIDEND, [ basicFormatter, dividendFormatter, averageCostFormatter ]);
255
+ formatters.set(TransactionType.DIVIDEND_STOCK, [ basicFormatter, dividendStockFormatter, averageCostFormatter ]);
256
+ formatters.set(TransactionType.DIVIDEND_REINVEST, [ basicFormatter, dividendReinvestFormatter, averageCostFormatter ]);
257
+ formatters.set(TransactionType.DISTRIBUTION_CASH, [ basicFormatter, distributionCashFormatter, averageCostFormatter ]);
258
+ formatters.set(TransactionType.DISTRIBUTION_FUND, [ basicFormatter, distributionFundFormatter, averageCostFormatter ]);
259
+ formatters.set(TransactionType.DISTRIBUTION_REINVEST, [ basicFormatter, distributionReinvestFormatter, averageCostFormatter ]);
260
+ formatters.set(TransactionType.INCOME, [ basicFormatter, incomeFormatter, averageCostFormatter ]);
261
+ formatters.set(TransactionType.FEE, [ basicFormatter, feeFormatter, averageCostFormatter ]);
262
+ formatters.set(TransactionType.FEE_UNITS, [ basicFormatter, feeUnitsFormatter, averageCostFormatter ]);
263
+ formatters.set(TransactionType.SPLIT, [ basicFormatter, splitFormatter, averageCostFormatter ]);
264
+ formatters.set(TransactionType.VALUATION, [ basicFormatter, valuationFormatter, averageCostFormatter ]);
265
+ formatters.set(TransactionType.DELIST, [ basicFormatter, averageCostFormatter ]);
266
+ formatters.set(TransactionType.DEPOSIT, [ basicFormatter, cashFormatter ]);
267
+ formatters.set(TransactionType.WITHDRAWAL, [ basicFormatter, cashFormatter ]);
268
+ formatters.set(TransactionType.DEBIT, [ basicFormatter, cashFormatter, debitFormatter ]);
269
+ formatters.set(TransactionType.CREDIT, [ basicFormatter, cashFormatter, creditFormatter ]);
286
270
 
287
271
  function getInstrumentTypePriority(type) {
288
272
  if (type === InstrumentType.CASH) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.119",
3
+ "version": "1.2.124",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -455,7 +455,7 @@ module.exports = (() => {
455
455
  *
456
456
  * @public
457
457
  * @param {Number} periods
458
- * @returns {Array.<PositionSummaryRange>}
458
+ * @returns {PositionSummaryRange[]}
459
459
  */
460
460
  getRecentRanges(periods) {
461
461
  const startDate = this.getStartDate(periods);
@@ -468,8 +468,8 @@ module.exports = (() => {
468
468
  * Returns the ranges for the set of {@link Transaction} objects.
469
469
  *
470
470
  * @public
471
- * @param {Array.<Transaction>} transactions
472
- * @returns {Array.<PositionSummaryRange>}
471
+ * @param {Transaction[]} transactions
472
+ * @returns {PositionSummaryRange[]}
473
473
  */
474
474
  getRanges(transactions) {
475
475
  assert.argumentIsArray(transactions, 'transactions');
@@ -482,7 +482,7 @@ module.exports = (() => {
482
482
  *
483
483
  * @public
484
484
  * @param {Day} date
485
- * @return {Array.<PositionSummaryRange>}
485
+ * @return {PositionSummaryRange[]}
486
486
  */
487
487
  getRangesFromDate(date) {
488
488
  assert.argumentIsRequired(date, 'date', Day, 'Day');
@@ -571,8 +571,8 @@ module.exports = (() => {
571
571
  }
572
572
 
573
573
  const yearly = new PositionSummaryFrame('YEARLY', 'year', false, getYearlyRanges, getYearlyStartDate, getYearlyRangeDescription);
574
- const quarterly = new PositionSummaryFrame('QUARTER', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
575
- const monthly = new PositionSummaryFrame('MONTH', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
574
+ const quarterly = new PositionSummaryFrame('QUARTERLY', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
575
+ const monthly = new PositionSummaryFrame('MONTHLY', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
576
576
  const ytd = new PositionSummaryFrame('YTD', 'year-to-date', true, getYearToDateRanges, getYearToDateStartDate, getYearToDateRangeDescription);
577
577
 
578
578
  /**
@@ -632,32 +632,32 @@ module.exports = (() => {
632
632
  }
633
633
 
634
634
  function getMonthlyRanges(transactions) {
635
- const ranges = [ ];
636
-
637
- if (!transactions.length) {
638
- return ranges;
635
+ const ranges = [ ];
636
+
637
+ if (!transactions.length) {
638
+ return ranges;
639
639
  }
640
640
 
641
641
  const first = array.first(transactions);
642
642
  const last = array.last(transactions);
643
643
 
644
644
  const firstDate = first.date;
645
+
645
646
  let lastDate;
646
647
 
647
- lastDate = last.snapshot.open.getIsZero()
648
- ? new Day(last.date.year, last.date.month, last.date.day).addMonths(1)
649
- : Day.getToday();
648
+ if (last.snapshot.open.getIsZero()) {
649
+ lastDate = new Day(last.date.year, last.date.month, last.date.day).addMonths(1);
650
+ } else {
651
+ lastDate = Day.getToday();
652
+ }
653
+
650
654
  lastDate = lastDate.getEndOfMonth();
651
655
 
652
- for (
653
- let end = firstDate.getEndOfMonth();
654
- end.format() <= lastDate.format();
655
- end = end.addMonths(1).getEndOfMonth()
656
- ) {
656
+ for (let end = firstDate.getEndOfMonth(); end.format() <= lastDate.format(); end = end.addMonths(1).getEndOfMonth()) {
657
657
  ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
658
658
  }
659
-
660
- return ranges;
659
+
660
+ return ranges;
661
661
  }
662
662
 
663
663
  function getYearToDateRanges(transactions) {
@@ -694,8 +694,8 @@ module.exports = (() => {
694
694
  }
695
695
 
696
696
  function getMonthlyStartDate(periods, date) {
697
- const today = date || Day.getToday();
698
-
697
+ const today = date || Day.getToday();
698
+
699
699
  return today
700
700
  .subtractMonths(periods)
701
701
  .subtractDays(today.day);
@@ -714,7 +714,7 @@ module.exports = (() => {
714
714
  }
715
715
 
716
716
  function getMonthlyRangeDescription(start, end) {
717
- return '';
717
+ return `Month ended ${end.format()}`;
718
718
  }
719
719
 
720
720
  function getYearToDateRangeDescription(start, end) {
@@ -17622,8 +17622,8 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17622
17622
  ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
17623
17623
  });
17624
17624
 
17625
- it('should have three ranges (assuming the current year is 2018)', () => {
17626
- expect(ranges.length).toEqual(3);
17625
+ it('should have four ranges (assuming the current year is 2019)', () => {
17626
+ expect(ranges.length).toEqual(4);
17627
17627
  });
17628
17628
 
17629
17629
  it('the first range should be from 12-31-2014 to 12-31-2015', () => {
@@ -17640,6 +17640,11 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17640
17640
  expect(ranges[2].start.format()).toEqual('2016-12-31');
17641
17641
  expect(ranges[2].end.format()).toEqual('2017-12-31');
17642
17642
  });
17643
+
17644
+ it('the fourth range should be from 12-31-2017 to 12-31-2018', () => {
17645
+ expect(ranges[3].start.format()).toEqual('2017-12-31');
17646
+ expect(ranges[3].end.format()).toEqual('2018-12-31');
17647
+ });
17643
17648
  });
17644
17649
 
17645
17650
  describe('and yearly position summary ranges are processed for a transaction set closes the same year', () => {
@@ -17715,7 +17720,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17715
17720
  });
17716
17721
  });
17717
17722
 
17718
- describe('and yearly position summary ranges are processed for a transaction set closes in the current next year -- assuming its 2018', () => {
17723
+ describe('and yearly position summary ranges are processed for a transaction set that opens in 2015 and closes in 2017', () => {
17719
17724
  let ranges;
17720
17725
 
17721
17726
  beforeEach(() => {
@@ -17739,7 +17744,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17739
17744
  ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
17740
17745
  });
17741
17746
 
17742
- it('should have two ranges', () => {
17747
+ it('should have three ranges', () => {
17743
17748
  expect(ranges.length).toEqual(3);
17744
17749
  });
17745
17750
 
@@ -17759,7 +17764,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17759
17764
  });
17760
17765
  });
17761
17766
 
17762
- describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
17767
+ describe('and yearly position summary ranges are processed for a transaction set that opens in 2019 and closes in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
17763
17768
  let ranges;
17764
17769
 
17765
17770
  beforeEach(() => {
@@ -17812,7 +17817,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17812
17817
  });
17813
17818
  });
17814
17819
 
17815
- describe('and a year-to-date position summary ranges are processed for a transaction set that closed last year', () => {
17820
+ describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
17816
17821
  let ranges;
17817
17822
 
17818
17823
  beforeEach(() => {
@@ -17841,13 +17846,13 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17841
17846
  });
17842
17847
  });
17843
17848
 
17844
- describe('and a year-to-date position summary ranges are processed for a transaction set that opened this year and has not yet closed', () => {
17849
+ describe('and a year-to-date position summary ranges are processed for a transaction set that opened this year and has not yet closed (assuming its 2019)', () => {
17845
17850
  let ranges;
17846
17851
 
17847
17852
  beforeEach(() => {
17848
17853
  const transactions = [
17849
17854
  {
17850
- date: new Day(2018, 1, 1),
17855
+ date: new Day(2019, 1, 1),
17851
17856
  snapshot: {
17852
17857
  open: new Decimal(100)
17853
17858
  },
@@ -17862,26 +17867,26 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17862
17867
  expect(ranges.length).toEqual(1);
17863
17868
  });
17864
17869
 
17865
- it('the first range should be from 12-31-2017 to 12-31-2015', () => {
17866
- expect(ranges[0].start.format()).toEqual('2017-12-31');
17867
- expect(ranges[0].end.format()).toEqual('2018-12-31');
17870
+ it('the first range should be from 12-31-2018 to 12-31-2019', () => {
17871
+ expect(ranges[0].start.format()).toEqual('2018-12-31');
17872
+ expect(ranges[0].end.format()).toEqual('2019-12-31');
17868
17873
  });
17869
17874
  });
17870
17875
 
17871
- describe('and a year-to-date position summary ranges are processed for a transaction set that opened and closed this year', () => {
17876
+ describe('and a year-to-date position summary ranges are processed for a transaction set that that opened and closed in 2019', () => {
17872
17877
  let ranges;
17873
17878
 
17874
17879
  beforeEach(() => {
17875
17880
  const transactions = [
17876
17881
  {
17877
- date: new Day(2018, 1, 1),
17882
+ date: new Day(2019, 1, 1),
17878
17883
  snapshot: {
17879
17884
  open: new Decimal(1)
17880
17885
  },
17881
17886
  type: TransactionType.BUY
17882
17887
  },
17883
17888
  {
17884
- date: new Day(2018, 1, 2),
17889
+ date: new Day(2019, 1, 2),
17885
17890
  snapshot: {
17886
17891
  open: new Decimal(0)
17887
17892
  },
@@ -17896,62 +17901,20 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17896
17901
  expect(ranges.length).toEqual(1);
17897
17902
  });
17898
17903
 
17899
- it('the first range should be from 12-31-2017 to 12-31-2015', () => {
17900
- expect(ranges[0].start.format()).toEqual('2017-12-31');
17901
- expect(ranges[0].end.format()).toEqual('2018-12-31');
17902
- });
17903
- });
17904
-
17905
- describe('and month position summary ranges are processed for a transaction set that does not close', () => {
17906
- let ranges;
17907
-
17908
- beforeEach(() => {
17909
- const transactions = [
17910
- {
17911
- date: new Day(2018, 10, 20),
17912
- snapshot: {
17913
- open: new Decimal(1)
17914
- },
17915
- type: TransactionType.BUY
17916
- },
17917
- {
17918
- date: new Day(2018, 11, 21),
17919
- snapshot: {
17920
- open: new Decimal(1)
17921
- },
17922
- type: TransactionType.BUY
17923
- }
17924
- ];
17925
-
17926
- ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
17927
- });
17928
-
17929
- it('should have three ranges (assuming the current year is 2018 and the current month is December)', () => {
17930
- expect(ranges.length).toEqual(3);
17931
- });
17932
-
17933
- it('the first range should be from 2018-09-30 to 2018-10-31', () => {
17934
- expect(ranges[0].start.format()).toEqual('2018-09-30');
17935
- expect(ranges[0].end.format()).toEqual('2018-10-31');
17936
- });
17937
-
17938
- it('the second range should be from 2018-10-31 to 2018-11-30', () => {
17939
- expect(ranges[1].start.format()).toEqual('2018-10-31');
17940
- expect(ranges[1].end.format()).toEqual('2018-11-30');
17941
- });
17942
-
17943
- it('the third range should be from 2018-10-31 to 2018-11-30', () => {
17944
- expect(ranges[2].start.format()).toEqual('2018-11-30');
17945
- expect(ranges[2].end.format()).toEqual('2018-12-31');
17904
+ it('the first range should be from 12-31-2018 to 12-31-2019', () => {
17905
+ expect(ranges[0].start.format()).toEqual('2018-12-31');
17906
+ expect(ranges[0].end.format()).toEqual('2019-12-31');
17946
17907
  });
17947
17908
  });
17948
17909
 
17949
17910
  describe('and getting the start date for yearly frames', () => {
17950
- describe('for one year ago', function() {
17911
+ describe('for one year ago', () => {
17951
17912
  let start;
17913
+ let today;
17952
17914
 
17953
17915
  beforeEach(() => {
17954
17916
  start = PositionSummaryFrame.YEARLY.getStartDate(1);
17917
+ today = new Date();
17955
17918
  });
17956
17919
 
17957
17920
  it('should be in December', () => {
@@ -17963,15 +17926,17 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17963
17926
  });
17964
17927
 
17965
17928
  it('should be two years ago', () => {
17966
- expect(start.year).toEqual(Day.getToday().year - 2);
17929
+ expect(start.year).toEqual(today.getFullYear() - 2);
17967
17930
  });
17968
17931
  });
17969
17932
 
17970
- describe('for two years ago', function() {
17933
+ describe('for two years ago', () => {
17971
17934
  let start;
17935
+ let today;
17972
17936
 
17973
17937
  beforeEach(() => {
17974
17938
  start = PositionSummaryFrame.YEARLY.getStartDate(2);
17939
+ today = new Date();
17975
17940
  });
17976
17941
 
17977
17942
  it('should be in December', () => {
@@ -17982,61 +17947,12 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17982
17947
  expect(start.day).toEqual(31);
17983
17948
  });
17984
17949
 
17985
- it('should be two years ago', () => {
17986
- expect(start.year).toEqual(Day.getToday().year - 3);
17987
- });
17988
- });
17989
- });
17990
-
17991
-
17992
-
17993
-
17994
- ////
17995
-
17996
- describe('and getting the start date for monthly frames', () => {
17997
- describe('for one month ago', function () {
17998
- let start;
17999
-
18000
- beforeEach(() => {
18001
- start = PositionSummaryFrame.MONTHLY.getStartDate(1);
18002
- });
18003
-
18004
- it('should be on the last day of month', () => {
18005
- const today = Day.getToday();
18006
-
18007
- expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 2));
18008
- });
18009
-
18010
- it('should be month ago', () => {
18011
- expect(start.month).toEqual(Day.getToday().month - 2);
17950
+ it('should be three years ago', () => {
17951
+ expect(start.year).toEqual(today.getFullYear() - 3);
18012
17952
  });
18013
17953
  });
18014
-
18015
- describe('for three months ago', function () {
18016
- let start;
18017
-
18018
- beforeEach(() => {
18019
- start = PositionSummaryFrame.MONTHLY.getStartDate(3);
18020
- });
18021
-
18022
- it('should be on the last day of month', () => {
18023
- const today = Day.getToday();
18024
-
18025
- expect(start.day).toEqual(Day.getDaysInMonth(today.year, today.month - 4));
18026
- });
18027
-
18028
- it('should be 3 month ago', () => {
18029
- expect(start.month).toEqual(Day.getToday().month - 4);
18030
- });
18031
- });
18032
17954
  });
18033
17955
 
18034
- ////
18035
-
18036
-
18037
-
18038
-
18039
-
18040
17956
  describe('and recent ranges are calculated', () => {
18041
17957
  let todayYear;
18042
17958
  let todayMonth;
@@ -31,8 +31,8 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
31
31
  ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
32
32
  });
33
33
 
34
- it('should have three ranges (assuming the current year is 2018)', () => {
35
- expect(ranges.length).toEqual(3);
34
+ it('should have four ranges (assuming the current year is 2019)', () => {
35
+ expect(ranges.length).toEqual(4);
36
36
  });
37
37
 
38
38
  it('the first range should be from 12-31-2014 to 12-31-2015', () => {
@@ -49,6 +49,11 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
49
49
  expect(ranges[2].start.format()).toEqual('2016-12-31');
50
50
  expect(ranges[2].end.format()).toEqual('2017-12-31');
51
51
  });
52
+
53
+ it('the fourth range should be from 12-31-2017 to 12-31-2018', () => {
54
+ expect(ranges[3].start.format()).toEqual('2017-12-31');
55
+ expect(ranges[3].end.format()).toEqual('2018-12-31');
56
+ });
52
57
  });
53
58
 
54
59
  describe('and yearly position summary ranges are processed for a transaction set closes the same year', () => {
@@ -124,7 +129,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
124
129
  });
125
130
  });
126
131
 
127
- describe('and yearly position summary ranges are processed for a transaction set closes in the current next year -- assuming its 2018', () => {
132
+ describe('and yearly position summary ranges are processed for a transaction set that opens in 2015 and closes in 2017', () => {
128
133
  let ranges;
129
134
 
130
135
  beforeEach(() => {
@@ -148,7 +153,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
148
153
  ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
149
154
  });
150
155
 
151
- it('should have two ranges', () => {
156
+ it('should have three ranges', () => {
152
157
  expect(ranges.length).toEqual(3);
153
158
  });
154
159
 
@@ -168,7 +173,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
168
173
  });
169
174
  });
170
175
 
171
- describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
176
+ describe('and yearly position summary ranges are processed for a transaction set that opens in 2019 and closes in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
172
177
  let ranges;
173
178
 
174
179
  beforeEach(() => {
@@ -221,7 +226,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
221
226
  });
222
227
  });
223
228
 
224
- describe('and a year-to-date position summary ranges are processed for a transaction set that closed last year', () => {
229
+ describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
225
230
  let ranges;
226
231
 
227
232
  beforeEach(() => {
@@ -250,13 +255,13 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
250
255
  });
251
256
  });
252
257
 
253
- describe('and a year-to-date position summary ranges are processed for a transaction set that opened this year and has not yet closed', () => {
258
+ describe('and a year-to-date position summary ranges are processed for a transaction set that opened this year and has not yet closed (assuming its 2019)', () => {
254
259
  let ranges;
255
260
 
256
261
  beforeEach(() => {
257
262
  const transactions = [
258
263
  {
259
- date: new Day(2018, 1, 1),
264
+ date: new Day(2019, 1, 1),
260
265
  snapshot: {
261
266
  open: new Decimal(100)
262
267
  },
@@ -271,26 +276,26 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
271
276
  expect(ranges.length).toEqual(1);
272
277
  });
273
278
 
274
- it('the first range should be from 12-31-2017 to 12-31-2015', () => {
275
- expect(ranges[0].start.format()).toEqual('2017-12-31');
276
- expect(ranges[0].end.format()).toEqual('2018-12-31');
279
+ it('the first range should be from 12-31-2018 to 12-31-2019', () => {
280
+ expect(ranges[0].start.format()).toEqual('2018-12-31');
281
+ expect(ranges[0].end.format()).toEqual('2019-12-31');
277
282
  });
278
283
  });
279
284
 
280
- describe('and a year-to-date position summary ranges are processed for a transaction set that opened and closed this year', () => {
285
+ describe('and a year-to-date position summary ranges are processed for a transaction set that that opened and closed in 2019', () => {
281
286
  let ranges;
282
287
 
283
288
  beforeEach(() => {
284
289
  const transactions = [
285
290
  {
286
- date: new Day(2018, 1, 1),
291
+ date: new Day(2019, 1, 1),
287
292
  snapshot: {
288
293
  open: new Decimal(1)
289
294
  },
290
295
  type: TransactionType.BUY
291
296
  },
292
297
  {
293
- date: new Day(2018, 1, 2),
298
+ date: new Day(2019, 1, 2),
294
299
  snapshot: {
295
300
  open: new Decimal(0)
296
301
  },
@@ -305,62 +310,20 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
305
310
  expect(ranges.length).toEqual(1);
306
311
  });
307
312
 
308
- it('the first range should be from 12-31-2017 to 12-31-2015', () => {
309
- expect(ranges[0].start.format()).toEqual('2017-12-31');
310
- expect(ranges[0].end.format()).toEqual('2018-12-31');
311
- });
312
- });
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');
313
+ it('the first range should be from 12-31-2018 to 12-31-2019', () => {
314
+ expect(ranges[0].start.format()).toEqual('2018-12-31');
315
+ expect(ranges[0].end.format()).toEqual('2019-12-31');
355
316
  });
356
317
  });
357
318
 
358
319
  describe('and getting the start date for yearly frames', () => {
359
- describe('for one year ago', function() {
320
+ describe('for one year ago', () => {
360
321
  let start;
322
+ let today;
361
323
 
362
324
  beforeEach(() => {
363
325
  start = PositionSummaryFrame.YEARLY.getStartDate(1);
326
+ today = new Date();
364
327
  });
365
328
 
366
329
  it('should be in December', () => {
@@ -372,15 +335,17 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
372
335
  });
373
336
 
374
337
  it('should be two years ago', () => {
375
- expect(start.year).toEqual(Day.getToday().year - 2);
338
+ expect(start.year).toEqual(today.getFullYear() - 2);
376
339
  });
377
340
  });
378
341
 
379
- describe('for two years ago', function() {
342
+ describe('for two years ago', () => {
380
343
  let start;
344
+ let today;
381
345
 
382
346
  beforeEach(() => {
383
347
  start = PositionSummaryFrame.YEARLY.getStartDate(2);
348
+ today = new Date();
384
349
  });
385
350
 
386
351
  it('should be in December', () => {
@@ -391,61 +356,12 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
391
356
  expect(start.day).toEqual(31);
392
357
  });
393
358
 
394
- it('should be two years ago', () => {
395
- expect(start.year).toEqual(Day.getToday().year - 3);
359
+ it('should be three years ago', () => {
360
+ expect(start.year).toEqual(today.getFullYear() - 3);
396
361
  });
397
362
  });
398
363
  });
399
364
 
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
-
449
365
  describe('and recent ranges are calculated', () => {
450
366
  let todayYear;
451
367
  let todayMonth;