@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.
- package/lib/data/PositionSummaryFrame.js +9 -10
- package/lib/data/TransactionType.js +35 -22
- package/lib/formatters/TransactionFormatter.js +4 -3
- package/lib/processing/PositionContainer.js +44 -19
- package/lib/processing/PositionGroup.js +23 -14
- package/lib/processing/PositionItem.js +56 -22
- package/package.json +1 -1
- package/test/SpecRunner.js +165 -85
|
@@ -37,12 +37,11 @@ module.exports = (() => {
|
|
|
37
37
|
* start and end dates.
|
|
38
38
|
*
|
|
39
39
|
* @public
|
|
40
|
-
* @
|
|
41
|
-
* @param {Day} endDate
|
|
40
|
+
* @return {PositionSummaryRange} range
|
|
42
41
|
* @return {String}
|
|
43
42
|
*/
|
|
44
|
-
describeRange(
|
|
45
|
-
return this._descriptionCalculator(
|
|
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(
|
|
230
|
-
return
|
|
228
|
+
function getYearlyRangeDescription(start, end) {
|
|
229
|
+
return end.year.toString();
|
|
231
230
|
}
|
|
232
231
|
|
|
233
|
-
function getQuarterlyRangeDescription(
|
|
232
|
+
function getQuarterlyRangeDescription(start, end) {
|
|
234
233
|
return '';
|
|
235
234
|
}
|
|
236
235
|
|
|
237
|
-
function getMonthlyRangeDescription(
|
|
236
|
+
function getMonthlyRangeDescription(start, end) {
|
|
238
237
|
return '';
|
|
239
238
|
}
|
|
240
239
|
|
|
241
|
-
function getYearToDateRangeDescription(
|
|
242
|
-
return `${
|
|
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',
|
|
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(
|
|
38
|
+
positions.map(p => positionMap[p.position] = p.instrument);
|
|
39
39
|
|
|
40
|
-
return transactions.filter(
|
|
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,
|
|
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
|
-
|
|
26
|
-
|
|
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.
|
|
35
|
-
if (
|
|
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(
|
|
55
|
+
map[key] = getSummaryArray(previousSummaryRanges);
|
|
40
56
|
}
|
|
41
57
|
|
|
42
|
-
const index =
|
|
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
|
|
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,
|
|
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.
|
|
46
|
-
this._dataActual.
|
|
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.
|
|
61
|
-
this.
|
|
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.
|
|
191
|
-
updates.
|
|
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
|
-
|
|
199
|
-
|
|
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.
|
|
206
|
-
actual.
|
|
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.
|
|
212
|
-
format.
|
|
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
|
|
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,
|
|
16
|
+
constructor(portfolio, position, currentSummary, previousSummaries) {
|
|
16
17
|
this._portfolio = portfolio;
|
|
17
18
|
this._position = position;
|
|
18
|
-
|
|
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
|
|
54
|
-
return this.
|
|
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
|
|
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
|
-
|
|
119
|
-
|
|
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
package/test/SpecRunner.js
CHANGED
|
@@ -156,12 +156,11 @@ module.exports = (() => {
|
|
|
156
156
|
* start and end dates.
|
|
157
157
|
*
|
|
158
158
|
* @public
|
|
159
|
-
* @
|
|
160
|
-
* @param {Day} endDate
|
|
159
|
+
* @return {PositionSummaryRange} range
|
|
161
160
|
* @return {String}
|
|
162
161
|
*/
|
|
163
|
-
describeRange(
|
|
164
|
-
return this._descriptionCalculator(
|
|
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(
|
|
349
|
-
return
|
|
347
|
+
function getYearlyRangeDescription(start, end) {
|
|
348
|
+
return end.year.toString();
|
|
350
349
|
}
|
|
351
350
|
|
|
352
|
-
function getQuarterlyRangeDescription(
|
|
351
|
+
function getQuarterlyRangeDescription(start, end) {
|
|
353
352
|
return '';
|
|
354
353
|
}
|
|
355
354
|
|
|
356
|
-
function getMonthlyRangeDescription(
|
|
355
|
+
function getMonthlyRangeDescription(start, end) {
|
|
357
356
|
return '';
|
|
358
357
|
}
|
|
359
358
|
|
|
360
|
-
function getYearToDateRangeDescription(
|
|
361
|
-
return `${
|
|
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',
|
|
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,
|
|
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
|
-
|
|
730
|
-
|
|
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.
|
|
739
|
-
if (
|
|
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(
|
|
771
|
+
map[key] = getSummaryArray(previousSummaryRanges);
|
|
744
772
|
}
|
|
745
773
|
|
|
746
|
-
const index =
|
|
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
|
|
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,
|
|
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.
|
|
989
|
-
this._dataActual.
|
|
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.
|
|
1004
|
-
this.
|
|
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.
|
|
1134
|
-
updates.
|
|
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
|
-
|
|
1142
|
-
|
|
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.
|
|
1149
|
-
actual.
|
|
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.
|
|
1155
|
-
format.
|
|
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
|
|
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,
|
|
1377
|
+
constructor(portfolio, position, currentSummary, previousSummaries) {
|
|
1331
1378
|
this._portfolio = portfolio;
|
|
1332
1379
|
this._position = position;
|
|
1333
|
-
|
|
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
|
|
1369
|
-
return this.
|
|
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
|
|
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
|
-
|
|
1434
|
-
|
|
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; }; }();
|