@barchart/portfolio-api-common 1.0.113 → 1.0.117

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.
@@ -59,6 +59,7 @@ module.exports = (() => {
59
59
  this._dataActual.income = null;
60
60
  this._dataActual.market = null;
61
61
  this._dataActual.marketPercent = null;
62
+ this._dataActual.unrealized = null;
62
63
  this._dataActual.unrealizedToday = null;
63
64
  this._dataActual.total = null;
64
65
  this._dataActual.summaryTotalCurrent = null;
@@ -72,6 +73,9 @@ module.exports = (() => {
72
73
  this._dataFormat.market = null;
73
74
  this._dataFormat.marketPercent = null;
74
75
  this._dataFormat.marketDirection = null;
76
+ this._dataFormat.unrealized = null;
77
+ this._dataFormat.unrealizedPercent = null;
78
+ this._dataFormat.unrealizedNegative = false;
75
79
  this._dataFormat.unrealizedToday = null;
76
80
  this._dataFormat.unrealizedTodayNegative = false;
77
81
  this._dataFormat.total = null;
@@ -94,7 +98,7 @@ module.exports = (() => {
94
98
  this._dataFormat.quoteHigh = formatNumber(quote.highPrice, precision);
95
99
  this._dataFormat.quoteLow = formatNumber(quote.lowPrice, precision);
96
100
  this._dataFormat.quoteChange = formatNumber(quote.priceChange, precision);
97
- //this._dataFormat.quoteChangePercent = formatPercent(new Decimal(quote.percentChange), 2);
101
+ this._dataFormat.quoteChangePercent = formatPercent(new Decimal(quote.percentChange || 0), 2);
98
102
  this._dataFormat.quoteTime = quote.timeDisplay;
99
103
  this._dataFormat.quoteVolume = formatNumber(quote.volume, 0);
100
104
  } else {
@@ -203,7 +207,7 @@ module.exports = (() => {
203
207
 
204
208
  function formatPercent(decimal, precision) {
205
209
  if (decimal !== null) {
206
- return formatDecimal(decimal.multiply(100), precision);
210
+ return formatDecimal(decimal.multiply(100), precision) + '%';
207
211
  } else {
208
212
  return '—';
209
213
  }
@@ -228,6 +232,7 @@ module.exports = (() => {
228
232
  let updates = items.reduce((updates, item) => {
229
233
  updates.basis = updates.basis.add(item.data.basis);
230
234
  updates.realized = updates.realized.add(item.data.realized);
235
+ updates.unrealized = updates.unrealized.add(item.data.unrealized);
231
236
  updates.income = updates.income.add(item.data.income);
232
237
  updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
233
238
  updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
@@ -236,6 +241,7 @@ module.exports = (() => {
236
241
  }, {
237
242
  basis: Decimal.ZERO,
238
243
  realized: Decimal.ZERO,
244
+ unrealized: Decimal.ZERO,
239
245
  income: Decimal.ZERO,
240
246
  summaryTotalCurrent: Decimal.ZERO,
241
247
  summaryTotalPrevious: Decimal.ZERO
@@ -243,19 +249,26 @@ module.exports = (() => {
243
249
 
244
250
  actual.basis = updates.basis;
245
251
  actual.realized = updates.realized;
252
+ actual.unrealized = updates.unrealized;
246
253
  actual.income = updates.income;
247
254
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
248
255
  actual.summaryTotalPrevious = updates.summaryTotalPrevious;
249
256
 
250
257
  format.basis = formatCurrency(actual.basis, currency);
251
258
  format.realized = formatCurrency(actual.basis, currency);
259
+ format.unrealized = formatCurrency(actual.unrealized, currency);
252
260
  format.income = formatCurrency(actual.income, currency);
253
261
  format.summaryTotalCurrent = formatCurrency(updates.summaryTotalCurrent, currency);
254
262
  format.summaryTotalPrevious = formatCurrency(updates.summaryTotalPrevious, currency);
255
263
  format.summaryTotalPreviousNegative = updates.summaryTotalPrevious.getIsNegative();
256
264
 
265
+ calculateUnrealizedPercent(group);
266
+
257
267
  if (group.single) {
258
- format.quantity = formatDecimal(group._items[0].position.snapshot.open, 2);
268
+ const item = group._items[0];
269
+
270
+ format.quantity = formatDecimal(item.position.snapshot.open, 2);
271
+ format.basisPrice = formatCurrency(item.basisPrice, currency);
259
272
  }
260
273
  }
261
274
 
@@ -280,6 +293,7 @@ module.exports = (() => {
280
293
 
281
294
  updates = items.reduce((updates, item) => {
282
295
  updates.market = updates.market.add(item.data.market);
296
+ updates.unrealized = updates.unrealized.add(item.data.unrealized);
283
297
  updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
284
298
  updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
285
299
 
@@ -287,6 +301,7 @@ module.exports = (() => {
287
301
  }, {
288
302
  market: Decimal.ZERO,
289
303
  marketDirection: unchanged,
304
+ unrealized: Decimal.ZERO,
290
305
  unrealizedToday: Decimal.ZERO,
291
306
  summaryTotalCurrent: Decimal.ZERO
292
307
 
@@ -295,6 +310,7 @@ module.exports = (() => {
295
310
  updates = {
296
311
  market: actual.market.add(item.data.marketChange),
297
312
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
313
+ unrealized: actual.unrealized.add(item.data.unrealizedChange),
298
314
  unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
299
315
  summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
300
316
  };
@@ -313,6 +329,7 @@ module.exports = (() => {
313
329
  }
314
330
 
315
331
  actual.market = updates.market;
332
+ actual.unrealized = updates.unrealized;
316
333
  actual.unrealizedToday = updates.unrealizedToday;
317
334
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
318
335
  actual.total = updates.unrealizedToday.add(actual.realized).add(actual.income);
@@ -324,6 +341,9 @@ module.exports = (() => {
324
341
  setTimeout(() => format.marketDirection = updates.marketDirection, 0);
325
342
  }
326
343
 
344
+ format.unrealized = formatCurrency(actual.unrealized, currency);
345
+ format.unrealizedNegative = actual.unrealized.getIsNegative();
346
+
327
347
  format.unrealizedToday = formatCurrency(actual.unrealizedToday, currency);
328
348
  format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
329
349
 
@@ -334,6 +354,7 @@ module.exports = (() => {
334
354
  format.totalNegative = actual.total.getIsNegative();
335
355
 
336
356
  calculateMarketPercent(group, false);
357
+ calculateUnrealizedPercent(group);
337
358
  }
338
359
 
339
360
  function calculateMarketPercent(group, silent) {
@@ -369,6 +390,19 @@ module.exports = (() => {
369
390
  }
370
391
  }
371
392
 
393
+ function calculateUnrealizedPercent(group) {
394
+ const actual = group._dataActual;
395
+ const format = group._dataFormat;
396
+
397
+ if (actual.basis.getIsZero()) {
398
+ actual.unrealizedPercent = null;
399
+ format.unrealizedPercent = '—';
400
+ } else {
401
+ actual.unrealizedPercent = actual.unrealized.divide(actual.basis);
402
+ format.unrealizedPercent = formatPercent(actual.unrealizedPercent, 2);
403
+ }
404
+ }
405
+
372
406
  const unchanged = { up: false, down: false };
373
407
 
374
408
  return PositionGroup;
@@ -36,14 +36,18 @@ module.exports = (() => {
36
36
  this._data.unrealizedToday = null;
37
37
  this._data.unrealizedTodayChange = null;
38
38
 
39
- this._data.realized = null;
40
- this._data.income = null;
39
+ this._data.unrealized = null;
40
+ this._data.unrealizedChange = null;
41
41
 
42
42
  this._data.summaryTotalCurrent = null;
43
43
  this._data.summaryTotalCurrentChange = null;
44
44
 
45
45
  this._data.summaryTotalPrevious = null;
46
46
 
47
+ this._data.realized = null;
48
+ this._data.income = null;
49
+ this._data.basisPrice = null;
50
+
47
51
  this._excluded = false;
48
52
 
49
53
  calculateStaticData(this);
@@ -138,10 +142,14 @@ module.exports = (() => {
138
142
  data.basis = basis;
139
143
 
140
144
  data.realized = snapshot.gain;
145
+ data.unrealized = Decimal.ZERO;
146
+
141
147
  data.income = snapshot.income;
142
148
 
143
149
  data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary);
144
150
  data.summaryTotalPrevious = calculateSummaryTotal(array.last(previousSummaries));
151
+
152
+ data.basisPrice = basis.divide(snapshot.open);
145
153
  }
146
154
 
147
155
  function calculatePriceData(item, price) {
@@ -174,7 +182,7 @@ module.exports = (() => {
174
182
 
175
183
  data.market = market;
176
184
  data.marketChange = marketChange;
177
-
185
+
178
186
  let unrealizedToday;
179
187
  let unrealizedTodayChange;
180
188
 
@@ -199,9 +207,16 @@ module.exports = (() => {
199
207
  if (summary && price) {
200
208
  const period = summary.period;
201
209
 
202
- let unrealizedCurrent = summary.end.open.multiply(price).add(summary.end.basis);
210
+ let unrealized = summary.end.open.multiply(price).add(summary.end.basis);
211
+ let unrealizedChange;
203
212
 
204
- let summaryTotalCurrent = period.realized.add(period.income).add(unrealizedCurrent);
213
+ if (data.unrealizedToday !== null) {
214
+ unrealizedChange = unrealized.subtract(data.unrealized);
215
+ } else {
216
+ unrealizedChange = Decimal.ZERO;
217
+ }
218
+
219
+ let summaryTotalCurrent = period.realized.add(period.income).add(unrealized);
205
220
  let summaryTotalCurrentChange;
206
221
 
207
222
  if (data.summaryTotalCurrent !== null) {
@@ -212,8 +227,14 @@ module.exports = (() => {
212
227
 
213
228
  data.summaryTotalCurrent = summaryTotalCurrent;
214
229
  data.summaryTotalCurrentChange = summaryTotalCurrentChange;
230
+
231
+ data.unrealized = unrealized;
232
+ data.unrealizedChange = unrealizedChange;
215
233
  } else {
216
234
  data.summaryTotalCurrentChange = Decimal.ZERO;
235
+
236
+ data.unrealized = Decimal.ZERO;
237
+ data.unrealizedChange = Decimal.ZERO;
217
238
  }
218
239
  }
219
240
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.113",
3
+ "version": "1.0.117",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -1064,6 +1064,7 @@ module.exports = (() => {
1064
1064
  this._dataActual.income = null;
1065
1065
  this._dataActual.market = null;
1066
1066
  this._dataActual.marketPercent = null;
1067
+ this._dataActual.unrealized = null;
1067
1068
  this._dataActual.unrealizedToday = null;
1068
1069
  this._dataActual.total = null;
1069
1070
  this._dataActual.summaryTotalCurrent = null;
@@ -1077,6 +1078,9 @@ module.exports = (() => {
1077
1078
  this._dataFormat.market = null;
1078
1079
  this._dataFormat.marketPercent = null;
1079
1080
  this._dataFormat.marketDirection = null;
1081
+ this._dataFormat.unrealized = null;
1082
+ this._dataFormat.unrealizedPercent = null;
1083
+ this._dataFormat.unrealizedNegative = false;
1080
1084
  this._dataFormat.unrealizedToday = null;
1081
1085
  this._dataFormat.unrealizedTodayNegative = false;
1082
1086
  this._dataFormat.total = null;
@@ -1099,7 +1103,7 @@ module.exports = (() => {
1099
1103
  this._dataFormat.quoteHigh = formatNumber(quote.highPrice, precision);
1100
1104
  this._dataFormat.quoteLow = formatNumber(quote.lowPrice, precision);
1101
1105
  this._dataFormat.quoteChange = formatNumber(quote.priceChange, precision);
1102
- //this._dataFormat.quoteChangePercent = formatPercent(new Decimal(quote.percentChange), 2);
1106
+ this._dataFormat.quoteChangePercent = formatPercent(new Decimal(quote.percentChange || 0), 2);
1103
1107
  this._dataFormat.quoteTime = quote.timeDisplay;
1104
1108
  this._dataFormat.quoteVolume = formatNumber(quote.volume, 0);
1105
1109
  } else {
@@ -1208,7 +1212,7 @@ module.exports = (() => {
1208
1212
 
1209
1213
  function formatPercent(decimal, precision) {
1210
1214
  if (decimal !== null) {
1211
- return formatDecimal(decimal.multiply(100), precision);
1215
+ return formatDecimal(decimal.multiply(100), precision) + '%';
1212
1216
  } else {
1213
1217
  return '—';
1214
1218
  }
@@ -1233,6 +1237,7 @@ module.exports = (() => {
1233
1237
  let updates = items.reduce((updates, item) => {
1234
1238
  updates.basis = updates.basis.add(item.data.basis);
1235
1239
  updates.realized = updates.realized.add(item.data.realized);
1240
+ updates.unrealized = updates.unrealized.add(item.data.unrealized);
1236
1241
  updates.income = updates.income.add(item.data.income);
1237
1242
  updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1238
1243
  updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
@@ -1241,6 +1246,7 @@ module.exports = (() => {
1241
1246
  }, {
1242
1247
  basis: Decimal.ZERO,
1243
1248
  realized: Decimal.ZERO,
1249
+ unrealized: Decimal.ZERO,
1244
1250
  income: Decimal.ZERO,
1245
1251
  summaryTotalCurrent: Decimal.ZERO,
1246
1252
  summaryTotalPrevious: Decimal.ZERO
@@ -1248,19 +1254,26 @@ module.exports = (() => {
1248
1254
 
1249
1255
  actual.basis = updates.basis;
1250
1256
  actual.realized = updates.realized;
1257
+ actual.unrealized = updates.unrealized;
1251
1258
  actual.income = updates.income;
1252
1259
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
1253
1260
  actual.summaryTotalPrevious = updates.summaryTotalPrevious;
1254
1261
 
1255
1262
  format.basis = formatCurrency(actual.basis, currency);
1256
1263
  format.realized = formatCurrency(actual.basis, currency);
1264
+ format.unrealized = formatCurrency(actual.unrealized, currency);
1257
1265
  format.income = formatCurrency(actual.income, currency);
1258
1266
  format.summaryTotalCurrent = formatCurrency(updates.summaryTotalCurrent, currency);
1259
1267
  format.summaryTotalPrevious = formatCurrency(updates.summaryTotalPrevious, currency);
1260
1268
  format.summaryTotalPreviousNegative = updates.summaryTotalPrevious.getIsNegative();
1261
1269
 
1270
+ calculateUnrealizedPercent(group);
1271
+
1262
1272
  if (group.single) {
1263
- format.quantity = formatDecimal(group._items[0].position.snapshot.open, 2);
1273
+ const item = group._items[0];
1274
+
1275
+ format.quantity = formatDecimal(item.position.snapshot.open, 2);
1276
+ format.basisPrice = formatCurrency(item.basisPrice, currency);
1264
1277
  }
1265
1278
  }
1266
1279
 
@@ -1285,6 +1298,7 @@ module.exports = (() => {
1285
1298
 
1286
1299
  updates = items.reduce((updates, item) => {
1287
1300
  updates.market = updates.market.add(item.data.market);
1301
+ updates.unrealized = updates.unrealized.add(item.data.unrealized);
1288
1302
  updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
1289
1303
  updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1290
1304
 
@@ -1292,6 +1306,7 @@ module.exports = (() => {
1292
1306
  }, {
1293
1307
  market: Decimal.ZERO,
1294
1308
  marketDirection: unchanged,
1309
+ unrealized: Decimal.ZERO,
1295
1310
  unrealizedToday: Decimal.ZERO,
1296
1311
  summaryTotalCurrent: Decimal.ZERO
1297
1312
 
@@ -1300,6 +1315,7 @@ module.exports = (() => {
1300
1315
  updates = {
1301
1316
  market: actual.market.add(item.data.marketChange),
1302
1317
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
1318
+ unrealized: actual.unrealized.add(item.data.unrealizedChange),
1303
1319
  unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
1304
1320
  summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
1305
1321
  };
@@ -1318,6 +1334,7 @@ module.exports = (() => {
1318
1334
  }
1319
1335
 
1320
1336
  actual.market = updates.market;
1337
+ actual.unrealized = updates.unrealized;
1321
1338
  actual.unrealizedToday = updates.unrealizedToday;
1322
1339
  actual.summaryTotalCurrent = updates.summaryTotalCurrent;
1323
1340
  actual.total = updates.unrealizedToday.add(actual.realized).add(actual.income);
@@ -1329,6 +1346,9 @@ module.exports = (() => {
1329
1346
  setTimeout(() => format.marketDirection = updates.marketDirection, 0);
1330
1347
  }
1331
1348
 
1349
+ format.unrealized = formatCurrency(actual.unrealized, currency);
1350
+ format.unrealizedNegative = actual.unrealized.getIsNegative();
1351
+
1332
1352
  format.unrealizedToday = formatCurrency(actual.unrealizedToday, currency);
1333
1353
  format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
1334
1354
 
@@ -1339,6 +1359,7 @@ module.exports = (() => {
1339
1359
  format.totalNegative = actual.total.getIsNegative();
1340
1360
 
1341
1361
  calculateMarketPercent(group, false);
1362
+ calculateUnrealizedPercent(group);
1342
1363
  }
1343
1364
 
1344
1365
  function calculateMarketPercent(group, silent) {
@@ -1374,6 +1395,19 @@ module.exports = (() => {
1374
1395
  }
1375
1396
  }
1376
1397
 
1398
+ function calculateUnrealizedPercent(group) {
1399
+ const actual = group._dataActual;
1400
+ const format = group._dataFormat;
1401
+
1402
+ if (actual.basis.getIsZero()) {
1403
+ actual.unrealizedPercent = null;
1404
+ format.unrealizedPercent = '—';
1405
+ } else {
1406
+ actual.unrealizedPercent = actual.unrealized.divide(actual.basis);
1407
+ format.unrealizedPercent = formatPercent(actual.unrealizedPercent, 2);
1408
+ }
1409
+ }
1410
+
1377
1411
  const unchanged = { up: false, down: false };
1378
1412
 
1379
1413
  return PositionGroup;
@@ -1418,14 +1452,18 @@ module.exports = (() => {
1418
1452
  this._data.unrealizedToday = null;
1419
1453
  this._data.unrealizedTodayChange = null;
1420
1454
 
1421
- this._data.realized = null;
1422
- this._data.income = null;
1455
+ this._data.unrealized = null;
1456
+ this._data.unrealizedChange = null;
1423
1457
 
1424
1458
  this._data.summaryTotalCurrent = null;
1425
1459
  this._data.summaryTotalCurrentChange = null;
1426
1460
 
1427
1461
  this._data.summaryTotalPrevious = null;
1428
1462
 
1463
+ this._data.realized = null;
1464
+ this._data.income = null;
1465
+ this._data.basisPrice = null;
1466
+
1429
1467
  this._excluded = false;
1430
1468
 
1431
1469
  calculateStaticData(this);
@@ -1520,10 +1558,14 @@ module.exports = (() => {
1520
1558
  data.basis = basis;
1521
1559
 
1522
1560
  data.realized = snapshot.gain;
1561
+ data.unrealized = Decimal.ZERO;
1562
+
1523
1563
  data.income = snapshot.income;
1524
1564
 
1525
1565
  data.summaryTotalCurrent = calculateSummaryTotal(item.currentSummary);
1526
1566
  data.summaryTotalPrevious = calculateSummaryTotal(array.last(previousSummaries));
1567
+
1568
+ data.basisPrice = basis.divide(snapshot.open);
1527
1569
  }
1528
1570
 
1529
1571
  function calculatePriceData(item, price) {
@@ -1556,7 +1598,7 @@ module.exports = (() => {
1556
1598
 
1557
1599
  data.market = market;
1558
1600
  data.marketChange = marketChange;
1559
-
1601
+
1560
1602
  let unrealizedToday;
1561
1603
  let unrealizedTodayChange;
1562
1604
 
@@ -1581,9 +1623,16 @@ module.exports = (() => {
1581
1623
  if (summary && price) {
1582
1624
  const period = summary.period;
1583
1625
 
1584
- let unrealizedCurrent = summary.end.open.multiply(price).add(summary.end.basis);
1626
+ let unrealized = summary.end.open.multiply(price).add(summary.end.basis);
1627
+ let unrealizedChange;
1585
1628
 
1586
- let summaryTotalCurrent = period.realized.add(period.income).add(unrealizedCurrent);
1629
+ if (data.unrealizedToday !== null) {
1630
+ unrealizedChange = unrealized.subtract(data.unrealized);
1631
+ } else {
1632
+ unrealizedChange = Decimal.ZERO;
1633
+ }
1634
+
1635
+ let summaryTotalCurrent = period.realized.add(period.income).add(unrealized);
1587
1636
  let summaryTotalCurrentChange;
1588
1637
 
1589
1638
  if (data.summaryTotalCurrent !== null) {
@@ -1594,8 +1643,14 @@ module.exports = (() => {
1594
1643
 
1595
1644
  data.summaryTotalCurrent = summaryTotalCurrent;
1596
1645
  data.summaryTotalCurrentChange = summaryTotalCurrentChange;
1646
+
1647
+ data.unrealized = unrealized;
1648
+ data.unrealizedChange = unrealizedChange;
1597
1649
  } else {
1598
1650
  data.summaryTotalCurrentChange = Decimal.ZERO;
1651
+
1652
+ data.unrealized = Decimal.ZERO;
1653
+ data.unrealizedChange = Decimal.ZERO;
1599
1654
  }
1600
1655
  }
1601
1656