@barchart/portfolio-api-common 1.0.121 → 1.0.122

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';
@@ -112,7 +113,7 @@ module.exports = (() => {
112
113
  this._dataFormat.currentPrice = null;
113
114
  }
114
115
 
115
- calculatePriceData(this, sender, false);
116
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
116
117
  });
117
118
  });
118
119
 
@@ -155,6 +156,10 @@ module.exports = (() => {
155
156
  return this._excluded;
156
157
  }
157
158
 
159
+ setForexQuote(quote) {
160
+
161
+ }
162
+
158
163
  setExcluded(value) {
159
164
  assert.argumentIsRequired(value, 'value', Boolean);
160
165
 
@@ -178,12 +183,14 @@ module.exports = (() => {
178
183
  }
179
184
 
180
185
  refresh() {
181
- calculateStaticData(this);
182
- calculatePriceData(this, null, true);
186
+ const rates = this._container.getForexQuotes();
187
+
188
+ calculateStaticData(this, rates);
189
+ calculatePriceData(this, rates, null, true);
183
190
  }
184
191
 
185
192
  refreshMarketPercent() {
186
- calculateMarketPercent(this, true);
193
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
187
194
  }
188
195
 
189
196
  registerMarketPercentChangeHandler(handler) {
@@ -223,7 +230,7 @@ module.exports = (() => {
223
230
  return formatDecimal(decimal, currency.precision);
224
231
  }
225
232
 
226
- function calculateStaticData(group) {
233
+ function calculateStaticData(group, rates) {
227
234
  if (group.suspended) {
228
235
  return;
229
236
  }
@@ -235,13 +242,25 @@ module.exports = (() => {
235
242
 
236
243
  const items = group._items;
237
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
+
238
257
  let updates = items.reduce((updates, item) => {
239
- updates.basis = updates.basis.add(item.data.basis);
240
- updates.realized = updates.realized.add(item.data.realized);
241
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
242
- updates.income = updates.income.add(item.data.income);
243
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
244
- 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));
245
264
 
246
265
  return updates;
247
266
  }, {
@@ -278,7 +297,7 @@ module.exports = (() => {
278
297
  }
279
298
  }
280
299
 
281
- function calculatePriceData(group, item, forceRefresh) {
300
+ function calculatePriceData(group, rates, item, forceRefresh) {
282
301
  if (group.suspended) {
283
302
  return;
284
303
  }
@@ -290,6 +309,18 @@ module.exports = (() => {
290
309
 
291
310
  const currency = group.currency;
292
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
+
293
324
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
294
325
 
295
326
  let updates;
@@ -298,10 +329,10 @@ module.exports = (() => {
298
329
  const items = group._items;
299
330
 
300
331
  updates = items.reduce((updates, item) => {
301
- updates.market = updates.market.add(item.data.market);
302
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
303
- updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
304
- 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));
305
336
 
306
337
  return updates;
307
338
  }, {
@@ -314,11 +345,11 @@ module.exports = (() => {
314
345
  });
315
346
  } else {
316
347
  updates = {
317
- market: actual.market.add(item.data.marketChange),
348
+ market: actual.market.add(translate(item, item.data.marketChange)),
318
349
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
319
- unrealized: actual.unrealized.add(item.data.unrealizedChange),
320
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
321
- 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))
322
353
  };
323
354
  }
324
355
 
@@ -359,11 +390,11 @@ module.exports = (() => {
359
390
  format.total = formatCurrency(actual.total, currency);
360
391
  format.totalNegative = actual.total.getIsNegative();
361
392
 
362
- calculateMarketPercent(group, false);
393
+ calculateMarketPercent(group, rates, false);
363
394
  calculateUnrealizedPercent(group);
364
395
  }
365
396
 
366
- function calculateMarketPercent(group, silent) {
397
+ function calculateMarketPercent(group, rates, silent) {
367
398
  if (group.suspended) {
368
399
  return;
369
400
  }
@@ -379,7 +410,15 @@ module.exports = (() => {
379
410
  const parentData = parent._dataActual;
380
411
 
381
412
  if (parentData.market !== null && !parentData.market.getIsZero()) {
382
- marketPercent = actual.market.divide(parentData.market);
413
+ let numerator;
414
+
415
+ if (group.currency !== parent.currency) {
416
+ numerator = Rate.convert(parentData.market, group.currency, parent.currency, ...rates);
417
+ } else {
418
+ numerator = actual.market;
419
+ }
420
+
421
+ marketPercent = numerator.divide(parentData.market);
383
422
  } else {
384
423
  marketPercent = null;
385
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
  }
@@ -102,7 +108,7 @@ module.exports = (() => {
102
108
  assert.argumentIsRequired(value, 'value', Boolean);
103
109
 
104
110
  if (this._excluded !== value) {
105
- this._excludedChangeEvent.fire(this, this._excluded = value);
111
+ this._excludedChangeEvent.fire(this._excluded = value);
106
112
  }
107
113
  }
108
114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.121",
3
+ "version": "1.0.122",
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';
@@ -1117,7 +1136,7 @@ module.exports = (() => {
1117
1136
  this._dataFormat.currentPrice = null;
1118
1137
  }
1119
1138
 
1120
- calculatePriceData(this, sender, false);
1139
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
1121
1140
  });
1122
1141
  });
1123
1142
 
@@ -1160,6 +1179,10 @@ module.exports = (() => {
1160
1179
  return this._excluded;
1161
1180
  }
1162
1181
 
1182
+ setForexQuote(quote) {
1183
+
1184
+ }
1185
+
1163
1186
  setExcluded(value) {
1164
1187
  assert.argumentIsRequired(value, 'value', Boolean);
1165
1188
 
@@ -1183,12 +1206,14 @@ module.exports = (() => {
1183
1206
  }
1184
1207
 
1185
1208
  refresh() {
1186
- calculateStaticData(this);
1187
- calculatePriceData(this, null, true);
1209
+ const rates = this._container.getForexQuotes();
1210
+
1211
+ calculateStaticData(this, rates);
1212
+ calculatePriceData(this, rates, null, true);
1188
1213
  }
1189
1214
 
1190
1215
  refreshMarketPercent() {
1191
- calculateMarketPercent(this, true);
1216
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
1192
1217
  }
1193
1218
 
1194
1219
  registerMarketPercentChangeHandler(handler) {
@@ -1228,7 +1253,7 @@ module.exports = (() => {
1228
1253
  return formatDecimal(decimal, currency.precision);
1229
1254
  }
1230
1255
 
1231
- function calculateStaticData(group) {
1256
+ function calculateStaticData(group, rates) {
1232
1257
  if (group.suspended) {
1233
1258
  return;
1234
1259
  }
@@ -1240,13 +1265,25 @@ module.exports = (() => {
1240
1265
 
1241
1266
  const items = group._items;
1242
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
+
1243
1280
  let updates = items.reduce((updates, item) => {
1244
- updates.basis = updates.basis.add(item.data.basis);
1245
- updates.realized = updates.realized.add(item.data.realized);
1246
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
1247
- updates.income = updates.income.add(item.data.income);
1248
- updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(item.data.summaryTotalCurrent);
1249
- 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));
1250
1287
 
1251
1288
  return updates;
1252
1289
  }, {
@@ -1283,7 +1320,7 @@ module.exports = (() => {
1283
1320
  }
1284
1321
  }
1285
1322
 
1286
- function calculatePriceData(group, item, forceRefresh) {
1323
+ function calculatePriceData(group, rates, item, forceRefresh) {
1287
1324
  if (group.suspended) {
1288
1325
  return;
1289
1326
  }
@@ -1295,6 +1332,18 @@ module.exports = (() => {
1295
1332
 
1296
1333
  const currency = group.currency;
1297
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
+
1298
1347
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1299
1348
 
1300
1349
  let updates;
@@ -1303,10 +1352,10 @@ module.exports = (() => {
1303
1352
  const items = group._items;
1304
1353
 
1305
1354
  updates = items.reduce((updates, item) => {
1306
- updates.market = updates.market.add(item.data.market);
1307
- updates.unrealized = updates.unrealized.add(item.data.unrealized);
1308
- updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
1309
- 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));
1310
1359
 
1311
1360
  return updates;
1312
1361
  }, {
@@ -1319,11 +1368,11 @@ module.exports = (() => {
1319
1368
  });
1320
1369
  } else {
1321
1370
  updates = {
1322
- market: actual.market.add(item.data.marketChange),
1371
+ market: actual.market.add(translate(item, item.data.marketChange)),
1323
1372
  marketDirection: { up: item.data.marketChange.getIsPositive(), down: item.data.marketChange.getIsNegative() },
1324
- unrealized: actual.unrealized.add(item.data.unrealizedChange),
1325
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange),
1326
- 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))
1327
1376
  };
1328
1377
  }
1329
1378
 
@@ -1364,11 +1413,11 @@ module.exports = (() => {
1364
1413
  format.total = formatCurrency(actual.total, currency);
1365
1414
  format.totalNegative = actual.total.getIsNegative();
1366
1415
 
1367
- calculateMarketPercent(group, false);
1416
+ calculateMarketPercent(group, rates, false);
1368
1417
  calculateUnrealizedPercent(group);
1369
1418
  }
1370
1419
 
1371
- function calculateMarketPercent(group, silent) {
1420
+ function calculateMarketPercent(group, rates, silent) {
1372
1421
  if (group.suspended) {
1373
1422
  return;
1374
1423
  }
@@ -1384,7 +1433,15 @@ module.exports = (() => {
1384
1433
  const parentData = parent._dataActual;
1385
1434
 
1386
1435
  if (parentData.market !== null && !parentData.market.getIsZero()) {
1387
- marketPercent = actual.market.divide(parentData.market);
1436
+ let numerator;
1437
+
1438
+ if (group.currency !== parent.currency) {
1439
+ numerator = Rate.convert(parentData.market, group.currency, parent.currency, ...rates);
1440
+ } else {
1441
+ numerator = actual.market;
1442
+ }
1443
+
1444
+ marketPercent = numerator.divide(parentData.market);
1388
1445
  } else {
1389
1446
  marketPercent = null;
1390
1447
  }
@@ -1419,9 +1476,10 @@ module.exports = (() => {
1419
1476
  return PositionGroup;
1420
1477
  })();
1421
1478
 
1422
- },{"@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){
1423
1480
  const array = require('@barchart/common-js/lang/array'),
1424
1481
  assert = require('@barchart/common-js/lang/assert'),
1482
+ Currency = require('@barchart/common-js/lang/Currency'),
1425
1483
  Decimal = require('@barchart/common-js/lang/Decimal'),
1426
1484
  Event = require('@barchart/common-js/messaging/Event'),
1427
1485
  is = require('@barchart/common-js/lang/is');
@@ -1438,6 +1496,7 @@ module.exports = (() => {
1438
1496
  constructor(portfolio, position, currentSummary, previousSummaries) {
1439
1497
  this._portfolio = portfolio;
1440
1498
  this._position = position;
1499
+ this._currency = position.instrument.currency || Currency.CAD;
1441
1500
 
1442
1501
  this._currentSummary = currentSummary || null;
1443
1502
  this._previousSummaries = previousSummaries || [ ];
@@ -1487,6 +1546,10 @@ module.exports = (() => {
1487
1546
  return this._position;
1488
1547
  }
1489
1548
 
1549
+ get currency() {
1550
+ return this._currency;
1551
+ }
1552
+
1490
1553
  get currentSummary() {
1491
1554
  return this._currentSummary;
1492
1555
  }
@@ -1524,7 +1587,7 @@ module.exports = (() => {
1524
1587
  assert.argumentIsRequired(value, 'value', Boolean);
1525
1588
 
1526
1589
  if (this._excluded !== value) {
1527
- this._excludedChangeEvent.fire(this, this._excluded = value);
1590
+ this._excludedChangeEvent.fire(this._excluded = value);
1528
1591
  }
1529
1592
  }
1530
1593
 
@@ -1678,7 +1741,7 @@ module.exports = (() => {
1678
1741
  return PositionItem;
1679
1742
  })();
1680
1743
 
1681
- },{"./../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){
1682
1745
  const assert = require('@barchart/common-js/lang/assert'),
1683
1746
  is = require('@barchart/common-js/lang/is');
1684
1747
 
@@ -1834,7 +1897,7 @@ module.exports = (() => {
1834
1897
  return PositionLevelDefinition;
1835
1898
  })();
1836
1899
 
1837
- },{"@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){
1838
1901
  const assert = require('@barchart/common-js/lang/assert');
1839
1902
 
1840
1903
  const PositionLevelDefinition = require('./PositionLevelDefinition');
@@ -1888,7 +1951,7 @@ module.exports = (() => {
1888
1951
  return PositionTreeDefinitions;
1889
1952
  })();
1890
1953
 
1891
- },{"./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){
1892
1955
  'use strict';
1893
1956
 
1894
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; }; }();
@@ -2197,7 +2260,7 @@ module.exports = function () {
2197
2260
  return Tree;
2198
2261
  }();
2199
2262
 
2200
- },{"./../lang/is":20}],10:[function(require,module,exports){
2263
+ },{"./../lang/is":21}],10:[function(require,module,exports){
2201
2264
  'use strict';
2202
2265
 
2203
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; }; }();
@@ -2341,7 +2404,7 @@ module.exports = function () {
2341
2404
  return ComparatorBuilder;
2342
2405
  }();
2343
2406
 
2344
- },{"./../../lang/assert":18,"./comparators":11}],11:[function(require,module,exports){
2407
+ },{"./../../lang/assert":19,"./comparators":11}],11:[function(require,module,exports){
2345
2408
  'use strict';
2346
2409
 
2347
2410
  var assert = require('./../../lang/assert');
@@ -2416,7 +2479,7 @@ module.exports = function () {
2416
2479
  };
2417
2480
  }();
2418
2481
 
2419
- },{"./../../lang/assert":18}],12:[function(require,module,exports){
2482
+ },{"./../../lang/assert":19}],12:[function(require,module,exports){
2420
2483
  'use strict';
2421
2484
 
2422
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; }; }();
@@ -2559,7 +2622,7 @@ module.exports = function () {
2559
2622
  return Currency;
2560
2623
  }();
2561
2624
 
2562
- },{"./Enum":16,"./assert":18,"./is":20}],13:[function(require,module,exports){
2625
+ },{"./Enum":16,"./assert":19,"./is":21}],13:[function(require,module,exports){
2563
2626
  'use strict';
2564
2627
 
2565
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; }; }();
@@ -3112,7 +3175,7 @@ module.exports = function () {
3112
3175
  return Day;
3113
3176
  }();
3114
3177
 
3115
- },{"./../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){
3116
3179
  'use strict';
3117
3180
 
3118
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; }; }();
@@ -3692,7 +3755,7 @@ module.exports = function () {
3692
3755
  return Decimal;
3693
3756
  }();
3694
3757
 
3695
- },{"./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){
3696
3759
  'use strict';
3697
3760
 
3698
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; }; }();
@@ -3841,7 +3904,7 @@ module.exports = function () {
3841
3904
  return Disposable;
3842
3905
  }();
3843
3906
 
3844
- },{"./assert":18}],16:[function(require,module,exports){
3907
+ },{"./assert":19}],16:[function(require,module,exports){
3845
3908
  'use strict';
3846
3909
 
3847
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; }; }();
@@ -3983,7 +4046,262 @@ module.exports = function () {
3983
4046
  return Enum;
3984
4047
  }();
3985
4048
 
3986
- },{"./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){
3987
4305
  'use strict';
3988
4306
 
3989
4307
  var assert = require('./assert'),
@@ -4364,7 +4682,7 @@ module.exports = function () {
4364
4682
  };
4365
4683
  }();
4366
4684
 
4367
- },{"./assert":18,"./is":20}],18:[function(require,module,exports){
4685
+ },{"./assert":19,"./is":21}],19:[function(require,module,exports){
4368
4686
  'use strict';
4369
4687
 
4370
4688
  var is = require('./is');
@@ -4512,7 +4830,7 @@ module.exports = function () {
4512
4830
  };
4513
4831
  }();
4514
4832
 
4515
- },{"./is":20}],19:[function(require,module,exports){
4833
+ },{"./is":21}],20:[function(require,module,exports){
4516
4834
  'use strict';
4517
4835
 
4518
4836
  module.exports = function () {
@@ -4577,7 +4895,7 @@ module.exports = function () {
4577
4895
  };
4578
4896
  }();
4579
4897
 
4580
- },{}],20:[function(require,module,exports){
4898
+ },{}],21:[function(require,module,exports){
4581
4899
  'use strict';
4582
4900
 
4583
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; };
@@ -4800,7 +5118,80 @@ module.exports = function () {
4800
5118
  };
4801
5119
  }();
4802
5120
 
4803
- },{}],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){
4804
5195
  'use strict';
4805
5196
 
4806
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; }; }();
@@ -4972,7 +5363,7 @@ module.exports = function () {
4972
5363
  return Event;
4973
5364
  }();
4974
5365
 
4975
- },{"./../lang/Disposable":15,"./../lang/assert":18}],22:[function(require,module,exports){
5366
+ },{"./../lang/Disposable":15,"./../lang/assert":19}],24:[function(require,module,exports){
4976
5367
  /*
4977
5368
  * big.js v5.0.3
4978
5369
  * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
@@ -5913,7 +6304,7 @@ module.exports = function () {
5913
6304
  }
5914
6305
  })(this);
5915
6306
 
5916
- },{}],23:[function(require,module,exports){
6307
+ },{}],25:[function(require,module,exports){
5917
6308
  const Day = require('@barchart/common-js/lang/Day'),
5918
6309
  Decimal = require('@barchart/common-js/lang/Decimal');
5919
6310
 
@@ -6270,7 +6661,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
6270
6661
  });
6271
6662
  });
6272
6663
 
6273
- },{"./../../../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){
6274
6665
  const Currency = require('@barchart/common-js/lang/Currency'),
6275
6666
  Decimal = require('@barchart/common-js/lang/Decimal');
6276
6667
 
@@ -6379,4 +6770,4 @@ describe('When a position container data is gathered', () => {
6379
6770
  });
6380
6771
  });
6381
6772
 
6382
- },{"./../../../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]);