@barchart/portfolio-api-common 1.2.120 → 1.2.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -64,7 +64,7 @@ module.exports = (() => {
64
64
  *
65
65
  * @public
66
66
  * @param {Number} periods
67
- * @returns {Array.<PositionSummaryRange>}
67
+ * @returns {PositionSummaryRange[]}
68
68
  */
69
69
  getRecentRanges(periods) {
70
70
  const startDate = this.getStartDate(periods);
@@ -77,8 +77,8 @@ module.exports = (() => {
77
77
  * Returns the ranges for the set of {@link Transaction} objects.
78
78
  *
79
79
  * @public
80
- * @param {Array.<Transaction>} transactions
81
- * @returns {Array.<PositionSummaryRange>}
80
+ * @param {Transaction[]} transactions
81
+ * @returns {PositionSummaryRange[]}
82
82
  */
83
83
  getRanges(transactions) {
84
84
  assert.argumentIsArray(transactions, 'transactions');
@@ -91,7 +91,7 @@ module.exports = (() => {
91
91
  *
92
92
  * @public
93
93
  * @param {Day} date
94
- * @return {Array.<PositionSummaryRange>}
94
+ * @return {PositionSummaryRange[]}
95
95
  */
96
96
  getRangesFromDate(date) {
97
97
  assert.argumentIsRequired(date, 'date', Day, 'Day');
@@ -180,8 +180,8 @@ module.exports = (() => {
180
180
  }
181
181
 
182
182
  const yearly = new PositionSummaryFrame('YEARLY', 'year', false, getYearlyRanges, getYearlyStartDate, getYearlyRangeDescription);
183
- const quarterly = new PositionSummaryFrame('QUARTER', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
184
- const monthly = new PositionSummaryFrame('MONTH', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
183
+ const quarterly = new PositionSummaryFrame('QUARTERLY', 'quarter', false, getQuarterlyRanges, getQuarterlyStartDate, getQuarterlyRangeDescription);
184
+ const monthly = new PositionSummaryFrame('MONTHLY', 'month', false, getMonthlyRanges, getMonthlyStartDate, getMonthlyRangeDescription);
185
185
  const ytd = new PositionSummaryFrame('YTD', 'year-to-date', true, getYearToDateRanges, getYearToDateStartDate, getYearToDateRangeDescription);
186
186
 
187
187
  /**
@@ -241,32 +241,32 @@ module.exports = (() => {
241
241
  }
242
242
 
243
243
  function getMonthlyRanges(transactions) {
244
- const ranges = [ ];
245
-
246
- if (!transactions.length) {
247
- return ranges;
244
+ const ranges = [ ];
245
+
246
+ if (!transactions.length) {
247
+ return ranges;
248
248
  }
249
249
 
250
250
  const first = array.first(transactions);
251
251
  const last = array.last(transactions);
252
252
 
253
253
  const firstDate = first.date;
254
+
254
255
  let lastDate;
255
256
 
256
- lastDate = last.snapshot.open.getIsZero()
257
- ? new Day(last.date.year, last.date.month, last.date.day).addMonths(1)
258
- : Day.getToday();
257
+ if (last.snapshot.open.getIsZero()) {
258
+ lastDate = new Day(last.date.year, last.date.month, last.date.day).addMonths(1);
259
+ } else {
260
+ lastDate = Day.getToday();
261
+ }
262
+
259
263
  lastDate = lastDate.getEndOfMonth();
260
264
 
261
- for (
262
- let end = firstDate.getEndOfMonth();
263
- end.format() <= lastDate.format();
264
- end = end.addMonths(1).getEndOfMonth()
265
- ) {
265
+ for (let end = firstDate.getEndOfMonth(); end.format() <= lastDate.format(); end = end.addMonths(1).getEndOfMonth()) {
266
266
  ranges.push(getRange(end.subtractMonths(1).getEndOfMonth(), end));
267
267
  }
268
-
269
- return ranges;
268
+
269
+ return ranges;
270
270
  }
271
271
 
272
272
  function getYearToDateRanges(transactions) {
@@ -303,8 +303,8 @@ module.exports = (() => {
303
303
  }
304
304
 
305
305
  function getMonthlyStartDate(periods, date) {
306
- const today = date || Day.getToday();
307
-
306
+ const today = date || Day.getToday();
307
+
308
308
  return today
309
309
  .subtractMonths(periods)
310
310
  .subtractDays(today.day);
@@ -323,7 +323,7 @@ module.exports = (() => {
323
323
  }
324
324
 
325
325
  function getMonthlyRangeDescription(start, end) {
326
- return '';
326
+ return `Month ended ${end.format()}`;
327
327
  }
328
328
 
329
329
  function getYearToDateRangeDescription(start, end) {
@@ -46,32 +46,33 @@ module.exports = (() => {
46
46
  return map;
47
47
  }, { });
48
48
 
49
- const a = transactions.reduce((list, transaction) => {
49
+ const list = transactions.reduce((accumulator, transaction) => {
50
50
  const position = transaction.position;
51
51
 
52
52
  if (instruments.hasOwnProperty(position)) {
53
53
  let instrument = instruments[position];
54
- let formatted = getBasicTransaction(transaction, instrument);
54
+ let formatted = { instrument: instrument };
55
55
 
56
- if (formatters.has(transaction.type)) {
57
- const formatterFunction = formatters.get(transaction.type);
58
- const formattedTransaction = formatterFunction(transaction);
56
+ const formatterFunctions = formatters.get(transaction.type);
59
57
 
60
- Object.keys(formattedTransaction).map((key) => {
61
- if (!is.undefined(formattedTransaction[key]) && formattedTransaction[key] instanceof Decimal) {
62
- const precision = instrument.currency.precision;
58
+ formatterFunctions.forEach((formatterFunction) => {
59
+ formatterFunction(transaction, formatted);
60
+ });
63
61
 
64
- formattedTransaction[key] = formatter.numberToString(formattedTransaction[key].toFloat(), precision, ',');
65
- }
66
- });
62
+ Object.keys(formatted).forEach((key) => {
63
+ const value = formatted[key];
67
64
 
68
- formatted = Object.assign({}, formatted, formattedTransaction);
69
- }
65
+ if (value instanceof Decimal) {
66
+ const precision = instrument.currency.precision;
70
67
 
71
- list.push(formatted);
68
+ formatted[key] = formatter.numberToString(value.toFloat(), precision, ',');
69
+ }
70
+ });
71
+
72
+ accumulator.push(formatted);
72
73
  }
73
74
 
74
- return list;
75
+ return accumulator;
75
76
  }, [ ]);
76
77
 
77
78
  let comparator;
@@ -82,13 +83,13 @@ module.exports = (() => {
82
83
  comparator = comparatorAscending;
83
84
  }
84
85
 
85
- a.sort(comparator);
86
+ list.sort(comparator);
86
87
 
87
- a.forEach((t) => {
88
+ list.forEach((t) => {
88
89
  delete t.instrument.id;
89
90
  });
90
91
 
91
- return a;
92
+ return list;
92
93
  }
93
94
 
94
95
  /**
@@ -120,126 +121,105 @@ module.exports = (() => {
120
121
  }
121
122
  }
122
123
 
123
- const getBasicTransaction = (t, i) => {
124
- return {
125
- date: t.date,
126
- type: t.type.display,
127
- code: t.type.code,
128
- sequence: t.sequence,
129
- instrument: i,
130
- position: t.position
131
- };
124
+ const basicFormatter = (t, f) => {
125
+ f.date = t.date;
126
+ f.type = t.type.display;
127
+ f.code = t.type.code;
128
+ f.sequence = t.sequence;
129
+ f.position = t.position;
132
130
  };
133
131
 
134
- const formatters = new Map();
135
-
136
- const buySellFormatter = (t) => {
137
- return {
138
- boughtSold: t.quantity,
139
- price: t.trade.price,
140
- fee: t.fee,
141
- total: t.amount
142
- };
132
+ const averageCostFormatter = (t, f) => {
133
+ const basis = t.snapshot.basis;
134
+ const open = t.snapshot.open;
135
+
136
+ let average;
137
+
138
+ if (basis && open && !open.getIsZero()) {
139
+ average = basis.divide(open).absolute();
140
+ } else {
141
+ average = '';
142
+ }
143
+
144
+ f.average = average;
143
145
  };
144
146
 
145
- formatters.set(TransactionType.BUY, buySellFormatter);
146
- formatters.set(TransactionType.SELL, buySellFormatter);
147
- formatters.set(TransactionType.BUY_SHORT, buySellFormatter);
148
- formatters.set(TransactionType.SELL_SHORT, buySellFormatter);
149
-
150
- formatters.set(TransactionType.DIVIDEND, (t) => {
151
- return {
152
- shares: t.snapshot.open,
153
- total: t.dividend.amount,
154
- rate: t.dividend.rate
155
- };
156
- });
157
-
158
- formatters.set(TransactionType.DIVIDEND_STOCK, (t) => {
159
- const data = {
160
- boughtSold: t.quantity,
161
- fee: t.fee
162
- };
147
+ const buySellFormatter = (t, f) => {
148
+ f.boughtSold = t.quantity;
149
+ f.price = t.trade.price;
150
+ f.fee = t.fee;
151
+ f.total = t.amount;
152
+ };
153
+
154
+ const dividendFormatter = (t, f) => {
155
+ f.shares = t.snapshot.open;
156
+ f.total = t.dividend.amount;
157
+ f.rate = t.dividend.rate;
158
+ };
159
+
160
+ const dividendStockFormatter = (t, f) => {
161
+ f.boughtSold = t.quantity;
162
+ f.fee = t.fee;
163
163
 
164
164
  if (t.dividend && t.dividend.rate && t.dividend.price) {
165
- data.shares = t.snapshot.open.subtract(t.quantity);
166
- data.price = t.dividend.price;
167
- data.rate = t.dividend.rate;
165
+ f.shares = t.snapshot.open.subtract(t.quantity);
166
+ f.price = t.dividend.price;
167
+ f.rate = t.dividend.rate;
168
168
  }
169
+ };
170
+
171
+ const dividendReinvestFormatter = (t, f) => {
172
+ f.boughtSold = t.quantity;
173
+ f.shares = t.snapshot.open.subtract(t.quantity);
174
+ f.price = t.dividend.price;
175
+ f.fee = t.fee;
176
+ f.rate = t.dividend.rate;
177
+ };
178
+
179
+ const distributionCashFormatter = (t, f) => {
180
+ f.shares = t.snapshot.open;
181
+ f.total = t.dividend.amount;
182
+ f.rate = t.dividend.rate;
183
+ };
169
184
 
170
- return data;
171
- });
172
-
173
- formatters.set(TransactionType.DIVIDEND_REINVEST, (t) => {
174
- return {
175
- boughtSold: t.quantity,
176
- shares: t.snapshot.open.subtract(t.quantity),
177
- price: t.dividend.price,
178
- fee: t.fee,
179
- rate: t.dividend.rate
180
- };
181
- });
182
-
183
- formatters.set(TransactionType.DISTRIBUTION_CASH, (t) => {
184
- return {
185
- shares: t.snapshot.open,
186
- total: t.dividend.amount,
187
- rate: t.dividend.rate
188
- };
189
- });
190
-
191
- formatters.set(TransactionType.DISTRIBUTION_FUND, (t) => {
192
- const data = {
193
- boughtSold: t.quantity,
194
- fee: t.fee
195
- };
185
+ const distributionFundFormatter = (t, f) => {
186
+ f.boughtSold =t.quantity;
187
+ f.fee = t.fee;
196
188
 
197
189
  if (t.dividend && t.dividend.rate && t.dividend.price) {
198
- data.shares = t.snapshot.open.subtract(t.quantity);
199
- data.price = t.dividend.price;
200
- data.rate = t.dividend.rate;
190
+ f.shares = t.snapshot.open.subtract(t.quantity);
191
+ f.price = t.dividend.price;
192
+ f.rate = t.dividend.rate;
201
193
  }
194
+ };
202
195
 
203
- return data;
204
- });
205
-
206
- formatters.set(TransactionType.DISTRIBUTION_REINVEST, (t) => {
207
- return {
208
- boughtSold: t.quantity,
209
- shares: t.snapshot.open.subtract(t.quantity),
210
- price: t.dividend.price,
211
- fee: t.fee,
212
- rate: t.dividend.rate
213
- };
214
- });
215
-
216
- formatters.set(TransactionType.INCOME, (t) => {
217
- return {
218
- total: t.income.amount
219
- };
220
- });
221
-
222
- formatters.set(TransactionType.FEE, (t) => {
223
- return {
224
- fee: t.charge.amount,
225
- total: t.charge.amount
226
- };
227
- });
228
-
229
- formatters.set(TransactionType.FEE_UNITS, (t) => {
230
- return {
231
- boughtSold: t.quantity
232
- };
233
- });
234
-
235
- formatters.set(TransactionType.SPLIT, (t) => {
236
- return {
237
- shares: t.quantity,
238
- rate: t.split.numerator.divide(t.split.denominator)
239
- };
240
- });
241
-
242
- formatters.set(TransactionType.VALUATION, (t) => {
196
+ const distributionReinvestFormatter = (t, f) => {
197
+ f.boughtSold = t.quantity;
198
+ f.shares = t.snapshot.open.subtract(t.quantity);
199
+ f.price = t.dividend.price;
200
+ f.fee = t.fee;
201
+ f.rate = t.dividend.rate;
202
+ };
203
+
204
+ const incomeFormatter = (t, f) => {
205
+ f.total = t.income.amount;
206
+ };
207
+
208
+ const feeFormatter = (t, f) => {
209
+ f.fee = t.charge.amount;
210
+ f.total = t.charge.amount;
211
+ };
212
+
213
+ const feeUnitsFormatter = (t, f) => {
214
+ f.boughtSold = t.quantity;
215
+ };
216
+
217
+ const splitFormatter = (t, f) => {
218
+ f.shares = t.quantity;
219
+ f.rate = t.split.numerator.divide(t.split.denominator);
220
+ };
221
+
222
+ const valuationFormatter = (t, f) => {
243
223
  let rate;
244
224
 
245
225
  if (t.valuation.rate) {
@@ -250,39 +230,43 @@ module.exports = (() => {
250
230
  rate = t.valuation.value.divide(t.snapshot.open);
251
231
  }
252
232
 
253
- return {
254
- price: rate
255
- };
256
- });
257
-
258
- formatters.set(TransactionType.DELIST, () => {
259
- return { };
260
- });
261
-
262
- const cashFormatter = (t) => {
263
- return {
264
- total: t.quantity
265
- };
233
+ f.price = rate;
266
234
  };
267
235
 
268
- formatters.set(TransactionType.DEPOSIT, cashFormatter);
269
- formatters.set(TransactionType.WITHDRAWAL, cashFormatter);
270
-
271
- formatters.set(TransactionType.DEBIT, (t) => {
272
- const formatted = cashFormatter(t);
273
-
274
- formatted.description = t.description;
236
+ const cashFormatter = (t, f) => {
237
+ f.total = t.quantity;
238
+ };
275
239
 
276
- return formatted;
277
- });
240
+ const debitFormatter = (t, f) => {
241
+ f.description = t.description;
242
+ };
278
243
 
279
- formatters.set(TransactionType.CREDIT, (t) => {
280
- const formatted = cashFormatter(t);
244
+ const creditFormatter = (t, f) => {
245
+ f.description = t.description;
246
+ };
281
247
 
282
- formatted.description = t.description;
248
+ const formatters = new Map();
283
249
 
284
- return formatted;
285
- });
250
+ formatters.set(TransactionType.BUY, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
251
+ formatters.set(TransactionType.SELL, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
252
+ formatters.set(TransactionType.BUY_SHORT, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
253
+ formatters.set(TransactionType.SELL_SHORT, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
254
+ formatters.set(TransactionType.DIVIDEND, [ basicFormatter, dividendFormatter, averageCostFormatter ]);
255
+ formatters.set(TransactionType.DIVIDEND_STOCK, [ basicFormatter, dividendStockFormatter, averageCostFormatter ]);
256
+ formatters.set(TransactionType.DIVIDEND_REINVEST, [ basicFormatter, dividendReinvestFormatter, averageCostFormatter ]);
257
+ formatters.set(TransactionType.DISTRIBUTION_CASH, [ basicFormatter, distributionCashFormatter, averageCostFormatter ]);
258
+ formatters.set(TransactionType.DISTRIBUTION_FUND, [ basicFormatter, distributionFundFormatter, averageCostFormatter ]);
259
+ formatters.set(TransactionType.DISTRIBUTION_REINVEST, [ basicFormatter, distributionReinvestFormatter, averageCostFormatter ]);
260
+ formatters.set(TransactionType.INCOME, [ basicFormatter, incomeFormatter, averageCostFormatter ]);
261
+ formatters.set(TransactionType.FEE, [ basicFormatter, feeFormatter, averageCostFormatter ]);
262
+ formatters.set(TransactionType.FEE_UNITS, [ basicFormatter, feeUnitsFormatter, averageCostFormatter ]);
263
+ formatters.set(TransactionType.SPLIT, [ basicFormatter, splitFormatter, averageCostFormatter ]);
264
+ formatters.set(TransactionType.VALUATION, [ basicFormatter, valuationFormatter, averageCostFormatter ]);
265
+ formatters.set(TransactionType.DELIST, [ basicFormatter, averageCostFormatter ]);
266
+ formatters.set(TransactionType.DEPOSIT, [ basicFormatter, cashFormatter ]);
267
+ formatters.set(TransactionType.WITHDRAWAL, [ basicFormatter, cashFormatter ]);
268
+ formatters.set(TransactionType.DEBIT, [ basicFormatter, cashFormatter, debitFormatter ]);
269
+ formatters.set(TransactionType.CREDIT, [ basicFormatter, cashFormatter, creditFormatter ]);
286
270
 
287
271
  function getInstrumentTypePriority(type) {
288
272
  if (type === InstrumentType.CASH) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.120",
3
+ "version": "1.2.125",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -23,9 +23,10 @@
23
23
  "gulp-bump": "~1.0.0",
24
24
  "gulp-git": "~1.6.0",
25
25
  "gulp-jasmine": "^2.2.1",
26
- "gulp-jshint": "~1.11.2",
26
+ "gulp-jshint": "~2.1.0",
27
27
  "gulp-util": "^3.0.7",
28
28
  "jsdoc": "^3.5.5",
29
+ "jshint": "2.9.5",
29
30
  "run-sequence": "~1.1.4",
30
31
  "vinyl-buffer": "^1.0.0",
31
32
  "vinyl-source-stream": "^1.1.0"