@barchart/portfolio-api-common 1.2.123 → 1.2.127

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.
@@ -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,36 @@ module.exports = (() => {
241
241
  }
242
242
 
243
243
  function getMonthlyRanges(transactions) {
244
- const ranges = [ ];
245
-
246
- if (!transactions.length) {
247
- return ranges;
248
- }
244
+ const ranges = [ ];
245
+
246
+ if (transactions.length !== 0) {
247
+ const today = Day.getToday();
248
+
249
+ const first = array.first(transactions);
250
+ const last = array.last(transactions);
251
+
252
+ const firstDate = first.date;
253
+
254
+ let lastDate;
249
255
 
250
- const first = array.first(transactions);
251
- const last = array.last(transactions);
256
+ if (last.snapshot.open.getIsZero()) {
257
+ lastDate = last.date;
258
+ } else {
259
+ lastDate = today;
260
+ }
252
261
 
253
- const firstDate = first.date;
254
- let lastDate;
262
+ if (today.month === lastDate.month && today.year === lastDate.year) {
263
+ lastDate = lastDate.subtractMonths(1);
264
+ }
255
265
 
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();
266
+ lastDate = lastDate.getEndOfMonth();
260
267
 
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));
268
+ for (let end = firstDate.getEndOfMonth(); !end.getIsAfter(lastDate); end = end.addMonths(1).getEndOfMonth()) {
269
+ ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
270
+ }
267
271
  }
268
-
269
- return ranges;
272
+
273
+ return ranges;
270
274
  }
271
275
 
272
276
  function getYearToDateRanges(transactions) {
@@ -303,8 +307,8 @@ module.exports = (() => {
303
307
  }
304
308
 
305
309
  function getMonthlyStartDate(periods, date) {
306
- const today = date || Day.getToday();
307
-
310
+ const today = date || Day.getToday();
311
+
308
312
  return today
309
313
  .subtractMonths(periods)
310
314
  .subtractDays(today.day);
@@ -323,7 +327,7 @@ module.exports = (() => {
323
327
  }
324
328
 
325
329
  function getMonthlyRangeDescription(start, end) {
326
- return '';
330
+ return `Month ended ${end.format()}`;
327
331
  }
328
332
 
329
333
  function getYearToDateRangeDescription(start, end) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.123",
3
+ "version": "1.2.127",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -23,9 +23,10 @@
23
23
  "gulp-bump": "~1.0.0",
24
24
  "gulp-git": "~1.6.0",
25
25
  "gulp-jasmine": "^2.2.1",
26
- "gulp-jshint": "~1.11.2",
26
+ "gulp-jshint": "~2.1.0",
27
27
  "gulp-util": "^3.0.7",
28
28
  "jsdoc": "^3.5.5",
29
+ "jshint": "2.9.5",
29
30
  "run-sequence": "~1.1.4",
30
31
  "vinyl-buffer": "^1.0.0",
31
32
  "vinyl-source-stream": "^1.1.0"
@@ -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,36 @@ module.exports = (() => {
632
632
  }
633
633
 
634
634
  function getMonthlyRanges(transactions) {
635
- const ranges = [ ];
636
-
637
- if (!transactions.length) {
638
- return ranges;
639
- }
635
+ const ranges = [ ];
640
636
 
641
- const first = array.first(transactions);
642
- const last = array.last(transactions);
637
+ if (transactions.length !== 0) {
638
+ const today = Day.getToday();
643
639
 
644
- const firstDate = first.date;
645
- let lastDate;
640
+ const first = array.first(transactions);
641
+ const last = array.last(transactions);
642
+
643
+ const firstDate = first.date;
646
644
 
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();
645
+ let lastDate;
646
+
647
+ if (last.snapshot.open.getIsZero()) {
648
+ lastDate = last.date;
649
+ } else {
650
+ lastDate = today;
651
+ }
652
+
653
+ if (today.month === lastDate.month && today.year === lastDate.year) {
654
+ lastDate = lastDate.subtractMonths(1);
655
+ }
651
656
 
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));
657
+ lastDate = lastDate.getEndOfMonth();
658
+
659
+ for (let end = firstDate.getEndOfMonth(); !end.getIsAfter(lastDate); end = end.addMonths(1).getEndOfMonth()) {
660
+ ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
661
+ }
658
662
  }
659
-
660
- return ranges;
663
+
664
+ return ranges;
661
665
  }
662
666
 
663
667
  function getYearToDateRanges(transactions) {
@@ -694,8 +698,8 @@ module.exports = (() => {
694
698
  }
695
699
 
696
700
  function getMonthlyStartDate(periods, date) {
697
- const today = date || Day.getToday();
698
-
701
+ const today = date || Day.getToday();
702
+
699
703
  return today
700
704
  .subtractMonths(periods)
701
705
  .subtractDays(today.day);
@@ -714,7 +718,7 @@ module.exports = (() => {
714
718
  }
715
719
 
716
720
  function getMonthlyRangeDescription(start, end) {
717
- return '';
721
+ return `Month ended ${end.format()}`;
718
722
  }
719
723
 
720
724
  function getYearToDateRangeDescription(start, end) {
@@ -14020,22 +14024,36 @@ moment.tz.load(require('./data/packed/latest.json'));
14020
14024
  function createDate (y, m, d, h, M, s, ms) {
14021
14025
  // can't just apply() to create a date:
14022
14026
  // https://stackoverflow.com/q/181348
14023
- var date = new Date(y, m, d, h, M, s, ms);
14024
-
14027
+ var date;
14025
14028
  // the date constructor remaps years 0-99 to 1900-1999
14026
- if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
14027
- date.setFullYear(y);
14029
+ if (y < 100 && y >= 0) {
14030
+ // preserve leap years using a full 400 year cycle, then reset
14031
+ date = new Date(y + 400, m, d, h, M, s, ms);
14032
+ if (isFinite(date.getFullYear())) {
14033
+ date.setFullYear(y);
14034
+ }
14035
+ } else {
14036
+ date = new Date(y, m, d, h, M, s, ms);
14028
14037
  }
14038
+
14029
14039
  return date;
14030
14040
  }
14031
14041
 
14032
14042
  function createUTCDate (y) {
14033
- var date = new Date(Date.UTC.apply(null, arguments));
14034
-
14043
+ var date;
14035
14044
  // the Date.UTC function remaps years 0-99 to 1900-1999
14036
- if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
14037
- date.setUTCFullYear(y);
14045
+ if (y < 100 && y >= 0) {
14046
+ var args = Array.prototype.slice.call(arguments);
14047
+ // preserve leap years using a full 400 year cycle, then reset
14048
+ args[0] = y + 400;
14049
+ date = new Date(Date.UTC.apply(null, args));
14050
+ if (isFinite(date.getUTCFullYear())) {
14051
+ date.setUTCFullYear(y);
14052
+ }
14053
+ } else {
14054
+ date = new Date(Date.UTC.apply(null, arguments));
14038
14055
  }
14056
+
14039
14057
  return date;
14040
14058
  }
14041
14059
 
@@ -14137,7 +14155,7 @@ moment.tz.load(require('./data/packed/latest.json'));
14137
14155
 
14138
14156
  var defaultLocaleWeek = {
14139
14157
  dow : 0, // Sunday is the first day of the week.
14140
- doy : 6 // The week that contains Jan 1st is the first week of the year.
14158
+ doy : 6 // The week that contains Jan 6th is the first week of the year.
14141
14159
  };
14142
14160
 
14143
14161
  function localeFirstDayOfWeek () {
@@ -14246,25 +14264,28 @@ moment.tz.load(require('./data/packed/latest.json'));
14246
14264
  }
14247
14265
 
14248
14266
  // LOCALES
14267
+ function shiftWeekdays (ws, n) {
14268
+ return ws.slice(n, 7).concat(ws.slice(0, n));
14269
+ }
14249
14270
 
14250
14271
  var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
14251
14272
  function localeWeekdays (m, format) {
14252
- if (!m) {
14253
- return isArray(this._weekdays) ? this._weekdays :
14254
- this._weekdays['standalone'];
14255
- }
14256
- return isArray(this._weekdays) ? this._weekdays[m.day()] :
14257
- this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
14273
+ var weekdays = isArray(this._weekdays) ? this._weekdays :
14274
+ this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone'];
14275
+ return (m === true) ? shiftWeekdays(weekdays, this._week.dow)
14276
+ : (m) ? weekdays[m.day()] : weekdays;
14258
14277
  }
14259
14278
 
14260
14279
  var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
14261
14280
  function localeWeekdaysShort (m) {
14262
- return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
14281
+ return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow)
14282
+ : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
14263
14283
  }
14264
14284
 
14265
14285
  var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
14266
14286
  function localeWeekdaysMin (m) {
14267
- return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
14287
+ return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow)
14288
+ : (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
14268
14289
  }
14269
14290
 
14270
14291
  function handleStrictParse$1(weekdayName, format, strict) {
@@ -15013,13 +15034,13 @@ moment.tz.load(require('./data/packed/latest.json'));
15013
15034
  weekdayOverflow = true;
15014
15035
  }
15015
15036
  } else if (w.e != null) {
15016
- // local weekday -- counting starts from begining of week
15037
+ // local weekday -- counting starts from beginning of week
15017
15038
  weekday = w.e + dow;
15018
15039
  if (w.e < 0 || w.e > 6) {
15019
15040
  weekdayOverflow = true;
15020
15041
  }
15021
15042
  } else {
15022
- // default to begining of week
15043
+ // default to beginning of week
15023
15044
  weekday = dow;
15024
15045
  }
15025
15046
  }
@@ -15613,7 +15634,7 @@ moment.tz.load(require('./data/packed/latest.json'));
15613
15634
  years = normalizedInput.year || 0,
15614
15635
  quarters = normalizedInput.quarter || 0,
15615
15636
  months = normalizedInput.month || 0,
15616
- weeks = normalizedInput.week || 0,
15637
+ weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
15617
15638
  days = normalizedInput.day || 0,
15618
15639
  hours = normalizedInput.hour || 0,
15619
15640
  minutes = normalizedInput.minute || 0,
@@ -15917,7 +15938,7 @@ moment.tz.load(require('./data/packed/latest.json'));
15917
15938
  ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
15918
15939
  };
15919
15940
  } else if (!!(match = isoRegex.exec(input))) {
15920
- sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
15941
+ sign = (match[1] === '-') ? -1 : 1;
15921
15942
  duration = {
15922
15943
  y : parseIso(match[2], sign),
15923
15944
  M : parseIso(match[3], sign),
@@ -15959,7 +15980,7 @@ moment.tz.load(require('./data/packed/latest.json'));
15959
15980
  }
15960
15981
 
15961
15982
  function positiveMomentsDifference(base, other) {
15962
- var res = {milliseconds: 0, months: 0};
15983
+ var res = {};
15963
15984
 
15964
15985
  res.months = other.month() - base.month() +
15965
15986
  (other.year() - base.year()) * 12;
@@ -16068,7 +16089,7 @@ moment.tz.load(require('./data/packed/latest.json'));
16068
16089
  if (!(this.isValid() && localInput.isValid())) {
16069
16090
  return false;
16070
16091
  }
16071
- units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
16092
+ units = normalizeUnits(units) || 'millisecond';
16072
16093
  if (units === 'millisecond') {
16073
16094
  return this.valueOf() > localInput.valueOf();
16074
16095
  } else {
@@ -16081,7 +16102,7 @@ moment.tz.load(require('./data/packed/latest.json'));
16081
16102
  if (!(this.isValid() && localInput.isValid())) {
16082
16103
  return false;
16083
16104
  }
16084
- units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
16105
+ units = normalizeUnits(units) || 'millisecond';
16085
16106
  if (units === 'millisecond') {
16086
16107
  return this.valueOf() < localInput.valueOf();
16087
16108
  } else {
@@ -16090,9 +16111,14 @@ moment.tz.load(require('./data/packed/latest.json'));
16090
16111
  }
16091
16112
 
16092
16113
  function isBetween (from, to, units, inclusivity) {
16114
+ var localFrom = isMoment(from) ? from : createLocal(from),
16115
+ localTo = isMoment(to) ? to : createLocal(to);
16116
+ if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
16117
+ return false;
16118
+ }
16093
16119
  inclusivity = inclusivity || '()';
16094
- return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
16095
- (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
16120
+ return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) &&
16121
+ (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
16096
16122
  }
16097
16123
 
16098
16124
  function isSame (input, units) {
@@ -16101,7 +16127,7 @@ moment.tz.load(require('./data/packed/latest.json'));
16101
16127
  if (!(this.isValid() && localInput.isValid())) {
16102
16128
  return false;
16103
16129
  }
16104
- units = normalizeUnits(units || 'millisecond');
16130
+ units = normalizeUnits(units) || 'millisecond';
16105
16131
  if (units === 'millisecond') {
16106
16132
  return this.valueOf() === localInput.valueOf();
16107
16133
  } else {
@@ -16111,11 +16137,11 @@ moment.tz.load(require('./data/packed/latest.json'));
16111
16137
  }
16112
16138
 
16113
16139
  function isSameOrAfter (input, units) {
16114
- return this.isSame(input, units) || this.isAfter(input,units);
16140
+ return this.isSame(input, units) || this.isAfter(input, units);
16115
16141
  }
16116
16142
 
16117
16143
  function isSameOrBefore (input, units) {
16118
- return this.isSame(input, units) || this.isBefore(input,units);
16144
+ return this.isSame(input, units) || this.isBefore(input, units);
16119
16145
  }
16120
16146
 
16121
16147
  function diff (input, units, asFloat) {
@@ -16292,62 +16318,130 @@ moment.tz.load(require('./data/packed/latest.json'));
16292
16318
  return this._locale;
16293
16319
  }
16294
16320
 
16321
+ var MS_PER_SECOND = 1000;
16322
+ var MS_PER_MINUTE = 60 * MS_PER_SECOND;
16323
+ var MS_PER_HOUR = 60 * MS_PER_MINUTE;
16324
+ var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
16325
+
16326
+ // actual modulo - handles negative numbers (for dates before 1970):
16327
+ function mod$1(dividend, divisor) {
16328
+ return (dividend % divisor + divisor) % divisor;
16329
+ }
16330
+
16331
+ function localStartOfDate(y, m, d) {
16332
+ // the date constructor remaps years 0-99 to 1900-1999
16333
+ if (y < 100 && y >= 0) {
16334
+ // preserve leap years using a full 400 year cycle, then reset
16335
+ return new Date(y + 400, m, d) - MS_PER_400_YEARS;
16336
+ } else {
16337
+ return new Date(y, m, d).valueOf();
16338
+ }
16339
+ }
16340
+
16341
+ function utcStartOfDate(y, m, d) {
16342
+ // Date.UTC remaps years 0-99 to 1900-1999
16343
+ if (y < 100 && y >= 0) {
16344
+ // preserve leap years using a full 400 year cycle, then reset
16345
+ return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
16346
+ } else {
16347
+ return Date.UTC(y, m, d);
16348
+ }
16349
+ }
16350
+
16295
16351
  function startOf (units) {
16352
+ var time;
16296
16353
  units = normalizeUnits(units);
16297
- // the following switch intentionally omits break keywords
16298
- // to utilize falling through the cases.
16354
+ if (units === undefined || units === 'millisecond' || !this.isValid()) {
16355
+ return this;
16356
+ }
16357
+
16358
+ var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
16359
+
16299
16360
  switch (units) {
16300
16361
  case 'year':
16301
- this.month(0);
16302
- /* falls through */
16362
+ time = startOfDate(this.year(), 0, 1);
16363
+ break;
16303
16364
  case 'quarter':
16365
+ time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
16366
+ break;
16304
16367
  case 'month':
16305
- this.date(1);
16306
- /* falls through */
16368
+ time = startOfDate(this.year(), this.month(), 1);
16369
+ break;
16307
16370
  case 'week':
16371
+ time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
16372
+ break;
16308
16373
  case 'isoWeek':
16374
+ time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
16375
+ break;
16309
16376
  case 'day':
16310
16377
  case 'date':
16311
- this.hours(0);
16312
- /* falls through */
16378
+ time = startOfDate(this.year(), this.month(), this.date());
16379
+ break;
16313
16380
  case 'hour':
16314
- this.minutes(0);
16315
- /* falls through */
16381
+ time = this._d.valueOf();
16382
+ time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
16383
+ break;
16316
16384
  case 'minute':
16317
- this.seconds(0);
16318
- /* falls through */
16385
+ time = this._d.valueOf();
16386
+ time -= mod$1(time, MS_PER_MINUTE);
16387
+ break;
16319
16388
  case 'second':
16320
- this.milliseconds(0);
16321
- }
16322
-
16323
- // weeks are a special case
16324
- if (units === 'week') {
16325
- this.weekday(0);
16326
- }
16327
- if (units === 'isoWeek') {
16328
- this.isoWeekday(1);
16329
- }
16330
-
16331
- // quarters are also special
16332
- if (units === 'quarter') {
16333
- this.month(Math.floor(this.month() / 3) * 3);
16389
+ time = this._d.valueOf();
16390
+ time -= mod$1(time, MS_PER_SECOND);
16391
+ break;
16334
16392
  }
16335
16393
 
16394
+ this._d.setTime(time);
16395
+ hooks.updateOffset(this, true);
16336
16396
  return this;
16337
16397
  }
16338
16398
 
16339
16399
  function endOf (units) {
16400
+ var time;
16340
16401
  units = normalizeUnits(units);
16341
- if (units === undefined || units === 'millisecond') {
16402
+ if (units === undefined || units === 'millisecond' || !this.isValid()) {
16342
16403
  return this;
16343
16404
  }
16344
16405
 
16345
- // 'date' is an alias for 'day', so it should be considered as such.
16346
- if (units === 'date') {
16347
- units = 'day';
16406
+ var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
16407
+
16408
+ switch (units) {
16409
+ case 'year':
16410
+ time = startOfDate(this.year() + 1, 0, 1) - 1;
16411
+ break;
16412
+ case 'quarter':
16413
+ time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
16414
+ break;
16415
+ case 'month':
16416
+ time = startOfDate(this.year(), this.month() + 1, 1) - 1;
16417
+ break;
16418
+ case 'week':
16419
+ time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
16420
+ break;
16421
+ case 'isoWeek':
16422
+ time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
16423
+ break;
16424
+ case 'day':
16425
+ case 'date':
16426
+ time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
16427
+ break;
16428
+ case 'hour':
16429
+ time = this._d.valueOf();
16430
+ time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
16431
+ break;
16432
+ case 'minute':
16433
+ time = this._d.valueOf();
16434
+ time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
16435
+ break;
16436
+ case 'second':
16437
+ time = this._d.valueOf();
16438
+ time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
16439
+ break;
16348
16440
  }
16349
16441
 
16350
- return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
16442
+ this._d.setTime(time);
16443
+ hooks.updateOffset(this, true);
16444
+ return this;
16351
16445
  }
16352
16446
 
16353
16447
  function valueOf () {
@@ -17053,10 +17147,14 @@ moment.tz.load(require('./data/packed/latest.json'));
17053
17147
 
17054
17148
  units = normalizeUnits(units);
17055
17149
 
17056
- if (units === 'month' || units === 'year') {
17057
- days = this._days + milliseconds / 864e5;
17150
+ if (units === 'month' || units === 'quarter' || units === 'year') {
17151
+ days = this._days + milliseconds / 864e5;
17058
17152
  months = this._months + daysToMonths(days);
17059
- return units === 'month' ? months : months / 12;
17153
+ switch (units) {
17154
+ case 'month': return months;
17155
+ case 'quarter': return months / 3;
17156
+ case 'year': return months / 12;
17157
+ }
17060
17158
  } else {
17061
17159
  // handle milliseconds separately because of floating point math errors (issue #1867)
17062
17160
  days = this._days + Math.round(monthsToDays(this._months));
@@ -17099,6 +17197,7 @@ moment.tz.load(require('./data/packed/latest.json'));
17099
17197
  var asDays = makeAs('d');
17100
17198
  var asWeeks = makeAs('w');
17101
17199
  var asMonths = makeAs('M');
17200
+ var asQuarters = makeAs('Q');
17102
17201
  var asYears = makeAs('y');
17103
17202
 
17104
17203
  function clone$1 () {
@@ -17290,6 +17389,7 @@ moment.tz.load(require('./data/packed/latest.json'));
17290
17389
  proto$2.asDays = asDays;
17291
17390
  proto$2.asWeeks = asWeeks;
17292
17391
  proto$2.asMonths = asMonths;
17392
+ proto$2.asQuarters = asQuarters;
17293
17393
  proto$2.asYears = asYears;
17294
17394
  proto$2.valueOf = valueOf$1;
17295
17395
  proto$2._bubble = bubble;
@@ -17334,7 +17434,7 @@ moment.tz.load(require('./data/packed/latest.json'));
17334
17434
  // Side effect imports
17335
17435
 
17336
17436
 
17337
- hooks.version = '2.22.2';
17437
+ hooks.version = '2.24.0';
17338
17438
 
17339
17439
  setHookCallback(createLocal);
17340
17440
 
@@ -17375,7 +17475,7 @@ moment.tz.load(require('./data/packed/latest.json'));
17375
17475
  TIME: 'HH:mm', // <input type="time" />
17376
17476
  TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
17377
17477
  TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
17378
- WEEK: 'YYYY-[W]WW', // <input type="week" />
17478
+ WEEK: 'GGGG-[W]WW', // <input type="week" />
17379
17479
  MONTH: 'YYYY-MM' // <input type="month" />
17380
17480
  };
17381
17481
 
@@ -17764,7 +17864,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17764
17864
  });
17765
17865
  });
17766
17866
 
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', () => {
17867
+ 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', () => {
17768
17868
  let ranges;
17769
17869
 
17770
17870
  beforeEach(() => {
@@ -17817,6 +17917,164 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17817
17917
  });
17818
17918
  });
17819
17919
 
17920
+ describe('and yearly position summary ranges are processed for a transaction set that opens in the current year', () => {
17921
+ let ranges;
17922
+
17923
+ beforeEach(() => {
17924
+ const transactions = [
17925
+ {
17926
+ date: Day.getToday(),
17927
+ snapshot: {
17928
+ open: new Decimal(1)
17929
+ },
17930
+ type: TransactionType.BUY
17931
+ }
17932
+ ];
17933
+
17934
+ ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
17935
+ });
17936
+
17937
+ it('should have zero ranges', () => {
17938
+ expect(ranges.length).toEqual(0);
17939
+ });
17940
+ });
17941
+
17942
+ describe('and monthly position summary ranges are processed for a transaction set that does not close', () => {
17943
+ let ranges;
17944
+
17945
+ beforeEach(() => {
17946
+ const transactions = [
17947
+ {
17948
+ date: new Day(2018, 12, 20),
17949
+ snapshot: {
17950
+ open: new Decimal(1)
17951
+ },
17952
+ type: TransactionType.BUY
17953
+ },
17954
+ {
17955
+ date: new Day(2019, 2, 21),
17956
+ snapshot: {
17957
+ open: new Decimal(1)
17958
+ },
17959
+ type: TransactionType.BUY
17960
+ }
17961
+ ];
17962
+
17963
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
17964
+ });
17965
+
17966
+ it('should have at least two ranges', () => {
17967
+ expect(ranges.length > 1).toEqual(true);
17968
+ });
17969
+
17970
+ it('the first range should be from 11-30-2018 to 12-31-2018', () => {
17971
+ expect(ranges[0].start.format()).toEqual('2018-11-30');
17972
+ expect(ranges[0].end.format()).toEqual('2018-12-31');
17973
+ });
17974
+
17975
+ it('the last range should be for the previous month', () => {
17976
+ const today = Day.getToday();
17977
+
17978
+ expect(ranges[ranges.length - 1].start.format()).toEqual(today.subtractMonths(2).getEndOfMonth().format());
17979
+ expect(ranges[ranges.length - 1].end.format()).toEqual(today.subtractMonths(1).getEndOfMonth().format());
17980
+ });
17981
+ });
17982
+
17983
+ describe('and monthly position summary ranges are processed for a transaction set closes the same month', () => {
17984
+ let ranges;
17985
+
17986
+ beforeEach(() => {
17987
+ const transactions = [
17988
+ {
17989
+ date: new Day(2018, 12, 1),
17990
+ snapshot: {
17991
+ open: new Decimal(1)
17992
+ },
17993
+ type: TransactionType.BUY
17994
+ },
17995
+ {
17996
+ date: new Day(2018, 12, 31),
17997
+ snapshot: {
17998
+ open: new Decimal(0)
17999
+ },
18000
+ type: TransactionType.SELL
18001
+ }
18002
+ ];
18003
+
18004
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
18005
+ });
18006
+
18007
+ it('should have one range', () => {
18008
+ expect(ranges.length).toEqual(1);
18009
+ });
18010
+
18011
+ it('the first range should be from 11-30-2018 to 12-31-2018', () => {
18012
+ expect(ranges[0].start.format()).toEqual('2018-11-30');
18013
+ expect(ranges[0].end.format()).toEqual('2018-12-31');
18014
+ });
18015
+ });
18016
+
18017
+ describe('and monthly position summary ranges are processed for a transaction set closes the next month', () => {
18018
+ let ranges;
18019
+
18020
+ beforeEach(() => {
18021
+ const transactions = [
18022
+ {
18023
+ date: new Day(2015, 10, 20),
18024
+ snapshot: {
18025
+ open: new Decimal(1)
18026
+ },
18027
+ type: TransactionType.BUY
18028
+ },
18029
+ {
18030
+ date: new Day(2015, 11, 20),
18031
+ snapshot: {
18032
+ open: new Decimal(0)
18033
+ },
18034
+ type: TransactionType.SELL
18035
+ }
18036
+ ];
18037
+
18038
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
18039
+ });
18040
+
18041
+ it('should have two ranges', () => {
18042
+ expect(ranges.length).toEqual(2);
18043
+ });
18044
+
18045
+ it('the first range should be from 09-30-2015 to 10-31-2015', () => {
18046
+ expect(ranges[0].start.format()).toEqual('2015-09-30');
18047
+ expect(ranges[0].end.format()).toEqual('2015-10-31');
18048
+ });
18049
+
18050
+ it('the second range should be from 10-31-2015 to 11-30-2015', () => {
18051
+ expect(ranges[1].start.format()).toEqual('2015-10-31');
18052
+ expect(ranges[1].end.format()).toEqual('2015-11-30');
18053
+ });
18054
+ });
18055
+
18056
+ describe('and monthly position summary ranges are processed for a transaction set that opens in the current month', () => {
18057
+ let ranges;
18058
+
18059
+ beforeEach(() => {
18060
+ const transactions = [
18061
+ {
18062
+ date: Day.getToday(),
18063
+ snapshot: {
18064
+ open: new Decimal(1)
18065
+ },
18066
+ type: TransactionType.BUY
18067
+ }
18068
+ ];
18069
+
18070
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
18071
+ });
18072
+
18073
+ it('should have zero ranges', () => {
18074
+ expect(ranges.length).toEqual(0);
18075
+ });
18076
+ });
18077
+
17820
18078
  describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
17821
18079
  let ranges;
17822
18080
 
@@ -18337,12 +18595,10 @@ describe('When a position container data is gathered', () => {
18337
18595
  });
18338
18596
 
18339
18597
  },{"./../../../lib/data/InstrumentType":1,"./../../../lib/data/PositionSummaryFrame":3,"./../../../lib/processing/PositionContainer":6,"./../../../lib/processing/definitions/PositionLevelDefinition":9,"./../../../lib/processing/definitions/PositionLevelType":10,"./../../../lib/processing/definitions/PositionTreeDefinition":11,"@barchart/common-js/lang/Currency":20,"@barchart/common-js/lang/Decimal":22}],55:[function(require,module,exports){
18340
- const Currency = require('@barchart/common-js/lang/Currency'),
18341
- Day = require('@barchart/common-js/lang/Day'),
18598
+ const Day = require('@barchart/common-js/lang/Day'),
18342
18599
  Decimal = require('@barchart/common-js/lang/Decimal');
18343
18600
 
18344
- const InstrumentType = require('./../../../lib/data/InstrumentType'),
18345
- TransactionType = require('./../../../lib/data/TransactionType');
18601
+ const TransactionType = require('./../../../lib/data/TransactionType');
18346
18602
 
18347
18603
  const TransactionSchema = require('./../../../lib/serialization/TransactionSchema');
18348
18604
 
@@ -18405,4 +18661,4 @@ describe('When transactions are serialized', () => {
18405
18661
  });
18406
18662
  });
18407
18663
 
18408
- },{"./../../../lib/data/InstrumentType":1,"./../../../lib/data/TransactionType":4,"./../../../lib/serialization/TransactionSchema":12,"@barchart/common-js/lang/Currency":20,"@barchart/common-js/lang/Day":21,"@barchart/common-js/lang/Decimal":22}]},{},[52,53,54,55]);
18664
+ },{"./../../../lib/data/TransactionType":4,"./../../../lib/serialization/TransactionSchema":12,"@barchart/common-js/lang/Day":21,"@barchart/common-js/lang/Decimal":22}]},{},[52,53,54,55]);
@@ -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 2019 and closes 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 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,164 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
226
226
  });
227
227
  });
228
228
 
229
+ describe('and yearly position summary ranges are processed for a transaction set that opens in the current year', () => {
230
+ let ranges;
231
+
232
+ beforeEach(() => {
233
+ const transactions = [
234
+ {
235
+ date: Day.getToday(),
236
+ snapshot: {
237
+ open: new Decimal(1)
238
+ },
239
+ type: TransactionType.BUY
240
+ }
241
+ ];
242
+
243
+ ranges = PositionSummaryFrame.YEARLY.getRanges(transactions);
244
+ });
245
+
246
+ it('should have zero ranges', () => {
247
+ expect(ranges.length).toEqual(0);
248
+ });
249
+ });
250
+
251
+ describe('and monthly position summary ranges are processed for a transaction set that does not close', () => {
252
+ let ranges;
253
+
254
+ beforeEach(() => {
255
+ const transactions = [
256
+ {
257
+ date: new Day(2018, 12, 20),
258
+ snapshot: {
259
+ open: new Decimal(1)
260
+ },
261
+ type: TransactionType.BUY
262
+ },
263
+ {
264
+ date: new Day(2019, 2, 21),
265
+ snapshot: {
266
+ open: new Decimal(1)
267
+ },
268
+ type: TransactionType.BUY
269
+ }
270
+ ];
271
+
272
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
273
+ });
274
+
275
+ it('should have at least two ranges', () => {
276
+ expect(ranges.length > 1).toEqual(true);
277
+ });
278
+
279
+ it('the first range should be from 11-30-2018 to 12-31-2018', () => {
280
+ expect(ranges[0].start.format()).toEqual('2018-11-30');
281
+ expect(ranges[0].end.format()).toEqual('2018-12-31');
282
+ });
283
+
284
+ it('the last range should be for the previous month', () => {
285
+ const today = Day.getToday();
286
+
287
+ expect(ranges[ranges.length - 1].start.format()).toEqual(today.subtractMonths(2).getEndOfMonth().format());
288
+ expect(ranges[ranges.length - 1].end.format()).toEqual(today.subtractMonths(1).getEndOfMonth().format());
289
+ });
290
+ });
291
+
292
+ describe('and monthly position summary ranges are processed for a transaction set closes the same month', () => {
293
+ let ranges;
294
+
295
+ beforeEach(() => {
296
+ const transactions = [
297
+ {
298
+ date: new Day(2018, 12, 1),
299
+ snapshot: {
300
+ open: new Decimal(1)
301
+ },
302
+ type: TransactionType.BUY
303
+ },
304
+ {
305
+ date: new Day(2018, 12, 31),
306
+ snapshot: {
307
+ open: new Decimal(0)
308
+ },
309
+ type: TransactionType.SELL
310
+ }
311
+ ];
312
+
313
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
314
+ });
315
+
316
+ it('should have one range', () => {
317
+ expect(ranges.length).toEqual(1);
318
+ });
319
+
320
+ it('the first range should be from 11-30-2018 to 12-31-2018', () => {
321
+ expect(ranges[0].start.format()).toEqual('2018-11-30');
322
+ expect(ranges[0].end.format()).toEqual('2018-12-31');
323
+ });
324
+ });
325
+
326
+ describe('and monthly position summary ranges are processed for a transaction set closes the next month', () => {
327
+ let ranges;
328
+
329
+ beforeEach(() => {
330
+ const transactions = [
331
+ {
332
+ date: new Day(2015, 10, 20),
333
+ snapshot: {
334
+ open: new Decimal(1)
335
+ },
336
+ type: TransactionType.BUY
337
+ },
338
+ {
339
+ date: new Day(2015, 11, 20),
340
+ snapshot: {
341
+ open: new Decimal(0)
342
+ },
343
+ type: TransactionType.SELL
344
+ }
345
+ ];
346
+
347
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
348
+ });
349
+
350
+ it('should have two ranges', () => {
351
+ expect(ranges.length).toEqual(2);
352
+ });
353
+
354
+ it('the first range should be from 09-30-2015 to 10-31-2015', () => {
355
+ expect(ranges[0].start.format()).toEqual('2015-09-30');
356
+ expect(ranges[0].end.format()).toEqual('2015-10-31');
357
+ });
358
+
359
+ it('the second range should be from 10-31-2015 to 11-30-2015', () => {
360
+ expect(ranges[1].start.format()).toEqual('2015-10-31');
361
+ expect(ranges[1].end.format()).toEqual('2015-11-30');
362
+ });
363
+ });
364
+
365
+ describe('and monthly position summary ranges are processed for a transaction set that opens in the current month', () => {
366
+ let ranges;
367
+
368
+ beforeEach(() => {
369
+ const transactions = [
370
+ {
371
+ date: Day.getToday(),
372
+ snapshot: {
373
+ open: new Decimal(1)
374
+ },
375
+ type: TransactionType.BUY
376
+ }
377
+ ];
378
+
379
+ ranges = PositionSummaryFrame.MONTHLY.getRanges(transactions);
380
+ });
381
+
382
+ it('should have zero ranges', () => {
383
+ expect(ranges.length).toEqual(0);
384
+ });
385
+ });
386
+
229
387
  describe('and a year-to-date position summary ranges are processed for a transaction set that closed in 2017', () => {
230
388
  let ranges;
231
389
 
@@ -1,9 +1,7 @@
1
- const Currency = require('@barchart/common-js/lang/Currency'),
2
- Day = require('@barchart/common-js/lang/Day'),
1
+ const Day = require('@barchart/common-js/lang/Day'),
3
2
  Decimal = require('@barchart/common-js/lang/Decimal');
4
3
 
5
- const InstrumentType = require('./../../../lib/data/InstrumentType'),
6
- TransactionType = require('./../../../lib/data/TransactionType');
4
+ const TransactionType = require('./../../../lib/data/TransactionType');
7
5
 
8
6
  const TransactionSchema = require('./../../../lib/serialization/TransactionSchema');
9
7