@barchart/portfolio-api-common 1.0.263 → 1.0.264

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.
@@ -1,4 +1,5 @@
1
- const assert = require('@barchart/common-js/lang/assert');
1
+ const assert = require('@barchart/common-js/lang/assert'),
2
+ array = require('@barchart/common-js/lang/array')
2
3
 
3
4
  const InstrumentType = require('./InstrumentType'),
4
5
  PositionDirection = require('./PositionDirection'),
@@ -17,6 +18,31 @@ module.exports = (() => {
17
18
 
18
19
  }
19
20
 
21
+ /**
22
+ * Given a set of transaction, ensures that sequence numbers and dates
23
+ * are properly ordered.
24
+ *
25
+ * @public
26
+ * @static
27
+ * @param {Array.<Object>} transactions
28
+ * @param {Boolean=} partial - If true, sequence validation starts with the array's first transaction.
29
+ * @return {boolean}
30
+ */
31
+ static validateOrder(transactions, partial) {
32
+ assert.argumentIsArray(transactions, 'transactions');
33
+ assert.argumentIsOptional(partial, 'partial', Boolean);
34
+
35
+ let startSequence;
36
+
37
+ if (partial && transactions.length !== 0) {
38
+ startSequence = array.first(transactions).sequence;
39
+ } else {
40
+ startSequence = 1;
41
+ }
42
+
43
+ return transactions.every((t, i) => t.sequence === (i + startSequence) && (i === 0 || !t.date.getIsBefore(transactions[i - 1].date)));
44
+ }
45
+
20
46
  /**
21
47
  * Given an instrument type, returns all valid transaction types.
22
48
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.263",
3
+ "version": "1.0.264",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -185,7 +185,137 @@ module.exports = (() => {
185
185
  return InstrumentType;
186
186
  })();
187
187
 
188
- },{"@barchart/common-js/lang/Enum":19,"@barchart/common-js/lang/assert":22,"uuid":28}],2:[function(require,module,exports){
188
+ },{"@barchart/common-js/lang/Enum":21,"@barchart/common-js/lang/assert":24,"uuid":30}],2:[function(require,module,exports){
189
+ const assert = require('@barchart/common-js/lang/assert'),
190
+ Decimal = require('@barchart/common-js/lang/Decimal'),
191
+ Enum = require('@barchart/common-js/lang/Enum');
192
+
193
+ module.exports = (() => {
194
+ 'use strict';
195
+
196
+ /**
197
+ * Describes a position size -- positive values are long, negative values
198
+ * are short and zero values are even.
199
+ *
200
+ * @public
201
+ * @extends {Enum}
202
+ * @param {String} code
203
+ * @param {String} description
204
+ * @param {sign} sign
205
+ */
206
+ class PositionDirection extends Enum {
207
+ constructor(code, description, sign) {
208
+ super(code, description);
209
+
210
+ assert.argumentIsRequired(sign, 'sign', String);
211
+
212
+ this._sign = sign;
213
+ }
214
+
215
+ /**
216
+ * A description of the positiveness or negativeness of the size of the
217
+ * position.
218
+ *
219
+ * @public
220
+ * @returns {String}
221
+ */
222
+ get sign() {
223
+ return this._sign;
224
+ }
225
+
226
+ /**
227
+ * Indicates if the position size is positive (i.e. is {@link PositionDirection.LONG}).
228
+ *
229
+ * @public
230
+ * @returns {boolean}
231
+ */
232
+ get positive() {
233
+ return this === long;
234
+ }
235
+
236
+ /**
237
+ * Indicates if the position size is negative (i.e. is {@link PositionDirection.SHORT}).
238
+ *
239
+ * @public
240
+ * @returns {boolean}
241
+ */
242
+ get negative() {
243
+ return this === short;
244
+ }
245
+
246
+ /**
247
+ * Indicates if the position size is zero (i.e. is {@link PositionDirection.EVEN}).
248
+ *
249
+ * @public
250
+ * @returns {boolean}
251
+ */
252
+ get closed() {
253
+ return this === even;
254
+ }
255
+
256
+ /**
257
+ * A positive quantity position.
258
+ *
259
+ * @public
260
+ * @static
261
+ * @returns {PositionDirection}
262
+ */
263
+ static get LONG() {
264
+ return long;
265
+ }
266
+
267
+ /**
268
+ * A positive quantity position.
269
+ *
270
+ * @public
271
+ * @static
272
+ * @returns {PositionDirection}
273
+ */
274
+ static get SHORT() {
275
+ return short;
276
+ }
277
+
278
+ /**
279
+ * A zero quantity position.
280
+ *
281
+ * @public
282
+ * @static
283
+ * @returns {PositionDirection}
284
+ */
285
+ static get EVEN() {
286
+ return even;
287
+ }
288
+
289
+ /**
290
+ * Given an open quantity, returns a {@link PositionDirection} that
291
+ * describes the quantity.
292
+ *
293
+ * @public
294
+ * @static
295
+ * @param {Decimal} open
296
+ * @returns {PositionDirection}
297
+ */
298
+ static for(open) {
299
+ assert.argumentIsRequired(open, 'open', Decimal, 'Decimal');
300
+
301
+ if (open.getIsPositive()) {
302
+ return long;
303
+ } else if (open.getIsNegative()) {
304
+ return short;
305
+ } else {
306
+ return even;
307
+ }
308
+ }
309
+ }
310
+
311
+ const long = new PositionDirection('LONG', 'Long', 'positive');
312
+ const short = new PositionDirection('SHORT', 'Short', 'negative');
313
+ const even = new PositionDirection('EVEN', 'Even', 'zero');
314
+
315
+ return PositionDirection;
316
+ })();
317
+
318
+ },{"@barchart/common-js/lang/Decimal":19,"@barchart/common-js/lang/Enum":21,"@barchart/common-js/lang/assert":24}],3:[function(require,module,exports){
189
319
  const array = require('@barchart/common-js/lang/array'),
190
320
  assert = require('@barchart/common-js/lang/assert'),
191
321
  Day = require('@barchart/common-js/lang/Day'),
@@ -458,7 +588,7 @@ module.exports = (() => {
458
588
  return PositionSummaryFrame;
459
589
  })();
460
590
 
461
- },{"@barchart/common-js/lang/Day":16,"@barchart/common-js/lang/Decimal":17,"@barchart/common-js/lang/Enum":19,"@barchart/common-js/lang/array":21,"@barchart/common-js/lang/assert":22,"@barchart/common-js/lang/is":24}],3:[function(require,module,exports){
591
+ },{"@barchart/common-js/lang/Day":18,"@barchart/common-js/lang/Decimal":19,"@barchart/common-js/lang/Enum":21,"@barchart/common-js/lang/array":23,"@barchart/common-js/lang/assert":24,"@barchart/common-js/lang/is":26}],4:[function(require,module,exports){
462
592
  const assert = require('@barchart/common-js/lang/assert'),
463
593
  Enum = require('@barchart/common-js/lang/Enum');
464
594
 
@@ -825,7 +955,205 @@ module.exports = (() => {
825
955
  return TransactionType;
826
956
  })();
827
957
 
828
- },{"@barchart/common-js/lang/Enum":19,"@barchart/common-js/lang/assert":22}],4:[function(require,module,exports){
958
+ },{"@barchart/common-js/lang/Enum":21,"@barchart/common-js/lang/assert":24}],5:[function(require,module,exports){
959
+ const assert = require('@barchart/common-js/lang/assert'),
960
+ array = require('@barchart/common-js/lang/array')
961
+
962
+ const InstrumentType = require('./InstrumentType'),
963
+ PositionDirection = require('./PositionDirection'),
964
+ TransactionType = require('./TransactionType');
965
+
966
+ module.exports = (() => {
967
+ 'use strict';
968
+
969
+ /**
970
+ * Static utilities for validating transactions.
971
+ *
972
+ * @public
973
+ */
974
+ class TransactionValidator {
975
+ constructor() {
976
+
977
+ }
978
+
979
+ /**
980
+ * Given a set of transaction, ensures that sequence numbers and dates
981
+ * are properly ordered.
982
+ *
983
+ * @public
984
+ * @static
985
+ * @param {Array.<Object>} transactions
986
+ * @param {Boolean=} partial - If true, sequence validation starts with the array's first transaction.
987
+ * @return {boolean}
988
+ */
989
+ static validateOrder(transactions, partial) {
990
+ assert.argumentIsArray(transactions, 'transactions');
991
+ assert.argumentIsOptional(partial, 'partial', Boolean);
992
+
993
+ let startSequence;
994
+
995
+ if (partial && transactions.length !== 0) {
996
+ startSequence = array.first(transactions).sequence;
997
+ } else {
998
+ startSequence = 1;
999
+ }
1000
+
1001
+ return transactions.every((t, i) => t.sequence === (i + startSequence) && (i === 0 || !t.date.getIsBefore(transactions[i - 1].date)));
1002
+ }
1003
+
1004
+ /**
1005
+ * Given an instrument type, returns all valid transaction types.
1006
+ *
1007
+ * @static
1008
+ * @public
1009
+ * @param {InstrumentType} instrumentType
1010
+ * @param {Boolean=} userInitiated
1011
+ * @pararm {PositionDirection=} currentDirection
1012
+ * @return {Array.<TransactionType>}
1013
+ */
1014
+ static getTransactionTypesFor(instrumentType, userInitiated, currentDirection) {
1015
+ assert.argumentIsRequired(instrumentType, 'instrumentType', InstrumentType, 'InstrumentType');
1016
+ assert.argumentIsOptional(userInitiated, 'userInitiated', Boolean);
1017
+
1018
+ let valid = validTransactionTypes[instrumentType.code] || [ ];
1019
+
1020
+ if (userInitiated) {
1021
+ valid = valid.filter(data => data.user === userInitiated);
1022
+ }
1023
+
1024
+ if (currentDirection) {
1025
+ valid = valid.filter(data => data.directions.some(d => d === currentDirection));
1026
+ }
1027
+
1028
+ return valid.map(d => d.type);
1029
+ }
1030
+
1031
+ /**
1032
+ * Checks to see if an transaction type is applicable to an instrument type.
1033
+ *
1034
+ * @static
1035
+ * @public
1036
+ * @param {InstrumentType} instrumentType
1037
+ * @param {TransactionType} transactionType
1038
+ * @param {Boolean=} userInitiated
1039
+ * @return {Boolean}
1040
+ */
1041
+ static validateTransactionType(instrumentType, transactionType, userInitiated) {
1042
+ assert.argumentIsRequired(transactionType, 'transactionType', TransactionType, 'TransactionType');
1043
+
1044
+ const transactionTypes = TransactionValidator.getTransactionTypesFor(instrumentType, userInitiated);
1045
+
1046
+ return transactionTypes.some(t => t === transactionType);
1047
+ }
1048
+
1049
+ /**
1050
+ * Checks to see if a position for a given instrument type can exist in
1051
+ * the given direction.
1052
+ *
1053
+ * @static
1054
+ * @public
1055
+ * @param {InstrumentType} instrumentType
1056
+ * @param {PositionDirection} direction
1057
+ * @return {Boolean}
1058
+ */
1059
+ static validateDirection(instrumentType, direction) {
1060
+ assert.argumentIsRequired(instrumentType, 'instrumentType', InstrumentType, 'InstrumentType');
1061
+ assert.argumentIsRequired(direction, 'direction', PositionDirection, 'PositionDirection');
1062
+
1063
+ return validDirections[instrumentType.code].some(d => d === direction);
1064
+ }
1065
+
1066
+ /**
1067
+ * Checks to see if the position switches direction and if the direction switch
1068
+ * is valid.
1069
+ *
1070
+ * @static
1071
+ * @public
1072
+ * @param {InstrumentType} instrumentType
1073
+ * @param {PositionDirection|null|undefined} currentDirection
1074
+ * @param {PositionDirection} proposedDirection
1075
+ * @return {Boolean}
1076
+ */
1077
+ static validateDirectionSwitch(instrumentType, currentDirection, proposedDirection) {
1078
+ return currentDirection === null || instrumentType.canSwitchDirection || (currentDirection.closed || proposedDirection.closed || currentDirection.positive === proposedDirection.positive);
1079
+ }
1080
+
1081
+ toString() {
1082
+ return '[TransactionValidator]';
1083
+ }
1084
+ }
1085
+
1086
+ const validTransactionTypes = { };
1087
+
1088
+ function associateTypes(instrumentType, transactionType, userInitiated, directions) {
1089
+ const instrumentTypeCode = instrumentType.code;
1090
+
1091
+ if (!validTransactionTypes.hasOwnProperty(instrumentTypeCode)) {
1092
+ validTransactionTypes[instrumentTypeCode] = [ ];
1093
+ }
1094
+
1095
+ validTransactionTypes[instrumentTypeCode].push({ type: transactionType, user: userInitiated, directions: directions || [ PositionDirection.LONG, PositionDirection.SHORT, PositionDirection.EVEN ] });
1096
+ }
1097
+
1098
+ associateTypes(InstrumentType.EQUITY, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
1099
+ associateTypes(InstrumentType.EQUITY, TransactionType.SELL, true, [ PositionDirection.LONG ]);
1100
+ associateTypes(InstrumentType.EQUITY, TransactionType.SELL_SHORT, true, [ PositionDirection.SHORT, PositionDirection.EVEN ]);
1101
+ associateTypes(InstrumentType.EQUITY, TransactionType.BUY_SHORT, true, [ PositionDirection.SHORT ]);
1102
+ associateTypes(InstrumentType.EQUITY, TransactionType.FEE, true, [ PositionDirection.LONG, PositionDirection.SHORT ]);
1103
+ associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND, false);
1104
+ associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_REINVEST, false);
1105
+ associateTypes(InstrumentType.EQUITY, TransactionType.DIVIDEND_STOCK, false);
1106
+ associateTypes(InstrumentType.EQUITY, TransactionType.SPLIT, false);
1107
+
1108
+ associateTypes(InstrumentType.FUND, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
1109
+ associateTypes(InstrumentType.FUND, TransactionType.SELL, true, [ PositionDirection.LONG ]);
1110
+ associateTypes(InstrumentType.FUND, TransactionType.FEE, true, [ PositionDirection.LONG ]);
1111
+ associateTypes(InstrumentType.FUND, TransactionType.FEE_UNITS, false);
1112
+ associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_CASH, false);
1113
+ associateTypes(InstrumentType.FUND, TransactionType.DISTRIBUTION_FUND, false);
1114
+
1115
+ associateTypes(InstrumentType.OTHER, TransactionType.BUY, true, [ PositionDirection.LONG, PositionDirection.EVEN ]);
1116
+ associateTypes(InstrumentType.OTHER, TransactionType.SELL, true, [ PositionDirection.LONG ]);
1117
+ associateTypes(InstrumentType.OTHER, TransactionType.INCOME, true, [ PositionDirection.LONG ]);
1118
+ associateTypes(InstrumentType.OTHER, TransactionType.FEE, true, [ PositionDirection.LONG ]);
1119
+ associateTypes(InstrumentType.OTHER, TransactionType.VALUATION, true, [ PositionDirection.LONG ]);
1120
+
1121
+ associateTypes(InstrumentType.CASH, TransactionType.DEPOSIT, true);
1122
+ associateTypes(InstrumentType.CASH, TransactionType.WITHDRAWAL, true);
1123
+ associateTypes(InstrumentType.CASH, TransactionType.FEE, true);
1124
+ associateTypes(InstrumentType.CASH, TransactionType.DEBIT, false);
1125
+ associateTypes(InstrumentType.CASH, TransactionType.CREDIT, false);
1126
+
1127
+ const validDirections = { };
1128
+
1129
+ function associateDirections(instrumentType, positionDirection) {
1130
+ const instrumentTypeCode = instrumentType.code;
1131
+
1132
+ if (!validDirections.hasOwnProperty(instrumentTypeCode)) {
1133
+ validDirections[instrumentTypeCode] = [ ];
1134
+ }
1135
+
1136
+ validDirections[instrumentTypeCode].push(positionDirection);
1137
+ }
1138
+
1139
+ associateDirections(InstrumentType.EQUITY, PositionDirection.EVEN);
1140
+ associateDirections(InstrumentType.EQUITY, PositionDirection.LONG);
1141
+ associateDirections(InstrumentType.EQUITY, PositionDirection.SHORT);
1142
+
1143
+ associateDirections(InstrumentType.FUND, PositionDirection.EVEN);
1144
+ associateDirections(InstrumentType.FUND, PositionDirection.LONG);
1145
+
1146
+ associateDirections(InstrumentType.OTHER, PositionDirection.EVEN);
1147
+ associateDirections(InstrumentType.OTHER, PositionDirection.LONG);
1148
+
1149
+ associateDirections(InstrumentType.CASH, PositionDirection.EVEN);
1150
+ associateDirections(InstrumentType.CASH, PositionDirection.LONG);
1151
+ associateDirections(InstrumentType.CASH, PositionDirection.SHORT);
1152
+
1153
+ return TransactionValidator;
1154
+ })();
1155
+
1156
+ },{"./InstrumentType":1,"./PositionDirection":2,"./TransactionType":4,"@barchart/common-js/lang/array":23,"@barchart/common-js/lang/assert":24}],6:[function(require,module,exports){
829
1157
  const array = require('@barchart/common-js/lang/array'),
830
1158
  assert = require('@barchart/common-js/lang/assert'),
831
1159
  ComparatorBuilder = require('@barchart/common-js/collections/sorting/ComparatorBuilder'),
@@ -1783,7 +2111,7 @@ module.exports = (() => {
1783
2111
  return PositionContainer;
1784
2112
  })();
1785
2113
 
1786
- },{"./../data/PositionSummaryFrame":2,"./PositionGroup":5,"./PositionItem":6,"./definitions/PositionLevelDefinition":7,"./definitions/PositionLevelType":8,"./definitions/PositionTreeDefinition":9,"@barchart/common-js/collections/Tree":11,"@barchart/common-js/collections/sorting/ComparatorBuilder":12,"@barchart/common-js/collections/sorting/comparators":13,"@barchart/common-js/collections/specialized/DisposableStack":14,"@barchart/common-js/lang/Currency":15,"@barchart/common-js/lang/Decimal":17,"@barchart/common-js/lang/Rate":20,"@barchart/common-js/lang/array":21,"@barchart/common-js/lang/assert":22,"@barchart/common-js/lang/is":24,"@barchart/common-js/messaging/Event":26}],5:[function(require,module,exports){
2114
+ },{"./../data/PositionSummaryFrame":3,"./PositionGroup":7,"./PositionItem":8,"./definitions/PositionLevelDefinition":9,"./definitions/PositionLevelType":10,"./definitions/PositionTreeDefinition":11,"@barchart/common-js/collections/Tree":13,"@barchart/common-js/collections/sorting/ComparatorBuilder":14,"@barchart/common-js/collections/sorting/comparators":15,"@barchart/common-js/collections/specialized/DisposableStack":16,"@barchart/common-js/lang/Currency":17,"@barchart/common-js/lang/Decimal":19,"@barchart/common-js/lang/Rate":22,"@barchart/common-js/lang/array":23,"@barchart/common-js/lang/assert":24,"@barchart/common-js/lang/is":26,"@barchart/common-js/messaging/Event":28}],7:[function(require,module,exports){
1787
2115
  const array = require('@barchart/common-js/lang/array'),
1788
2116
  assert = require('@barchart/common-js/lang/assert'),
1789
2117
  Currency = require('@barchart/common-js/lang/Currency'),
@@ -2658,7 +2986,7 @@ module.exports = (() => {
2658
2986
  return PositionGroup;
2659
2987
  })();
2660
2988
 
2661
- },{"./../data/InstrumentType":1,"./definitions/PositionLevelDefinition":7,"./definitions/PositionLevelType":8,"@barchart/common-js/collections/specialized/DisposableStack":14,"@barchart/common-js/lang/Currency":15,"@barchart/common-js/lang/Decimal":17,"@barchart/common-js/lang/Disposable":18,"@barchart/common-js/lang/Rate":20,"@barchart/common-js/lang/array":21,"@barchart/common-js/lang/assert":22,"@barchart/common-js/lang/formatter":23,"@barchart/common-js/lang/is":24,"@barchart/common-js/messaging/Event":26}],6:[function(require,module,exports){
2989
+ },{"./../data/InstrumentType":1,"./definitions/PositionLevelDefinition":9,"./definitions/PositionLevelType":10,"@barchart/common-js/collections/specialized/DisposableStack":16,"@barchart/common-js/lang/Currency":17,"@barchart/common-js/lang/Decimal":19,"@barchart/common-js/lang/Disposable":20,"@barchart/common-js/lang/Rate":22,"@barchart/common-js/lang/array":23,"@barchart/common-js/lang/assert":24,"@barchart/common-js/lang/formatter":25,"@barchart/common-js/lang/is":26,"@barchart/common-js/messaging/Event":28}],8:[function(require,module,exports){
2662
2990
  const assert = require('@barchart/common-js/lang/assert'),
2663
2991
  Currency = require('@barchart/common-js/lang/Currency'),
2664
2992
  Decimal = require('@barchart/common-js/lang/Decimal'),
@@ -3118,7 +3446,7 @@ module.exports = (() => {
3118
3446
  return PositionItem;
3119
3447
  })();
3120
3448
 
3121
- },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Currency":15,"@barchart/common-js/lang/Decimal":17,"@barchart/common-js/lang/Disposable":18,"@barchart/common-js/lang/assert":22,"@barchart/common-js/lang/is":24,"@barchart/common-js/messaging/Event":26}],7:[function(require,module,exports){
3449
+ },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Currency":17,"@barchart/common-js/lang/Decimal":19,"@barchart/common-js/lang/Disposable":20,"@barchart/common-js/lang/assert":24,"@barchart/common-js/lang/is":26,"@barchart/common-js/messaging/Event":28}],9:[function(require,module,exports){
3122
3450
  const assert = require('@barchart/common-js/lang/assert'),
3123
3451
  Currency = require('@barchart/common-js/lang/Currency'),
3124
3452
  is = require('@barchart/common-js/lang/is');
@@ -3397,7 +3725,7 @@ module.exports = (() => {
3397
3725
  return PositionLevelDefinition;
3398
3726
  })();
3399
3727
 
3400
- },{"./../../data/InstrumentType":1,"./PositionLevelType":8,"@barchart/common-js/lang/Currency":15,"@barchart/common-js/lang/assert":22,"@barchart/common-js/lang/is":24}],8:[function(require,module,exports){
3728
+ },{"./../../data/InstrumentType":1,"./PositionLevelType":10,"@barchart/common-js/lang/Currency":17,"@barchart/common-js/lang/assert":24,"@barchart/common-js/lang/is":26}],10:[function(require,module,exports){
3401
3729
  const Enum = require('@barchart/common-js/lang/Enum');
3402
3730
 
3403
3731
  module.exports = (() => {
@@ -3428,7 +3756,7 @@ module.exports = (() => {
3428
3756
  return PositionLevelType;
3429
3757
  })();
3430
3758
 
3431
- },{"@barchart/common-js/lang/Enum":19}],9:[function(require,module,exports){
3759
+ },{"@barchart/common-js/lang/Enum":21}],11:[function(require,module,exports){
3432
3760
  const assert = require('@barchart/common-js/lang/assert');
3433
3761
 
3434
3762
  const PositionLevelDefinition = require('./PositionLevelDefinition');
@@ -3499,7 +3827,7 @@ module.exports = (() => {
3499
3827
  return PositionTreeDefinitions;
3500
3828
  })();
3501
3829
 
3502
- },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":22}],10:[function(require,module,exports){
3830
+ },{"./PositionLevelDefinition":9,"@barchart/common-js/lang/assert":24}],12:[function(require,module,exports){
3503
3831
  'use strict';
3504
3832
 
3505
3833
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -3631,7 +3959,7 @@ module.exports = function () {
3631
3959
  return Stack;
3632
3960
  }();
3633
3961
 
3634
- },{"./../lang/assert":22}],11:[function(require,module,exports){
3962
+ },{"./../lang/assert":24}],13:[function(require,module,exports){
3635
3963
  'use strict';
3636
3964
 
3637
3965
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -4001,7 +4329,7 @@ module.exports = function () {
4001
4329
  return Tree;
4002
4330
  }();
4003
4331
 
4004
- },{"./../lang/is":24}],12:[function(require,module,exports){
4332
+ },{"./../lang/is":26}],14:[function(require,module,exports){
4005
4333
  'use strict';
4006
4334
 
4007
4335
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -4145,7 +4473,7 @@ module.exports = function () {
4145
4473
  return ComparatorBuilder;
4146
4474
  }();
4147
4475
 
4148
- },{"./../../lang/assert":22,"./comparators":13}],13:[function(require,module,exports){
4476
+ },{"./../../lang/assert":24,"./comparators":15}],15:[function(require,module,exports){
4149
4477
  'use strict';
4150
4478
 
4151
4479
  var assert = require('./../../lang/assert');
@@ -4220,7 +4548,7 @@ module.exports = function () {
4220
4548
  };
4221
4549
  }();
4222
4550
 
4223
- },{"./../../lang/assert":22}],14:[function(require,module,exports){
4551
+ },{"./../../lang/assert":24}],16:[function(require,module,exports){
4224
4552
  'use strict';
4225
4553
 
4226
4554
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -4328,7 +4656,7 @@ module.exports = function () {
4328
4656
  return DisposableStack;
4329
4657
  }();
4330
4658
 
4331
- },{"./../../lang/Disposable":18,"./../../lang/assert":22,"./../../lang/is":24,"./../Stack":10}],15:[function(require,module,exports){
4659
+ },{"./../../lang/Disposable":20,"./../../lang/assert":24,"./../../lang/is":26,"./../Stack":12}],17:[function(require,module,exports){
4332
4660
  'use strict';
4333
4661
 
4334
4662
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -4471,7 +4799,7 @@ module.exports = function () {
4471
4799
  return Currency;
4472
4800
  }();
4473
4801
 
4474
- },{"./Enum":19,"./assert":22,"./is":24}],16:[function(require,module,exports){
4802
+ },{"./Enum":21,"./assert":24,"./is":26}],18:[function(require,module,exports){
4475
4803
  'use strict';
4476
4804
 
4477
4805
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -5024,7 +5352,7 @@ module.exports = function () {
5024
5352
  return Day;
5025
5353
  }();
5026
5354
 
5027
- },{"./../collections/sorting/ComparatorBuilder":12,"./../collections/sorting/comparators":13,"./assert":22,"./is":24}],17:[function(require,module,exports){
5355
+ },{"./../collections/sorting/ComparatorBuilder":14,"./../collections/sorting/comparators":15,"./assert":24,"./is":26}],19:[function(require,module,exports){
5028
5356
  'use strict';
5029
5357
 
5030
5358
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -5632,7 +5960,7 @@ module.exports = function () {
5632
5960
  return Decimal;
5633
5961
  }();
5634
5962
 
5635
- },{"./Enum":19,"./assert":22,"./is":24,"big.js":27}],18:[function(require,module,exports){
5963
+ },{"./Enum":21,"./assert":24,"./is":26,"big.js":29}],20:[function(require,module,exports){
5636
5964
  'use strict';
5637
5965
 
5638
5966
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -5781,7 +6109,7 @@ module.exports = function () {
5781
6109
  return Disposable;
5782
6110
  }();
5783
6111
 
5784
- },{"./assert":22}],19:[function(require,module,exports){
6112
+ },{"./assert":24}],21:[function(require,module,exports){
5785
6113
  'use strict';
5786
6114
 
5787
6115
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -5923,7 +6251,7 @@ module.exports = function () {
5923
6251
  return Enum;
5924
6252
  }();
5925
6253
 
5926
- },{"./assert":22}],20:[function(require,module,exports){
6254
+ },{"./assert":24}],22:[function(require,module,exports){
5927
6255
  'use strict';
5928
6256
 
5929
6257
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -6178,7 +6506,7 @@ module.exports = function () {
6178
6506
  return Rate;
6179
6507
  }();
6180
6508
 
6181
- },{"./Currency":15,"./Decimal":17,"./assert":22,"./memoize":25}],21:[function(require,module,exports){
6509
+ },{"./Currency":17,"./Decimal":19,"./assert":24,"./memoize":27}],23:[function(require,module,exports){
6182
6510
  'use strict';
6183
6511
 
6184
6512
  var assert = require('./assert'),
@@ -6579,7 +6907,7 @@ module.exports = function () {
6579
6907
  };
6580
6908
  }();
6581
6909
 
6582
- },{"./assert":22,"./is":24}],22:[function(require,module,exports){
6910
+ },{"./assert":24,"./is":26}],24:[function(require,module,exports){
6583
6911
  'use strict';
6584
6912
 
6585
6913
  var is = require('./is');
@@ -6727,7 +7055,7 @@ module.exports = function () {
6727
7055
  };
6728
7056
  }();
6729
7057
 
6730
- },{"./is":24}],23:[function(require,module,exports){
7058
+ },{"./is":26}],25:[function(require,module,exports){
6731
7059
  'use strict';
6732
7060
 
6733
7061
  module.exports = function () {
@@ -6792,7 +7120,7 @@ module.exports = function () {
6792
7120
  };
6793
7121
  }();
6794
7122
 
6795
- },{}],24:[function(require,module,exports){
7123
+ },{}],26:[function(require,module,exports){
6796
7124
  'use strict';
6797
7125
 
6798
7126
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
@@ -7015,7 +7343,7 @@ module.exports = function () {
7015
7343
  };
7016
7344
  }();
7017
7345
 
7018
- },{}],25:[function(require,module,exports){
7346
+ },{}],27:[function(require,module,exports){
7019
7347
  'use strict';
7020
7348
 
7021
7349
  var assert = require('./assert'),
@@ -7088,7 +7416,7 @@ module.exports = function () {
7088
7416
  };
7089
7417
  }();
7090
7418
 
7091
- },{"./assert":22,"./is":24}],26:[function(require,module,exports){
7419
+ },{"./assert":24,"./is":26}],28:[function(require,module,exports){
7092
7420
  'use strict';
7093
7421
 
7094
7422
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
@@ -7260,7 +7588,7 @@ module.exports = function () {
7260
7588
  return Event;
7261
7589
  }();
7262
7590
 
7263
- },{"./../lang/Disposable":18,"./../lang/assert":22}],27:[function(require,module,exports){
7591
+ },{"./../lang/Disposable":20,"./../lang/assert":24}],29:[function(require,module,exports){
7264
7592
  /*
7265
7593
  * big.js v5.0.3
7266
7594
  * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
@@ -8201,7 +8529,7 @@ module.exports = function () {
8201
8529
  }
8202
8530
  })(this);
8203
8531
 
8204
- },{}],28:[function(require,module,exports){
8532
+ },{}],30:[function(require,module,exports){
8205
8533
  var v1 = require('./v1');
8206
8534
  var v4 = require('./v4');
8207
8535
 
@@ -8211,7 +8539,7 @@ uuid.v4 = v4;
8211
8539
 
8212
8540
  module.exports = uuid;
8213
8541
 
8214
- },{"./v1":31,"./v4":32}],29:[function(require,module,exports){
8542
+ },{"./v1":33,"./v4":34}],31:[function(require,module,exports){
8215
8543
  /**
8216
8544
  * Convert array of 16 byte values to UUID string format of the form:
8217
8545
  * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
@@ -8236,7 +8564,7 @@ function bytesToUuid(buf, offset) {
8236
8564
 
8237
8565
  module.exports = bytesToUuid;
8238
8566
 
8239
- },{}],30:[function(require,module,exports){
8567
+ },{}],32:[function(require,module,exports){
8240
8568
  (function (global){
8241
8569
  // Unique ID creation requires a high quality random # generator. In the
8242
8570
  // browser this is a little complicated due to unknown quality of Math.random()
@@ -8273,7 +8601,7 @@ if (!rng) {
8273
8601
  module.exports = rng;
8274
8602
 
8275
8603
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
8276
- },{}],31:[function(require,module,exports){
8604
+ },{}],33:[function(require,module,exports){
8277
8605
  var rng = require('./lib/rng');
8278
8606
  var bytesToUuid = require('./lib/bytesToUuid');
8279
8607
 
@@ -8375,7 +8703,7 @@ function v1(options, buf, offset) {
8375
8703
 
8376
8704
  module.exports = v1;
8377
8705
 
8378
- },{"./lib/bytesToUuid":29,"./lib/rng":30}],32:[function(require,module,exports){
8706
+ },{"./lib/bytesToUuid":31,"./lib/rng":32}],34:[function(require,module,exports){
8379
8707
  var rng = require('./lib/rng');
8380
8708
  var bytesToUuid = require('./lib/bytesToUuid');
8381
8709
 
@@ -8406,7 +8734,7 @@ function v4(options, buf, offset) {
8406
8734
 
8407
8735
  module.exports = v4;
8408
8736
 
8409
- },{"./lib/bytesToUuid":29,"./lib/rng":30}],33:[function(require,module,exports){
8737
+ },{"./lib/bytesToUuid":31,"./lib/rng":32}],35:[function(require,module,exports){
8410
8738
  const Day = require('@barchart/common-js/lang/Day'),
8411
8739
  Decimal = require('@barchart/common-js/lang/Decimal');
8412
8740
 
@@ -8577,7 +8905,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
8577
8905
  });
8578
8906
  });
8579
8907
 
8580
- describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-face superfluous valuations in 2017 and 2018', () => {
8908
+ describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
8581
8909
  let ranges;
8582
8910
 
8583
8911
  beforeEach(() => {
@@ -8763,7 +9091,60 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
8763
9091
  });
8764
9092
  });
8765
9093
 
8766
- },{"./../../../lib/data/PositionSummaryFrame":2,"./../../../lib/data/TransactionType":3,"@barchart/common-js/lang/Day":16,"@barchart/common-js/lang/Decimal":17}],34:[function(require,module,exports){
9094
+ },{"./../../../lib/data/PositionSummaryFrame":3,"./../../../lib/data/TransactionType":4,"@barchart/common-js/lang/Day":18,"@barchart/common-js/lang/Decimal":19}],36:[function(require,module,exports){
9095
+ const Day = require('@barchart/common-js/lang/Day');
9096
+
9097
+ const TransactionValidator = require('./../../../lib/data/TransactionValidator');
9098
+
9099
+ describe('When validating transaction order', () => {
9100
+ 'use strict';
9101
+
9102
+ const build = (sequence, day) => {
9103
+ return { sequence: sequence, date: Day.parse(day) };
9104
+ };
9105
+
9106
+ it('An array of zero transactions should be valid', () => {
9107
+ expect(TransactionValidator.validateOrder([])).toEqual(true);
9108
+ });
9109
+
9110
+ it('An array of transactions with ordered sequences, on the same day should be valid', () => {
9111
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(2, '2018-04-30'), build(3, '2018-04-30') ])).toEqual(true);
9112
+ });
9113
+
9114
+ it('An array of transactions with ordered sequences, on the sequential days should be valid', () => {
9115
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(2, '2018-05-01'), build(3, '2018-05-02') ])).toEqual(true);
9116
+ });
9117
+
9118
+ it('An array of transactions with ordered sequences (starting after one), on the same day should not be valid', () => {
9119
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(4, '2018-04-30'), build(5, '2018-04-30') ])).toEqual(false);
9120
+ });
9121
+
9122
+ it('An array of transactions with duplicate sequences, on the same day should not be valid', () => {
9123
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(1, '2018-04-30') ])).toEqual(false);
9124
+ });
9125
+
9126
+ it('An array of transactions with with a gap in sequences, on the same day should not be valid', () => {
9127
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(3, '2018-04-30') ])).toEqual(false);
9128
+ });
9129
+
9130
+ it('An array of transactions with with a reversed sequences, on the same subsequent days should not be valid', () => {
9131
+ expect(TransactionValidator.validateOrder([ build(2, '2018-04-30'), build(1, '2018-05-01') ])).toEqual(false);
9132
+ });
9133
+
9134
+ it('An array of transactions with ordered sequences, on the reversed days should not be valid', () => {
9135
+ expect(TransactionValidator.validateOrder([ build(1, '2018-05-02'), build(2, '2018-05-01'), build(3, '2018-04-30') ])).toEqual(false);
9136
+ });
9137
+
9138
+ it('A partial array of transactions with ordered sequences (starting after one), on the same day should be valid', () => {
9139
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(4, '2018-04-30'), build(5, '2018-04-30') ], true)).toEqual(true);
9140
+ });
9141
+
9142
+ it('A partial array of transactions with gap in sequences (starting after one), on the same day should be not valid', () => {
9143
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(5, '2018-04-30'), build(6, '2018-04-30') ], true)).toEqual(false);
9144
+ });
9145
+ });
9146
+
9147
+ },{"./../../../lib/data/TransactionValidator":5,"@barchart/common-js/lang/Day":18}],37:[function(require,module,exports){
8767
9148
  const Currency = require('@barchart/common-js/lang/Currency'),
8768
9149
  Decimal = require('@barchart/common-js/lang/Decimal');
8769
9150
 
@@ -8873,4 +9254,4 @@ describe('When a position container data is gathered', () => {
8873
9254
  });
8874
9255
  });
8875
9256
 
8876
- },{"./../../../lib/data/InstrumentType":1,"./../../../lib/processing/PositionContainer":4,"./../../../lib/processing/definitions/PositionLevelDefinition":7,"./../../../lib/processing/definitions/PositionLevelType":8,"./../../../lib/processing/definitions/PositionTreeDefinition":9,"@barchart/common-js/lang/Currency":15,"@barchart/common-js/lang/Decimal":17}]},{},[33,34]);
9257
+ },{"./../../../lib/data/InstrumentType":1,"./../../../lib/processing/PositionContainer":6,"./../../../lib/processing/definitions/PositionLevelDefinition":9,"./../../../lib/processing/definitions/PositionLevelType":10,"./../../../lib/processing/definitions/PositionTreeDefinition":11,"@barchart/common-js/lang/Currency":17,"@barchart/common-js/lang/Decimal":19}]},{},[35,36,37]);
@@ -168,7 +168,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
168
168
  });
169
169
  });
170
170
 
171
- describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-face superfluous valuations in 2017 and 2018', () => {
171
+ describe('and yearly position summary ranges are processed for a transaction set closed in 2016, but has after-the-fact superfluous valuations in 2017 and 2018', () => {
172
172
  let ranges;
173
173
 
174
174
  beforeEach(() => {
@@ -0,0 +1,51 @@
1
+ const Day = require('@barchart/common-js/lang/Day');
2
+
3
+ const TransactionValidator = require('./../../../lib/data/TransactionValidator');
4
+
5
+ describe('When validating transaction order', () => {
6
+ 'use strict';
7
+
8
+ const build = (sequence, day) => {
9
+ return { sequence: sequence, date: Day.parse(day) };
10
+ };
11
+
12
+ it('An array of zero transactions should be valid', () => {
13
+ expect(TransactionValidator.validateOrder([])).toEqual(true);
14
+ });
15
+
16
+ it('An array of transactions with ordered sequences, on the same day should be valid', () => {
17
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(2, '2018-04-30'), build(3, '2018-04-30') ])).toEqual(true);
18
+ });
19
+
20
+ it('An array of transactions with ordered sequences, on the sequential days should be valid', () => {
21
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(2, '2018-05-01'), build(3, '2018-05-02') ])).toEqual(true);
22
+ });
23
+
24
+ it('An array of transactions with ordered sequences (starting after one), on the same day should not be valid', () => {
25
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(4, '2018-04-30'), build(5, '2018-04-30') ])).toEqual(false);
26
+ });
27
+
28
+ it('An array of transactions with duplicate sequences, on the same day should not be valid', () => {
29
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(1, '2018-04-30') ])).toEqual(false);
30
+ });
31
+
32
+ it('An array of transactions with with a gap in sequences, on the same day should not be valid', () => {
33
+ expect(TransactionValidator.validateOrder([ build(1, '2018-04-30'), build(3, '2018-04-30') ])).toEqual(false);
34
+ });
35
+
36
+ it('An array of transactions with with a reversed sequences, on the same subsequent days should not be valid', () => {
37
+ expect(TransactionValidator.validateOrder([ build(2, '2018-04-30'), build(1, '2018-05-01') ])).toEqual(false);
38
+ });
39
+
40
+ it('An array of transactions with ordered sequences, on the reversed days should not be valid', () => {
41
+ expect(TransactionValidator.validateOrder([ build(1, '2018-05-02'), build(2, '2018-05-01'), build(3, '2018-04-30') ])).toEqual(false);
42
+ });
43
+
44
+ it('A partial array of transactions with ordered sequences (starting after one), on the same day should be valid', () => {
45
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(4, '2018-04-30'), build(5, '2018-04-30') ], true)).toEqual(true);
46
+ });
47
+
48
+ it('A partial array of transactions with gap in sequences (starting after one), on the same day should be not valid', () => {
49
+ expect(TransactionValidator.validateOrder([ build(3, '2018-04-30'), build(5, '2018-04-30'), build(6, '2018-04-30') ], true)).toEqual(false);
50
+ });
51
+ });