@barchart/portfolio-api-common 1.2.117 → 1.2.118

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.
@@ -88,6 +88,18 @@ module.exports = (() => {
88
88
  static get TRANSACTION_CREATE_FAILED_OUT_OF_SEQUENCE() {
89
89
  return transactionCreateFailedOutOfSequence;
90
90
  }
91
+
92
+ /**
93
+ * The transaction date is invalid.
94
+ * For example create opening transaction after delist date.
95
+ *
96
+ * @public
97
+ * @static
98
+ * @returns {FailureType}
99
+ */
100
+ static get TRANSACTION_CREATE_FAILED_INVALID_DATE() {
101
+ return transactionCreateFailedInvalidDate;
102
+ }
91
103
 
92
104
  /**
93
105
  * @public
@@ -164,6 +176,18 @@ module.exports = (() => {
164
176
  static get TRANSACTION_CREATE_FAILED_POSITION_LOCKED() {
165
177
  return transactionCreateFailedPositionLocked;
166
178
  }
179
+
180
+ /**
181
+ * The transaction (of this type) cannot be deleted by a user, instead,
182
+ * it is created and managed by the system (e.g. dividends).
183
+ *
184
+ * @public
185
+ * @static
186
+ * @returns {FailureType}
187
+ */
188
+ static get TRANSACTION_DELETE_FAILED_TYPE_RESERVED() {
189
+ return transactionDeleteFailedTypeReserved;
190
+ }
167
191
 
168
192
  /**
169
193
  * Deleting any transaction except for the most recent requires
@@ -209,6 +233,18 @@ module.exports = (() => {
209
233
  static get TRANSACTION_DELETE_FAILED_POSITION_LOCKED() {
210
234
  return transactionDeleteFailedPositionLocked;
211
235
  }
236
+
237
+ /**
238
+ * The transaction date is invalid.
239
+ * For example edit opening transaction after delist date.
240
+ *
241
+ * @public
242
+ * @static
243
+ * @returns {FailureType}
244
+ */
245
+ static get TRANSACTION_EDIT_FAILED_INVALID_DATE() {
246
+ return transactionEditFailedInvalidDate;
247
+ }
212
248
 
213
249
  /**
214
250
  * Unable to edit, the transaction doesn't exist.
@@ -247,10 +283,12 @@ module.exports = (() => {
247
283
 
248
284
  const transactionCreateFailedNoPosition = new FailureType('TRANSACTION_CREATE_FAILED_NO_POSITION', 'Unable to create transaction. The referenced position does not exist. Has it been deleted?');
249
285
  const transactionCreateFailedOutOfSequence = new FailureType('TRANSACTION_CREATE_FAILED_OUT_OF_SEQUENCE', 'Unable to process transaction, because the transaction date is out-of-sequence. In other words, it would occur before an existing transaction. Please confirm your intent to re-write transaction history (which could take some time and alter the historical results for this position).');
286
+ const transactionCreateFailedInvalidDate = new FailureType('TRANSACTION_CREATE_FAILED_INVALID_DATE', 'Unable to process transaction with given date.');
250
287
  const transactionCreateFailedTypeInvalidForInstrument = new FailureType('TRANSACTION_CREATE_FAILED_TYPE_INVALID_FOR_INSTRUMENT', 'Unable to process transaction, {L|transactionType.description} transactions cannot be used with {L|instrumentType.description} positions.');
251
288
  const transactionCreateFailedTypeInvalidForDirection = new FailureType('TRANSACTION_CREATE_FAILED_TYPE_INVALID_FOR_DIRECTION', 'Unable to process transaction, a {L|positionDirection.description} position would be created (i.e. you would have {L|positionDirection.sign} shares/units). {u|instrumentType.description} positions cannot have {L|positionDirection.description} positions.');
252
289
  const transactionCreateFailedInvalidDirectionSwitch = new FailureType('TRANSACTION_CREATE_FAILED_INVALID_DIRECTION_SWITCH', 'Unable to process transaction, the transaction would switch the position from {L|currentDirection.description} to {L|proposedDirection.description} (i.e. {L|currentDirection.sign} to {L|proposedDirection.sign} shares/units). This is not allowed. Please close the current position (i.e. zero it out) and then enter a second transaction.');
253
290
  const transactionCreateFailedInvalidInitialType = new FailureType('TRANSACTION_CREATE_FAILED_INVALID_INITIAL_TYPE', 'Unable to process operation because the first transaction would to be a {U|transactionType.description}, which is not allowed -- since {U|transactionType.description} transactions cannot open a position.');
291
+
254
292
  const transactionCreateFailedTypeReserved = new FailureType('TRANSACTION_CREATE_FAILED_TYPE_RESERVED', 'Unable to create {U|type.description} transaction, this type of transaction is managed by the system.');
255
293
  const transactionCreateFailedReinvestPriceUnavailable = new FailureType('TRANSACTION_CREATE_FAILED_REINVEST_PRICE_UNAVAILABLE', 'Unable to create transaction, a dividend was paid on {L|day}; however no historical price is available for this day. To successfully create this transaction, please turn off dividend reinvestment for this position.');
256
294
  const transactionCreateFailedPositionLocked = new FailureType('TRANSACTION_CREATE_FAILED_POSITION_LOCKED', 'Unable to create transaction, your {L|description} history is being recalculated. Please re-enter this transaction in a minute or two.');
@@ -259,9 +297,11 @@ module.exports = (() => {
259
297
  const transactionDeleteFailedNoTransaction = new FailureType('TRANSACTION_DELETE_FAILED_NO_TRANSACTION', 'Unable to delete transaction. The referenced transaction does not exist.');
260
298
  const transactionDeleteFailedDirectionSwitchOnRewrite = new FailureType('TRANSACTION_DELETE_FAILED_DIRECTION_SWITCH_ON_REWRITE', 'Deleting this transaction would cause your history to be re-written and the position to switch from long to short (i.e. positive to negative) or vice versa.');
261
299
  const transactionDeleteFailedPositionLocked = new FailureType('TRANSACTION_DELETE_FAILED_POSITION_LOCKED', 'Unable to delete transaction, your {L|description} history is being recalculated. Please wait a minute or two and retry.');
300
+ const transactionDeleteFailedTypeReserved = new FailureType('TRANSACTION_DELETE_FAILED_TYPE_RESERVED', 'Unable to delete {U|type.description} transaction, this type of transaction is managed by the system.');
262
301
 
302
+ const transactionEditFailedInvalidDate = new FailureType('TRANSACTION_EDIT_FAILED_INVALID_DATE', 'Unable to edit transaction with given date.');
263
303
  const transactionEditFailedNoTransaction = new FailureType('TRANSACTION_EDIT_FAILED_NO_TRANSACTION', 'Unable to edit transaction. The referenced transaction does not exist.');
264
304
  const transactionEditFailedTypeReserved = new FailureType('TRANSACTION_EDIT_FAILED_TYPE_RESERVED', 'Unable to edit {U|type.description} transaction, this type of transaction is managed by the system.');
265
305
 
266
306
  return PortfolioFailureType;
267
- })();
307
+ })();
@@ -22,7 +22,6 @@ module.exports = (() => {
22
22
  * @param {Boolean} corporateAction
23
23
  * @param {Boolean} initial
24
24
  * @param {Boolean} significant
25
- * @param {Boolean} eod
26
25
  */
27
26
  class TransactionType extends Enum {
28
27
  constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, significant) {
@@ -352,7 +351,7 @@ module.exports = (() => {
352
351
  static get DEBIT() {
353
352
  return debit;
354
353
  }
355
-
354
+
356
355
  /**
357
356
  * A system-generated transaction, indicating the security has stopped active trading.
358
357
  *
@@ -412,7 +411,7 @@ module.exports = (() => {
412
411
  const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
413
412
  const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
414
413
  const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false);
415
- const delist = new TransactionType('DL', 'Delist', 'Delist', 0, false, false, false, false, false, false, false, false, false);
414
+ const delist = new TransactionType('DL', 'Delist', 'Delist', 1, false, false, false, false, false, false, true, false, false);
416
415
 
417
416
  const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
418
417
  const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
@@ -1,6 +1,7 @@
1
1
  const assert = require('@barchart/common-js/lang/assert'),
2
2
  array = require('@barchart/common-js/lang/array'),
3
- is = require('@barchart/common-js/lang/is');
3
+ is = require('@barchart/common-js/lang/is'),
4
+ Day = require('@barchart/common-js/lang/Day');
4
5
 
5
6
  const InstrumentType = require('./InstrumentType'),
6
7
  PositionDirection = require('./PositionDirection'),
@@ -217,6 +218,23 @@ module.exports = (() => {
217
218
  static validateDirectionSwitch(instrumentType, currentDirection, proposedDirection) {
218
219
  return currentDirection === null || instrumentType.canSwitchDirection || (currentDirection.closed || proposedDirection.closed || currentDirection.positive === proposedDirection.positive);
219
220
  }
221
+
222
+ /**
223
+ * Assuming the transaction list is ordered by sequence, validates that
224
+ * no opening transactions exist after delisting date.
225
+ *
226
+ * @static
227
+ * @public
228
+ * @param {Array.<Object>} transactions
229
+ * @returns {Boolean}
230
+ */
231
+ static validateDelisting(transactions) {
232
+ assert.argumentIsArray(transactions, 'transactions');
233
+
234
+ const delistIndex = transactions.findIndex(t => t.type === TransactionType.DELIST);
235
+
236
+ return delistIndex < 0 || !transactions.some((t, i) => delistIndex < i && t.type.opening);
237
+ }
220
238
 
221
239
  toString() {
222
240
  return '[TransactionValidator]';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.2.117",
3
+ "version": "1.2.118",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -759,7 +759,6 @@ module.exports = (() => {
759
759
  * @param {Boolean} corporateAction
760
760
  * @param {Boolean} initial
761
761
  * @param {Boolean} significant
762
- * @param {Boolean} eod
763
762
  */
764
763
  class TransactionType extends Enum {
765
764
  constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, significant) {
@@ -1089,7 +1088,7 @@ module.exports = (() => {
1089
1088
  static get DEBIT() {
1090
1089
  return debit;
1091
1090
  }
1092
-
1091
+
1093
1092
  /**
1094
1093
  * A system-generated transaction, indicating the security has stopped active trading.
1095
1094
  *
@@ -1149,7 +1148,7 @@ module.exports = (() => {
1149
1148
  const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
1150
1149
  const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
1151
1150
  const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false);
1152
- const delist = new TransactionType('DL', 'Delist', 'Delist', 0, false, false, false, false, false, false, false, false, false);
1151
+ const delist = new TransactionType('DL', 'Delist', 'Delist', 1, false, false, false, false, false, false, true, false, false);
1153
1152
 
1154
1153
  const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
1155
1154
  const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
@@ -1169,7 +1168,8 @@ module.exports = (() => {
1169
1168
  },{"@barchart/common-js/lang/Enum":24,"@barchart/common-js/lang/assert":29}],5:[function(require,module,exports){
1170
1169
  const assert = require('@barchart/common-js/lang/assert'),
1171
1170
  array = require('@barchart/common-js/lang/array'),
1172
- is = require('@barchart/common-js/lang/is');
1171
+ is = require('@barchart/common-js/lang/is'),
1172
+ Day = require('@barchart/common-js/lang/Day');
1173
1173
 
1174
1174
  const InstrumentType = require('./InstrumentType'),
1175
1175
  PositionDirection = require('./PositionDirection'),
@@ -1386,6 +1386,23 @@ module.exports = (() => {
1386
1386
  static validateDirectionSwitch(instrumentType, currentDirection, proposedDirection) {
1387
1387
  return currentDirection === null || instrumentType.canSwitchDirection || (currentDirection.closed || proposedDirection.closed || currentDirection.positive === proposedDirection.positive);
1388
1388
  }
1389
+
1390
+ /**
1391
+ * Assuming the transaction list is ordered by sequence, validates that
1392
+ * no opening transactions exist after delisting date.
1393
+ *
1394
+ * @static
1395
+ * @public
1396
+ * @param {Array.<Object>} transactions
1397
+ * @returns {Boolean}
1398
+ */
1399
+ static validateDelisting(transactions) {
1400
+ assert.argumentIsArray(transactions, 'transactions');
1401
+
1402
+ const delistIndex = transactions.findIndex(t => t.type === TransactionType.DELIST);
1403
+
1404
+ return delistIndex < 0 || !transactions.some((t, i) => delistIndex < i && t.type.opening);
1405
+ }
1389
1406
 
1390
1407
  toString() {
1391
1408
  return '[TransactionValidator]';
@@ -1464,7 +1481,7 @@ module.exports = (() => {
1464
1481
  return TransactionValidator;
1465
1482
  })();
1466
1483
 
1467
- },{"./InstrumentType":1,"./PositionDirection":2,"./TransactionType":4,"@barchart/common-js/lang/array":28,"@barchart/common-js/lang/assert":29,"@barchart/common-js/lang/is":33}],6:[function(require,module,exports){
1484
+ },{"./InstrumentType":1,"./PositionDirection":2,"./TransactionType":4,"@barchart/common-js/lang/Day":21,"@barchart/common-js/lang/array":28,"@barchart/common-js/lang/assert":29,"@barchart/common-js/lang/is":33}],6:[function(require,module,exports){
1468
1485
  const array = require('@barchart/common-js/lang/array'),
1469
1486
  assert = require('@barchart/common-js/lang/assert'),
1470
1487
  ComparatorBuilder = require('@barchart/common-js/collections/sorting/ComparatorBuilder'),
@@ -18150,7 +18167,7 @@ describe('When validating transaction order', () => {
18150
18167
  'use strict';
18151
18168
 
18152
18169
  const build = (sequence, day, type) => {
18153
- return { sequence: sequence, date: Day.parse(day), type: (type || TransactionType.BUY ) };
18170
+ return { sequence: sequence, date: Day.parse(day), type: (type || TransactionType.BUY) };
18154
18171
  };
18155
18172
 
18156
18173
  it('An array of zero transactions should be valid', () => {
@@ -18222,6 +18239,28 @@ describe('When validating transaction references', () => {
18222
18239
  });
18223
18240
  });
18224
18241
 
18242
+ describe('When validating transactions which could include instrument delisting', () => {
18243
+ const build = (type) => {
18244
+ return { type: type };
18245
+ };
18246
+
18247
+ it('An array without a DELSIT transaction should be valid', () => {
18248
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL) ])).toEqual(true);
18249
+ });
18250
+
18251
+ it('An array with a final DELSIT transaction should be valid', () => {
18252
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST) ])).toEqual(true);
18253
+ });
18254
+
18255
+ it('An array with a closing transaction after a DELIST transaction should be valid', () => {
18256
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST), build(TransactionType.SELL) ])).toEqual(true);
18257
+ });
18258
+
18259
+ it('An array with an opening transaction after a DELIST transaction should not be valid', () => {
18260
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST), build(TransactionType.BUY) ])).toEqual(false);
18261
+ });
18262
+ });
18263
+
18225
18264
  describe('When requesting all the user-initiated transaction types', () => {
18226
18265
  'use strict';
18227
18266
 
@@ -7,7 +7,7 @@ describe('When validating transaction order', () => {
7
7
  'use strict';
8
8
 
9
9
  const build = (sequence, day, type) => {
10
- return { sequence: sequence, date: Day.parse(day), type: (type || TransactionType.BUY ) };
10
+ return { sequence: sequence, date: Day.parse(day), type: (type || TransactionType.BUY) };
11
11
  };
12
12
 
13
13
  it('An array of zero transactions should be valid', () => {
@@ -79,6 +79,28 @@ describe('When validating transaction references', () => {
79
79
  });
80
80
  });
81
81
 
82
+ describe('When validating transactions which could include instrument delisting', () => {
83
+ const build = (type) => {
84
+ return { type: type };
85
+ };
86
+
87
+ it('An array without a DELSIT transaction should be valid', () => {
88
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL) ])).toEqual(true);
89
+ });
90
+
91
+ it('An array with a final DELSIT transaction should be valid', () => {
92
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST) ])).toEqual(true);
93
+ });
94
+
95
+ it('An array with a closing transaction after a DELIST transaction should be valid', () => {
96
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST), build(TransactionType.SELL) ])).toEqual(true);
97
+ });
98
+
99
+ it('An array with an opening transaction after a DELIST transaction should not be valid', () => {
100
+ expect(TransactionValidator.validateDelisting([ build(TransactionType.BUY), build(TransactionType.SELL), build(TransactionType.DELIST), build(TransactionType.BUY) ])).toEqual(false);
101
+ });
102
+ });
103
+
82
104
  describe('When requesting all the user-initiated transaction types', () => {
83
105
  'use strict';
84
106