@barchart/portfolio-api-common 1.0.127 → 1.0.131
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/lib/processing/PositionContainer.js +78 -10
- package/lib/processing/PositionGroup.js +97 -4
- package/lib/processing/PositionItem.js +101 -5
- package/package.json +1 -1
- package/test/SpecRunner.js +276 -19
|
@@ -22,11 +22,11 @@ module.exports = (() => {
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* A container for positions which groups the positions into one or more
|
|
25
|
-
* trees for aggregation and display purposes. For example,
|
|
26
|
-
* grouped first by asset class then by position
|
|
25
|
+
* trees for aggregation and display purposes. For example, positions could be
|
|
26
|
+
* grouped first by asset class then by position.
|
|
27
27
|
*
|
|
28
28
|
* Furthermore, the container performs aggregation (driven primarily by price
|
|
29
|
-
* changes) for each level of grouping
|
|
29
|
+
* changes) for each level of grouping.
|
|
30
30
|
*
|
|
31
31
|
* @public
|
|
32
32
|
* @param {Array.<PositionTreeDefinition>} definitions
|
|
@@ -219,10 +219,14 @@ module.exports = (() => {
|
|
|
219
219
|
}, { });
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Returns a distinct list of all symbols used by the positions
|
|
224
|
+
* within the container.
|
|
225
|
+
*
|
|
226
|
+
* @public
|
|
227
|
+
* @param {Boolean} display - If true, all "display" symbols are returned; otherwise Barchart symbols are returned.
|
|
228
|
+
* @returns {Array.<String>}
|
|
229
|
+
*/
|
|
226
230
|
getPositionSymbols(display) {
|
|
227
231
|
const symbols = this._items.reduce((symbols, item) => {
|
|
228
232
|
const position = item.position;
|
|
@@ -245,6 +249,14 @@ module.exports = (() => {
|
|
|
245
249
|
return array.unique(symbols);
|
|
246
250
|
}
|
|
247
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Updates the quote for a single symbol; causing updates to any grouping
|
|
254
|
+
* level that contains the position(s) for the symbol.
|
|
255
|
+
*
|
|
256
|
+
* @public
|
|
257
|
+
* @param {String} symbol
|
|
258
|
+
* @param {Object} quote
|
|
259
|
+
*/
|
|
248
260
|
setPositionQuote(symbol, quote) {
|
|
249
261
|
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
250
262
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
@@ -254,14 +266,34 @@ module.exports = (() => {
|
|
|
254
266
|
}
|
|
255
267
|
}
|
|
256
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Returns all forex symbols that are required to do currency translations.
|
|
271
|
+
*
|
|
272
|
+
* @public
|
|
273
|
+
* @returns {Array.<String>}
|
|
274
|
+
*/
|
|
257
275
|
getForexSymbols() {
|
|
258
276
|
return this._forexSymbols;
|
|
259
277
|
}
|
|
260
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Returns all current forex quotes.
|
|
281
|
+
*
|
|
282
|
+
* @public
|
|
283
|
+
* @returns {Array.<Object>}
|
|
284
|
+
*/
|
|
261
285
|
getForexQuotes() {
|
|
262
286
|
return this._forexQuotes;
|
|
263
287
|
}
|
|
264
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Updates the forex quote for a single currency pair; causing updates to
|
|
291
|
+
* any grouping level that contains that requires translation.
|
|
292
|
+
*
|
|
293
|
+
* @public
|
|
294
|
+
* @param {String} symbol
|
|
295
|
+
* @param {Object} quote
|
|
296
|
+
*/
|
|
265
297
|
setForexQuote(symbol, quote) {
|
|
266
298
|
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
267
299
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
@@ -279,10 +311,40 @@ module.exports = (() => {
|
|
|
279
311
|
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.setForexRate(rate), true, false));
|
|
280
312
|
}
|
|
281
313
|
|
|
282
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Updates fundamental data for a single symbol.
|
|
316
|
+
*
|
|
317
|
+
* @public
|
|
318
|
+
* @param {String} symbol
|
|
319
|
+
* @param {Object} data
|
|
320
|
+
*/
|
|
321
|
+
setPositionFundamentalData(symbol, data) {
|
|
283
322
|
return;
|
|
284
323
|
}
|
|
285
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Indicates if a news article exists for a symbol.
|
|
327
|
+
*
|
|
328
|
+
* @public
|
|
329
|
+
* @param {String} symbol
|
|
330
|
+
* @param {Boolean} exists
|
|
331
|
+
*/
|
|
332
|
+
setNewsArticleExists(symbol, exists) {
|
|
333
|
+
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
334
|
+
assert.argumentIsRequired(exists, 'exists', Boolean);
|
|
335
|
+
|
|
336
|
+
if (this._symbols.hasOwnProperty(symbol)) {
|
|
337
|
+
this._symbols[symbol].forEach(item => item.setNewsArticleExists(exists));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Returns a single level of grouping from one of the internal trees.
|
|
343
|
+
*
|
|
344
|
+
* @param {String} name
|
|
345
|
+
* @param {Array.<String> keys
|
|
346
|
+
* @returns {PositionGroup}
|
|
347
|
+
*/
|
|
286
348
|
getGroup(name, keys) {
|
|
287
349
|
assert.argumentIsRequired(name, 'name', String);
|
|
288
350
|
assert.argumentIsArray(keys, 'keys', Number);
|
|
@@ -290,6 +352,14 @@ module.exports = (() => {
|
|
|
290
352
|
return findNode(this._trees[name], keys).getValue();
|
|
291
353
|
}
|
|
292
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Returns all child groups from a level of grouping within one of
|
|
357
|
+
* the internal trees.
|
|
358
|
+
*
|
|
359
|
+
* @param {String} name
|
|
360
|
+
* @param {Array.<String> keys
|
|
361
|
+
* @returns {Array.<PositionGroup>}
|
|
362
|
+
*/
|
|
293
363
|
getGroups(name, keys) {
|
|
294
364
|
assert.argumentIsRequired(name, 'name', String);
|
|
295
365
|
assert.argumentIsArray(keys, 'keys', Number);
|
|
@@ -301,8 +371,6 @@ module.exports = (() => {
|
|
|
301
371
|
assert.argumentIsRequired(name, 'name', String);
|
|
302
372
|
assert.argumentIsRequired(executor, 'executor', Function);
|
|
303
373
|
|
|
304
|
-
assert.argumentIsRequired(executor, 'executor', Function);
|
|
305
|
-
|
|
306
374
|
this._trees[name].walk(group => group.setSuspended(true), false, false);
|
|
307
375
|
|
|
308
376
|
executor(this);
|
|
@@ -10,7 +10,17 @@ module.exports = (() => {
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
+
* A grouping of {@link PositionItem} instances. The group aggregates from across
|
|
14
|
+
* all the positions and performs currency translation, as necessary.
|
|
15
|
+
*
|
|
13
16
|
* @public
|
|
17
|
+
* @param {PositionContainer} container
|
|
18
|
+
* @param {PositionGroup|null} parent
|
|
19
|
+
* @param {Array.<PositionItem>} items
|
|
20
|
+
* @param {Currency} currency
|
|
21
|
+
* @param {String} key
|
|
22
|
+
* @param {String} description
|
|
23
|
+
* @param {Boolean=} single
|
|
14
24
|
*/
|
|
15
25
|
class PositionGroup {
|
|
16
26
|
constructor(container, parent, items, currency, key, description, single) {
|
|
@@ -36,8 +46,15 @@ module.exports = (() => {
|
|
|
36
46
|
|
|
37
47
|
this._dataFormat.key = this._key;
|
|
38
48
|
this._dataFormat.description = this._description;
|
|
39
|
-
|
|
49
|
+
this._dataFormat.newsExists = false;
|
|
40
50
|
this._dataFormat.quantity = null;
|
|
51
|
+
this._dataFormat.basisPrice = null;
|
|
52
|
+
|
|
53
|
+
this._dataActual.key = this._key;
|
|
54
|
+
this._dataActual.description = this._description;
|
|
55
|
+
this._dataActual.newsExists = false;
|
|
56
|
+
this._dataActual.quantity = null;
|
|
57
|
+
this._dataActual.basisPrice = null;
|
|
41
58
|
|
|
42
59
|
if (this._single) {
|
|
43
60
|
const item = items[0];
|
|
@@ -116,35 +133,85 @@ module.exports = (() => {
|
|
|
116
133
|
|
|
117
134
|
calculatePriceData(this, this._container.getForexQuotes(), sender, false);
|
|
118
135
|
});
|
|
136
|
+
|
|
137
|
+
if (this._single) {
|
|
138
|
+
item.registerNewsExistsChangeHandler((exists, sender) => {
|
|
139
|
+
this._dataFormat.newsExists = exists;
|
|
140
|
+
this._dataFormat.newsExists = exists;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
119
143
|
});
|
|
120
144
|
|
|
121
145
|
this.refresh();
|
|
122
146
|
}
|
|
123
147
|
|
|
148
|
+
/**
|
|
149
|
+
* The key of the group.
|
|
150
|
+
*
|
|
151
|
+
* @public
|
|
152
|
+
* @returns {String}
|
|
153
|
+
*/
|
|
124
154
|
get key() {
|
|
125
155
|
return this._key;
|
|
126
156
|
}
|
|
127
157
|
|
|
158
|
+
/**
|
|
159
|
+
* The description of the group.
|
|
160
|
+
*
|
|
161
|
+
* @public
|
|
162
|
+
* @returns {String}
|
|
163
|
+
*/
|
|
128
164
|
get description() {
|
|
129
165
|
return this._description;
|
|
130
166
|
}
|
|
131
167
|
|
|
168
|
+
/**
|
|
169
|
+
* The {@link Currency} which all aggregated data is presented in.
|
|
170
|
+
*
|
|
171
|
+
* @public
|
|
172
|
+
* @returns {Currency}
|
|
173
|
+
*/
|
|
132
174
|
get currency() {
|
|
133
175
|
return this._currency;
|
|
134
176
|
}
|
|
135
177
|
|
|
178
|
+
/**
|
|
179
|
+
* The {@link PositionItem} instances which for which aggregated data is compiled.
|
|
180
|
+
*
|
|
181
|
+
* @public
|
|
182
|
+
* @returns {Currency}
|
|
183
|
+
*/
|
|
136
184
|
get items() {
|
|
137
185
|
return this._items;
|
|
138
186
|
}
|
|
139
187
|
|
|
188
|
+
/**
|
|
189
|
+
* The string-based, human-readable aggregated data for the group.
|
|
190
|
+
*
|
|
191
|
+
* @public
|
|
192
|
+
* @returns {Object}
|
|
193
|
+
*/
|
|
140
194
|
get data() {
|
|
141
195
|
return this._dataFormat;
|
|
142
196
|
}
|
|
143
197
|
|
|
198
|
+
/**
|
|
199
|
+
* The raw aggregated data for the group (typically {@link Decimal} instances).
|
|
200
|
+
*
|
|
201
|
+
* @public
|
|
202
|
+
* @returns {Object}
|
|
203
|
+
*/
|
|
144
204
|
get actual() {
|
|
145
205
|
return this._dataActual;
|
|
146
206
|
}
|
|
147
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Indicates if the group will only contain one {@link PositionItem} -- that is,
|
|
210
|
+
* indicates if the group represents a single position.
|
|
211
|
+
*
|
|
212
|
+
* @public
|
|
213
|
+
* @returns {Boolean}
|
|
214
|
+
*/
|
|
148
215
|
get single() {
|
|
149
216
|
return this._single;
|
|
150
217
|
}
|
|
@@ -153,10 +220,22 @@ module.exports = (() => {
|
|
|
153
220
|
return this._suspended;
|
|
154
221
|
}
|
|
155
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Indicates if the group should be excluded from higher-level aggregations.
|
|
225
|
+
*
|
|
226
|
+
* @public
|
|
227
|
+
* @returns {Boolean}
|
|
228
|
+
*/
|
|
156
229
|
get excluded() {
|
|
157
230
|
return this._excluded;
|
|
158
231
|
}
|
|
159
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Causes aggregated data to be recalculated using a new exchange rate.
|
|
235
|
+
*
|
|
236
|
+
* @public
|
|
237
|
+
* @param {Rate} rate
|
|
238
|
+
*/
|
|
160
239
|
setForexRate(rate) {
|
|
161
240
|
if (!this._bypassCurrencyTranslation) {
|
|
162
241
|
this.refresh();
|
|
@@ -185,6 +264,11 @@ module.exports = (() => {
|
|
|
185
264
|
}
|
|
186
265
|
}
|
|
187
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Causes all aggregated data to be recalculated.
|
|
269
|
+
*
|
|
270
|
+
* @public
|
|
271
|
+
*/
|
|
188
272
|
refresh() {
|
|
189
273
|
const rates = this._container.getForexQuotes();
|
|
190
274
|
|
|
@@ -192,6 +276,12 @@ module.exports = (() => {
|
|
|
192
276
|
calculatePriceData(this, rates, null, true);
|
|
193
277
|
}
|
|
194
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Causes the percent of the position, with respect to the parent container's
|
|
281
|
+
* total, to be recalculated.
|
|
282
|
+
*
|
|
283
|
+
* @public
|
|
284
|
+
*/
|
|
195
285
|
refreshMarketPercent() {
|
|
196
286
|
calculateMarketPercent(this, this._container.getForexQuotes(), true);
|
|
197
287
|
}
|
|
@@ -245,7 +335,7 @@ module.exports = (() => {
|
|
|
245
335
|
|
|
246
336
|
const items = group._items;
|
|
247
337
|
|
|
248
|
-
group._bypassCurrencyTranslation = items.
|
|
338
|
+
group._bypassCurrencyTranslation = items.every(item => item.currency === currency);
|
|
249
339
|
|
|
250
340
|
const translate = (item, value) => {
|
|
251
341
|
let translated;
|
|
@@ -297,8 +387,11 @@ module.exports = (() => {
|
|
|
297
387
|
if (group.single) {
|
|
298
388
|
const item = group._items[0];
|
|
299
389
|
|
|
300
|
-
|
|
301
|
-
|
|
390
|
+
actual.quantity = item.position.snapshot.open;
|
|
391
|
+
actual.basisPrice = item.data.basisPrice;
|
|
392
|
+
|
|
393
|
+
format.quantity = formatDecimal(actual.quantity, 2);
|
|
394
|
+
format.basisPrice = formatCurrency(actual.basisPrice, currency);
|
|
302
395
|
}
|
|
303
396
|
}
|
|
304
397
|
|
|
@@ -11,7 +11,15 @@ module.exports = (() => {
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
+
* A container for a single position, which handles quote changes and
|
|
15
|
+
* notifies observers -- which are typically parent-level {@link PositionGroup}
|
|
16
|
+
* instances.
|
|
17
|
+
*
|
|
14
18
|
* @public
|
|
19
|
+
* @param {Object} portfolio
|
|
20
|
+
* @param {Object} position
|
|
21
|
+
* @param {Object} currentSummary
|
|
22
|
+
* @param {Array.<Object>} previousSummaries
|
|
15
23
|
*/
|
|
16
24
|
class PositionItem {
|
|
17
25
|
constructor(portfolio, position, currentSummary, previousSummaries) {
|
|
@@ -27,10 +35,12 @@ module.exports = (() => {
|
|
|
27
35
|
this._data.basis = null;
|
|
28
36
|
|
|
29
37
|
this._currentQuote = null;
|
|
30
|
-
|
|
38
|
+
|
|
39
|
+
this._currentPrice = null;
|
|
40
|
+
this._previousPrice = null;
|
|
31
41
|
|
|
32
42
|
this._data.currentPrice = null;
|
|
33
|
-
this._data.
|
|
43
|
+
this._data.currentPricePrevious = null;
|
|
34
44
|
|
|
35
45
|
this._data.market = null;
|
|
36
46
|
this._data.marketChange = null;
|
|
@@ -50,6 +60,8 @@ module.exports = (() => {
|
|
|
50
60
|
this._data.income = null;
|
|
51
61
|
this._data.basisPrice = null;
|
|
52
62
|
|
|
63
|
+
this._data.newsExists = false;
|
|
64
|
+
|
|
53
65
|
this._excluded = false;
|
|
54
66
|
|
|
55
67
|
calculateStaticData(this);
|
|
@@ -57,32 +69,75 @@ module.exports = (() => {
|
|
|
57
69
|
|
|
58
70
|
this._quoteChangedEvent = new Event(this);
|
|
59
71
|
this._excludedChangeEvent = new Event(this);
|
|
72
|
+
this._newsExistsChangedEvent = new Event(this);
|
|
60
73
|
}
|
|
61
74
|
|
|
75
|
+
/**
|
|
76
|
+
* The portfolio of the encapsulated position.
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
* @returns {Object}
|
|
80
|
+
*/
|
|
62
81
|
get portfolio() {
|
|
63
82
|
return this._portfolio;
|
|
64
83
|
}
|
|
65
84
|
|
|
85
|
+
/**
|
|
86
|
+
* The encapsulated position.
|
|
87
|
+
*
|
|
88
|
+
* @public
|
|
89
|
+
* @returns {Object}
|
|
90
|
+
*/
|
|
66
91
|
get position() {
|
|
67
92
|
return this._position;
|
|
68
93
|
}
|
|
69
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The {@link Currency} of the encapsulated position.
|
|
97
|
+
*
|
|
98
|
+
* @public
|
|
99
|
+
* @returns {Object}
|
|
100
|
+
*/
|
|
70
101
|
get currency() {
|
|
71
102
|
return this._currency;
|
|
72
103
|
}
|
|
73
104
|
|
|
105
|
+
/**
|
|
106
|
+
* The year-to-date position summary of the encapsulated position.
|
|
107
|
+
*
|
|
108
|
+
* @public
|
|
109
|
+
* @returns {Object}
|
|
110
|
+
*/
|
|
74
111
|
get currentSummary() {
|
|
75
112
|
return this._currentSummary;
|
|
76
113
|
}
|
|
77
|
-
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Previous year's summaries for the encapsulated position.
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
* @returns {Object}
|
|
120
|
+
*/
|
|
78
121
|
get previousSummaries() {
|
|
79
122
|
return this._previousSummaries;
|
|
80
123
|
}
|
|
81
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Various data regarding the encapsulated position.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
* @returns {*}
|
|
130
|
+
*/
|
|
82
131
|
get data() {
|
|
83
132
|
return this._data;
|
|
84
133
|
}
|
|
85
134
|
|
|
135
|
+
/**
|
|
136
|
+
* The current quote for the symbol of the encapsulated position.
|
|
137
|
+
*
|
|
138
|
+
* @public
|
|
139
|
+
* @returns {null|{Object}}
|
|
140
|
+
*/
|
|
86
141
|
get quote() {
|
|
87
142
|
return this._currentQuote;
|
|
88
143
|
}
|
|
@@ -91,13 +146,22 @@ module.exports = (() => {
|
|
|
91
146
|
return this._excluded;
|
|
92
147
|
}
|
|
93
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Sets the current quote -- causing position-level data (e.g. market value) to
|
|
151
|
+
* be recalculated.
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
* @param {Object} quote
|
|
155
|
+
*/
|
|
94
156
|
setQuote(quote) {
|
|
95
157
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
96
158
|
|
|
97
|
-
if (this.
|
|
159
|
+
if (this._currentPricePrevious !== quote.lastPrice) {
|
|
98
160
|
calculatePriceData(this, quote.lastPrice);
|
|
99
161
|
|
|
100
|
-
this.
|
|
162
|
+
this._currentPricePrevious = this._currentPrice;
|
|
163
|
+
this._currentPrice = quote.lastPrice;
|
|
164
|
+
|
|
101
165
|
this._currentQuote = quote;
|
|
102
166
|
|
|
103
167
|
this._quoteChangedEvent.fire(this._currentQuote);
|
|
@@ -112,6 +176,28 @@ module.exports = (() => {
|
|
|
112
176
|
}
|
|
113
177
|
}
|
|
114
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Sets a flag which indicates if news article(s) exist for the encapsulated position's
|
|
181
|
+
* symbol.
|
|
182
|
+
*
|
|
183
|
+
* @public
|
|
184
|
+
* @param {Boolean} value
|
|
185
|
+
*/
|
|
186
|
+
setNewsArticleExists(value) {
|
|
187
|
+
assert.argumentIsRequired(value, 'value', Boolean);
|
|
188
|
+
|
|
189
|
+
if (this._data.newsExists !== value) {
|
|
190
|
+
this._newsExistsChangedEvent.fire(this._data.newsExists = value);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Registers an observer for quote changes, which is fired after internal recalculations
|
|
196
|
+
* of position data are complete.
|
|
197
|
+
*
|
|
198
|
+
* @public
|
|
199
|
+
* @param {Function} handler
|
|
200
|
+
*/
|
|
115
201
|
registerQuoteChangeHandler(handler) {
|
|
116
202
|
this._quoteChangedEvent.register(handler);
|
|
117
203
|
}
|
|
@@ -120,6 +206,16 @@ module.exports = (() => {
|
|
|
120
206
|
this._excludedChangeEvent.register(handler);
|
|
121
207
|
}
|
|
122
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Registers an observer changes to the status of news existence.
|
|
211
|
+
*
|
|
212
|
+
* @public
|
|
213
|
+
* @param {Function} handler
|
|
214
|
+
*/
|
|
215
|
+
registerNewsExistsChangeHandler(handler) {
|
|
216
|
+
this._newsExistsChangedEvent.register(handler);
|
|
217
|
+
}
|
|
218
|
+
|
|
123
219
|
toString() {
|
|
124
220
|
return '[PositionItem]';
|
|
125
221
|
}
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -738,11 +738,11 @@ module.exports = (() => {
|
|
|
738
738
|
|
|
739
739
|
/**
|
|
740
740
|
* A container for positions which groups the positions into one or more
|
|
741
|
-
* trees for aggregation and display purposes. For example,
|
|
742
|
-
* grouped first by asset class then by position
|
|
741
|
+
* trees for aggregation and display purposes. For example, positions could be
|
|
742
|
+
* grouped first by asset class then by position.
|
|
743
743
|
*
|
|
744
744
|
* Furthermore, the container performs aggregation (driven primarily by price
|
|
745
|
-
* changes) for each level of grouping
|
|
745
|
+
* changes) for each level of grouping.
|
|
746
746
|
*
|
|
747
747
|
* @public
|
|
748
748
|
* @param {Array.<PositionTreeDefinition>} definitions
|
|
@@ -935,10 +935,14 @@ module.exports = (() => {
|
|
|
935
935
|
}, { });
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
938
|
+
/**
|
|
939
|
+
* Returns a distinct list of all symbols used by the positions
|
|
940
|
+
* within the container.
|
|
941
|
+
*
|
|
942
|
+
* @public
|
|
943
|
+
* @param {Boolean} display - If true, all "display" symbols are returned; otherwise Barchart symbols are returned.
|
|
944
|
+
* @returns {Array.<String>}
|
|
945
|
+
*/
|
|
942
946
|
getPositionSymbols(display) {
|
|
943
947
|
const symbols = this._items.reduce((symbols, item) => {
|
|
944
948
|
const position = item.position;
|
|
@@ -961,6 +965,14 @@ module.exports = (() => {
|
|
|
961
965
|
return array.unique(symbols);
|
|
962
966
|
}
|
|
963
967
|
|
|
968
|
+
/**
|
|
969
|
+
* Updates the quote for a single symbol; causing updates to any grouping
|
|
970
|
+
* level that contains the position(s) for the symbol.
|
|
971
|
+
*
|
|
972
|
+
* @public
|
|
973
|
+
* @param {String} symbol
|
|
974
|
+
* @param {Object} quote
|
|
975
|
+
*/
|
|
964
976
|
setPositionQuote(symbol, quote) {
|
|
965
977
|
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
966
978
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
@@ -970,14 +982,34 @@ module.exports = (() => {
|
|
|
970
982
|
}
|
|
971
983
|
}
|
|
972
984
|
|
|
985
|
+
/**
|
|
986
|
+
* Returns all forex symbols that are required to do currency translations.
|
|
987
|
+
*
|
|
988
|
+
* @public
|
|
989
|
+
* @returns {Array.<String>}
|
|
990
|
+
*/
|
|
973
991
|
getForexSymbols() {
|
|
974
992
|
return this._forexSymbols;
|
|
975
993
|
}
|
|
976
994
|
|
|
995
|
+
/**
|
|
996
|
+
* Returns all current forex quotes.
|
|
997
|
+
*
|
|
998
|
+
* @public
|
|
999
|
+
* @returns {Array.<Object>}
|
|
1000
|
+
*/
|
|
977
1001
|
getForexQuotes() {
|
|
978
1002
|
return this._forexQuotes;
|
|
979
1003
|
}
|
|
980
1004
|
|
|
1005
|
+
/**
|
|
1006
|
+
* Updates the forex quote for a single currency pair; causing updates to
|
|
1007
|
+
* any grouping level that contains that requires translation.
|
|
1008
|
+
*
|
|
1009
|
+
* @public
|
|
1010
|
+
* @param {String} symbol
|
|
1011
|
+
* @param {Object} quote
|
|
1012
|
+
*/
|
|
981
1013
|
setForexQuote(symbol, quote) {
|
|
982
1014
|
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
983
1015
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
@@ -995,10 +1027,40 @@ module.exports = (() => {
|
|
|
995
1027
|
Object.keys(this._trees).forEach(key => this._trees[key].walk(group => group.setForexRate(rate), true, false));
|
|
996
1028
|
}
|
|
997
1029
|
|
|
998
|
-
|
|
1030
|
+
/**
|
|
1031
|
+
* Updates fundamental data for a single symbol.
|
|
1032
|
+
*
|
|
1033
|
+
* @public
|
|
1034
|
+
* @param {String} symbol
|
|
1035
|
+
* @param {Object} data
|
|
1036
|
+
*/
|
|
1037
|
+
setPositionFundamentalData(symbol, data) {
|
|
999
1038
|
return;
|
|
1000
1039
|
}
|
|
1001
1040
|
|
|
1041
|
+
/**
|
|
1042
|
+
* Indicates if a news article exists for a symbol.
|
|
1043
|
+
*
|
|
1044
|
+
* @public
|
|
1045
|
+
* @param {String} symbol
|
|
1046
|
+
* @param {Boolean} exists
|
|
1047
|
+
*/
|
|
1048
|
+
setNewsArticleExists(symbol, exists) {
|
|
1049
|
+
assert.argumentIsRequired(symbol, 'symbol', String);
|
|
1050
|
+
assert.argumentIsRequired(exists, 'exists', Boolean);
|
|
1051
|
+
|
|
1052
|
+
if (this._symbols.hasOwnProperty(symbol)) {
|
|
1053
|
+
this._symbols[symbol].forEach(item => item.setNewsArticleExists(exists));
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Returns a single level of grouping from one of the internal trees.
|
|
1059
|
+
*
|
|
1060
|
+
* @param {String} name
|
|
1061
|
+
* @param {Array.<String> keys
|
|
1062
|
+
* @returns {PositionGroup}
|
|
1063
|
+
*/
|
|
1002
1064
|
getGroup(name, keys) {
|
|
1003
1065
|
assert.argumentIsRequired(name, 'name', String);
|
|
1004
1066
|
assert.argumentIsArray(keys, 'keys', Number);
|
|
@@ -1006,6 +1068,14 @@ module.exports = (() => {
|
|
|
1006
1068
|
return findNode(this._trees[name], keys).getValue();
|
|
1007
1069
|
}
|
|
1008
1070
|
|
|
1071
|
+
/**
|
|
1072
|
+
* Returns all child groups from a level of grouping within one of
|
|
1073
|
+
* the internal trees.
|
|
1074
|
+
*
|
|
1075
|
+
* @param {String} name
|
|
1076
|
+
* @param {Array.<String> keys
|
|
1077
|
+
* @returns {Array.<PositionGroup>}
|
|
1078
|
+
*/
|
|
1009
1079
|
getGroups(name, keys) {
|
|
1010
1080
|
assert.argumentIsRequired(name, 'name', String);
|
|
1011
1081
|
assert.argumentIsArray(keys, 'keys', Number);
|
|
@@ -1017,8 +1087,6 @@ module.exports = (() => {
|
|
|
1017
1087
|
assert.argumentIsRequired(name, 'name', String);
|
|
1018
1088
|
assert.argumentIsRequired(executor, 'executor', Function);
|
|
1019
1089
|
|
|
1020
|
-
assert.argumentIsRequired(executor, 'executor', Function);
|
|
1021
|
-
|
|
1022
1090
|
this._trees[name].walk(group => group.setSuspended(true), false, false);
|
|
1023
1091
|
|
|
1024
1092
|
executor(this);
|
|
@@ -1072,7 +1140,17 @@ module.exports = (() => {
|
|
|
1072
1140
|
'use strict';
|
|
1073
1141
|
|
|
1074
1142
|
/**
|
|
1143
|
+
* A grouping of {@link PositionItem} instances. The group aggregates from across
|
|
1144
|
+
* all the positions and performs currency translation, as necessary.
|
|
1145
|
+
*
|
|
1075
1146
|
* @public
|
|
1147
|
+
* @param {PositionContainer} container
|
|
1148
|
+
* @param {PositionGroup|null} parent
|
|
1149
|
+
* @param {Array.<PositionItem>} items
|
|
1150
|
+
* @param {Currency} currency
|
|
1151
|
+
* @param {String} key
|
|
1152
|
+
* @param {String} description
|
|
1153
|
+
* @param {Boolean=} single
|
|
1076
1154
|
*/
|
|
1077
1155
|
class PositionGroup {
|
|
1078
1156
|
constructor(container, parent, items, currency, key, description, single) {
|
|
@@ -1098,8 +1176,15 @@ module.exports = (() => {
|
|
|
1098
1176
|
|
|
1099
1177
|
this._dataFormat.key = this._key;
|
|
1100
1178
|
this._dataFormat.description = this._description;
|
|
1101
|
-
|
|
1179
|
+
this._dataFormat.newsExists = false;
|
|
1102
1180
|
this._dataFormat.quantity = null;
|
|
1181
|
+
this._dataFormat.basisPrice = null;
|
|
1182
|
+
|
|
1183
|
+
this._dataActual.key = this._key;
|
|
1184
|
+
this._dataActual.description = this._description;
|
|
1185
|
+
this._dataActual.newsExists = false;
|
|
1186
|
+
this._dataActual.quantity = null;
|
|
1187
|
+
this._dataActual.basisPrice = null;
|
|
1103
1188
|
|
|
1104
1189
|
if (this._single) {
|
|
1105
1190
|
const item = items[0];
|
|
@@ -1178,35 +1263,85 @@ module.exports = (() => {
|
|
|
1178
1263
|
|
|
1179
1264
|
calculatePriceData(this, this._container.getForexQuotes(), sender, false);
|
|
1180
1265
|
});
|
|
1266
|
+
|
|
1267
|
+
if (this._single) {
|
|
1268
|
+
item.registerNewsExistsChangeHandler((exists, sender) => {
|
|
1269
|
+
this._dataFormat.newsExists = exists;
|
|
1270
|
+
this._dataFormat.newsExists = exists;
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1181
1273
|
});
|
|
1182
1274
|
|
|
1183
1275
|
this.refresh();
|
|
1184
1276
|
}
|
|
1185
1277
|
|
|
1278
|
+
/**
|
|
1279
|
+
* The key of the group.
|
|
1280
|
+
*
|
|
1281
|
+
* @public
|
|
1282
|
+
* @returns {String}
|
|
1283
|
+
*/
|
|
1186
1284
|
get key() {
|
|
1187
1285
|
return this._key;
|
|
1188
1286
|
}
|
|
1189
1287
|
|
|
1288
|
+
/**
|
|
1289
|
+
* The description of the group.
|
|
1290
|
+
*
|
|
1291
|
+
* @public
|
|
1292
|
+
* @returns {String}
|
|
1293
|
+
*/
|
|
1190
1294
|
get description() {
|
|
1191
1295
|
return this._description;
|
|
1192
1296
|
}
|
|
1193
1297
|
|
|
1298
|
+
/**
|
|
1299
|
+
* The {@link Currency} which all aggregated data is presented in.
|
|
1300
|
+
*
|
|
1301
|
+
* @public
|
|
1302
|
+
* @returns {Currency}
|
|
1303
|
+
*/
|
|
1194
1304
|
get currency() {
|
|
1195
1305
|
return this._currency;
|
|
1196
1306
|
}
|
|
1197
1307
|
|
|
1308
|
+
/**
|
|
1309
|
+
* The {@link PositionItem} instances which for which aggregated data is compiled.
|
|
1310
|
+
*
|
|
1311
|
+
* @public
|
|
1312
|
+
* @returns {Currency}
|
|
1313
|
+
*/
|
|
1198
1314
|
get items() {
|
|
1199
1315
|
return this._items;
|
|
1200
1316
|
}
|
|
1201
1317
|
|
|
1318
|
+
/**
|
|
1319
|
+
* The string-based, human-readable aggregated data for the group.
|
|
1320
|
+
*
|
|
1321
|
+
* @public
|
|
1322
|
+
* @returns {Object}
|
|
1323
|
+
*/
|
|
1202
1324
|
get data() {
|
|
1203
1325
|
return this._dataFormat;
|
|
1204
1326
|
}
|
|
1205
1327
|
|
|
1328
|
+
/**
|
|
1329
|
+
* The raw aggregated data for the group (typically {@link Decimal} instances).
|
|
1330
|
+
*
|
|
1331
|
+
* @public
|
|
1332
|
+
* @returns {Object}
|
|
1333
|
+
*/
|
|
1206
1334
|
get actual() {
|
|
1207
1335
|
return this._dataActual;
|
|
1208
1336
|
}
|
|
1209
1337
|
|
|
1338
|
+
/**
|
|
1339
|
+
* Indicates if the group will only contain one {@link PositionItem} -- that is,
|
|
1340
|
+
* indicates if the group represents a single position.
|
|
1341
|
+
*
|
|
1342
|
+
* @public
|
|
1343
|
+
* @returns {Boolean}
|
|
1344
|
+
*/
|
|
1210
1345
|
get single() {
|
|
1211
1346
|
return this._single;
|
|
1212
1347
|
}
|
|
@@ -1215,10 +1350,22 @@ module.exports = (() => {
|
|
|
1215
1350
|
return this._suspended;
|
|
1216
1351
|
}
|
|
1217
1352
|
|
|
1353
|
+
/**
|
|
1354
|
+
* Indicates if the group should be excluded from higher-level aggregations.
|
|
1355
|
+
*
|
|
1356
|
+
* @public
|
|
1357
|
+
* @returns {Boolean}
|
|
1358
|
+
*/
|
|
1218
1359
|
get excluded() {
|
|
1219
1360
|
return this._excluded;
|
|
1220
1361
|
}
|
|
1221
1362
|
|
|
1363
|
+
/**
|
|
1364
|
+
* Causes aggregated data to be recalculated using a new exchange rate.
|
|
1365
|
+
*
|
|
1366
|
+
* @public
|
|
1367
|
+
* @param {Rate} rate
|
|
1368
|
+
*/
|
|
1222
1369
|
setForexRate(rate) {
|
|
1223
1370
|
if (!this._bypassCurrencyTranslation) {
|
|
1224
1371
|
this.refresh();
|
|
@@ -1247,6 +1394,11 @@ module.exports = (() => {
|
|
|
1247
1394
|
}
|
|
1248
1395
|
}
|
|
1249
1396
|
|
|
1397
|
+
/**
|
|
1398
|
+
* Causes all aggregated data to be recalculated.
|
|
1399
|
+
*
|
|
1400
|
+
* @public
|
|
1401
|
+
*/
|
|
1250
1402
|
refresh() {
|
|
1251
1403
|
const rates = this._container.getForexQuotes();
|
|
1252
1404
|
|
|
@@ -1254,6 +1406,12 @@ module.exports = (() => {
|
|
|
1254
1406
|
calculatePriceData(this, rates, null, true);
|
|
1255
1407
|
}
|
|
1256
1408
|
|
|
1409
|
+
/**
|
|
1410
|
+
* Causes the percent of the position, with respect to the parent container's
|
|
1411
|
+
* total, to be recalculated.
|
|
1412
|
+
*
|
|
1413
|
+
* @public
|
|
1414
|
+
*/
|
|
1257
1415
|
refreshMarketPercent() {
|
|
1258
1416
|
calculateMarketPercent(this, this._container.getForexQuotes(), true);
|
|
1259
1417
|
}
|
|
@@ -1307,7 +1465,7 @@ module.exports = (() => {
|
|
|
1307
1465
|
|
|
1308
1466
|
const items = group._items;
|
|
1309
1467
|
|
|
1310
|
-
group._bypassCurrencyTranslation = items.
|
|
1468
|
+
group._bypassCurrencyTranslation = items.every(item => item.currency === currency);
|
|
1311
1469
|
|
|
1312
1470
|
const translate = (item, value) => {
|
|
1313
1471
|
let translated;
|
|
@@ -1359,8 +1517,11 @@ module.exports = (() => {
|
|
|
1359
1517
|
if (group.single) {
|
|
1360
1518
|
const item = group._items[0];
|
|
1361
1519
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1520
|
+
actual.quantity = item.position.snapshot.open;
|
|
1521
|
+
actual.basisPrice = item.data.basisPrice;
|
|
1522
|
+
|
|
1523
|
+
format.quantity = formatDecimal(actual.quantity, 2);
|
|
1524
|
+
format.basisPrice = formatCurrency(actual.basisPrice, currency);
|
|
1364
1525
|
}
|
|
1365
1526
|
}
|
|
1366
1527
|
|
|
@@ -1534,7 +1695,15 @@ module.exports = (() => {
|
|
|
1534
1695
|
'use strict';
|
|
1535
1696
|
|
|
1536
1697
|
/**
|
|
1698
|
+
* A container for a single position, which handles quote changes and
|
|
1699
|
+
* notifies observers -- which are typically parent-level {@link PositionGroup}
|
|
1700
|
+
* instances.
|
|
1701
|
+
*
|
|
1537
1702
|
* @public
|
|
1703
|
+
* @param {Object} portfolio
|
|
1704
|
+
* @param {Object} position
|
|
1705
|
+
* @param {Object} currentSummary
|
|
1706
|
+
* @param {Array.<Object>} previousSummaries
|
|
1538
1707
|
*/
|
|
1539
1708
|
class PositionItem {
|
|
1540
1709
|
constructor(portfolio, position, currentSummary, previousSummaries) {
|
|
@@ -1550,10 +1719,12 @@ module.exports = (() => {
|
|
|
1550
1719
|
this._data.basis = null;
|
|
1551
1720
|
|
|
1552
1721
|
this._currentQuote = null;
|
|
1553
|
-
|
|
1722
|
+
|
|
1723
|
+
this._currentPrice = null;
|
|
1724
|
+
this._previousPrice = null;
|
|
1554
1725
|
|
|
1555
1726
|
this._data.currentPrice = null;
|
|
1556
|
-
this._data.
|
|
1727
|
+
this._data.currentPricePrevious = null;
|
|
1557
1728
|
|
|
1558
1729
|
this._data.market = null;
|
|
1559
1730
|
this._data.marketChange = null;
|
|
@@ -1573,6 +1744,8 @@ module.exports = (() => {
|
|
|
1573
1744
|
this._data.income = null;
|
|
1574
1745
|
this._data.basisPrice = null;
|
|
1575
1746
|
|
|
1747
|
+
this._data.newsExists = false;
|
|
1748
|
+
|
|
1576
1749
|
this._excluded = false;
|
|
1577
1750
|
|
|
1578
1751
|
calculateStaticData(this);
|
|
@@ -1580,32 +1753,75 @@ module.exports = (() => {
|
|
|
1580
1753
|
|
|
1581
1754
|
this._quoteChangedEvent = new Event(this);
|
|
1582
1755
|
this._excludedChangeEvent = new Event(this);
|
|
1756
|
+
this._newsExistsChangedEvent = new Event(this);
|
|
1583
1757
|
}
|
|
1584
1758
|
|
|
1759
|
+
/**
|
|
1760
|
+
* The portfolio of the encapsulated position.
|
|
1761
|
+
*
|
|
1762
|
+
* @public
|
|
1763
|
+
* @returns {Object}
|
|
1764
|
+
*/
|
|
1585
1765
|
get portfolio() {
|
|
1586
1766
|
return this._portfolio;
|
|
1587
1767
|
}
|
|
1588
1768
|
|
|
1769
|
+
/**
|
|
1770
|
+
* The encapsulated position.
|
|
1771
|
+
*
|
|
1772
|
+
* @public
|
|
1773
|
+
* @returns {Object}
|
|
1774
|
+
*/
|
|
1589
1775
|
get position() {
|
|
1590
1776
|
return this._position;
|
|
1591
1777
|
}
|
|
1592
1778
|
|
|
1779
|
+
/**
|
|
1780
|
+
* The {@link Currency} of the encapsulated position.
|
|
1781
|
+
*
|
|
1782
|
+
* @public
|
|
1783
|
+
* @returns {Object}
|
|
1784
|
+
*/
|
|
1593
1785
|
get currency() {
|
|
1594
1786
|
return this._currency;
|
|
1595
1787
|
}
|
|
1596
1788
|
|
|
1789
|
+
/**
|
|
1790
|
+
* The year-to-date position summary of the encapsulated position.
|
|
1791
|
+
*
|
|
1792
|
+
* @public
|
|
1793
|
+
* @returns {Object}
|
|
1794
|
+
*/
|
|
1597
1795
|
get currentSummary() {
|
|
1598
1796
|
return this._currentSummary;
|
|
1599
1797
|
}
|
|
1600
|
-
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* Previous year's summaries for the encapsulated position.
|
|
1801
|
+
*
|
|
1802
|
+
* @public
|
|
1803
|
+
* @returns {Object}
|
|
1804
|
+
*/
|
|
1601
1805
|
get previousSummaries() {
|
|
1602
1806
|
return this._previousSummaries;
|
|
1603
1807
|
}
|
|
1604
1808
|
|
|
1809
|
+
/**
|
|
1810
|
+
* Various data regarding the encapsulated position.
|
|
1811
|
+
*
|
|
1812
|
+
* @public
|
|
1813
|
+
* @returns {*}
|
|
1814
|
+
*/
|
|
1605
1815
|
get data() {
|
|
1606
1816
|
return this._data;
|
|
1607
1817
|
}
|
|
1608
1818
|
|
|
1819
|
+
/**
|
|
1820
|
+
* The current quote for the symbol of the encapsulated position.
|
|
1821
|
+
*
|
|
1822
|
+
* @public
|
|
1823
|
+
* @returns {null|{Object}}
|
|
1824
|
+
*/
|
|
1609
1825
|
get quote() {
|
|
1610
1826
|
return this._currentQuote;
|
|
1611
1827
|
}
|
|
@@ -1614,13 +1830,22 @@ module.exports = (() => {
|
|
|
1614
1830
|
return this._excluded;
|
|
1615
1831
|
}
|
|
1616
1832
|
|
|
1833
|
+
/**
|
|
1834
|
+
* Sets the current quote -- causing position-level data (e.g. market value) to
|
|
1835
|
+
* be recalculated.
|
|
1836
|
+
*
|
|
1837
|
+
* @public
|
|
1838
|
+
* @param {Object} quote
|
|
1839
|
+
*/
|
|
1617
1840
|
setQuote(quote) {
|
|
1618
1841
|
assert.argumentIsRequired(quote, 'quote', Object);
|
|
1619
1842
|
|
|
1620
|
-
if (this.
|
|
1843
|
+
if (this._currentPricePrevious !== quote.lastPrice) {
|
|
1621
1844
|
calculatePriceData(this, quote.lastPrice);
|
|
1622
1845
|
|
|
1623
|
-
this.
|
|
1846
|
+
this._currentPricePrevious = this._currentPrice;
|
|
1847
|
+
this._currentPrice = quote.lastPrice;
|
|
1848
|
+
|
|
1624
1849
|
this._currentQuote = quote;
|
|
1625
1850
|
|
|
1626
1851
|
this._quoteChangedEvent.fire(this._currentQuote);
|
|
@@ -1635,6 +1860,28 @@ module.exports = (() => {
|
|
|
1635
1860
|
}
|
|
1636
1861
|
}
|
|
1637
1862
|
|
|
1863
|
+
/**
|
|
1864
|
+
* Sets a flag which indicates if news article(s) exist for the encapsulated position's
|
|
1865
|
+
* symbol.
|
|
1866
|
+
*
|
|
1867
|
+
* @public
|
|
1868
|
+
* @param {Boolean} value
|
|
1869
|
+
*/
|
|
1870
|
+
setNewsArticleExists(value) {
|
|
1871
|
+
assert.argumentIsRequired(value, 'value', Boolean);
|
|
1872
|
+
|
|
1873
|
+
if (this._data.newsExists !== value) {
|
|
1874
|
+
this._newsExistsChangedEvent.fire(this._data.newsExists = value);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
/**
|
|
1879
|
+
* Registers an observer for quote changes, which is fired after internal recalculations
|
|
1880
|
+
* of position data are complete.
|
|
1881
|
+
*
|
|
1882
|
+
* @public
|
|
1883
|
+
* @param {Function} handler
|
|
1884
|
+
*/
|
|
1638
1885
|
registerQuoteChangeHandler(handler) {
|
|
1639
1886
|
this._quoteChangedEvent.register(handler);
|
|
1640
1887
|
}
|
|
@@ -1643,6 +1890,16 @@ module.exports = (() => {
|
|
|
1643
1890
|
this._excludedChangeEvent.register(handler);
|
|
1644
1891
|
}
|
|
1645
1892
|
|
|
1893
|
+
/**
|
|
1894
|
+
* Registers an observer changes to the status of news existence.
|
|
1895
|
+
*
|
|
1896
|
+
* @public
|
|
1897
|
+
* @param {Function} handler
|
|
1898
|
+
*/
|
|
1899
|
+
registerNewsExistsChangeHandler(handler) {
|
|
1900
|
+
this._newsExistsChangedEvent.register(handler);
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1646
1903
|
toString() {
|
|
1647
1904
|
return '[PositionItem]';
|
|
1648
1905
|
}
|