@barchart/portfolio-api-common 1.3.19 → 1.3.23

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/.jshintrc CHANGED
@@ -1,3 +1,6 @@
1
1
  {
2
- "validthis": true
2
+ "esversion": 6,
3
+ "validthis": true,
4
+ "-W018": true,
5
+ "-W093": true
3
6
  }
package/README.md CHANGED
@@ -1,7 +1,32 @@
1
1
  # @barchart/portfolio-api-common
2
- ## Barchart Portfolio API Common Components
3
2
 
4
- Shared code, used by the serverless application and the client-side SDK. See:
3
+ [![AWS CodeBuild](https://codebuild.us-east-1.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiSXBJTDZKWVFmSGVOSG9XQUgwbzB3Um5BZ0JsN2h1U3NQNWNhZTRHMlJKTVpEVVlVMENPaEFmR0NYS29rSStZWmZ5M1d0YVh2eXErVGhiekFtdHBpVmhJPSIsIml2UGFyYW1ldGVyU3BlYyI6ImROM3ZLMURwaXFyekltdDYiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)](https://github.com/barchart/portfolio-api-common)
5
4
 
6
- * https://github.com/barchart/aws-lambda-portfolio and
7
- * https://github.com/barchart/portfolio-client-js
5
+ A *private* library of shared JavaScript code pertaining to the paper-trading portfolio system.
6
+
7
+ ### Overview
8
+
9
+ Simply put, this project contains code that runs on both the servers (i.e. Serverless applications) and clients (e.g. browser, mobile, etc).
10
+
11
+ #### [lib/serialization](https://github.com/barchart/portfolio-api-common/tree/master/lib/serialization)
12
+
13
+ Data is passed between client and server in JSON format. However, the code works with more complex types. For example, [Decimal](https://github.com/barchart/barchart-common-js/blob/master/lang/Decimal.js) instances are used in place of [native JavaScript floats](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). [Day](https://github.com/barchart/barchart-common-js/blob/master/lang/Day.js) instances are used instead of [native JavaScript Dates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date).
14
+
15
+ So, before data is exchanged, it must be converted to pure JSON. Conversely, when data is received, as pure JSON, its translated into more complex types before use. This is facilitated by the [Schema](https://github.com/barchart/barchart-common-js/blob/master/serialization/json/Schema.js) definitions which build custom "reviver" functions for [JSON parsing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
16
+
17
+ #### [lib/processing](https://github.com/barchart/portfolio-api-common/tree/master/lib/processing)
18
+
19
+ For reporting and display purposes, positions can be grouped together (by asset class, by portfolio, by user, etc). This code supports aggregation and gain/loss calculation. It is used by server-generated reports and dynamic user interfaces.
20
+
21
+ ### Notable Consumers
22
+
23
+ * [aws-lambda-portfolio](https://github.com/barchart/aws-lambda-portfolio) - Serverless applications (i.e. the servers)
24
+ * [portfolio-client-js](https://github.com/barchart/portfolio-client-js) - JavaScript client SDK for communicating with server API's.
25
+ * [tgam-portfolio-ui-js](https://github.com/barchart/tgam-portfolio-ui-js) - A dynamic, single-page HTML UI.
26
+
27
+ ### Package Managers
28
+
29
+ This library has been published as a *private* module to NPM as [@barchart/portfolio-api-common](https://www.npmjs.com/package/@barchart/portfolio-api-common).
30
+
31
+ > npm login
32
+ > npm install @barchart/portfolio-api-common -S
package/buildspec.yml ADDED
@@ -0,0 +1,15 @@
1
+ version: 0.2
2
+
3
+ phases:
4
+ install:
5
+ runtime-versions:
6
+ nodejs: 12.x
7
+
8
+ pre_build:
9
+ commands:
10
+ - npm install
11
+
12
+ build:
13
+ commands:
14
+ - ./node_modules/.bin/gulp lint
15
+ - ./node_modules/.bin/gulp test
package/gulpfile.js CHANGED
@@ -5,17 +5,15 @@ const fs = require('fs');
5
5
  const browserify = require('browserify'),
6
6
  buffer = require('vinyl-buffer'),
7
7
  bump = require('gulp-bump'),
8
- exec = require('child_process').exec,
9
8
  git = require('gulp-git'),
10
9
  gitStatus = require('git-get-status'),
11
10
  glob = require('glob'),
12
11
  jasmine = require('gulp-jasmine'),
13
12
  jshint = require('gulp-jshint'),
14
- replace = require('gulp-replace'),
15
13
  source = require('vinyl-source-stream');
16
14
 
17
15
  function getVersionFromPackage() {
18
- return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
16
+ return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
19
17
  }
20
18
 
21
19
  gulp.task('ensure-clean-working-directory', (cb) => {
@@ -30,39 +28,30 @@ gulp.task('ensure-clean-working-directory', (cb) => {
30
28
 
31
29
  gulp.task('bump-version', () => {
32
30
  return gulp.src([ './package.json' ])
33
- .pipe(bump({ type: 'patch' }))
34
- .pipe(gulp.dest('./'));
35
- });
36
-
37
- gulp.task('document', (cb) => {
38
- exec('jsdoc . -c jsdoc.json -r -d docs', (error, stdout, stderr) => {
39
- console.log(stdout);
40
- console.log(stderr);
41
-
42
- cb();
43
- });
31
+ .pipe(bump({ type: 'patch' }))
32
+ .pipe(gulp.dest('./'));
44
33
  });
45
34
 
46
35
  gulp.task('commit-changes', () => {
47
- return gulp.src([ './', './test/', './package.json' ])
48
- .pipe(git.add())
49
- .pipe(git.commit('Release. Bump version number'));
36
+ return gulp.src([ './', './test/', './package.json' ])
37
+ .pipe(git.add())
38
+ .pipe(git.commit('Release. Bump version number'));
50
39
  });
51
40
 
52
41
  gulp.task('push-changes', (cb) => {
53
- git.push('origin', 'master', cb);
42
+ git.push('origin', 'master', cb);
54
43
  });
55
44
 
56
45
  gulp.task('create-tag', (cb) => {
57
- const version = getVersionFromPackage();
46
+ const version = getVersionFromPackage();
58
47
 
59
- git.tag(version, 'Release ' + version, (error) => {
60
- if (error) {
61
- return cb(error);
62
- }
48
+ git.tag(version, 'Release ' + version, (error) => {
49
+ if (error) {
50
+ return cb(error);
51
+ }
63
52
 
64
- git.push('origin', 'master', { args: '--tags' }, cb);
65
- });
53
+ git.push('origin', 'master', { args: '--tags' }, cb);
54
+ });
66
55
  });
67
56
 
68
57
  gulp.task('build-test-bundle', () => {
@@ -74,13 +63,13 @@ gulp.task('build-test-bundle', () => {
74
63
  });
75
64
 
76
65
  gulp.task('execute-browser-tests', () => {
77
- return gulp.src('test/SpecRunner.js')
78
- .pipe(jasmine());
66
+ return gulp.src('test/SpecRunner.js')
67
+ .pipe(jasmine());
79
68
  });
80
69
 
81
70
  gulp.task('execute-node-tests', () => {
82
- return gulp.src(['test/specs/**/*.js'])
83
- .pipe(jasmine());
71
+ return gulp.src(['test/specs/**/*.js'])
72
+ .pipe(jasmine());
84
73
  });
85
74
 
86
75
  gulp.task('execute-tests', gulp.series(
@@ -92,7 +81,6 @@ gulp.task('execute-tests', gulp.series(
92
81
  gulp.task('release', gulp.series(
93
82
  'ensure-clean-working-directory',
94
83
  'execute-tests',
95
- 'document',
96
84
  'bump-version',
97
85
  'commit-changes',
98
86
  'push-changes',
@@ -100,9 +88,10 @@ gulp.task('release', gulp.series(
100
88
  ));
101
89
 
102
90
  gulp.task('lint', () => {
103
- return gulp.src([ './**/*.js', './test/specs/**/*.js', '!./node_modules/**', '!./docs/**', '!./test/SpecRunner.js' ])
104
- .pipe(jshint({'esversion': 6}))
105
- .pipe(jshint.reporter('default'));
91
+ return gulp.src([ './**/*.js', './test/specs/**/*.js', '!./node_modules/**', '!./docs/**', '!./test/SpecRunner.js' ])
92
+ .pipe(jshint({'esversion': 6}))
93
+ .pipe(jshint.reporter('default'))
94
+ .pipe(jshint.reporter('fail'));
106
95
  });
107
96
 
108
97
  gulp.task('test', gulp.series('execute-tests'));
@@ -88,7 +88,7 @@ module.exports = (() => {
88
88
  static get TRANSACTION_CREATE_FAILED_OUT_OF_SEQUENCE() {
89
89
  return transactionCreateFailedOutOfSequence;
90
90
  }
91
-
91
+
92
92
  /**
93
93
  * The transaction date is invalid.
94
94
  * For example create opening transaction after delist date.
@@ -101,6 +101,18 @@ module.exports = (() => {
101
101
  return transactionCreateFailedInvalidDate;
102
102
  }
103
103
 
104
+ /**
105
+ * The target instrument is invalid.
106
+ * Can be used in Merger and Acquisition.
107
+ *
108
+ * @public
109
+ * @static
110
+ * @returns {FailureType}
111
+ */
112
+ static get TRANSACTION_CREATE_FAILED_TARGET_INSTRUMENT_MISSING() {
113
+ return transactionCreateFailedTargetInstrumentMissing;
114
+ }
115
+
104
116
  /**
105
117
  * @public
106
118
  * @static
@@ -142,6 +154,40 @@ module.exports = (() => {
142
154
  return transactionCreateFailedInvalidInitialType;
143
155
  }
144
156
 
157
+ /**
158
+ * A valuation transaction cannot have a negative rate (or amount).
159
+ *
160
+ * @public
161
+ * @static
162
+ * @returns {FailureType}
163
+ */
164
+ static get TRANSACTION_CREATE_FAILED_VALUATION_NEGATIVE() {
165
+ return transactionCreateFailedValuationNegative;
166
+ }
167
+
168
+ /**
169
+ * A "terminal" transaction must be the last transaction is the history.
170
+ *
171
+ * @public
172
+ * @static
173
+ * @returns {FailureType}
174
+ */
175
+ static get TRANSACTION_CREATE_FAILED_INVALID_TERMINATION() {
176
+ return transactionCreateFailedInvalidTermination;
177
+ }
178
+
179
+ /**
180
+ * A transaction cannot be created after the termination date of
181
+ * the instrument.
182
+ *
183
+ * @public
184
+ * @static
185
+ * @returns {FailureType}
186
+ */
187
+ static get TRANSACTION_CREATE_FAILED_AFTER_TERMINATION() {
188
+ return transactionCreateFailedAfterTermination;
189
+ }
190
+
145
191
  /**
146
192
  * The transaction (of this type) cannot be created by a user, instead,
147
193
  * it is created and managed by the system (e.g. dividends).
@@ -244,7 +290,7 @@ module.exports = (() => {
244
290
  static get TRANSACTION_DELETE_FAILED_POSITION_LOCKED() {
245
291
  return transactionDeleteFailedPositionLocked;
246
292
  }
247
-
293
+
248
294
  /**
249
295
  * The transaction date is invalid.
250
296
  * For example edit opening transaction after delist date.
@@ -295,10 +341,14 @@ module.exports = (() => {
295
341
  const transactionCreateFailedNoPosition = new FailureType('TRANSACTION_CREATE_FAILED_NO_POSITION', 'Unable to create transaction. The referenced position does not exist. Has it been deleted?', false);
296
342
  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).');
297
343
  const transactionCreateFailedInvalidDate = new FailureType('TRANSACTION_CREATE_FAILED_INVALID_DATE', 'Unable to process transaction with given date.');
344
+ const transactionCreateFailedTargetInstrumentMissing = new FailureType('TRANSACTION_CREATE_FAILED_TARGET_INSTRUMENT_MISSING', 'Unable to create transaction. The target instrument does not exist.');
298
345
  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.');
299
346
  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.', false);
300
347
  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.', false);
301
348
  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.', false);
349
+ const transactionCreateFailedValuationNegative = new FailureType('TRANSACTION_CREATE_FAILED_VALUATION_NEGATIVE', 'Unable to process operation, valuations cannot be negative.', false);
350
+ const transactionCreateFailedInvalidTermination = new FailureType('TRANSACTION_CREATE_FAILED_INVALID_TERMINATION', 'Unable to process operation, a {U|transactionType.description} must be the final transaction in the position history.', false);
351
+ const transactionCreateFailedAfterTermination = new FailureType('TRANSACTION_CREATE_FAILED_AFTER_TERMINATION', 'Unable to process operation, one or more transactions would exist after {L|termination}, the final day of trading for this instrument', false);
302
352
 
303
353
  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.');
304
354
  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.');
@@ -82,6 +82,28 @@ module.exports = (() => {
82
82
  static get DELIST() {
83
83
  return delist;
84
84
  }
85
+
86
+ /**
87
+ * A merging.
88
+ *
89
+ * @public
90
+ * @static
91
+ * @returns {CorporateActionType}
92
+ */
93
+ static get MERGER() {
94
+ return merger;
95
+ }
96
+
97
+ /**
98
+ * A spinoff.
99
+ *
100
+ * @public
101
+ * @static
102
+ * @returns {CorporateActionType}
103
+ */
104
+ static get SPINOFF() {
105
+ return spinoff;
106
+ }
85
107
  }
86
108
 
87
109
  const split = new CorporateActionType('SPLIT', 'Split', false);
@@ -90,6 +112,8 @@ module.exports = (() => {
90
112
  const symbolChange = new CorporateActionType('SYMBOL_CHANGE', 'Symbol Change', false);
91
113
  const nameChange = new CorporateActionType('NAME_CHANGE', 'Name Change', false);
92
114
  const delist = new CorporateActionType('DELIST', 'Delist', false);
115
+ const merger = new CorporateActionType('MERGER', 'Merger', false);
116
+ const spinoff = new CorporateActionType('SPINOFF', 'Spinoff', false);
93
117
 
94
118
  return CorporateActionType;
95
119
  })();
@@ -21,11 +21,14 @@ module.exports = (() => {
21
21
  * @param {Boolean} fee
22
22
  * @param {Boolean} corporateAction
23
23
  * @param {Boolean} initial
24
+ * @param {Boolean} terminal
24
25
  * @param {Boolean} significant
25
- * @param {Boolean} system
26
+ * @param {Boolean} chaining
27
+ * @param {Boolean} chained
28
+ * @param {Boolean} transfer
26
29
  */
27
30
  class TransactionType extends Enum {
28
- constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, significant) {
31
+ constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, terminal, significant, chaining, chained, transfer) {
29
32
  super(code, description);
30
33
 
31
34
  assert.argumentIsRequired(display, 'display', String);
@@ -38,7 +41,11 @@ module.exports = (() => {
38
41
  assert.argumentIsRequired(fee, 'fee', Boolean);
39
42
  assert.argumentIsRequired(corporateAction, 'corporateAction', Boolean);
40
43
  assert.argumentIsRequired(initial, 'initial', Boolean);
44
+ assert.argumentIsRequired(terminal, 'terminal', Boolean);
41
45
  assert.argumentIsRequired(significant, 'significant', Boolean);
46
+ assert.argumentIsRequired(chaining, 'chaining', Boolean);
47
+ assert.argumentIsRequired(chained, 'chained', Boolean);
48
+ assert.argumentIsRequired(transfer, 'transfer', Boolean);
42
49
 
43
50
  this._display = display;
44
51
  this._sequence = sequence;
@@ -50,7 +57,11 @@ module.exports = (() => {
50
57
  this._fee = fee;
51
58
  this._corporateAction = corporateAction;
52
59
  this._initial = initial;
60
+ this._terminal = terminal;
53
61
  this._significant = significant;
62
+ this._chaining = chaining;
63
+ this._chained = chained;
64
+ this._transfer = transfer;
54
65
  }
55
66
 
56
67
  /**
@@ -167,6 +178,16 @@ module.exports = (() => {
167
178
  return this._initial;
168
179
  }
169
180
 
181
+ /**
182
+ * Indicates if the transaction must be the last
183
+ *
184
+ * @public
185
+ * @returns {Boolean}
186
+ */
187
+ get terminal() {
188
+ return this._terminal;
189
+ }
190
+
170
191
  /**
171
192
  * Significant transactions cannot be discarded during transaction re-write.
172
193
  *
@@ -177,6 +198,37 @@ module.exports = (() => {
177
198
  return this._significant;
178
199
  }
179
200
 
201
+ /**
202
+ * Chain transactions cause another position to be created.
203
+ *
204
+ * @public
205
+ * @returns {Boolean}
206
+ */
207
+ get chaining() {
208
+ return this._chaining;
209
+ }
210
+
211
+ /**
212
+ * Chained transactions are created from another position.
213
+ *
214
+ * @public
215
+ * @returns {Boolean}
216
+ */
217
+ get chained() {
218
+ return this._chained;
219
+ }
220
+
221
+ /**
222
+ * Indicates if the transaction should cause gains and losses to be
223
+ * transferred from the original (chaining) position.
224
+ *
225
+ * @public
226
+ * @returns {Boolean}
227
+ */
228
+ get transfer() {
229
+ return this._transfer;
230
+ }
231
+
180
232
  /**
181
233
  * A purchase.
182
234
  *
@@ -352,7 +404,7 @@ module.exports = (() => {
352
404
  static get DEBIT() {
353
405
  return debit;
354
406
  }
355
-
407
+
356
408
  /**
357
409
  * A system-generated transaction, indicating the security has stopped active trading.
358
410
  *
@@ -397,34 +449,84 @@ module.exports = (() => {
397
449
  return income;
398
450
  }
399
451
 
452
+ /**
453
+ * A merger opening.
454
+ *
455
+ * @public
456
+ * @static
457
+ * @returns {TransactionType}
458
+ */
459
+ static get MERGER_OPEN() {
460
+ return mergerOpen;
461
+ }
462
+
463
+ /**
464
+ * A merger closing.
465
+ *
466
+ * @public
467
+ * @static
468
+ * @returns {TransactionType}
469
+ */
470
+ static get MERGER_CLOSE() {
471
+ return mergerClose;
472
+ }
473
+
474
+ /**
475
+ * A spin-off.
476
+ *
477
+ * @public
478
+ * @static
479
+ * @returns {TransactionType}
480
+ */
481
+ static get SPINOFF() {
482
+ return spinoff;
483
+ }
484
+
485
+ /**
486
+ * A spin-off opening.
487
+ *
488
+ * @public
489
+ * @static
490
+ * @returns {TransactionType}
491
+ */
492
+ static get SPINOFF_OPEN() {
493
+ return spinoffOpen;
494
+ }
495
+
400
496
  toString() {
401
497
  return '[TransactionType]';
402
498
  }
403
499
  }
404
500
 
405
- const buy = new TransactionType('B', 'Buy', 'Buy', 0, true, false, false, true, false, false, false, true, true);
406
- const sell = new TransactionType('S', 'Sell', 'Sell', 0, false, true, false, false, true, false, false, false, true);
407
- const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', 0, true, false, false, false, true, false, false, false, true);
408
- const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', 0, false, true, false, true, false, false, false, true, true);
409
- const dividend = new TransactionType('DV', 'Dividend', 'Dividend', 1, false, false, true, false, false, false, true, false, false);
410
- const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', 1, false, false, false, true, false, false, true, false, false);
411
- const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', 1, false, false, false, true, false, false, true, false, false);
412
- const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
413
- const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
414
- 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', 1, false, false, false, false, false, false, true, false, false);
416
-
417
- const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
418
- const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
419
- const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', 1, false, false, false, true, false, false, true, false, false);
420
-
421
- const deposit = new TransactionType('D', 'Deposit', 'Deposit', 0, false, false, false, false, false, false, false, true, true);
422
- const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', 0, false, false, false, false, false, false, false, true, true);
423
- const debit = new TransactionType('DR', 'Debit', 'Debit', 0, false, false, false, false, false, false, false, true, true);
424
- const credit = new TransactionType('CR', 'Credit', 'Credit', 0, false, false, false, false, false, false, false, true, true);
425
-
426
- const valuation = new TransactionType('V', 'Valuation', 'Valuation', 0, false, false, false, false, false, false, false, false, false);
427
- const income = new TransactionType('I', 'Income', 'Income', 0, false, false, true, false, false, false, false, false, false);
501
+ const buy = new TransactionType('B', 'Buy', 'Buy', 0, true, false, false, true, false, false, false, true, false, true, false, false, false);
502
+ const sell = new TransactionType('S', 'Sell', 'Sell', 0, false, true, false, false, true, false, false, false, false, true, false, false, false);
503
+ const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', 0, true, false, false, false, true, false, false, false, false, true, false, false, false);
504
+ const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', 0, false, true, false, true, false, false, false, true, false, true, false, false, false);
505
+ const dividend = new TransactionType('DV', 'Dividend', 'Dividend', 1, false, false, true, false, false, false, true, false, false, false, false, false, false);
506
+ const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
507
+ const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
508
+ const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
509
+ const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false, false, false, false, false);
510
+ const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false, false, false, false, false);
511
+ const delist = new TransactionType('DL', 'Delist', 'Delist', 1, false, false, false, false, false, false, true, false, true, false, false, false, false);
512
+
513
+ const mergerOpen = new TransactionType('MO', 'Merger Open', 'Merger Open', 1, false, false, false, true, false, false, true, true, false, true, false, true, true);
514
+ const mergerClose = new TransactionType('MC', 'Merger Close', 'Merger Close', 1, false, false, false, false, true, false, true, false, true, false, true, false, false);
515
+
516
+ const spinoff = new TransactionType('SPF', 'Spinoff', 'Spinoff', 1, false, false, false, false, false, false, true, false, false, false, true, false, false);
517
+ const spinoffOpen = new TransactionType('SPFO', 'Spinoff Open', 'Spinoff Open', 1, false, false, false, true, false, false, true, true, false, true, false, false, false);
518
+
519
+ const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false, false, false, false, false);
520
+ const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
521
+ const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
522
+
523
+ const deposit = new TransactionType('D', 'Deposit', 'Deposit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
524
+ const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
525
+ const debit = new TransactionType('DR', 'Debit', 'Debit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
526
+ const credit = new TransactionType('CR', 'Credit', 'Credit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
527
+
528
+ const valuation = new TransactionType('V', 'Valuation', 'Valuation', 0, false, false, false, false, false, false, false, false, false, false, false, false, false);
529
+ const income = new TransactionType('I', 'Income', 'Income', 0, false, false, true, false, false, false, false, false, false, false, false, false, false);
428
530
 
429
531
  return TransactionType;
430
532
  })();
@@ -70,20 +70,20 @@ module.exports = (() => {
70
70
  return transactions.every((t) => {
71
71
  let valid = true;
72
72
 
73
- if (is.object(t.reference) && is.string(t.reference.root) && is.number(t.reference.sequence)) {
73
+ if (is.object(t.reference) && is.string(t.reference.root) && is.string(t.reference.transaction)) {
74
74
  const root = t.reference.root;
75
- const sequence = t.reference.sequence;
75
+ const transaction = t.reference.transaction;
76
76
 
77
77
  if (!references.hasOwnProperty(root)) {
78
78
  references[root] = [ ];
79
79
  }
80
80
 
81
- const sequences = references[root];
81
+ const transactions = references[root];
82
82
 
83
- if (sequences.some(s => s === sequence)) {
83
+ if (transactions.some(t => t === transaction)) {
84
84
  valid = false;
85
85
  } else {
86
- sequences.push(sequence);
86
+ transactions.push(transaction);
87
87
  }
88
88
  }
89
89
 
@@ -186,7 +186,7 @@ module.exports = (() => {
186
186
  static validateInitialTransactionType(transactionType) {
187
187
  return transactionType.initial;
188
188
  }
189
-
189
+
190
190
  /**
191
191
  * Determines if a position for a given instrument type can exist in
192
192
  * the given direction.
@@ -246,6 +246,10 @@ module.exports = (() => {
246
246
  associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_STOCK, false);
247
247
  associateTypes(InstrumentType.EQUITY, TransactionType.SPLIT, false);
248
248
  associateTypes(InstrumentType.EQUITY, TransactionType.DELIST, false);
249
+ associateTypes(InstrumentType.EQUITY, TransactionType.MERGER_OPEN, false);
250
+ associateTypes(InstrumentType.EQUITY, TransactionType.MERGER_CLOSE, false);
251
+ associateTypes(InstrumentType.EQUITY, TransactionType.SPINOFF, false);
252
+ associateTypes(InstrumentType.EQUITY, TransactionType.SPINOFF_OPEN, false);
249
253
 
250
254
  associateTypes(InstrumentType.FUND, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
251
255
  associateTypes(InstrumentType.FUND, TransactionType.SELL, true, [ PositionDirection.LONG ]);
@@ -255,6 +259,10 @@ module.exports = (() => {
255
259
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_REINVEST, false);
256
260
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
257
261
  associateTypes(InstrumentType.FUND, TransactionType.DELIST, false);
262
+ associateTypes(InstrumentType.FUND, TransactionType.MERGER_OPEN, false);
263
+ associateTypes(InstrumentType.FUND, TransactionType.MERGER_CLOSE, false);
264
+ associateTypes(InstrumentType.FUND, TransactionType.SPINOFF, false);
265
+ associateTypes(InstrumentType.FUND, TransactionType.SPINOFF_OPEN, false);
258
266
 
259
267
  associateTypes(InstrumentType.OTHER, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
260
268
  associateTypes(InstrumentType.OTHER, TransactionType.SELL, true, [ PositionDirection.LONG ]);
@@ -326,6 +326,38 @@ module.exports = (() => {
326
326
  f.description = t.description;
327
327
  };
328
328
 
329
+ const mergerFormatter = (t, f) => {
330
+ f.boughtSold = t.quantity;
331
+
332
+ let rate;
333
+
334
+ if (!t.merger.denominator.getIsZero()) {
335
+ rate = t.merger.numerator.divide(t.merger.denominator);
336
+ } else {
337
+ rate = '';
338
+ }
339
+
340
+ f.rate = rate;
341
+
342
+ f.shares = t.snapshot.open.subtract(t.quantity);
343
+ };
344
+
345
+ const spinoffFormatter = (t, f) => {
346
+ f.boughtSold = t.quantity;
347
+
348
+ let rate;
349
+
350
+ if (!t.spinoff.denominator.getIsZero()) {
351
+ rate = t.spinoff.numerator.divide(t.spinoff.denominator);
352
+ } else {
353
+ rate = '';
354
+ }
355
+
356
+ f.rate = rate;
357
+
358
+ f.shares = t.snapshot.open.subtract(t.quantity);
359
+ };
360
+
329
361
  const formatters = new Map();
330
362
 
331
363
  formatters.set(TransactionType.BUY, [ basicFormatter, buySellFormatter, averageCostFormatter ]);
@@ -348,6 +380,10 @@ module.exports = (() => {
348
380
  formatters.set(TransactionType.WITHDRAWAL, [ basicFormatter, cashFormatter ]);
349
381
  formatters.set(TransactionType.DEBIT, [ basicFormatter, cashFormatter, debitFormatter ]);
350
382
  formatters.set(TransactionType.CREDIT, [ basicFormatter, cashFormatter, creditFormatter ]);
383
+ formatters.set(TransactionType.MERGER_OPEN, [ basicFormatter ]);
384
+ formatters.set(TransactionType.MERGER_CLOSE, [ basicFormatter, mergerFormatter ]);
385
+ formatters.set(TransactionType.SPINOFF, [ basicFormatter, spinoffFormatter ]);
386
+ formatters.set(TransactionType.SPINOFF_OPEN, [ basicFormatter ]);
351
387
 
352
388
  function getInstrumentTypePriority(type) {
353
389
  if (type === InstrumentType.CASH) {
@@ -113,7 +113,7 @@ module.exports = (() => {
113
113
  static get VALUATION() {
114
114
  return valuation;
115
115
  }
116
-
116
+
117
117
  static get DELIST() {
118
118
  return delist;
119
119
  }
@@ -138,7 +138,7 @@ module.exports = (() => {
138
138
  .withField('quantity', DataType.DECIMAL)
139
139
  .withField('fee', DataType.DECIMAL, true)
140
140
  .withField('reference.position', DataType.STRING, true)
141
- .withField('reference.sequence', DataType.NUMBER, true)
141
+ .withField('reference.transaction', DataType.STRING, true)
142
142
  .withField('snapshot.open', DataType.DECIMAL)
143
143
  .withField('snapshot.direction', DataType.forEnum(PositionDirection, 'PositionDirection'))
144
144
  .withField('snapshot.buys', DataType.DECIMAL)
@@ -162,6 +162,10 @@ module.exports = (() => {
162
162
  .withField('split.denominator', DataType.DECIMAL, true)
163
163
  .withField('split.effective', DataType.DAY, true)
164
164
  .withField('split.reference', DataType.STRING, true)
165
+ .withField('merger.numerator', DataType.DECIMAL, true)
166
+ .withField('merger.denominator', DataType.DECIMAL, true)
167
+ .withField('spinoff.numerator', DataType.DECIMAL, true)
168
+ .withField('spinoff.denominator', DataType.DECIMAL, true)
165
169
  .withField('charge.amount', DataType.DECIMAL, true)
166
170
  .withField('income.amount', DataType.DECIMAL, true)
167
171
  .withField('valuation.rate', DataType.DECIMAL, true)
@@ -183,7 +187,7 @@ module.exports = (() => {
183
187
  .withField('quantity', DataType.DECIMAL)
184
188
  .withField('fee', DataType.DECIMAL, true)
185
189
  .withField('reference.position', DataType.STRING, true)
186
- .withField('reference.sequence', DataType.NUMBER, true)
190
+ .withField('reference.transaction', DataType.NUMBER, true)
187
191
  .withField('snapshot.open', DataType.DECIMAL)
188
192
  .withField('snapshot.direction', DataType.forEnum(PositionDirection, 'PositionDirection'))
189
193
  .withField('snapshot.buys', DataType.DECIMAL)
@@ -201,6 +205,10 @@ module.exports = (() => {
201
205
  .withField('split.denominator', DataType.DECIMAL, true)
202
206
  .withField('split.effective', DataType.DAY, true)
203
207
  .withField('split.reference', DataType.STRING, true)
208
+ .withField('merger.numerator', DataType.DECIMAL, true)
209
+ .withField('merger.denominator', DataType.DECIMAL, true)
210
+ .withField('spinoff.numerator', DataType.DECIMAL, true)
211
+ .withField('spinoff.denominator', DataType.DECIMAL, true)
204
212
  .withField('charge.amount', DataType.DECIMAL, true)
205
213
  .withField('income.amount', DataType.DECIMAL, true)
206
214
  .withField('valuation.rate', DataType.DECIMAL, true)
@@ -326,7 +334,7 @@ module.exports = (() => {
326
334
  .withField('force', DataType.BOOLEAN, true)
327
335
  .schema
328
336
  );
329
-
337
+
330
338
  const delist = new TransactionSchema(SchemaBuilder.withName(TransactionType.DELIST.code)
331
339
  .withField('portfolio', DataType.STRING)
332
340
  .withField('position', DataType.STRING)
@@ -336,7 +344,7 @@ module.exports = (() => {
336
344
  .withField('force', DataType.BOOLEAN, true)
337
345
  .schema
338
346
  );
339
-
347
+
340
348
  const income = new TransactionSchema(SchemaBuilder.withName(TransactionType.INCOME.code)
341
349
  .withField('portfolio', DataType.STRING)
342
350
  .withField('position', DataType.STRING)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.3.19",
4
- "description": "Common classes used by the Portfolio system",
3
+ "version": "1.3.23",
4
+ "description": "Common code used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
7
7
  "email": "bryan.ingle@barchart.com",
@@ -22,9 +22,7 @@
22
22
  "gulp-bump": "~1.0.0",
23
23
  "gulp-git": "^2.9.0",
24
24
  "gulp-jasmine": "^2.2.1",
25
- "gulp-jsdoc3": "^1.0.1",
26
25
  "gulp-jshint": "~2.1.0",
27
- "gulp-replace": "^0.5.4",
28
26
  "jsdoc": "^3.5.5",
29
27
  "jshint": "2.9.5",
30
28
  "vinyl-buffer": "^1.0.1",
@@ -774,11 +774,14 @@ module.exports = (() => {
774
774
  * @param {Boolean} fee
775
775
  * @param {Boolean} corporateAction
776
776
  * @param {Boolean} initial
777
+ * @param {Boolean} terminal
777
778
  * @param {Boolean} significant
778
- * @param {Boolean} system
779
+ * @param {Boolean} chaining
780
+ * @param {Boolean} chained
781
+ * @param {Boolean} transfer
779
782
  */
780
783
  class TransactionType extends Enum {
781
- constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, significant) {
784
+ constructor(code, description, display, sequence, purchase, sale, income, opening, closing, fee, corporateAction, initial, terminal, significant, chaining, chained, transfer) {
782
785
  super(code, description);
783
786
 
784
787
  assert.argumentIsRequired(display, 'display', String);
@@ -791,7 +794,11 @@ module.exports = (() => {
791
794
  assert.argumentIsRequired(fee, 'fee', Boolean);
792
795
  assert.argumentIsRequired(corporateAction, 'corporateAction', Boolean);
793
796
  assert.argumentIsRequired(initial, 'initial', Boolean);
797
+ assert.argumentIsRequired(terminal, 'terminal', Boolean);
794
798
  assert.argumentIsRequired(significant, 'significant', Boolean);
799
+ assert.argumentIsRequired(chaining, 'chaining', Boolean);
800
+ assert.argumentIsRequired(chained, 'chained', Boolean);
801
+ assert.argumentIsRequired(transfer, 'transfer', Boolean);
795
802
 
796
803
  this._display = display;
797
804
  this._sequence = sequence;
@@ -803,7 +810,11 @@ module.exports = (() => {
803
810
  this._fee = fee;
804
811
  this._corporateAction = corporateAction;
805
812
  this._initial = initial;
813
+ this._terminal = terminal;
806
814
  this._significant = significant;
815
+ this._chaining = chaining;
816
+ this._chained = chained;
817
+ this._transfer = transfer;
807
818
  }
808
819
 
809
820
  /**
@@ -920,6 +931,16 @@ module.exports = (() => {
920
931
  return this._initial;
921
932
  }
922
933
 
934
+ /**
935
+ * Indicates if the transaction must be the last
936
+ *
937
+ * @public
938
+ * @returns {Boolean}
939
+ */
940
+ get terminal() {
941
+ return this._terminal;
942
+ }
943
+
923
944
  /**
924
945
  * Significant transactions cannot be discarded during transaction re-write.
925
946
  *
@@ -930,6 +951,37 @@ module.exports = (() => {
930
951
  return this._significant;
931
952
  }
932
953
 
954
+ /**
955
+ * Chain transactions cause another position to be created.
956
+ *
957
+ * @public
958
+ * @returns {Boolean}
959
+ */
960
+ get chaining() {
961
+ return this._chaining;
962
+ }
963
+
964
+ /**
965
+ * Chained transactions are created from another position.
966
+ *
967
+ * @public
968
+ * @returns {Boolean}
969
+ */
970
+ get chained() {
971
+ return this._chained;
972
+ }
973
+
974
+ /**
975
+ * Indicates if the transaction should cause gains and losses to be
976
+ * transferred from the original (chaining) position.
977
+ *
978
+ * @public
979
+ * @returns {Boolean}
980
+ */
981
+ get transfer() {
982
+ return this._transfer;
983
+ }
984
+
933
985
  /**
934
986
  * A purchase.
935
987
  *
@@ -1105,7 +1157,7 @@ module.exports = (() => {
1105
1157
  static get DEBIT() {
1106
1158
  return debit;
1107
1159
  }
1108
-
1160
+
1109
1161
  /**
1110
1162
  * A system-generated transaction, indicating the security has stopped active trading.
1111
1163
  *
@@ -1150,34 +1202,84 @@ module.exports = (() => {
1150
1202
  return income;
1151
1203
  }
1152
1204
 
1205
+ /**
1206
+ * A merger opening.
1207
+ *
1208
+ * @public
1209
+ * @static
1210
+ * @returns {TransactionType}
1211
+ */
1212
+ static get MERGER_OPEN() {
1213
+ return mergerOpen;
1214
+ }
1215
+
1216
+ /**
1217
+ * A merger closing.
1218
+ *
1219
+ * @public
1220
+ * @static
1221
+ * @returns {TransactionType}
1222
+ */
1223
+ static get MERGER_CLOSE() {
1224
+ return mergerClose;
1225
+ }
1226
+
1227
+ /**
1228
+ * A spin-off.
1229
+ *
1230
+ * @public
1231
+ * @static
1232
+ * @returns {TransactionType}
1233
+ */
1234
+ static get SPINOFF() {
1235
+ return spinoff;
1236
+ }
1237
+
1238
+ /**
1239
+ * A spin-off opening.
1240
+ *
1241
+ * @public
1242
+ * @static
1243
+ * @returns {TransactionType}
1244
+ */
1245
+ static get SPINOFF_OPEN() {
1246
+ return spinoffOpen;
1247
+ }
1248
+
1153
1249
  toString() {
1154
1250
  return '[TransactionType]';
1155
1251
  }
1156
1252
  }
1157
1253
 
1158
- const buy = new TransactionType('B', 'Buy', 'Buy', 0, true, false, false, true, false, false, false, true, true);
1159
- const sell = new TransactionType('S', 'Sell', 'Sell', 0, false, true, false, false, true, false, false, false, true);
1160
- const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', 0, true, false, false, false, true, false, false, false, true);
1161
- const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', 0, false, true, false, true, false, false, false, true, true);
1162
- const dividend = new TransactionType('DV', 'Dividend', 'Dividend', 1, false, false, true, false, false, false, true, false, false);
1163
- const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', 1, false, false, false, true, false, false, true, false, false);
1164
- const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', 1, false, false, false, true, false, false, true, false, false);
1165
- const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false);
1166
- const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false);
1167
- const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false);
1168
- const delist = new TransactionType('DL', 'Delist', 'Delist', 1, false, false, false, false, false, false, true, false, false);
1169
-
1170
- const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false);
1171
- const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false);
1172
- const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', 1, false, false, false, true, false, false, true, false, false);
1173
-
1174
- const deposit = new TransactionType('D', 'Deposit', 'Deposit', 0, false, false, false, false, false, false, false, true, true);
1175
- const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', 0, false, false, false, false, false, false, false, true, true);
1176
- const debit = new TransactionType('DR', 'Debit', 'Debit', 0, false, false, false, false, false, false, false, true, true);
1177
- const credit = new TransactionType('CR', 'Credit', 'Credit', 0, false, false, false, false, false, false, false, true, true);
1178
-
1179
- const valuation = new TransactionType('V', 'Valuation', 'Valuation', 0, false, false, false, false, false, false, false, false, false);
1180
- const income = new TransactionType('I', 'Income', 'Income', 0, false, false, true, false, false, false, false, false, false);
1254
+ const buy = new TransactionType('B', 'Buy', 'Buy', 0, true, false, false, true, false, false, false, true, false, true, false, false, false);
1255
+ const sell = new TransactionType('S', 'Sell', 'Sell', 0, false, true, false, false, true, false, false, false, false, true, false, false, false);
1256
+ const buyShort = new TransactionType('BS', 'Buy To Cover', 'Buy To Cover', 0, true, false, false, false, true, false, false, false, false, true, false, false, false);
1257
+ const sellShort = new TransactionType('SS', 'Sell Short', 'Sell Short', 0, false, true, false, true, false, false, false, true, false, true, false, false, false);
1258
+ const dividend = new TransactionType('DV', 'Dividend', 'Dividend', 1, false, false, true, false, false, false, true, false, false, false, false, false, false);
1259
+ const dividendReinvest = new TransactionType('DX', 'Dividend (Reinvested)', 'Dividend Reinvest', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
1260
+ const dividendStock = new TransactionType('DS', 'Dividend (Stock)', 'Dividend Stock', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
1261
+ const split = new TransactionType('SP', 'Split', 'Split', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
1262
+ const fee = new TransactionType('F', 'Fee', 'Fee', 0, false, false, false, false, false, true, false, false, false, false, false, false, false);
1263
+ const feeUnits = new TransactionType('FU', 'Fee Units', 'Fee', 0, false, false, false, false, true, false, false, false, false, false, false, false, false);
1264
+ const delist = new TransactionType('DL', 'Delist', 'Delist', 1, false, false, false, false, false, false, true, false, true, false, false, false, false);
1265
+
1266
+ const mergerOpen = new TransactionType('MO', 'Merger Open', 'Merger Open', 1, false, false, false, true, false, false, true, true, false, true, false, true, true);
1267
+ const mergerClose = new TransactionType('MC', 'Merger Close', 'Merger Close', 1, false, false, false, false, true, false, true, false, true, false, true, false, false);
1268
+
1269
+ const spinoff = new TransactionType('SPF', 'Spinoff', 'Spinoff', 1, false, false, false, false, false, false, true, false, false, false, true, false, false);
1270
+ const spinoffOpen = new TransactionType('SPFO', 'Spinoff Open', 'Spinoff Open', 1, false, false, false, true, false, false, true, true, false, true, false, false, false);
1271
+
1272
+ const distributionCash = new TransactionType('DC', 'Distribution (Cash)', 'Cash Distribution', 1, false, false, true, false, false, false, true, false, false, false, false, false, false);
1273
+ const distributionReinvest = new TransactionType('DY', 'Distribution (Reinvested)', 'Distribution Reinvest', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
1274
+ const distributionFund = new TransactionType('DF', 'Distribution (Units)', 'Unit Distribution', 1, false, false, false, true, false, false, true, false, false, false, false, false, false);
1275
+
1276
+ const deposit = new TransactionType('D', 'Deposit', 'Deposit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
1277
+ const withdrawal = new TransactionType('W', 'Withdrawal', 'Withdrawal', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
1278
+ const debit = new TransactionType('DR', 'Debit', 'Debit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
1279
+ const credit = new TransactionType('CR', 'Credit', 'Credit', 0, false, false, false, false, false, false, false, true, false, true, false, false, false);
1280
+
1281
+ const valuation = new TransactionType('V', 'Valuation', 'Valuation', 0, false, false, false, false, false, false, false, false, false, false, false, false, false);
1282
+ const income = new TransactionType('I', 'Income', 'Income', 0, false, false, true, false, false, false, false, false, false, false, false, false, false);
1181
1283
 
1182
1284
  return TransactionType;
1183
1285
  })();
@@ -1255,20 +1357,20 @@ module.exports = (() => {
1255
1357
  return transactions.every((t) => {
1256
1358
  let valid = true;
1257
1359
 
1258
- if (is.object(t.reference) && is.string(t.reference.root) && is.number(t.reference.sequence)) {
1360
+ if (is.object(t.reference) && is.string(t.reference.root) && is.string(t.reference.transaction)) {
1259
1361
  const root = t.reference.root;
1260
- const sequence = t.reference.sequence;
1362
+ const transaction = t.reference.transaction;
1261
1363
 
1262
1364
  if (!references.hasOwnProperty(root)) {
1263
1365
  references[root] = [ ];
1264
1366
  }
1265
1367
 
1266
- const sequences = references[root];
1368
+ const transactions = references[root];
1267
1369
 
1268
- if (sequences.some(s => s === sequence)) {
1370
+ if (transactions.some(t => t === transaction)) {
1269
1371
  valid = false;
1270
1372
  } else {
1271
- sequences.push(sequence);
1373
+ transactions.push(transaction);
1272
1374
  }
1273
1375
  }
1274
1376
 
@@ -1371,7 +1473,7 @@ module.exports = (() => {
1371
1473
  static validateInitialTransactionType(transactionType) {
1372
1474
  return transactionType.initial;
1373
1475
  }
1374
-
1476
+
1375
1477
  /**
1376
1478
  * Determines if a position for a given instrument type can exist in
1377
1479
  * the given direction.
@@ -1431,6 +1533,10 @@ module.exports = (() => {
1431
1533
  associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_STOCK, false);
1432
1534
  associateTypes(InstrumentType.EQUITY, TransactionType.SPLIT, false);
1433
1535
  associateTypes(InstrumentType.EQUITY, TransactionType.DELIST, false);
1536
+ associateTypes(InstrumentType.EQUITY, TransactionType.MERGER_OPEN, false);
1537
+ associateTypes(InstrumentType.EQUITY, TransactionType.MERGER_CLOSE, false);
1538
+ associateTypes(InstrumentType.EQUITY, TransactionType.SPINOFF, false);
1539
+ associateTypes(InstrumentType.EQUITY, TransactionType.SPINOFF_OPEN, false);
1434
1540
 
1435
1541
  associateTypes(InstrumentType.FUND, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
1436
1542
  associateTypes(InstrumentType.FUND, TransactionType.SELL, true, [ PositionDirection.LONG ]);
@@ -1440,6 +1546,10 @@ module.exports = (() => {
1440
1546
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_REINVEST, false);
1441
1547
  associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
1442
1548
  associateTypes(InstrumentType.FUND, TransactionType.DELIST, false);
1549
+ associateTypes(InstrumentType.FUND, TransactionType.MERGER_OPEN, false);
1550
+ associateTypes(InstrumentType.FUND, TransactionType.MERGER_CLOSE, false);
1551
+ associateTypes(InstrumentType.FUND, TransactionType.SPINOFF, false);
1552
+ associateTypes(InstrumentType.FUND, TransactionType.SPINOFF_OPEN, false);
1443
1553
 
1444
1554
  associateTypes(InstrumentType.OTHER, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
1445
1555
  associateTypes(InstrumentType.OTHER, TransactionType.SELL, true, [ PositionDirection.LONG ]);
@@ -4853,7 +4963,7 @@ module.exports = (() => {
4853
4963
  static get VALUATION() {
4854
4964
  return valuation;
4855
4965
  }
4856
-
4966
+
4857
4967
  static get DELIST() {
4858
4968
  return delist;
4859
4969
  }
@@ -4878,7 +4988,7 @@ module.exports = (() => {
4878
4988
  .withField('quantity', DataType.DECIMAL)
4879
4989
  .withField('fee', DataType.DECIMAL, true)
4880
4990
  .withField('reference.position', DataType.STRING, true)
4881
- .withField('reference.sequence', DataType.NUMBER, true)
4991
+ .withField('reference.transaction', DataType.STRING, true)
4882
4992
  .withField('snapshot.open', DataType.DECIMAL)
4883
4993
  .withField('snapshot.direction', DataType.forEnum(PositionDirection, 'PositionDirection'))
4884
4994
  .withField('snapshot.buys', DataType.DECIMAL)
@@ -4902,6 +5012,10 @@ module.exports = (() => {
4902
5012
  .withField('split.denominator', DataType.DECIMAL, true)
4903
5013
  .withField('split.effective', DataType.DAY, true)
4904
5014
  .withField('split.reference', DataType.STRING, true)
5015
+ .withField('merger.numerator', DataType.DECIMAL, true)
5016
+ .withField('merger.denominator', DataType.DECIMAL, true)
5017
+ .withField('spinoff.numerator', DataType.DECIMAL, true)
5018
+ .withField('spinoff.denominator', DataType.DECIMAL, true)
4905
5019
  .withField('charge.amount', DataType.DECIMAL, true)
4906
5020
  .withField('income.amount', DataType.DECIMAL, true)
4907
5021
  .withField('valuation.rate', DataType.DECIMAL, true)
@@ -4923,7 +5037,7 @@ module.exports = (() => {
4923
5037
  .withField('quantity', DataType.DECIMAL)
4924
5038
  .withField('fee', DataType.DECIMAL, true)
4925
5039
  .withField('reference.position', DataType.STRING, true)
4926
- .withField('reference.sequence', DataType.NUMBER, true)
5040
+ .withField('reference.transaction', DataType.NUMBER, true)
4927
5041
  .withField('snapshot.open', DataType.DECIMAL)
4928
5042
  .withField('snapshot.direction', DataType.forEnum(PositionDirection, 'PositionDirection'))
4929
5043
  .withField('snapshot.buys', DataType.DECIMAL)
@@ -4941,6 +5055,10 @@ module.exports = (() => {
4941
5055
  .withField('split.denominator', DataType.DECIMAL, true)
4942
5056
  .withField('split.effective', DataType.DAY, true)
4943
5057
  .withField('split.reference', DataType.STRING, true)
5058
+ .withField('merger.numerator', DataType.DECIMAL, true)
5059
+ .withField('merger.denominator', DataType.DECIMAL, true)
5060
+ .withField('spinoff.numerator', DataType.DECIMAL, true)
5061
+ .withField('spinoff.denominator', DataType.DECIMAL, true)
4944
5062
  .withField('charge.amount', DataType.DECIMAL, true)
4945
5063
  .withField('income.amount', DataType.DECIMAL, true)
4946
5064
  .withField('valuation.rate', DataType.DECIMAL, true)
@@ -5066,7 +5184,7 @@ module.exports = (() => {
5066
5184
  .withField('force', DataType.BOOLEAN, true)
5067
5185
  .schema
5068
5186
  );
5069
-
5187
+
5070
5188
  const delist = new TransactionSchema(SchemaBuilder.withName(TransactionType.DELIST.code)
5071
5189
  .withField('portfolio', DataType.STRING)
5072
5190
  .withField('position', DataType.STRING)
@@ -5076,7 +5194,7 @@ module.exports = (() => {
5076
5194
  .withField('force', DataType.BOOLEAN, true)
5077
5195
  .schema
5078
5196
  );
5079
-
5197
+
5080
5198
  const income = new TransactionSchema(SchemaBuilder.withName(TransactionType.INCOME.code)
5081
5199
  .withField('portfolio', DataType.STRING)
5082
5200
  .withField('position', DataType.STRING)
@@ -7370,6 +7488,7 @@ module.exports = (() => {
7370
7488
  * item's value. If no matching item can be found, a null value is returned.
7371
7489
  *
7372
7490
  * @public
7491
+ * @static
7373
7492
  * @param {Function} type - The enumeration type.
7374
7493
  * @param {String} code - The enumeration item's code.
7375
7494
  * @returns {*|null}
@@ -7383,6 +7502,7 @@ module.exports = (() => {
7383
7502
  * Returns all of the enumeration's items (given an enumeration type).
7384
7503
  *
7385
7504
  * @public
7505
+ * @static
7386
7506
  * @param {Function} type - The enumeration to list.
7387
7507
  * @returns {Array}
7388
7508
  */
@@ -17467,7 +17587,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
17467
17587
  }
17468
17588
  ];
17469
17589
 
17470
- ranges = PositionSummaryFrame.YTD.getRanges(transactions);;
17590
+ ranges = PositionSummaryFrame.YTD.getRanges(transactions);
17471
17591
  });
17472
17592
 
17473
17593
  it('should have one range', () => {
@@ -17724,8 +17844,8 @@ describe('When validating transaction order', () => {
17724
17844
  describe('When validating transaction references', () => {
17725
17845
  'use strict';
17726
17846
 
17727
- const build = (root, sequence) => {
17728
- return { reference: { root: root, sequence: sequence } };
17847
+ const build = (root, transaction) => {
17848
+ return { reference: { root: root, transaction: transaction } };
17729
17849
  };
17730
17850
 
17731
17851
  it('An array of zero transactions should be valid', () => {
@@ -17737,11 +17857,11 @@ describe('When validating transaction references', () => {
17737
17857
  });
17738
17858
 
17739
17859
  it('An array with distinct references should be valid', () => {
17740
- expect(TransactionValidator.validateReferences([ build('a', 1), build('a', 2), build('b', 1) ])).toEqual(true);
17860
+ expect(TransactionValidator.validateReferences([ build('a', 'x'), build('a', 'y'), build('b', 'y') ])).toEqual(true);
17741
17861
  });
17742
17862
 
17743
17863
  it('An array with non-distinct references should be not valid', () => {
17744
- expect(TransactionValidator.validateReferences([ build('a', 1), build('a', 2), build('b', 1), build('a', 2) ])).toEqual(false);
17864
+ expect(TransactionValidator.validateReferences([ build('a', 'x'), build('a', 'y'), build('b', 'x'), build('a', 'y') ])).toEqual(false);
17745
17865
  });
17746
17866
  });
17747
17867
 
@@ -432,7 +432,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
432
432
  }
433
433
  ];
434
434
 
435
- ranges = PositionSummaryFrame.YTD.getRanges(transactions);;
435
+ ranges = PositionSummaryFrame.YTD.getRanges(transactions);
436
436
  });
437
437
 
438
438
  it('should have one range', () => {
@@ -58,8 +58,8 @@ describe('When validating transaction order', () => {
58
58
  describe('When validating transaction references', () => {
59
59
  'use strict';
60
60
 
61
- const build = (root, sequence) => {
62
- return { reference: { root: root, sequence: sequence } };
61
+ const build = (root, transaction) => {
62
+ return { reference: { root: root, transaction: transaction } };
63
63
  };
64
64
 
65
65
  it('An array of zero transactions should be valid', () => {
@@ -71,11 +71,11 @@ describe('When validating transaction references', () => {
71
71
  });
72
72
 
73
73
  it('An array with distinct references should be valid', () => {
74
- expect(TransactionValidator.validateReferences([ build('a', 1), build('a', 2), build('b', 1) ])).toEqual(true);
74
+ expect(TransactionValidator.validateReferences([ build('a', 'x'), build('a', 'y'), build('b', 'y') ])).toEqual(true);
75
75
  });
76
76
 
77
77
  it('An array with non-distinct references should be not valid', () => {
78
- expect(TransactionValidator.validateReferences([ build('a', 1), build('a', 2), build('b', 1), build('a', 2) ])).toEqual(false);
78
+ expect(TransactionValidator.validateReferences([ build('a', 'x'), build('a', 'y'), build('b', 'x'), build('a', 'y') ])).toEqual(false);
79
79
  });
80
80
  });
81
81