@barchart/portfolio-api-common 1.0.119 → 1.0.123

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.
@@ -3,13 +3,14 @@ const array = require('@barchart/common-js/lang/array'),
3
3
  ComparatorBuilder = require('@barchart/common-js/collections/sorting/ComparatorBuilder'),
4
4
  comparators = require('@barchart/common-js/collections/sorting/comparators'),
5
5
  Currency = require('@barchart/common-js/lang/Currency'),
6
+ Decimal = require('@barchart/common-js/lang/Decimal'),
6
7
  is = require('@barchart/common-js/lang/is'),
8
+ Rate = require('@barchart/common-js/lang/Rate'),
7
9
  Tree = require('@barchart/common-js/collections/Tree');
8
10
 
9
11
  const PositionSummaryFrame = require('./../data/PositionSummaryFrame');
10
12
 
11
- const PositionLevelDefinition = require('./definitions/PositionLevelDefinition'),
12
- PositionTreeDefinition = require('./definitions/PositionTreeDefinition');
13
+ const PositionTreeDefinition = require('./definitions/PositionTreeDefinition');
13
14
 
14
15
  const PositionGroup = require('./PositionGroup'),
15
16
  PositionItem = require('./PositionItem');
@@ -17,6 +18,8 @@ const PositionGroup = require('./PositionGroup'),
17
18
  module.exports = (() => {
18
19
  'use strict';
19
20
 
21
+ const DEFAULT_CURRENCY = Currency.CAD;
22
+
20
23
  /**
21
24
  * A container for positions which groups the positions into one or more
22
25
  * trees for aggregation and display purposes. For example, perhaps a positions
@@ -37,7 +40,7 @@ module.exports = (() => {
37
40
  assert.argumentIsArray(portfolios, 'portfolios');
38
41
  assert.argumentIsArray(positions, 'positions');
39
42
  assert.argumentIsArray(summaries, 'summaries');
40
-
43
+
41
44
  const previousSummaryFrame = PositionSummaryFrame.YEARLY;
42
45
  const previousSummaryRanges = previousSummaryFrame.getRecentRanges(0);
43
46
 
@@ -112,18 +115,29 @@ module.exports = (() => {
112
115
 
113
116
  if (position.instrument && position.instrument.currency) {
114
117
  const currency = position.instrument.currency;
118
+ const code = currency.code;
115
119
 
116
- if (!map.hasOwnProperty(currency)) {
117
- map[currency] = [ ];
120
+ if (!map.hasOwnProperty(code)) {
121
+ map[code] = [ ];
118
122
  }
119
123
 
120
- map[currency].push(item);
124
+ map[code].push(item);
121
125
  }
122
126
 
123
127
  return map;
124
128
  }, { });
125
129
 
126
- this._forex = { };
130
+ this._forexSymbols = Object.keys(this._currencies).reduce((symbols, code) => {
131
+ if (code !== DEFAULT_CURRENCY.code) {
132
+ symbols.push(`^${DEFAULT_CURRENCY.code}${code}`);
133
+ }
134
+
135
+ return symbols;
136
+ }, [ ]);
137
+
138
+ this._forexQuotes = this._forexSymbols.map((symbol) => {
139
+ return Rate.fromPair(Decimal.ONE, symbol);
140
+ });
127
141
 
128
142
  this._trees = definitions.reduce((map, treeDefinition) => {
129
143
  const tree = new Tree();
@@ -225,22 +239,26 @@ module.exports = (() => {
225
239
  }
226
240
 
227
241
  getForexSymbols() {
228
- const codes = Object.keys(this._currencies);
229
-
230
- return codes.reduce((symbols, code) => {
231
- if (code !== this._defaultCurrency) {
232
- symbols.push(`^${this._defaultCurrency}${code}`);
233
- }
242
+ return this._forexSymbols;
243
+ }
234
244
 
235
- return symbols;
236
- }, [ ]);
245
+ getForexQuotes() {
246
+ return this._forexQuotes;
237
247
  }
238
248
 
239
249
  setForexQuote(symbol, quote) {
240
250
  assert.argumentIsRequired(symbol, 'symbol', String);
241
251
  assert.argumentIsRequired(quote, 'quote', Object);
242
252
 
243
- this._forex[symbol] = quote;
253
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
254
+
255
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
256
+
257
+ if (index < 0) {
258
+ this._forexQuotes.push(rate);
259
+ } else {
260
+ this._forexQuotes[index] = rate;
261
+ }
244
262
  }
245
263
 
246
264
  getGroup(name, keys) {
@@ -3,7 +3,8 @@ const assert = require('@barchart/common-js/lang/assert'),
3
3
  Decimal = require('@barchart/common-js/lang/Decimal'),
4
4
  Event = require('@barchart/common-js/messaging/Event'),
5
5
  formatter = require('@barchart/common-js/lang/formatter'),
6
- is = require('@barchart/common-js/lang/is');
6
+ is = require('@barchart/common-js/lang/is'),
7
+ Rate = require('@barchart/common-js/lang/Rate');
7
8
 
8
9
  module.exports = (() => {
9
10
  'use strict';
@@ -38,8 +39,14 @@ module.exports = (() => {
38
39
  this._dataFormat.quantity = null;
39
40
 
40
41
  if (this._single) {
41
- this._dataFormat.instrument = items[0].position.instrument;
42
+ const item = items[0];
43
+
44
+ this._dataFormat.portfolio = item.portfolio.portfolio;
45
+ this._dataFormat.position = item.position.position;
46
+ this._dataFormat.instrument = item.position.instrument;
42
47
  } else {
48
+ this._dataFormat.portfolio = null;
49
+ this._dataFormat.position = null;
43
50
  this._dataFormat.instrument = null;
44
51
  }
45
52
 
@@ -90,7 +97,7 @@ module.exports = (() => {
90
97
  if (this._single) {
91
98
  const precision = sender.position.instrument.currency.precision;
92
99
 
93
- this._dataActual.currentPrice = sender.data.currentPrice;
100
+ this._dataActual.currentPrice = quote.lastPrice;
94
101
  this._dataFormat.currentPrice = formatNumber(this._dataActual.currentPrice, precision);
95
102
 
96
103
  this._dataFormat.quoteLast = formatNumber(quote.previousPrice, precision);
@@ -106,7 +113,7 @@ module.exports = (() => {
106
113
  this._dataFormat.currentPrice = null;
107
114
  }
108
115
 
109
- calculatePriceData(this, sender, false);
116
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
110
117
  });
111
118
  });
112
119
 
@@ -149,6 +156,10 @@ module.exports = (() => {
149
156
  return this._excluded;
150
157
  }
151
158
 
159
+ setForexQuote(quote) {
160
+
161
+ }
162
+
152
163
  setExcluded(value) {
153
164
  assert.argumentIsRequired(value, 'value', Boolean);
154
165
 
@@ -172,12 +183,14 @@ module.exports = (() => {
172
183
  }
173
184
 
174
185
  refresh() {
175
- calculateStaticData(this);
176
- calculatePriceData(this, null, true);
186
+ const rates = this._container.getForexQuotes();
187
+
188
+ calculateStaticData(this, rates);
189
+ calculatePriceData(this, rates, null, true);
177
190
  }
178
191
 
179
192
  refreshMarketPercent() {
180
- calculateMarketPercent(this, true);
193
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
181
194
  }
182
195
 
183
196
  registerMarketPercentChangeHandler(handler) {
@@ -217,7 +230,7 @@ module.exports = (() => {
217
230
  return formatDecimal(decimal, currency.precision);
218
231
  }
219
232
 
220
- function calculateStaticData(group) {
233
+ function calculateStaticData(group, rates) {
221
234
  if (group.suspended) {
222
235
  return;
223
236
  }
@@ -229,13 +242,25 @@ module.exports = (() => {
229
242
 
230
243
  const items = group._items;
231
244
 
245
+ const translate = (item, value) => {
246
+ let translated;
247
+
248
+ if (item.currency !== currency) {
249
+ translated = Rate.convert(value, item.currency, currency, ...rates);
250
+ } else {
251
+ translated = value;
252
+ }
253
+
254
+ return translated;
255
+ };
256
+
232
257
  let updates = items.reduce((updates, item) => {
233
- updates.basis = updates.basis.add(item.data.basis);
234
- updates.realized = updates.realized.add(item.data.realized);
235
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
236
- updates.income = updates.income.add(item.data.income);
237
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
238
- updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
258
+ updates.basis = updates.basis.add(translate(item, item.data.basis));
259
+ updates.realized = updates.realized.add(translate(item, item.data.realized));
260
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
261
+ updates.income = updates.income.add(translate(item, item.data.income));
262
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
263
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
239
264
 
240
265
  return updates;
241
266
  }, {
@@ -272,7 +297,7 @@ module.exports = (() => {
272
297
  }
273
298
  }
274
299
 
275
- function calculatePriceData(group, item, forceRefresh) {
300
+ function calculatePriceData(group, rates, item, forceRefresh) {
276
301
  if (group.suspended) {
277
302
  return;
278
303
  }
@@ -284,6 +309,18 @@ module.exports = (() => {
284
309
 
285
310
  const currency = group.currency;
286
311
 
312
+ const translate = (item, value) => {
313
+ let translated;
314
+
315
+ if (item.currency !== currency) {
316
+ translated = Rate.convert(value, item.currency, currency, ...rates);
317
+ } else {
318
+ translated = value;
319
+ }
320
+
321
+ return translated;
322
+ };
323
+
287
324
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
288
325
 
289
326
  let updates;
@@ -292,10 +329,10 @@ module.exports = (() => {
292
329
  const items = group._items;
293
330
 
294
331
  updates = items.reduce((updates, item) => {
295
- updates.market = updates.market.add(item.data.market);
296
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
297
- updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
298
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
332
+ updates.market = updates.market.add(translate(item, item.data.market));
333
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
334
+ updates.unrealizedToday = updates.unrealizedToday.add(translate(item, item.data.unrealizedToday));
335
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
299
336
 
300
337
  return updates;
301
338
  }, {
@@ -308,11 +345,11 @@ module.exports = (() => {
308
345
  });
309
346
  } else {
310
347
  updates = {
311
- market: actual.market.add(item.data.marketChange),
348
+ market: actual.market.add(translate(item, item.data.marketChange)),
312
349
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
313
- unrealized: actual.unrealized.add(item.data.unrealizedChange),
314
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
315
- summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
350
+ unrealized: actual.unrealized.add(translate(item, item.data.unrealizedChange)),
351
+ unrealizedToday: actual.unrealizedToday.add(translate(item, item.data.unrealizedTodayChange)),
352
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrentChange))
316
353
  };
317
354
  }
318
355
 
@@ -353,11 +390,11 @@ module.exports = (() => {
353
390
  format.total = formatCurrency(actual.total, currency);
354
391
  format.totalNegative = actual.total.getIsNegative();
355
392
 
356
- calculateMarketPercent(group, false);
393
+ calculateMarketPercent(group, rates, false);
357
394
  calculateUnrealizedPercent(group);
358
395
  }
359
396
 
360
- function calculateMarketPercent(group, silent) {
397
+ function calculateMarketPercent(group, rates, silent) {
361
398
  if (group.suspended) {
362
399
  return;
363
400
  }
@@ -373,7 +410,15 @@ module.exports = (() => {
373
410
  const parentData = parent._dataActual;
374
411
 
375
412
  if (parentData.market !== null && !parentData.market.getIsZero()) {
376
- marketPercent = actual.market.divide(parentData.market);
413
+ let numerator;
414
+
415
+ if (group.currency !== parent.currency) {
416
+ numerator = Rate.convert(actual.market, group.currency, parent.currency, ...rates);
417
+ } else {
418
+ numerator = actual.market;
419
+ }
420
+
421
+ marketPercent = numerator.divide(parentData.market);
377
422
  } else {
378
423
  marketPercent = null;
379
424
  }
@@ -1,5 +1,6 @@
1
1
  const array = require('@barchart/common-js/lang/array'),
2
2
  assert = require('@barchart/common-js/lang/assert'),
3
+ Currency = require('@barchart/common-js/lang/Currency'),
3
4
  Decimal = require('@barchart/common-js/lang/Decimal'),
4
5
  Event = require('@barchart/common-js/messaging/Event'),
5
6
  is = require('@barchart/common-js/lang/is');
@@ -16,6 +17,7 @@ module.exports = (() => {
16
17
  constructor(portfolio, position, currentSummary, previousSummaries) {
17
18
  this._portfolio = portfolio;
18
19
  this._position = position;
20
+ this._currency = position.instrument.currency || Currency.CAD;
19
21
 
20
22
  this._currentSummary = currentSummary || null;
21
23
  this._previousSummaries = previousSummaries || [ ];
@@ -65,6 +67,10 @@ module.exports = (() => {
65
67
  return this._position;
66
68
  }
67
69
 
70
+ get currency() {
71
+ return this._currency;
72
+ }
73
+
68
74
  get currentSummary() {
69
75
  return this._currentSummary;
70
76
  }
@@ -94,9 +100,6 @@ module.exports = (() => {
94
100
  this._previousQuote = this._currentQuote;
95
101
  this._currentQuote = quote;
96
102
 
97
- this._data.previousPrice = this._data.currentPrice;
98
- this._data.currentPrice = quote.lastPrice;
99
-
100
103
  this._quoteChangedEvent.fire(this._currentQuote);
101
104
  }
102
105
  }
@@ -105,7 +108,7 @@ module.exports = (() => {
105
108
  assert.argumentIsRequired(value, 'value', Boolean);
106
109
 
107
110
  if (this._excluded !== value) {
108
- this._excludedChangeEvent.fire(this, this._excluded = value);
111
+ this._excludedChangeEvent.fire(this._excluded = value);
109
112
  }
110
113
  }
111
114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.119",
3
+ "version": "1.0.123",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -116,7 +116,7 @@ module.exports = (() => {
116
116
  return InstrumentType;
117
117
  })();
118
118
 
119
- },{"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/assert":18}],2:[function(require,module,exports){
119
+ },{"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/assert":19}],2:[function(require,module,exports){
120
120
  const array = require('@barchart/common-js/lang/array'),
121
121
  assert = require('@barchart/common-js/lang/assert'),
122
122
  Day = require('@barchart/common-js/lang/Day'),
@@ -373,7 +373,7 @@ module.exports = (() => {
373
373
  return PositionSummaryFrame;
374
374
  })();
375
375
 
376
- },{"@barchart/common-js/lang/Day":13,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/array":17,"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20}],3:[function(require,module,exports){
376
+ },{"@barchart/common-js/lang/Day":13,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/array":18,"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21}],3:[function(require,module,exports){
377
377
  const assert = require('@barchart/common-js/lang/assert'),
378
378
  Enum = require('@barchart/common-js/lang/Enum');
379
379
 
@@ -713,19 +713,20 @@ module.exports = (() => {
713
713
  return TransactionType;
714
714
  })();
715
715
 
716
- },{"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/assert":18}],4:[function(require,module,exports){
716
+ },{"@barchart/common-js/lang/Enum":16,"@barchart/common-js/lang/assert":19}],4:[function(require,module,exports){
717
717
  const array = require('@barchart/common-js/lang/array'),
718
718
  assert = require('@barchart/common-js/lang/assert'),
719
719
  ComparatorBuilder = require('@barchart/common-js/collections/sorting/ComparatorBuilder'),
720
720
  comparators = require('@barchart/common-js/collections/sorting/comparators'),
721
721
  Currency = require('@barchart/common-js/lang/Currency'),
722
+ Decimal = require('@barchart/common-js/lang/Decimal'),
722
723
  is = require('@barchart/common-js/lang/is'),
724
+ Rate = require('@barchart/common-js/lang/Rate'),
723
725
  Tree = require('@barchart/common-js/collections/Tree');
724
726
 
725
727
  const PositionSummaryFrame = require('./../data/PositionSummaryFrame');
726
728
 
727
- const PositionLevelDefinition = require('./definitions/PositionLevelDefinition'),
728
- PositionTreeDefinition = require('./definitions/PositionTreeDefinition');
729
+ const PositionTreeDefinition = require('./definitions/PositionTreeDefinition');
729
730
 
730
731
  const PositionGroup = require('./PositionGroup'),
731
732
  PositionItem = require('./PositionItem');
@@ -733,6 +734,8 @@ const PositionGroup = require('./PositionGroup'),
733
734
  module.exports = (() => {
734
735
  'use strict';
735
736
 
737
+ const DEFAULT_CURRENCY = Currency.CAD;
738
+
736
739
  /**
737
740
  * A container for positions which groups the positions into one or more
738
741
  * trees for aggregation and display purposes. For example, perhaps a positions
@@ -753,7 +756,7 @@ module.exports = (() => {
753
756
  assert.argumentIsArray(portfolios, 'portfolios');
754
757
  assert.argumentIsArray(positions, 'positions');
755
758
  assert.argumentIsArray(summaries, 'summaries');
756
-
759
+
757
760
  const previousSummaryFrame = PositionSummaryFrame.YEARLY;
758
761
  const previousSummaryRanges = previousSummaryFrame.getRecentRanges(0);
759
762
 
@@ -828,18 +831,29 @@ module.exports = (() => {
828
831
 
829
832
  if (position.instrument && position.instrument.currency) {
830
833
  const currency = position.instrument.currency;
834
+ const code = currency.code;
831
835
 
832
- if (!map.hasOwnProperty(currency)) {
833
- map[currency] = [ ];
836
+ if (!map.hasOwnProperty(code)) {
837
+ map[code] = [ ];
834
838
  }
835
839
 
836
- map[currency].push(item);
840
+ map[code].push(item);
837
841
  }
838
842
 
839
843
  return map;
840
844
  }, { });
841
845
 
842
- this._forex = { };
846
+ this._forexSymbols = Object.keys(this._currencies).reduce((symbols, code) => {
847
+ if (code !== DEFAULT_CURRENCY.code) {
848
+ symbols.push(`^${DEFAULT_CURRENCY.code}${code}`);
849
+ }
850
+
851
+ return symbols;
852
+ }, [ ]);
853
+
854
+ this._forexQuotes = this._forexSymbols.map((symbol) => {
855
+ return Rate.fromPair(Decimal.ONE, symbol);
856
+ });
843
857
 
844
858
  this._trees = definitions.reduce((map, treeDefinition) => {
845
859
  const tree = new Tree();
@@ -941,22 +955,26 @@ module.exports = (() => {
941
955
  }
942
956
 
943
957
  getForexSymbols() {
944
- const codes = Object.keys(this._currencies);
945
-
946
- return codes.reduce((symbols, code) => {
947
- if (code !== this._defaultCurrency) {
948
- symbols.push(`^${this._defaultCurrency}${code}`);
949
- }
958
+ return this._forexSymbols;
959
+ }
950
960
 
951
- return symbols;
952
- }, [ ]);
961
+ getForexQuotes() {
962
+ return this._forexQuotes;
953
963
  }
954
964
 
955
965
  setForexQuote(symbol, quote) {
956
966
  assert.argumentIsRequired(symbol, 'symbol', String);
957
967
  assert.argumentIsRequired(quote, 'quote', Object);
958
968
 
959
- this._forex[symbol] = quote;
969
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
970
+
971
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
972
+
973
+ if (index < 0) {
974
+ this._forexQuotes.push(rate);
975
+ } else {
976
+ this._forexQuotes[index] = rate;
977
+ }
960
978
  }
961
979
 
962
980
  getGroup(name, keys) {
@@ -1002,13 +1020,14 @@ module.exports = (() => {
1002
1020
  return PositionContainer;
1003
1021
  })();
1004
1022
 
1005
- },{"./../data/PositionSummaryFrame":2,"./PositionGroup":5,"./PositionItem":6,"./definitions/PositionLevelDefinition":7,"./definitions/PositionTreeDefinition":8,"@barchart/common-js/collections/Tree":9,"@barchart/common-js/collections/sorting/ComparatorBuilder":10,"@barchart/common-js/collections/sorting/comparators":11,"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/array":17,"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20}],5:[function(require,module,exports){
1023
+ },{"./../data/PositionSummaryFrame":2,"./PositionGroup":5,"./PositionItem":6,"./definitions/PositionTreeDefinition":8,"@barchart/common-js/collections/Tree":9,"@barchart/common-js/collections/sorting/ComparatorBuilder":10,"@barchart/common-js/collections/sorting/comparators":11,"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/Rate":17,"@barchart/common-js/lang/array":18,"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21}],5:[function(require,module,exports){
1006
1024
  const assert = require('@barchart/common-js/lang/assert'),
1007
1025
  Currency = require('@barchart/common-js/lang/Currency'),
1008
1026
  Decimal = require('@barchart/common-js/lang/Decimal'),
1009
1027
  Event = require('@barchart/common-js/messaging/Event'),
1010
1028
  formatter = require('@barchart/common-js/lang/formatter'),
1011
- is = require('@barchart/common-js/lang/is');
1029
+ is = require('@barchart/common-js/lang/is'),
1030
+ Rate = require('@barchart/common-js/lang/Rate');
1012
1031
 
1013
1032
  module.exports = (() => {
1014
1033
  'use strict';
@@ -1043,8 +1062,14 @@ module.exports = (() => {
1043
1062
  this._dataFormat.quantity = null;
1044
1063
 
1045
1064
  if (this._single) {
1046
- this._dataFormat.instrument = items[0].position.instrument;
1065
+ const item = items[0];
1066
+
1067
+ this._dataFormat.portfolio = item.portfolio.portfolio;
1068
+ this._dataFormat.position = item.position.position;
1069
+ this._dataFormat.instrument = item.position.instrument;
1047
1070
  } else {
1071
+ this._dataFormat.portfolio = null;
1072
+ this._dataFormat.position = null;
1048
1073
  this._dataFormat.instrument = null;
1049
1074
  }
1050
1075
 
@@ -1095,7 +1120,7 @@ module.exports = (() => {
1095
1120
  if (this._single) {
1096
1121
  const precision = sender.position.instrument.currency.precision;
1097
1122
 
1098
- this._dataActual.currentPrice = sender.data.currentPrice;
1123
+ this._dataActual.currentPrice = quote.lastPrice;
1099
1124
  this._dataFormat.currentPrice = formatNumber(this._dataActual.currentPrice, precision);
1100
1125
 
1101
1126
  this._dataFormat.quoteLast = formatNumber(quote.previousPrice, precision);
@@ -1111,7 +1136,7 @@ module.exports = (() => {
1111
1136
  this._dataFormat.currentPrice = null;
1112
1137
  }
1113
1138
 
1114
- calculatePriceData(this, sender, false);
1139
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
1115
1140
  });
1116
1141
  });
1117
1142
 
@@ -1154,6 +1179,10 @@ module.exports = (() => {
1154
1179
  return this._excluded;
1155
1180
  }
1156
1181
 
1182
+ setForexQuote(quote) {
1183
+
1184
+ }
1185
+
1157
1186
  setExcluded(value) {
1158
1187
  assert.argumentIsRequired(value, 'value', Boolean);
1159
1188
 
@@ -1177,12 +1206,14 @@ module.exports = (() => {
1177
1206
  }
1178
1207
 
1179
1208
  refresh() {
1180
- calculateStaticData(this);
1181
- calculatePriceData(this, null, true);
1209
+ const rates = this._container.getForexQuotes();
1210
+
1211
+ calculateStaticData(this, rates);
1212
+ calculatePriceData(this, rates, null, true);
1182
1213
  }
1183
1214
 
1184
1215
  refreshMarketPercent() {
1185
- calculateMarketPercent(this, true);
1216
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
1186
1217
  }
1187
1218
 
1188
1219
  registerMarketPercentChangeHandler(handler) {
@@ -1222,7 +1253,7 @@ module.exports = (() => {
1222
1253
  return formatDecimal(decimal, currency.precision);
1223
1254
  }
1224
1255
 
1225
- function calculateStaticData(group) {
1256
+ function calculateStaticData(group, rates) {
1226
1257
  if (group.suspended) {
1227
1258
  return;
1228
1259
  }
@@ -1234,13 +1265,25 @@ module.exports = (() => {
1234
1265
 
1235
1266
  const items = group._items;
1236
1267
 
1268
+ const translate = (item, value) => {
1269
+ let translated;
1270
+
1271
+ if (item.currency !== currency) {
1272
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1273
+ } else {
1274
+ translated = value;
1275
+ }
1276
+
1277
+ return translated;
1278
+ };
1279
+
1237
1280
  let updates = items.reduce((updates, item) => {
1238
- updates.basis = updates.basis.add(item.data.basis);
1239
- updates.realized = updates.realized.add(item.data.realized);
1240
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
1241
- updates.income = updates.income.add(item.data.income);
1242
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1243
- updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(item.data.summaryTotalPrevious);
1281
+ updates.basis = updates.basis.add(translate(item, item.data.basis));
1282
+ updates.realized = updates.realized.add(translate(item, item.data.realized));
1283
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1284
+ updates.income = updates.income.add(translate(item, item.data.income));
1285
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1286
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
1244
1287
 
1245
1288
  return updates;
1246
1289
  }, {
@@ -1277,7 +1320,7 @@ module.exports = (() => {
1277
1320
  }
1278
1321
  }
1279
1322
 
1280
- function calculatePriceData(group, item, forceRefresh) {
1323
+ function calculatePriceData(group, rates, item, forceRefresh) {
1281
1324
  if (group.suspended) {
1282
1325
  return;
1283
1326
  }
@@ -1289,6 +1332,18 @@ module.exports = (() => {
1289
1332
 
1290
1333
  const currency = group.currency;
1291
1334
 
1335
+ const translate = (item, value) => {
1336
+ let translated;
1337
+
1338
+ if (item.currency !== currency) {
1339
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1340
+ } else {
1341
+ translated = value;
1342
+ }
1343
+
1344
+ return translated;
1345
+ };
1346
+
1292
1347
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1293
1348
 
1294
1349
  let updates;
@@ -1297,10 +1352,10 @@ module.exports = (() => {
1297
1352
  const items = group._items;
1298
1353
 
1299
1354
  updates = items.reduce((updates, item) => {
1300
- updates.market = updates.market.add(item.data.market);
1301
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
1302
- updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
1303
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1355
+ updates.market = updates.market.add(translate(item, item.data.market));
1356
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1357
+ updates.unrealizedToday = updates.unrealizedToday.add(translate(item, item.data.unrealizedToday));
1358
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1304
1359
 
1305
1360
  return updates;
1306
1361
  }, {
@@ -1313,11 +1368,11 @@ module.exports = (() => {
1313
1368
  });
1314
1369
  } else {
1315
1370
  updates = {
1316
- market: actual.market.add(item.data.marketChange),
1371
+ market: actual.market.add(translate(item, item.data.marketChange)),
1317
1372
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
1318
- unrealized: actual.unrealized.add(item.data.unrealizedChange),
1319
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
1320
- summaryTotalCurrent: actual.summaryTotalCurrent.add(item.data.summaryTotalCurrentChange)
1373
+ unrealized: actual.unrealized.add(translate(item, item.data.unrealizedChange)),
1374
+ unrealizedToday: actual.unrealizedToday.add(translate(item, item.data.unrealizedTodayChange)),
1375
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrentChange))
1321
1376
  };
1322
1377
  }
1323
1378
 
@@ -1358,11 +1413,11 @@ module.exports = (() => {
1358
1413
  format.total = formatCurrency(actual.total, currency);
1359
1414
  format.totalNegative = actual.total.getIsNegative();
1360
1415
 
1361
- calculateMarketPercent(group, false);
1416
+ calculateMarketPercent(group, rates, false);
1362
1417
  calculateUnrealizedPercent(group);
1363
1418
  }
1364
1419
 
1365
- function calculateMarketPercent(group, silent) {
1420
+ function calculateMarketPercent(group, rates, silent) {
1366
1421
  if (group.suspended) {
1367
1422
  return;
1368
1423
  }
@@ -1378,7 +1433,15 @@ module.exports = (() => {
1378
1433
  const parentData = parent._dataActual;
1379
1434
 
1380
1435
  if (parentData.market !== null && !parentData.market.getIsZero()) {
1381
- marketPercent = actual.market.divide(parentData.market);
1436
+ let numerator;
1437
+
1438
+ if (group.currency !== parent.currency) {
1439
+ numerator = Rate.convert(actual.market, group.currency, parent.currency, ...rates);
1440
+ } else {
1441
+ numerator = actual.market;
1442
+ }
1443
+
1444
+ marketPercent = numerator.divide(parentData.market);
1382
1445
  } else {
1383
1446
  marketPercent = null;
1384
1447
  }
@@ -1413,9 +1476,10 @@ module.exports = (() => {
1413
1476
  return PositionGroup;
1414
1477
  })();
1415
1478
 
1416
- },{"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/formatter":19,"@barchart/common-js/lang/is":20,"@barchart/common-js/messaging/Event":21}],6:[function(require,module,exports){
1479
+ },{"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/Rate":17,"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/formatter":20,"@barchart/common-js/lang/is":21,"@barchart/common-js/messaging/Event":23}],6:[function(require,module,exports){
1417
1480
  const array = require('@barchart/common-js/lang/array'),
1418
1481
  assert = require('@barchart/common-js/lang/assert'),
1482
+ Currency = require('@barchart/common-js/lang/Currency'),
1419
1483
  Decimal = require('@barchart/common-js/lang/Decimal'),
1420
1484
  Event = require('@barchart/common-js/messaging/Event'),
1421
1485
  is = require('@barchart/common-js/lang/is');
@@ -1432,6 +1496,7 @@ module.exports = (() => {
1432
1496
  constructor(portfolio, position, currentSummary, previousSummaries) {
1433
1497
  this._portfolio = portfolio;
1434
1498
  this._position = position;
1499
+ this._currency = position.instrument.currency || Currency.CAD;
1435
1500
 
1436
1501
  this._currentSummary = currentSummary || null;
1437
1502
  this._previousSummaries = previousSummaries || [ ];
@@ -1481,6 +1546,10 @@ module.exports = (() => {
1481
1546
  return this._position;
1482
1547
  }
1483
1548
 
1549
+ get currency() {
1550
+ return this._currency;
1551
+ }
1552
+
1484
1553
  get currentSummary() {
1485
1554
  return this._currentSummary;
1486
1555
  }
@@ -1510,9 +1579,6 @@ module.exports = (() => {
1510
1579
  this._previousQuote = this._currentQuote;
1511
1580
  this._currentQuote = quote;
1512
1581
 
1513
- this._data.previousPrice = this._data.currentPrice;
1514
- this._data.currentPrice = quote.lastPrice;
1515
-
1516
1582
  this._quoteChangedEvent.fire(this._currentQuote);
1517
1583
  }
1518
1584
  }
@@ -1521,7 +1587,7 @@ module.exports = (() => {
1521
1587
  assert.argumentIsRequired(value, 'value', Boolean);
1522
1588
 
1523
1589
  if (this._excluded !== value) {
1524
- this._excludedChangeEvent.fire(this, this._excluded = value);
1590
+ this._excludedChangeEvent.fire(this._excluded = value);
1525
1591
  }
1526
1592
  }
1527
1593
 
@@ -1675,7 +1741,7 @@ module.exports = (() => {
1675
1741
  return PositionItem;
1676
1742
  })();
1677
1743
 
1678
- },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/array":17,"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20,"@barchart/common-js/messaging/Event":21}],7:[function(require,module,exports){
1744
+ },{"./../data/InstrumentType":1,"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14,"@barchart/common-js/lang/array":18,"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21,"@barchart/common-js/messaging/Event":23}],7:[function(require,module,exports){
1679
1745
  const assert = require('@barchart/common-js/lang/assert'),
1680
1746
  is = require('@barchart/common-js/lang/is');
1681
1747
 
@@ -1831,7 +1897,7 @@ module.exports = (() => {
1831
1897
  return PositionLevelDefinition;
1832
1898
  })();
1833
1899
 
1834
- },{"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20}],8:[function(require,module,exports){
1900
+ },{"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21}],8:[function(require,module,exports){
1835
1901
  const assert = require('@barchart/common-js/lang/assert');
1836
1902
 
1837
1903
  const PositionLevelDefinition = require('./PositionLevelDefinition');
@@ -1885,7 +1951,7 @@ module.exports = (() => {
1885
1951
  return PositionTreeDefinitions;
1886
1952
  })();
1887
1953
 
1888
- },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":18}],9:[function(require,module,exports){
1954
+ },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":19}],9:[function(require,module,exports){
1889
1955
  'use strict';
1890
1956
 
1891
1957
  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; }; }();
@@ -2194,7 +2260,7 @@ module.exports = function () {
2194
2260
  return Tree;
2195
2261
  }();
2196
2262
 
2197
- },{"./../lang/is":20}],10:[function(require,module,exports){
2263
+ },{"./../lang/is":21}],10:[function(require,module,exports){
2198
2264
  'use strict';
2199
2265
 
2200
2266
  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; }; }();
@@ -2338,7 +2404,7 @@ module.exports = function () {
2338
2404
  return ComparatorBuilder;
2339
2405
  }();
2340
2406
 
2341
- },{"./../../lang/assert":18,"./comparators":11}],11:[function(require,module,exports){
2407
+ },{"./../../lang/assert":19,"./comparators":11}],11:[function(require,module,exports){
2342
2408
  'use strict';
2343
2409
 
2344
2410
  var assert = require('./../../lang/assert');
@@ -2413,7 +2479,7 @@ module.exports = function () {
2413
2479
  };
2414
2480
  }();
2415
2481
 
2416
- },{"./../../lang/assert":18}],12:[function(require,module,exports){
2482
+ },{"./../../lang/assert":19}],12:[function(require,module,exports){
2417
2483
  'use strict';
2418
2484
 
2419
2485
  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; }; }();
@@ -2556,7 +2622,7 @@ module.exports = function () {
2556
2622
  return Currency;
2557
2623
  }();
2558
2624
 
2559
- },{"./Enum":16,"./assert":18,"./is":20}],13:[function(require,module,exports){
2625
+ },{"./Enum":16,"./assert":19,"./is":21}],13:[function(require,module,exports){
2560
2626
  'use strict';
2561
2627
 
2562
2628
  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; }; }();
@@ -3109,7 +3175,7 @@ module.exports = function () {
3109
3175
  return Day;
3110
3176
  }();
3111
3177
 
3112
- },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":18,"./is":20}],14:[function(require,module,exports){
3178
+ },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":19,"./is":21}],14:[function(require,module,exports){
3113
3179
  'use strict';
3114
3180
 
3115
3181
  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; }; }();
@@ -3689,7 +3755,7 @@ module.exports = function () {
3689
3755
  return Decimal;
3690
3756
  }();
3691
3757
 
3692
- },{"./Enum":16,"./assert":18,"./is":20,"big.js":22}],15:[function(require,module,exports){
3758
+ },{"./Enum":16,"./assert":19,"./is":21,"big.js":24}],15:[function(require,module,exports){
3693
3759
  'use strict';
3694
3760
 
3695
3761
  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; }; }();
@@ -3838,7 +3904,7 @@ module.exports = function () {
3838
3904
  return Disposable;
3839
3905
  }();
3840
3906
 
3841
- },{"./assert":18}],16:[function(require,module,exports){
3907
+ },{"./assert":19}],16:[function(require,module,exports){
3842
3908
  'use strict';
3843
3909
 
3844
3910
  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; }; }();
@@ -3980,7 +4046,262 @@ module.exports = function () {
3980
4046
  return Enum;
3981
4047
  }();
3982
4048
 
3983
- },{"./assert":18}],17:[function(require,module,exports){
4049
+ },{"./assert":19}],17:[function(require,module,exports){
4050
+ 'use strict';
4051
+
4052
+ 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; }; }();
4053
+
4054
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4055
+
4056
+ var assert = require('./assert'),
4057
+ memoize = require('./memoize');
4058
+
4059
+ var Currency = require('./Currency'),
4060
+ Decimal = require('./Decimal');
4061
+
4062
+ module.exports = function () {
4063
+ 'use strict';
4064
+
4065
+ /**
4066
+ * A component that represents an exchange rate, composed of a {@link Decimal}
4067
+ * value and two currencies -- a quote (i.e. the numerator) currency and a
4068
+ * base (i.e. denominator) currency.
4069
+ *
4070
+ * @public
4071
+ * @param {Number|String|Decimal} value - The rate
4072
+ * @param {Currency} numerator - The quote currency
4073
+ * @param {Currency} denominator - The base currency
4074
+ */
4075
+
4076
+ var Rate = function () {
4077
+ function Rate(value, numerator, denominator) {
4078
+ _classCallCheck(this, Rate);
4079
+
4080
+ assert.argumentIsRequired(numerator, 'numerator', Currency, 'Currency');
4081
+ assert.argumentIsRequired(denominator, 'denominator', Currency, 'Currency');
4082
+
4083
+ if (numerator === denominator) {
4084
+ throw new Error('A rate cannot use two identical currencies.');
4085
+ }
4086
+
4087
+ var decimal = getDecimal(value);
4088
+
4089
+ if (!decimal.getIsPositive()) {
4090
+ throw new Error('Rate value must be positive.');
4091
+ }
4092
+
4093
+ this._decimal = decimal;
4094
+ this._numerator = numerator;
4095
+ this._denominator = denominator;
4096
+ }
4097
+
4098
+ /**
4099
+ * The rate.
4100
+ *
4101
+ * @public
4102
+ * @returns {Decimal}
4103
+ */
4104
+
4105
+
4106
+ _createClass(Rate, [{
4107
+ key: 'invert',
4108
+
4109
+
4110
+ /**
4111
+ * Returns the equivalent rate with the numerator and denominator (i.e. the qoute and base)
4112
+ * currencies.
4113
+ *
4114
+ * @public
4115
+ * @returns {Rate}
4116
+ */
4117
+ value: function invert() {
4118
+ return new Rate(Decimal.ONE.divide(this._decimal), this._denominator, this._numerator);
4119
+ }
4120
+
4121
+ /**
4122
+ * Formats the currency pair as a string (e.g. "EURUSD" or "^EURUSD").
4123
+ *
4124
+ * @public
4125
+ * @param {Boolean=} useCarat - If true, a carat is used as a prefix to the resulting string.
4126
+ * @returns {string}
4127
+ */
4128
+
4129
+ }, {
4130
+ key: 'formatPair',
4131
+ value: function formatPair(useCarat) {
4132
+ assert.argumentIsOptional(useCarat, 'useCarat', Boolean);
4133
+
4134
+ return '' + (useCarat ? '^' : '') + this._numerator + this._denominator;
4135
+ }
4136
+
4137
+ /**
4138
+ * Creates a {@link Rate} instance, when given a value
4139
+ *
4140
+ * @public
4141
+ * @param {Number|String|Decimal} value - The rate.
4142
+ * @param {String} symbol - A string that can be parsed as a currency pair.
4143
+ * @returns {Rate}
4144
+ */
4145
+
4146
+ }, {
4147
+ key: 'toString',
4148
+ value: function toString() {
4149
+ return '[Rate]';
4150
+ }
4151
+ }, {
4152
+ key: 'decimal',
4153
+ get: function get() {
4154
+ return this._decimal;
4155
+ }
4156
+
4157
+ /**
4158
+ * The numerator (i.e. quote) currency. In other words,
4159
+ * this is EUR of the EURUSD pair.
4160
+ *
4161
+ * @public
4162
+ * @returns {Currency}
4163
+ */
4164
+
4165
+ }, {
4166
+ key: 'numerator',
4167
+ get: function get() {
4168
+ return this._numerator;
4169
+ }
4170
+
4171
+ /**
4172
+ * The quote (i.e. numerator) currency. In other words,
4173
+ * this is EUR of the EURUSD pair.
4174
+ *
4175
+ * @public
4176
+ * @returns {Currency}
4177
+ */
4178
+
4179
+ }, {
4180
+ key: 'quote',
4181
+ get: function get() {
4182
+ return this._numerator;
4183
+ }
4184
+
4185
+ /**
4186
+ * The denominator (i.e. base) currency. In other words,
4187
+ * this is USD of the EURUSD pair.
4188
+ *
4189
+ * @public
4190
+ * @returns {Currency}
4191
+ */
4192
+
4193
+ }, {
4194
+ key: 'denominator',
4195
+ get: function get() {
4196
+ return this._denominator;
4197
+ }
4198
+
4199
+ /**
4200
+ * The base (i.e. denominator) currency. In other words,
4201
+ * this is USD of the EURUSD pair.
4202
+ *
4203
+ * @public
4204
+ * @returns {Currency}
4205
+ */
4206
+
4207
+ }, {
4208
+ key: 'base',
4209
+ get: function get() {
4210
+ return this._denominator;
4211
+ }
4212
+ }], [{
4213
+ key: 'fromPair',
4214
+ value: function fromPair(value, symbol) {
4215
+ assert.argumentIsRequired(symbol, 'symbol', String);
4216
+
4217
+ var pair = parsePair(symbol);
4218
+
4219
+ return new Rate(value, Currency.parse(pair.numerator), Currency.parse(pair.denominator));
4220
+ }
4221
+
4222
+ /**
4223
+ * Given a {@link Decimal} value in a known currency, output
4224
+ * a {@link Decimal} converted to an alternate currency.
4225
+ *
4226
+ * @public
4227
+ * @param {Decimal} amount - The amount to convert.
4228
+ * @param {Currency} currency - The currency of the amount.
4229
+ * @param {Currency} desiredCurrency - The currency to convert to.
4230
+ * @param {...Rate} rates - A list of exchange rates to be used for the conversion.
4231
+ * @returns {Decimal}
4232
+ */
4233
+
4234
+ }, {
4235
+ key: 'convert',
4236
+ value: function convert(amount, currency, desiredCurrency) {
4237
+ assert.argumentIsRequired(amount, 'amount', Decimal, 'Decimal');
4238
+ assert.argumentIsRequired(currency, 'currency', Currency, 'Currency');
4239
+ assert.argumentIsRequired(desiredCurrency, 'desiredCurrency', Currency, 'Currency');
4240
+ //assert.argumentIsArray(rates, 'rates', Rate, 'Rate');
4241
+
4242
+ var converted = void 0;
4243
+
4244
+ if (currency === desiredCurrency) {
4245
+ converted = amount;
4246
+ } else {
4247
+ var numerator = desiredCurrency;
4248
+ var denominator = currency;
4249
+
4250
+ for (var _len = arguments.length, rates = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
4251
+ rates[_key - 3] = arguments[_key];
4252
+ }
4253
+
4254
+ var rate = rates.find(function (r) {
4255
+ return r.numerator === numerator && r.denominator === denominator || r.numerator === denominator && r.denominator === numerator;
4256
+ });
4257
+
4258
+ if (rate) {
4259
+ if (rate.numerator === denominator) {
4260
+ rate = rate.invert();
4261
+ }
4262
+ }
4263
+
4264
+ if (!rate) {
4265
+ throw new Error('Unable to perform conversion, given the rates provided.');
4266
+ }
4267
+
4268
+ converted = amount.multiply(rate.decimal);
4269
+ }
4270
+
4271
+ return converted;
4272
+ }
4273
+ }]);
4274
+
4275
+ return Rate;
4276
+ }();
4277
+
4278
+ var pairExpression = /^\^?([A-Z]{3})([A-Z]{3})$/;
4279
+
4280
+ function getDecimal(value) {
4281
+ if (value instanceof Decimal) {
4282
+ return value;
4283
+ } else {
4284
+ return new Decimal(value);
4285
+ }
4286
+ }
4287
+
4288
+ var parsePair = memoize.simple(function (symbol) {
4289
+ var match = symbol.match(pairExpression);
4290
+
4291
+ if (match === null) {
4292
+ throw new Error('The "pair" argument cannot be parsed.');
4293
+ }
4294
+
4295
+ return {
4296
+ numerator: match[2],
4297
+ denominator: match[1]
4298
+ };
4299
+ });
4300
+
4301
+ return Rate;
4302
+ }();
4303
+
4304
+ },{"./Currency":12,"./Decimal":14,"./assert":19,"./memoize":22}],18:[function(require,module,exports){
3984
4305
  'use strict';
3985
4306
 
3986
4307
  var assert = require('./assert'),
@@ -4361,7 +4682,7 @@ module.exports = function () {
4361
4682
  };
4362
4683
  }();
4363
4684
 
4364
- },{"./assert":18,"./is":20}],18:[function(require,module,exports){
4685
+ },{"./assert":19,"./is":21}],19:[function(require,module,exports){
4365
4686
  'use strict';
4366
4687
 
4367
4688
  var is = require('./is');
@@ -4509,7 +4830,7 @@ module.exports = function () {
4509
4830
  };
4510
4831
  }();
4511
4832
 
4512
- },{"./is":20}],19:[function(require,module,exports){
4833
+ },{"./is":21}],20:[function(require,module,exports){
4513
4834
  'use strict';
4514
4835
 
4515
4836
  module.exports = function () {
@@ -4574,7 +4895,7 @@ module.exports = function () {
4574
4895
  };
4575
4896
  }();
4576
4897
 
4577
- },{}],20:[function(require,module,exports){
4898
+ },{}],21:[function(require,module,exports){
4578
4899
  'use strict';
4579
4900
 
4580
4901
  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; };
@@ -4797,7 +5118,80 @@ module.exports = function () {
4797
5118
  };
4798
5119
  }();
4799
5120
 
4800
- },{}],21:[function(require,module,exports){
5121
+ },{}],22:[function(require,module,exports){
5122
+ 'use strict';
5123
+
5124
+ var assert = require('./assert'),
5125
+ is = require('./is');
5126
+
5127
+ module.exports = function () {
5128
+ 'use strict';
5129
+
5130
+ /**
5131
+ * Utilities for caching results of function invocations (a.k.a. memoization).
5132
+ *
5133
+ * @public
5134
+ * @module lang/memoize
5135
+ */
5136
+
5137
+ return {
5138
+ /**
5139
+ * Memoizes a function that accepts a single argument only. Furthermore,
5140
+ * the parameter's toString function must return a unique value.
5141
+ *
5142
+ * @static
5143
+ * @public
5144
+ * @param {Function} fn - The function to memoize. This function should accept one parameters whose "toString" function outputs a unique value.
5145
+ */
5146
+ simple: function simple(fn) {
5147
+ var cache = {};
5148
+
5149
+ return function (x) {
5150
+ if (cache.hasOwnProperty(x)) {
5151
+ return cache[x];
5152
+ } else {
5153
+ return cache[x] = fn(x);
5154
+ }
5155
+ };
5156
+ },
5157
+
5158
+
5159
+ /**
5160
+ * Wraps a function. The resulting function will call the wrapped function
5161
+ * once and cache the result. If a specific duration is supplied, the
5162
+ * cache will be dropped after the duration expires and the wrapped
5163
+ * function will be invoked again.
5164
+ *
5165
+ * @public
5166
+ * @param {Function} fn
5167
+ * @param {Number} duration
5168
+ * @returns {Function}
5169
+ */
5170
+ cache: function cache(fn, duration) {
5171
+ assert.argumentIsRequired(fn, 'fn', Function);
5172
+ assert.argumentIsOptional(duration, 'duration', Number);
5173
+
5174
+ var durationToUse = duration || 0;
5175
+
5176
+ var executionTime = null;
5177
+ var cacheResult = null;
5178
+
5179
+ return function () {
5180
+ var currentTime = new Date().getTime();
5181
+
5182
+ if (executionTime === null || durationToUse > 0 && currentTime > executionTime + durationToUse) {
5183
+ executionTime = currentTime;
5184
+
5185
+ cacheResult = fn();
5186
+ }
5187
+
5188
+ return cacheResult;
5189
+ };
5190
+ }
5191
+ };
5192
+ }();
5193
+
5194
+ },{"./assert":19,"./is":21}],23:[function(require,module,exports){
4801
5195
  'use strict';
4802
5196
 
4803
5197
  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; }; }();
@@ -4969,7 +5363,7 @@ module.exports = function () {
4969
5363
  return Event;
4970
5364
  }();
4971
5365
 
4972
- },{"./../lang/Disposable":15,"./../lang/assert":18}],22:[function(require,module,exports){
5366
+ },{"./../lang/Disposable":15,"./../lang/assert":19}],24:[function(require,module,exports){
4973
5367
  /*
4974
5368
  * big.js v5.0.3
4975
5369
  * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
@@ -5910,7 +6304,7 @@ module.exports = function () {
5910
6304
  }
5911
6305
  })(this);
5912
6306
 
5913
- },{}],23:[function(require,module,exports){
6307
+ },{}],25:[function(require,module,exports){
5914
6308
  const Day = require('@barchart/common-js/lang/Day'),
5915
6309
  Decimal = require('@barchart/common-js/lang/Decimal');
5916
6310
 
@@ -6267,7 +6661,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
6267
6661
  });
6268
6662
  });
6269
6663
 
6270
- },{"./../../../lib/data/PositionSummaryFrame":2,"./../../../lib/data/TransactionType":3,"@barchart/common-js/lang/Day":13,"@barchart/common-js/lang/Decimal":14}],24:[function(require,module,exports){
6664
+ },{"./../../../lib/data/PositionSummaryFrame":2,"./../../../lib/data/TransactionType":3,"@barchart/common-js/lang/Day":13,"@barchart/common-js/lang/Decimal":14}],26:[function(require,module,exports){
6271
6665
  const Currency = require('@barchart/common-js/lang/Currency'),
6272
6666
  Decimal = require('@barchart/common-js/lang/Decimal');
6273
6667
 
@@ -6376,4 +6770,4 @@ describe('When a position container data is gathered', () => {
6376
6770
  });
6377
6771
  });
6378
6772
 
6379
- },{"./../../../lib/data/InstrumentType":1,"./../../../lib/processing/PositionContainer":4,"./../../../lib/processing/definitions/PositionLevelDefinition":7,"./../../../lib/processing/definitions/PositionTreeDefinition":8,"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14}]},{},[23,24]);
6773
+ },{"./../../../lib/data/InstrumentType":1,"./../../../lib/processing/PositionContainer":4,"./../../../lib/processing/definitions/PositionLevelDefinition":7,"./../../../lib/processing/definitions/PositionTreeDefinition":8,"@barchart/common-js/lang/Currency":12,"@barchart/common-js/lang/Decimal":14}]},{},[25,26]);