@barchart/portfolio-api-common 1.0.88 → 1.0.92

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.
@@ -37,12 +37,11 @@ module.exports = (() => {
37
37
  * start and end dates.
38
38
  *
39
39
  * @public
40
- * @param {Day} startDate
41
- * @param {Day} endDate
40
+ * @return {PositionSummaryRange} range
42
41
  * @return {String}
43
42
  */
44
- describeRange(startDate, endDate) {
45
- return this._descriptionCalculator(startDate, endDate);
43
+ describeRange(range) {
44
+ return this._descriptionCalculator(range.start, range.end);
46
45
  }
47
46
 
48
47
  /**
@@ -226,20 +225,20 @@ module.exports = (() => {
226
225
  return null;
227
226
  }
228
227
 
229
- function getYearlyRangeDescription(startDate, endDate) {
230
- return endDate.year.toString();
228
+ function getYearlyRangeDescription(start, end) {
229
+ return end.year.toString();
231
230
  }
232
231
 
233
- function getQuarterlyRangeDescription(startDate, endDate) {
232
+ function getQuarterlyRangeDescription(start, end) {
234
233
  return '';
235
234
  }
236
235
 
237
- function getMonthlyRangeDescription(startDate, endDate) {
236
+ function getMonthlyRangeDescription(start, end) {
238
237
  return '';
239
238
  }
240
239
 
241
- function getYearToDateRangeDescription(startDate, endDate) {
242
- return `${endDate.year.toString()} YTD`;
240
+ function getYearToDateRangeDescription(start, end) {
241
+ return `${end.year.toString()} YTD`;
243
242
  }
244
243
 
245
244
  function getFilteredTransactions(transactions) {
@@ -11,6 +11,7 @@ module.exports = (() => {
11
11
  * @extends {Enum}
12
12
  * @param {String} code
13
13
  * @param {String} description
14
+ * @param {String} display
14
15
  * @param {Boolean} purchase
15
16
  * @param {Boolean} sale
16
17
  * @param {Boolean} income
@@ -18,15 +19,17 @@ module.exports = (() => {
18
19
  * @param {Boolean} closing
19
20
  */
20
21
  class TransactionType extends Enum {
21
- constructor(code, description, purchase, sale, income, opening, closing) {
22
+ constructor(code, description, display, purchase, sale, income, opening, closing) {
22
23
  super(code, description);
23
24
 
25
+ assert.argumentIsRequired(display, 'display', String);
24
26
  assert.argumentIsRequired(purchase, 'purchase', Boolean);
25
27
  assert.argumentIsRequired(sale, 'sale', Boolean);
26
28
  assert.argumentIsRequired(income, 'income', Boolean);
27
29
  assert.argumentIsRequired(opening, 'opening', Boolean);
28
30
  assert.argumentIsRequired(closing, 'closing', Boolean);
29
31
 
32
+ this._display = display;
30
33
  this._purchase = purchase;
31
34
  this._sale = sale;
32
35
  this._income = income;
@@ -34,6 +37,16 @@ module.exports = (() => {
34
37
  this._closing = closing;
35
38
  }
36
39
 
40
+ /**
41
+ * A human-readable description of the transaction type.
42
+ *
43
+ * @public
44
+ * @returns {String}
45
+ */
46
+ get display() {
47
+ return this._display;
48
+ }
49
+
37
50
  /**
38
51
  * Indicates if the transaction was a trade.
39
52
  *
@@ -299,27 +312,27 @@ module.exports = (() => {
299
312
  }
300
313
  }
301
314
 
302
- const buy = new TransactionType('B', 'Buy', true, false, false, true, false);
303
- const sell = new TransactionType('S', 'Sell', false, true, false, false, true);
304
- const buyShort = new TransactionType('BS', 'Buy To Cover', true, false, false, false, true);
305
- const sellShort = new TransactionType('SS', 'Sell Short', false, true, false, true, false);
306
- const dividend = new TransactionType('DV', 'Dividend', false, false, true, false, false);
307
- const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', false, false, false, true, false);
308
- const dividendStock = new TransactionType('DS', 'Dividend (Stock)', false, false, false, true, false);
309
- const split = new TransactionType('SP', 'Split', false, false, false, true, false);
310
- const fee = new TransactionType('F', 'Fee', false, false, false, true, false);
311
- const feeUnits = new TransactionType('FU', 'Fee', false, false, false, false, false);
312
-
313
- const distributionCash = new TransactionType('DC', 'Distribution (Cash)', false, false, true, false, false);
314
- const distributionFund = new TransactionType('DF', 'Distribution (Units)', false, false, false, true, false);
315
-
316
- const deposit = new TransactionType('D', 'Deposit', false, false, false, true, false);
317
- const withdrawal = new TransactionType('W', 'Withdrawal', false, false, false, false, true);
318
- const debit = new TransactionType('DR', 'Debit', false, false, false, false, true);
319
- const credit = new TransactionType('CR', 'Credit', false, false, false, true, false);
320
-
321
- const valuation = new TransactionType('V', 'Valuation', false, false, false, false, false);
322
- const income = new TransactionType('I', 'Income', false, false, true, false, false);
315
+ const buy = new TransactionType('B', 'Buy', 'Buy', true, false, false, true, false);
316
+ const sell = new TransactionType('S', 'Sell', 'Sell', false, true, false, false, true);
317
+ const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', true, false, false, false, true);
318
+ const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', false, true, false, true, false);
319
+ const dividend = new TransactionType('DV', 'Dividend', 'Dividend', false, false, true, false, false);
320
+ const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', false, false, false, true, false);
321
+ const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', false, false, false, true, false);
322
+ const split = new TransactionType('SP', 'Split', 'Split', false, false, false, true, false);
323
+ const fee = new TransactionType('F', 'Fee', 'Fee', false, false, false, true, false);
324
+ const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', false, false, false, false, false);
325
+
326
+ const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', false, false, true, false, false);
327
+ const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', false, false, false, true, false);
328
+
329
+ const deposit = new TransactionType('D', 'Deposit', 'Deposit', false, false, false, true, false);
330
+ const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', false, false, false, false, true);
331
+ const debit = new TransactionType('DR', 'Debit', 'Debit', false, false, false, false, true);
332
+ const credit = new TransactionType('CR', 'Credit', 'Credit', false, false, false, true, false);
333
+
334
+ const valuation = new TransactionType('V', 'Valuation', 'Valuation', false, false, false, false, false);
335
+ const income = new TransactionType('I', 'Income', 'Income', false, false, true, false, false);
323
336
 
324
337
  return TransactionType;
325
338
  })();
@@ -35,9 +35,9 @@ module.exports = (() => {
35
35
 
36
36
  const positionMap = {};
37
37
 
38
- positions.map((p) => positionMap[p.position] = p.instrument);
38
+ positions.map(p => positionMap[p.position] = p.instrument);
39
39
 
40
- return transactions.filter((t) => positionMap[t.position]).map((transaction) => {
40
+ return transactions.filter(t => positionMap[t.position]).map((transaction) => {
41
41
  transaction.instrument = positionMap[transaction.position];
42
42
 
43
43
  let formatted = getBasicTransaction(transaction);
@@ -76,7 +76,7 @@ module.exports = (() => {
76
76
  const getBasicTransaction = (t) => {
77
77
  const basic = {
78
78
  date: t.date,
79
- type: t.type,
79
+ type: t.type.display,
80
80
  sequence: t.sequence,
81
81
  instrument: t.instrument
82
82
  };
@@ -98,6 +98,7 @@ module.exports = (() => {
98
98
  total: t.amount
99
99
  };
100
100
  };
101
+
101
102
  formatters.set(TransactionType.BUY, buySellFormatter);
102
103
  formatters.set(TransactionType.SELL, buySellFormatter);
103
104
  formatters.set(TransactionType.BUY_SHORT, buySellFormatter);
@@ -18,12 +18,18 @@ module.exports = (() => {
18
18
  * @public
19
19
  */
20
20
  class PositionContainer {
21
- constructor(portfolios, positions, summaries, definitions, defaultCurrency, summaryFrameType) {
21
+ constructor(portfolios, positions, summaries, definitions, defaultCurrency, summaryFrame) {
22
22
  this._definitions = definitions;
23
23
  this._defaultCurrency = defaultCurrency || Currency.CAD;
24
+
25
+ const previousSummaryFrame = summaryFrame || PositionSummaryFrame.YEARLY;
26
+ const previousSummaryRanges = previousSummaryFrame.getRecentRanges(0);
24
27
 
25
- this._summaryFrame = summaryFrameType || PositionSummaryFrame.YEARLY;
26
- this._summaryRanges = this._summaryFrame.getRecentRanges(1);
28
+ const currentSummaryFrame = PositionSummaryFrame.YTD;
29
+ const currentSummaryRange = array.last(currentSummaryFrame.getRecentRanges(0));
30
+
31
+ this._summaryDescriptionCurrent = previousSummaryFrame.describeRange(array.last(previousSummaryRanges));
32
+ this._summaryDescriptionPrevious = currentSummaryFrame.describeRange(currentSummaryRange);
27
33
 
28
34
  this._portfolios = portfolios.reduce((map, portfolio) => {
29
35
  map[portfolio.portfolio] = portfolio;
@@ -31,15 +37,25 @@ module.exports = (() => {
31
37
  return map;
32
38
  }, { });
33
39
 
34
- this._summaries = summaries.reduce((map, summary) => {
35
- if (this._summaryFrame === summary.frame) {
40
+ this._summariesCurrent = summaries.reduce((map, summary) => {
41
+ if (summary.frame === currentSummaryFrame && currentSummaryRange.start.getIsEqual(summary.start.date) && currentSummaryRange.end.getIsEqual(summary.end.date)) {
42
+ const key = summary.position;
43
+
44
+ map[key] = summary;
45
+ }
46
+
47
+ return map;
48
+ }, { });
49
+
50
+ this._summariesPrevious = summaries.reduce((map, summary) => {
51
+ if (summary.frame === previousSummaryFrame) {
36
52
  const key = summary.position;
37
53
 
38
54
  if (!map.hasOwnProperty(key)) {
39
- map[key] = getSummaryArray(this._summaryRanges);
55
+ map[key] = getSummaryArray(previousSummaryRanges);
40
56
  }
41
57
 
42
- const index = this._summaryRanges.findIndex(r => r.start.getIsEqual(summary.start.date) && r.end.getIsEqual(summary.end.date));
58
+ const index = previousSummaryRanges.findIndex(r => r.start.getIsEqual(summary.start.date) && r.end.getIsEqual(summary.end.date));
43
59
 
44
60
  if (!(index < 0)) {
45
61
  map[key][index] = summary;
@@ -53,9 +69,10 @@ module.exports = (() => {
53
69
  const portfolio = this._portfolios[position.portfolio];
54
70
 
55
71
  if (position) {
56
- const summaries = this._summaries[position.position] || getSummaryArray(this._summaryRanges);
72
+ const currentSummary = this._summariesCurrent[position.position] || null;
73
+ const previousSummaries = this._summariesPrevious[position.position] || getSummaryArray(previousSummaryRanges);
57
74
 
58
- items.push(new PositionItem(portfolio, position, summaries));
75
+ items.push(new PositionItem(portfolio, position, currentSummary, previousSummaries));
59
76
  }
60
77
 
61
78
  return items;
@@ -167,7 +184,25 @@ module.exports = (() => {
167
184
  get defaultCurrency() {
168
185
  return this._defaultCurrency;
169
186
  }
187
+
188
+ getCurrentSummaryDescription() {
189
+ return this._summaryDescriptionCurrent;
190
+ }
191
+
192
+ getPreviousSummaryDescription() {
193
+ return this._summaryDescriptionPrevious;
194
+ }
195
+
196
+ startTransaction(executor) {
197
+ assert.argumentIsRequired(executor, 'executor', Function);
198
+
199
+ this._tree.walk(group => group.setSuspended(true), false, false);
170
200
 
201
+ executor(this);
202
+
203
+ this._tree.walk(group => group.setSuspended(false), false, false);
204
+ }
205
+
171
206
  getSymbols() {
172
207
  return Object.keys(this._symbols);
173
208
  }
@@ -194,16 +229,6 @@ module.exports = (() => {
194
229
 
195
230
  }
196
231
 
197
- startTransaction(executor) {
198
- assert.argumentIsRequired(executor, 'executor', Function);
199
-
200
- this._tree.walk(group => group.setSuspended(true), false, false);
201
-
202
- executor(this);
203
-
204
- this._tree.walk(group => group.setSuspended(false), false, false);
205
- }
206
-
207
232
  getGroup(keys) {
208
233
  const node = keys.reduce((tree, key) => {
209
234
  tree = tree.findChild(group => group.description === key);
@@ -42,8 +42,8 @@ module.exports = (() => {
42
42
  this._dataActual.marketPercent = null;
43
43
  this._dataActual.unrealizedToday = null;
44
44
  this._dataActual.total = null;
45
- this._dataActual.summaryOneTotal = null;
46
- this._dataActual.summaryTwoTotal = null;
45
+ this._dataActual.summaryTotalCurrent = null;
46
+ this._dataActual.summaryTotalPrevious = null;
47
47
 
48
48
  this._dataFormat.currentPrice = null;
49
49
  this._dataFormat.previousPrice = null;
@@ -57,8 +57,9 @@ module.exports = (() => {
57
57
  this._dataFormat.unrealizedTodayNegative = false;
58
58
  this._dataFormat.total = null;
59
59
  this._dataFormat.totalNegative = false;
60
- this._dataFormat.summaryOneTotal = null;
61
- this._dataFormat.summaryTwoTotal = null;
60
+ this._dataFormat.summaryTotalCurrent = null;
61
+ this._dataActual.summaryTotalNegative = false;
62
+ this._dataFormat.summaryTotalPrevious = null;
62
63
 
63
64
  this._dataFormat.unrealizedTodayNegative = false;
64
65
 
@@ -187,29 +188,29 @@ module.exports = (() => {
187
188
  updates.basis = updates.basis.add(item.data.basis);
188
189
  updates.realized = updates.realized.add(item.data.realized);
189
190
  updates.income = updates.income.add(item.data.income);
190
- updates.summaryOneTotal = updates.summaryOneTotal.add(item.data.summaryOneTotal);
191
- updates.summaryTwoTotal = updates.summaryTwoTotal.add(item.data.summaryTwoTotal);
191
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
192
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
192
193
 
193
194
  return updates;
194
195
  }, {
195
196
  basis: Decimal.ZERO,
196
197
  realized: Decimal.ZERO,
197
198
  income: Decimal.ZERO,
198
- summaryOneTotal: Decimal.ZERO,
199
- summaryTwoTotal: Decimal.ZERO
199
+ summaryTotalCurrent: Decimal.ZERO,
200
+ summaryTotalPrevious: Decimal.ZERO
200
201
  });
201
202
 
202
203
  actual.basis = updates.basis;
203
204
  actual.realized = updates.realized;
204
205
  actual.income = updates.income;
205
- actual.summaryOneTotal = updates.summaryOneTotal;
206
- actual.summaryTwoTotal = updates.summaryTwoTotal;
206
+ actual.summaryTotalCurrent = updates.summaryTotalCurrent;
207
+ actual.summaryTotalPrevious = updates.summaryTotalPrevious;
207
208
 
208
209
  format.basis = formatCurrency(actual.basis, currency);
209
210
  format.realized = formatCurrency(actual.basis, currency);
210
211
  format.income = formatCurrency(actual.income, currency);
211
- format.summaryOneTotal = formatCurrency(updates.summaryOneTotal, currency);
212
- format.summaryTwoTotal = formatCurrency(updates.summaryTwoTotal, currency);
212
+ format.summaryTotalCurrent = formatCurrency(updates.summaryTotalCurrent, currency);
213
+ format.summaryTotalPrevious = formatCurrency(updates.summaryTotalPrevious, currency);
213
214
  }
214
215
 
215
216
  function calculatePriceData(group, item, forceRefresh) {
@@ -234,19 +235,22 @@ module.exports = (() => {
234
235
  updates = items.reduce((updates, item) => {
235
236
  updates.market = updates.market.add(item.data.market);
236
237
  updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
238
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
237
239
 
238
240
  return updates;
239
241
  }, {
240
242
  market: Decimal.ZERO,
241
243
  marketDirection: unchanged,
242
- unrealizedToday: Decimal.ZERO
244
+ unrealizedToday: Decimal.ZERO,
245
+ summaryTotalCurrent: Decimal.ZERO
243
246
 
244
247
  });
245
248
  } else {
246
249
  updates = {
247
250
  market: actual.market.add(item.data.marketChange),
248
251
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
249
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
252
+ unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
253
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
250
254
  };
251
255
  }
252
256
 
@@ -264,6 +268,7 @@ module.exports = (() => {
264
268
 
265
269
  actual.market = updates.market;
266
270
  actual.unrealizedToday = updates.unrealizedToday;
271
+ actual.summaryTotalCurrent = updates.summaryTotalCurrent;
267
272
  actual.total = updates.unrealizedToday.add(actual.realized).add(actual.income);
268
273
 
269
274
  format.market = formatCurrency(actual.market, currency);
@@ -275,6 +280,10 @@ module.exports = (() => {
275
280
 
276
281
  format.unrealizedToday = formatCurrency(actual.unrealizedToday, currency);
277
282
  format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
283
+
284
+ format.summaryTotalCurrent = formatCurrency(actual.summaryTotalCurrent, currency);
285
+ format.summaryTotalCurrentNegative = actual.summaryTotalCurrent.getIsNegative();
286
+
278
287
  format.total = formatCurrency(actual.total, currency);
279
288
  format.totalNegative = actual.total.getIsNegative();
280
289
 
@@ -1,4 +1,5 @@
1
- const assert = require('@barchart/common-js/lang/assert'),
1
+ const array = require('@barchart/common-js/lang/array'),
2
+ assert = require('@barchart/common-js/lang/assert'),
2
3
  Decimal = require('@barchart/common-js/lang/Decimal'),
3
4
  Event = require('@barchart/common-js/messaging/Event'),
4
5
  is = require('@barchart/common-js/lang/is');
@@ -12,10 +13,12 @@ module.exports = (() => {
12
13
  * @public
13
14
  */
14
15
  class PositionItem {
15
- constructor(portfolio, position, summaries) {
16
+ constructor(portfolio, position, currentSummary, previousSummaries) {
16
17
  this._portfolio = portfolio;
17
18
  this._position = position;
18
- this._summaries = summaries || [ ];
19
+
20
+ this._currentSummary = currentSummary || null;
21
+ this._previousSummaries = previousSummaries || [ ];
19
22
 
20
23
  this._data = { };
21
24
 
@@ -32,6 +35,11 @@ module.exports = (() => {
32
35
 
33
36
  this._data.realized = null;
34
37
  this._data.income = null;
38
+
39
+ this._data.summaryTotalCurrent = null;
40
+ this._data.summaryTotalCurrentChange = null;
41
+
42
+ this._data.summaryTotalPrevious = null;
35
43
 
36
44
  this._excluded = false;
37
45
 
@@ -50,8 +58,12 @@ module.exports = (() => {
50
58
  return this._position;
51
59
  }
52
60
 
53
- get summaries() {
54
- return this._summaries;
61
+ get currentSummary() {
62
+ return this._currentSummary;
63
+ }
64
+
65
+ get previousSummaries() {
66
+ return this._previousSummaries;
55
67
  }
56
68
 
57
69
  get data() {
@@ -96,7 +108,7 @@ module.exports = (() => {
96
108
  function calculateStaticData(item) {
97
109
  const position = item.position;
98
110
  const snapshot = item.position.snapshot;
99
- const summaries = item.summaries;
111
+ const previousSummaries = item.previousSummaries;
100
112
 
101
113
  const data = item._data;
102
114
 
@@ -115,22 +127,8 @@ module.exports = (() => {
115
127
  data.realized = snapshot.gain;
116
128
  data.income = snapshot.income;
117
129
 
118
- const getSummaryTotal = (index) => {
119
- let summaryTotal;
120
-
121
- if (summaries.length > index && summaries[index] !== null) {
122
- const period = summaries[index].period;
123
-
124
- summaryTotal = period.realized.add(period.unrealized).add(period.income);
125
- } else {
126
- summaryTotal = Decimal.ZERO;
127
- }
128
-
129
- return summaryTotal;
130
- };
131
-
132
- data.summaryOneTotal = getSummaryTotal(0);
133
- data.summaryTwoTotal = getSummaryTotal(1);
130
+ data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary);
131
+ data.summaryTotalPrevious = calculateSummaryTotal(array.last(previousSummaries));
134
132
  }
135
133
 
136
134
  function calculatePriceData(item, price) {
@@ -182,6 +180,42 @@ module.exports = (() => {
182
180
 
183
181
  data.unrealizedToday = unrealizedToday;
184
182
  data.unrealizedTodayChange = unrealizedTodayChange;
183
+
184
+ const summary = item.currentSummary;
185
+
186
+ if (summary && price) {
187
+ const period = summary.period;
188
+
189
+ let unrealizedCurrent = summary.open.multiply(price).add(summary.end.basis);
190
+
191
+ let summaryTotalCurrent = period.realized.add(period.income).add(unrealizedCurrent);
192
+ let summaryTotalCurrentChange;
193
+
194
+ if (data.summaryTotalCurrent !== null) {
195
+ summaryTotalCurrentChange = summaryTotalCurrent.subtract(data.summaryTotalCurrent);
196
+ } else {
197
+ summaryTotalCurrentChange = Decimal.ZERO;
198
+ }
199
+
200
+ data.summaryTotalCurrent = summaryTotalCurrent;
201
+ data.summaryTotalCurrentChange = summaryTotalCurrentChange;
202
+ } else {
203
+ data.summaryTotalCurrentChange = Decimal.ZERO;
204
+ }
205
+ }
206
+
207
+ function calculateSummaryTotal(summary) {
208
+ let returnRef;
209
+
210
+ if (summary) {
211
+ const period = summary.period;
212
+
213
+ returnRef = period.realized.add(period.income).add(period.unrealized);
214
+ } else {
215
+ returnRef = Decimal.ZERO;
216
+ }
217
+
218
+ return returnRef;
185
219
  }
186
220
 
187
221
  return PositionItem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.88",
3
+ "version": "1.0.92",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -156,12 +156,11 @@ module.exports = (() => {
156
156
  * start and end dates.
157
157
  *
158
158
  * @public
159
- * @param {Day} startDate
160
- * @param {Day} endDate
159
+ * @return {PositionSummaryRange} range
161
160
  * @return {String}
162
161
  */
163
- describeRange(startDate, endDate) {
164
- return this._descriptionCalculator(startDate, endDate);
162
+ describeRange(range) {
163
+ return this._descriptionCalculator(range.start, range.end);
165
164
  }
166
165
 
167
166
  /**
@@ -345,20 +344,20 @@ module.exports = (() => {
345
344
  return null;
346
345
  }
347
346
 
348
- function getYearlyRangeDescription(startDate, endDate) {
349
- return endDate.year.toString();
347
+ function getYearlyRangeDescription(start, end) {
348
+ return end.year.toString();
350
349
  }
351
350
 
352
- function getQuarterlyRangeDescription(startDate, endDate) {
351
+ function getQuarterlyRangeDescription(start, end) {
353
352
  return '';
354
353
  }
355
354
 
356
- function getMonthlyRangeDescription(startDate, endDate) {
355
+ function getMonthlyRangeDescription(start, end) {
357
356
  return '';
358
357
  }
359
358
 
360
- function getYearToDateRangeDescription(startDate, endDate) {
361
- return `${endDate.year.toString()} YTD`;
359
+ function getYearToDateRangeDescription(start, end) {
360
+ return `${end.year.toString()} YTD`;
362
361
  }
363
362
 
364
363
  function getFilteredTransactions(transactions) {
@@ -388,6 +387,7 @@ module.exports = (() => {
388
387
  * @extends {Enum}
389
388
  * @param {String} code
390
389
  * @param {String} description
390
+ * @param {String} display
391
391
  * @param {Boolean} purchase
392
392
  * @param {Boolean} sale
393
393
  * @param {Boolean} income
@@ -395,15 +395,17 @@ module.exports = (() => {
395
395
  * @param {Boolean} closing
396
396
  */
397
397
  class TransactionType extends Enum {
398
- constructor(code, description, purchase, sale, income, opening, closing) {
398
+ constructor(code, description, display, purchase, sale, income, opening, closing) {
399
399
  super(code, description);
400
400
 
401
+ assert.argumentIsRequired(display, 'display', String);
401
402
  assert.argumentIsRequired(purchase, 'purchase', Boolean);
402
403
  assert.argumentIsRequired(sale, 'sale', Boolean);
403
404
  assert.argumentIsRequired(income, 'income', Boolean);
404
405
  assert.argumentIsRequired(opening, 'opening', Boolean);
405
406
  assert.argumentIsRequired(closing, 'closing', Boolean);
406
407
 
408
+ this._display = display;
407
409
  this._purchase = purchase;
408
410
  this._sale = sale;
409
411
  this._income = income;
@@ -411,6 +413,16 @@ module.exports = (() => {
411
413
  this._closing = closing;
412
414
  }
413
415
 
416
+ /**
417
+ * A human-readable description of the transaction type.
418
+ *
419
+ * @public
420
+ * @returns {String}
421
+ */
422
+ get display() {
423
+ return this._display;
424
+ }
425
+
414
426
  /**
415
427
  * Indicates if the transaction was a trade.
416
428
  *
@@ -676,27 +688,27 @@ module.exports = (() => {
676
688
  }
677
689
  }
678
690
 
679
- const buy = new TransactionType('B', 'Buy', true, false, false, true, false);
680
- const sell = new TransactionType('S', 'Sell', false, true, false, false, true);
681
- const buyShort = new TransactionType('BS', 'Buy To Cover', true, false, false, false, true);
682
- const sellShort = new TransactionType('SS', 'Sell Short', false, true, false, true, false);
683
- const dividend = new TransactionType('DV', 'Dividend', false, false, true, false, false);
684
- const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', false, false, false, true, false);
685
- const dividendStock = new TransactionType('DS', 'Dividend (Stock)', false, false, false, true, false);
686
- const split = new TransactionType('SP', 'Split', false, false, false, true, false);
687
- const fee = new TransactionType('F', 'Fee', false, false, false, true, false);
688
- const feeUnits = new TransactionType('FU', 'Fee', false, false, false, false, false);
691
+ const buy = new TransactionType('B', 'Buy', 'Buy', true, false, false, true, false);
692
+ const sell = new TransactionType('S', 'Sell', 'Sell', false, true, false, false, true);
693
+ const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', true, false, false, false, true);
694
+ const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', false, true, false, true, false);
695
+ const dividend = new TransactionType('DV', 'Dividend', 'Dividend', false, false, true, false, false);
696
+ const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', false, false, false, true, false);
697
+ const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', false, false, false, true, false);
698
+ const split = new TransactionType('SP', 'Split', 'Split', false, false, false, true, false);
699
+ const fee = new TransactionType('F', 'Fee', 'Fee', false, false, false, true, false);
700
+ const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', false, false, false, false, false);
689
701
 
690
- const distributionCash = new TransactionType('DC', 'Distribution (Cash)', false, false, true, false, false);
691
- const distributionFund = new TransactionType('DF', 'Distribution (Units)', false, false, false, true, false);
702
+ const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', false, false, true, false, false);
703
+ const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', false, false, false, true, false);
692
704
 
693
- const deposit = new TransactionType('D', 'Deposit', false, false, false, true, false);
694
- const withdrawal = new TransactionType('W', 'Withdrawal', false, false, false, false, true);
695
- const debit = new TransactionType('DR', 'Debit', false, false, false, false, true);
696
- const credit = new TransactionType('CR', 'Credit', false, false, false, true, false);
705
+ const deposit = new TransactionType('D', 'Deposit', 'Deposit', false, false, false, true, false);
706
+ const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', false, false, false, false, true);
707
+ const debit = new TransactionType('DR', 'Debit', 'Debit', false, false, false, false, true);
708
+ const credit = new TransactionType('CR', 'Credit', 'Credit', false, false, false, true, false);
697
709
 
698
- const valuation = new TransactionType('V', 'Valuation', false, false, false, false, false);
699
- const income = new TransactionType('I', 'Income', false, false, true, false, false);
710
+ const valuation = new TransactionType('V', 'Valuation', 'Valuation', false, false, false, false, false);
711
+ const income = new TransactionType('I', 'Income', 'Income', false, false, true, false, false);
700
712
 
701
713
  return TransactionType;
702
714
  })();
@@ -722,12 +734,18 @@ module.exports = (() => {
722
734
  * @public
723
735
  */
724
736
  class PositionContainer {
725
- constructor(portfolios, positions, summaries, definitions, defaultCurrency, summaryFrameType) {
737
+ constructor(portfolios, positions, summaries, definitions, defaultCurrency, summaryFrame) {
726
738
  this._definitions = definitions;
727
739
  this._defaultCurrency = defaultCurrency || Currency.CAD;
740
+
741
+ const previousSummaryFrame = summaryFrame || PositionSummaryFrame.YEARLY;
742
+ const previousSummaryRanges = previousSummaryFrame.getRecentRanges(0);
728
743
 
729
- this._summaryFrame = summaryFrameType || PositionSummaryFrame.YEARLY;
730
- this._summaryRanges = this._summaryFrame.getRecentRanges(1);
744
+ const currentSummaryFrame = PositionSummaryFrame.YTD;
745
+ const currentSummaryRange = array.last(currentSummaryFrame.getRecentRanges(0));
746
+
747
+ this._summaryDescriptionCurrent = previousSummaryFrame.describeRange(array.last(previousSummaryRanges));
748
+ this._summaryDescriptionPrevious = currentSummaryFrame.describeRange(currentSummaryRange);
731
749
 
732
750
  this._portfolios = portfolios.reduce((map, portfolio) => {
733
751
  map[portfolio.portfolio] = portfolio;
@@ -735,15 +753,25 @@ module.exports = (() => {
735
753
  return map;
736
754
  }, { });
737
755
 
738
- this._summaries = summaries.reduce((map, summary) => {
739
- if (this._summaryFrame === summary.frame) {
756
+ this._summariesCurrent = summaries.reduce((map, summary) => {
757
+ if (summary.frame === currentSummaryFrame && currentSummaryRange.start.getIsEqual(summary.start.date) && currentSummaryRange.end.getIsEqual(summary.end.date)) {
758
+ const key = summary.position;
759
+
760
+ map[key] = summary;
761
+ }
762
+
763
+ return map;
764
+ }, { });
765
+
766
+ this._summariesPrevious = summaries.reduce((map, summary) => {
767
+ if (summary.frame === previousSummaryFrame) {
740
768
  const key = summary.position;
741
769
 
742
770
  if (!map.hasOwnProperty(key)) {
743
- map[key] = getSummaryArray(this._summaryRanges);
771
+ map[key] = getSummaryArray(previousSummaryRanges);
744
772
  }
745
773
 
746
- const index = this._summaryRanges.findIndex(r => r.start.getIsEqual(summary.start.date) && r.end.getIsEqual(summary.end.date));
774
+ const index = previousSummaryRanges.findIndex(r => r.start.getIsEqual(summary.start.date) && r.end.getIsEqual(summary.end.date));
747
775
 
748
776
  if (!(index < 0)) {
749
777
  map[key][index] = summary;
@@ -757,9 +785,10 @@ module.exports = (() => {
757
785
  const portfolio = this._portfolios[position.portfolio];
758
786
 
759
787
  if (position) {
760
- const summaries = this._summaries[position.position] || getSummaryArray(this._summaryRanges);
788
+ const currentSummary = this._summariesCurrent[position.position] || null;
789
+ const previousSummaries = this._summariesPrevious[position.position] || getSummaryArray(previousSummaryRanges);
761
790
 
762
- items.push(new PositionItem(portfolio, position, summaries));
791
+ items.push(new PositionItem(portfolio, position, currentSummary, previousSummaries));
763
792
  }
764
793
 
765
794
  return items;
@@ -871,7 +900,25 @@ module.exports = (() => {
871
900
  get defaultCurrency() {
872
901
  return this._defaultCurrency;
873
902
  }
903
+
904
+ getCurrentSummaryDescription() {
905
+ return this._summaryDescriptionCurrent;
906
+ }
907
+
908
+ getPreviousSummaryDescription() {
909
+ return this._summaryDescriptionPrevious;
910
+ }
874
911
 
912
+ startTransaction(executor) {
913
+ assert.argumentIsRequired(executor, 'executor', Function);
914
+
915
+ this._tree.walk(group => group.setSuspended(true), false, false);
916
+
917
+ executor(this);
918
+
919
+ this._tree.walk(group => group.setSuspended(false), false, false);
920
+ }
921
+
875
922
  getSymbols() {
876
923
  return Object.keys(this._symbols);
877
924
  }
@@ -898,16 +945,6 @@ module.exports = (() => {
898
945
 
899
946
  }
900
947
 
901
- startTransaction(executor) {
902
- assert.argumentIsRequired(executor, 'executor', Function);
903
-
904
- this._tree.walk(group => group.setSuspended(true), false, false);
905
-
906
- executor(this);
907
-
908
- this._tree.walk(group => group.setSuspended(false), false, false);
909
- }
910
-
911
948
  getGroup(keys) {
912
949
  const node = keys.reduce((tree, key) => {
913
950
  tree = tree.findChild(group => group.description === key);
@@ -985,8 +1022,8 @@ module.exports = (() => {
985
1022
  this._dataActual.marketPercent = null;
986
1023
  this._dataActual.unrealizedToday = null;
987
1024
  this._dataActual.total = null;
988
- this._dataActual.summaryOneTotal = null;
989
- this._dataActual.summaryTwoTotal = null;
1025
+ this._dataActual.summaryTotalCurrent = null;
1026
+ this._dataActual.summaryTotalPrevious = null;
990
1027
 
991
1028
  this._dataFormat.currentPrice = null;
992
1029
  this._dataFormat.previousPrice = null;
@@ -1000,8 +1037,9 @@ module.exports = (() => {
1000
1037
  this._dataFormat.unrealizedTodayNegative = false;
1001
1038
  this._dataFormat.total = null;
1002
1039
  this._dataFormat.totalNegative = false;
1003
- this._dataFormat.summaryOneTotal = null;
1004
- this._dataFormat.summaryTwoTotal = null;
1040
+ this._dataFormat.summaryTotalCurrent = null;
1041
+ this._dataActual.summaryTotalNegative = false;
1042
+ this._dataFormat.summaryTotalPrevious = null;
1005
1043
 
1006
1044
  this._dataFormat.unrealizedTodayNegative = false;
1007
1045
 
@@ -1130,29 +1168,29 @@ module.exports = (() => {
1130
1168
  updates.basis = updates.basis.add(item.data.basis);
1131
1169
  updates.realized = updates.realized.add(item.data.realized);
1132
1170
  updates.income = updates.income.add(item.data.income);
1133
- updates.summaryOneTotal = updates.summaryOneTotal.add(item.data.summaryOneTotal);
1134
- updates.summaryTwoTotal = updates.summaryTwoTotal.add(item.data.summaryTwoTotal);
1171
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1172
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
1135
1173
 
1136
1174
  return updates;
1137
1175
  }, {
1138
1176
  basis: Decimal.ZERO,
1139
1177
  realized: Decimal.ZERO,
1140
1178
  income: Decimal.ZERO,
1141
- summaryOneTotal: Decimal.ZERO,
1142
- summaryTwoTotal: Decimal.ZERO
1179
+ summaryTotalCurrent: Decimal.ZERO,
1180
+ summaryTotalPrevious: Decimal.ZERO
1143
1181
  });
1144
1182
 
1145
1183
  actual.basis = updates.basis;
1146
1184
  actual.realized = updates.realized;
1147
1185
  actual.income = updates.income;
1148
- actual.summaryOneTotal = updates.summaryOneTotal;
1149
- actual.summaryTwoTotal = updates.summaryTwoTotal;
1186
+ actual.summaryTotalCurrent = updates.summaryTotalCurrent;
1187
+ actual.summaryTotalPrevious = updates.summaryTotalPrevious;
1150
1188
 
1151
1189
  format.basis = formatCurrency(actual.basis, currency);
1152
1190
  format.realized = formatCurrency(actual.basis, currency);
1153
1191
  format.income = formatCurrency(actual.income, currency);
1154
- format.summaryOneTotal = formatCurrency(updates.summaryOneTotal, currency);
1155
- format.summaryTwoTotal = formatCurrency(updates.summaryTwoTotal, currency);
1192
+ format.summaryTotalCurrent = formatCurrency(updates.summaryTotalCurrent, currency);
1193
+ format.summaryTotalPrevious = formatCurrency(updates.summaryTotalPrevious, currency);
1156
1194
  }
1157
1195
 
1158
1196
  function calculatePriceData(group, item, forceRefresh) {
@@ -1177,19 +1215,22 @@ module.exports = (() => {
1177
1215
  updates = items.reduce((updates, item) => {
1178
1216
  updates.market = updates.market.add(item.data.market);
1179
1217
  updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
1218
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1180
1219
 
1181
1220
  return updates;
1182
1221
  }, {
1183
1222
  market: Decimal.ZERO,
1184
1223
  marketDirection: unchanged,
1185
- unrealizedToday: Decimal.ZERO
1224
+ unrealizedToday: Decimal.ZERO,
1225
+ summaryTotalCurrent: Decimal.ZERO
1186
1226
 
1187
1227
  });
1188
1228
  } else {
1189
1229
  updates = {
1190
1230
  market: actual.market.add(item.data.marketChange),
1191
1231
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
1192
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
1232
+ unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
1233
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
1193
1234
  };
1194
1235
  }
1195
1236
 
@@ -1207,6 +1248,7 @@ module.exports = (() => {
1207
1248
 
1208
1249
  actual.market = updates.market;
1209
1250
  actual.unrealizedToday = updates.unrealizedToday;
1251
+ actual.summaryTotalCurrent = updates.summaryTotalCurrent;
1210
1252
  actual.total = updates.unrealizedToday.add(actual.realized).add(actual.income);
1211
1253
 
1212
1254
  format.market = formatCurrency(actual.market, currency);
@@ -1218,6 +1260,10 @@ module.exports = (() => {
1218
1260
 
1219
1261
  format.unrealizedToday = formatCurrency(actual.unrealizedToday, currency);
1220
1262
  format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
1263
+
1264
+ format.summaryTotalCurrent = formatCurrency(actual.summaryTotalCurrent, currency);
1265
+ format.summaryTotalCurrentNegative = actual.summaryTotalCurrent.getIsNegative();
1266
+
1221
1267
  format.total = formatCurrency(actual.total, currency);
1222
1268
  format.totalNegative = actual.total.getIsNegative();
1223
1269
 
@@ -1313,7 +1359,8 @@ module.exports = (() => {
1313
1359
  })();
1314
1360
 
1315
1361
  },{"@barchart/common-js/lang/assert":17,"@barchart/common-js/lang/is":19}],7:[function(require,module,exports){
1316
- const assert = require('@barchart/common-js/lang/assert'),
1362
+ const array = require('@barchart/common-js/lang/array'),
1363
+ assert = require('@barchart/common-js/lang/assert'),
1317
1364
  Decimal = require('@barchart/common-js/lang/Decimal'),
1318
1365
  Event = require('@barchart/common-js/messaging/Event'),
1319
1366
  is = require('@barchart/common-js/lang/is');
@@ -1327,10 +1374,12 @@ module.exports = (() => {
1327
1374
  * @public
1328
1375
  */
1329
1376
  class PositionItem {
1330
- constructor(portfolio, position, summaries) {
1377
+ constructor(portfolio, position, currentSummary, previousSummaries) {
1331
1378
  this._portfolio = portfolio;
1332
1379
  this._position = position;
1333
- this._summaries = summaries || [ ];
1380
+
1381
+ this._currentSummary = currentSummary || null;
1382
+ this._previousSummaries = previousSummaries || [ ];
1334
1383
 
1335
1384
  this._data = { };
1336
1385
 
@@ -1347,6 +1396,11 @@ module.exports = (() => {
1347
1396
 
1348
1397
  this._data.realized = null;
1349
1398
  this._data.income = null;
1399
+
1400
+ this._data.summaryTotalCurrent = null;
1401
+ this._data.summaryTotalCurrentChange = null;
1402
+
1403
+ this._data.summaryTotalPrevious = null;
1350
1404
 
1351
1405
  this._excluded = false;
1352
1406
 
@@ -1365,8 +1419,12 @@ module.exports = (() => {
1365
1419
  return this._position;
1366
1420
  }
1367
1421
 
1368
- get summaries() {
1369
- return this._summaries;
1422
+ get currentSummary() {
1423
+ return this._currentSummary;
1424
+ }
1425
+
1426
+ get previousSummaries() {
1427
+ return this._previousSummaries;
1370
1428
  }
1371
1429
 
1372
1430
  get data() {
@@ -1411,7 +1469,7 @@ module.exports = (() => {
1411
1469
  function calculateStaticData(item) {
1412
1470
  const position = item.position;
1413
1471
  const snapshot = item.position.snapshot;
1414
- const summaries = item.summaries;
1472
+ const previousSummaries = item.previousSummaries;
1415
1473
 
1416
1474
  const data = item._data;
1417
1475
 
@@ -1430,22 +1488,8 @@ module.exports = (() => {
1430
1488
  data.realized = snapshot.gain;
1431
1489
  data.income = snapshot.income;
1432
1490
 
1433
- const getSummaryTotal = (index) => {
1434
- let summaryTotal;
1435
-
1436
- if (summaries.length > index && summaries[index] !== null) {
1437
- const period = summaries[index].period;
1438
-
1439
- summaryTotal = period.realized.add(period.unrealized).add(period.income);
1440
- } else {
1441
- summaryTotal = Decimal.ZERO;
1442
- }
1443
-
1444
- return summaryTotal;
1445
- };
1446
-
1447
- data.summaryOneTotal = getSummaryTotal(0);
1448
- data.summaryTwoTotal = getSummaryTotal(1);
1491
+ data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary);
1492
+ data.summaryTotalPrevious = calculateSummaryTotal(array.last(previousSummaries));
1449
1493
  }
1450
1494
 
1451
1495
  function calculatePriceData(item, price) {
@@ -1497,12 +1541,48 @@ module.exports = (() => {
1497
1541
 
1498
1542
  data.unrealizedToday = unrealizedToday;
1499
1543
  data.unrealizedTodayChange = unrealizedTodayChange;
1544
+
1545
+ const summary = item.currentSummary;
1546
+
1547
+ if (summary && price) {
1548
+ const period = summary.period;
1549
+
1550
+ let unrealizedCurrent = summary.open.multiply(price).add(summary.end.basis);
1551
+
1552
+ let summaryTotalCurrent = period.realized.add(period.income).add(unrealizedCurrent);
1553
+ let summaryTotalCurrentChange;
1554
+
1555
+ if (data.summaryTotalCurrent !== null) {
1556
+ summaryTotalCurrentChange = summaryTotalCurrent.subtract(data.summaryTotalCurrent);
1557
+ } else {
1558
+ summaryTotalCurrentChange = Decimal.ZERO;
1559
+ }
1560
+
1561
+ data.summaryTotalCurrent = summaryTotalCurrent;
1562
+ data.summaryTotalCurrentChange = summaryTotalCurrentChange;
1563
+ } else {
1564
+ data.summaryTotalCurrentChange = Decimal.ZERO;
1565
+ }
1566
+ }
1567
+
1568
+ function calculateSummaryTotal(summary) {
1569
+ let returnRef;
1570
+
1571
+ if (summary) {
1572
+ const period = summary.period;
1573
+
1574
+ returnRef = period.realized.add(period.income).add(period.unrealized);
1575
+ } else {
1576
+ returnRef = Decimal.ZERO;
1577
+ }
1578
+
1579
+ return returnRef;
1500
1580
  }
1501
1581
 
1502
1582
  return PositionItem;
1503
1583
  })();
1504
1584
 
1505
- },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Decimal":13,"@barchart/common-js/lang/assert":17,"@barchart/common-js/lang/is":19,"@barchart/common-js/messaging/Event":20}],8:[function(require,module,exports){
1585
+ },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Decimal":13,"@barchart/common-js/lang/array":16,"@barchart/common-js/lang/assert":17,"@barchart/common-js/lang/is":19,"@barchart/common-js/messaging/Event":20}],8:[function(require,module,exports){
1506
1586
  'use strict';
1507
1587
 
1508
1588
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();