@barchart/portfolio-api-common 1.26.0 → 1.27.0

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.
@@ -416,17 +416,6 @@ module.exports = (() => {
416
416
  static get TRANSACTION_SWITCH_FAILED_INVALID_REINVEST() {
417
417
  return transactionSwitchFailedInvalidReinvest;
418
418
  }
419
-
420
- /**
421
- * Unable to generate analytics report. The portfolio does not exist.
422
- *
423
- * @public
424
- * @static
425
- * @returns {FailureType}
426
- */
427
- static get WEALTHSCOPE_TOKEN_CREATE_FAIL_NO_PORTFOLIO() {
428
- return wealthscopeTokenCreateFailNoPortfolio;
429
- }
430
419
 
431
420
  toString() {
432
421
  return '[PortfolioFailureType]';
@@ -476,7 +465,5 @@ module.exports = (() => {
476
465
  const transactionSwitchFailedInvalidConversion = new FailureType('TRANSACTION_SWITCH_FAILED_INVALID_CONVERSION', 'Unable to convert transaction from {U|existing.description} to {U|desired.description}. This conversion is not supported.');
477
466
  const transactionSwitchFailedInvalidReinvest = new FailureType('TRANSACTION_SWITCH_FAILED_INVALID_REINVEST', 'Unable to convert transaction from {U|existing.description} to {U|desired.description}. Reinvestment is not supported for short positions.');
478
467
 
479
- const wealthscopeTokenCreateFailNoPortfolio = new FailureType('WEALTHSCOPE_TOKEN_CREATE_FAIL_NO_PORTFOLIO', 'Unable to generate analytics report. The portfolio does not exist, has it been deleted?', false);
480
-
481
468
  return PortfolioFailureType;
482
469
  })();
@@ -356,7 +356,7 @@ module.exports = (() => {
356
356
  *
357
357
  * @public
358
358
  * @param {Object} position
359
- * @param {Object>[]} summaries
359
+ * @param {Object[]} summaries
360
360
  */
361
361
  updatePosition(position, summaries) {
362
362
  assert.argumentIsRequired(position, 'position', Object);
@@ -662,6 +662,7 @@ module.exports = (() => {
662
662
  *
663
663
  * @public
664
664
  * @param {String} symbol
665
+ * @param {Boolean} display
665
666
  * @param {Object} data
666
667
  */
667
668
  setPositionFundamentalData(symbol, display, data) {
@@ -718,7 +719,7 @@ module.exports = (() => {
718
719
  */
719
720
  getGroup(name, keys) {
720
721
  assert.argumentIsRequired(name, 'name', String);
721
- assert.argumentIsArray(keys, 'keys', Number);
722
+ assert.argumentIsArray(keys, 'keys', String);
722
723
 
723
724
  return findNode(this._trees[name], keys).getValue();
724
725
  }
@@ -734,7 +735,7 @@ module.exports = (() => {
734
735
  */
735
736
  getGroups(name, keys) {
736
737
  assert.argumentIsRequired(name, 'name', String);
737
- assert.argumentIsArray(keys, 'keys', Number);
738
+ assert.argumentIsArray(keys, 'keys', String);
738
739
 
739
740
  return findNode(this._trees[name], keys).getChildren().map(node => node.getValue());
740
741
  }
@@ -743,7 +744,7 @@ module.exports = (() => {
743
744
  * Returns the immediate parent {@link PositionGroup} of a {@link PositionGroup}.
744
745
  *
745
746
  * @public
746
- * @param {PositionGroup} position
747
+ * @param {PositionGroup} group
747
748
  * @returns {PositionGroup|null}
748
749
  */
749
750
  getParentGroup(group) {
@@ -756,7 +757,7 @@ module.exports = (() => {
756
757
  * Returns the a parent {@link PositionGroup} which represents a portfolio.
757
758
  *
758
759
  * @public
759
- * @param {PositionGroup} position
760
+ * @param {PositionGroup} group
760
761
  * @returns {PositionGroup|null}
761
762
  */
762
763
  getParentGroupForPortfolio(group) {
@@ -265,7 +265,7 @@ module.exports = (() => {
265
265
  * The {@link PositionItem} instances which for which aggregated data is compiled.
266
266
  *
267
267
  * @public
268
- * @returns {Currency}
268
+ * @returns {PositionItem[]}
269
269
  */
270
270
  get items() {
271
271
  return this._items;
@@ -333,7 +333,7 @@ module.exports = (() => {
333
333
  * percentages).
334
334
  *
335
335
  * @public
336
- * @param {PortfolioGroup} group
336
+ * @param {PositionGroup} group
337
337
  */
338
338
  setParentGroup(group) {
339
339
  assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
@@ -350,7 +350,7 @@ module.exports = (() => {
350
350
  * of relative percentages).
351
351
  *
352
352
  * @public
353
- * @param {PortfolioGroup} group
353
+ * @param {PositionGroup} group
354
354
  */
355
355
  setPortfolioGroup(group) {
356
356
  assert.argumentIsOptional(group, 'group', PositionGroup, 'PositionGroup');
@@ -16,6 +16,7 @@ module.exports = (() => {
16
16
  *
17
17
  * @public
18
18
  * @param {String} name
19
+ * @param {PositionLevelType} type
19
20
  * @param {PositionLevelDefinition~keySelector} keySelector
20
21
  * @param {PositionLevelDefinition~descriptionSelector} descriptionSelector
21
22
  * @param {PositionLevelDefinition~currencySelector} currencySelector
@@ -173,6 +174,15 @@ module.exports = (() => {
173
174
  };
174
175
  }
175
176
 
177
+ /**
178
+ * Generates the key for a {@link PositionGroup}, representing a portfolio, held
179
+ * within a {@link PositionContainer}.
180
+ *
181
+ * @public
182
+ * @static
183
+ * @param {Object} portfolio
184
+ * @returns {String}
185
+ */
176
186
  static getKeyForPortfolioGroup(portfolio) {
177
187
  assert.argumentIsRequired(portfolio, 'portfolio', Object);
178
188
 
@@ -217,6 +227,16 @@ module.exports = (() => {
217
227
  };
218
228
  }
219
229
 
230
+ /**
231
+ * Generates the key for a {@link PositionGroup}, representing a grouping of positions
232
+ * by asset class, held within a {@link PositionContainer}.
233
+ *
234
+ * @public
235
+ * @static
236
+ * @param {InstrumentType} type
237
+ * @param {Currency} currency
238
+ * @returns {String}
239
+ */
220
240
  static getKeyForAssetClassGroup(type, currency) {
221
241
  assert.argumentIsRequired(type, 'type', InstrumentType, 'InstrumentType');
222
242
  assert.argumentIsRequired(currency, 'currency', Currency, 'Currency');
@@ -0,0 +1,98 @@
1
+ const assert = require('@barchart/common-js/lang/assert'),
2
+ is = require('@barchart/common-js/lang/is'),
3
+ promise = require('@barchart/common-js/lang/promise');
4
+
5
+ const EndpointBuilder = require('@barchart/common-js/api/http/builders/EndpointBuilder'),
6
+ ErrorInterceptor = require('@barchart/common-js/api/http/interceptors/ErrorInterceptor'),
7
+ Gateway = require('@barchart/common-js/api/http/Gateway'),
8
+ ProtocolType = require('@barchart/common-js/api/http/definitions/ProtocolType'),
9
+ ResponseInterceptor = require('@barchart/common-js/api/http/interceptors/ResponseInterceptor'),
10
+ VerbType = require('@barchart/common-js/api/http/definitions/VerbType');
11
+
12
+ module.exports = (() => {
13
+ 'use strict';
14
+
15
+ const MAXIMUM_WAIT_BEFORE_TIMEOUT_IN_MILLISECONDS = 3 * 1000;
16
+
17
+ const cache = { };
18
+
19
+ /**
20
+ * A utility that downloads instrument metadata (i.e. instrument "profile" data).
21
+ *
22
+ * @public
23
+ */
24
+ class InstrumentProvider {
25
+ constructor() {
26
+ }
27
+
28
+ /**
29
+ * Returns a promise for instrument metadata (i.e. "profile" data). If no instrument
30
+ * can be found with a matching symbol, the promise is rejected.
31
+ *
32
+ * @public
33
+ * @async
34
+ * @param {String} symbol
35
+ * @returns {Promise<Object>}
36
+ */
37
+ async getInstrument(symbol) {
38
+ return Promise.resolve()
39
+ .then(() => {
40
+ assert.argumentIsRequired(symbol, 'symbol', String);
41
+
42
+ return promise.timeout(Gateway.invoke(getInstrumentLookupEndpoint(), {symbol}), MAXIMUM_WAIT_BEFORE_TIMEOUT_IN_MILLISECONDS, 'instrument lookup')
43
+ .catch((e) => {
44
+ delete cache[symbol];
45
+
46
+ let message;
47
+
48
+ if (is.string(e) && e === 'timeout') {
49
+ message = `Instrument lookup for [ ${symbol} ] failed due to timed out`;
50
+ } else {
51
+ message = `Instrument lookup for [ ${symbol} ] failed due to an unspecified error`;
52
+ }
53
+
54
+ return Promise.reject(message);
55
+ }).then((result) => {
56
+ if (result.instrument === null) {
57
+ return Promise.reject(`Instrument lookup for [ ${symbol} ] failed, the instrument does not exist`);
58
+ }
59
+
60
+ return result;
61
+ });
62
+ });
63
+ }
64
+
65
+ toString() {
66
+ return '[InstrumentProvider]';
67
+ }
68
+ }
69
+
70
+ function buildInstrumentLookupEndpoint(host) {
71
+ return EndpointBuilder.for('query-instrument', 'query instrument')
72
+ .withVerb(VerbType.GET)
73
+ .withProtocol(ProtocolType.HTTPS)
74
+ .withHost(host)
75
+ .withPort(443)
76
+ .withPathBuilder((pb) => {
77
+ pb.withLiteralParameter('instruments', 'instruments')
78
+ .withVariableParameter('symbol', 'symbol', 'symbol');
79
+ })
80
+ .withResponseInterceptor(ResponseInterceptor.DATA)
81
+ .withErrorInterceptor(ErrorInterceptor.GENERAL)
82
+ .endpoint;
83
+ }
84
+
85
+ const instrumentLookupEndpoints = new Map();
86
+
87
+ function getInstrumentLookupEndpoint() {
88
+ const host = 'instruments-prod.aws.barchart.com';
89
+
90
+ if (!instrumentLookupEndpoints.has(host)) {
91
+ instrumentLookupEndpoints.set(host, buildInstrumentLookupEndpoint(host));
92
+ }
93
+
94
+ return instrumentLookupEndpoints.get(host);
95
+ }
96
+
97
+ return InstrumentProvider;
98
+ })();
@@ -0,0 +1,66 @@
1
+ const assert = require('@barchart/common-js/lang/assert'),
2
+ TimeMap = require('@barchart/common-js/collections/specialized/TimeMap');
3
+
4
+ const InstrumentProvider = require('./InstrumentProvider');
5
+
6
+ module.exports = (() => {
7
+ 'use strict';
8
+
9
+ const MAXIMUM_CACHE_AGE_IN_MILLISECONDS = 15 * 60 * 1000;
10
+
11
+ /**
12
+ * A caching layer on top of the {@link InstrumentProvider}.
13
+ *
14
+ * @public
15
+ * @param {InstrumentProvider} provider
16
+ * @param {Number} cacheDuration - The maximum number of milliseconds to cache an instrument.
17
+ */
18
+ class InstrumentProviderCache {
19
+ constructor(provider, cacheDuration) {
20
+ assert.argumentIsRequired(provider, 'provider', InstrumentProvider, 'InstrumentProvider');
21
+
22
+ this._provider = provider;
23
+ this._cache = new TimeMap(cacheDuration || MAXIMUM_CACHE_AGE_IN_MILLISECONDS);
24
+ }
25
+
26
+ /**
27
+ * Returns a promise for instrument metadata from an internal cache. If the instrument
28
+ * does not exist in the cache, or the data has expired, then a new request for the
29
+ * instrument is made using the {@link InstrumentProvider}.
30
+ *
31
+ * @public
32
+ * @async
33
+ * @param {String} symbol
34
+ * @returns {Promise<Object>}
35
+ */
36
+ async getInstrument(symbol) {
37
+ return Promise.resolve()
38
+ .then(() => {
39
+ assert.argumentIsRequired(symbol, 'symbol', String);
40
+
41
+ let promise = this._cache.get(symbol);
42
+
43
+ if (promise !== null) {
44
+ return promise;
45
+ }
46
+
47
+ promise = this._provider.getInstrument(symbol)
48
+ .then((profile) => {
49
+ if (profile) {
50
+ this._cache.put(symbol, promise);
51
+
52
+ return profile;
53
+ }
54
+ });
55
+
56
+ return promise;
57
+ });
58
+ }
59
+
60
+ toString() {
61
+ return '[InstrumentProviderCache]';
62
+ }
63
+ }
64
+
65
+ return InstrumentProviderCache;
66
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.26.0",
3
+ "version": "1.27.0",
4
4
  "description": "Common JavaScript code used by Barchart's Portfolio Service",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",