@barchart/portfolio-api-common 1.0.121 → 1.0.125

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
 
@@ -92,11 +95,9 @@ module.exports = (() => {
92
95
  }, [ ]);
93
96
 
94
97
  this._symbols = this._items.reduce((map, item) => {
95
- const position = item.position;
96
-
97
- if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
98
- const symbol = position.instrument.symbol.barchart;
98
+ const symbol = extractSymbolForBarchart(item.position);
99
99
 
100
+ if (symbol) {
100
101
  if (!map.hasOwnProperty(symbol)) {
101
102
  map[symbol] = [ ];
102
103
  }
@@ -112,18 +113,29 @@ module.exports = (() => {
112
113
 
113
114
  if (position.instrument && position.instrument.currency) {
114
115
  const currency = position.instrument.currency;
116
+ const code = currency.code;
115
117
 
116
- if (!map.hasOwnProperty(currency)) {
117
- map[currency] = [ ];
118
+ if (!map.hasOwnProperty(code)) {
119
+ map[code] = [ ];
118
120
  }
119
121
 
120
- map[currency].push(item);
122
+ map[code].push(item);
121
123
  }
122
124
 
123
125
  return map;
124
126
  }, { });
125
127
 
126
- this._forex = { };
128
+ this._forexSymbols = Object.keys(this._currencies).reduce((symbols, code) => {
129
+ if (code !== DEFAULT_CURRENCY.code) {
130
+ symbols.push(`^${DEFAULT_CURRENCY.code}${code}`);
131
+ }
132
+
133
+ return symbols;
134
+ }, [ ]);
135
+
136
+ this._forexQuotes = this._forexSymbols.map((symbol) => {
137
+ return Rate.fromPair(Decimal.ONE, symbol);
138
+ });
127
139
 
128
140
  this._trees = definitions.reduce((map, treeDefinition) => {
129
141
  const tree = new Tree();
@@ -211,8 +223,26 @@ module.exports = (() => {
211
223
  return this._defaultCurrency;
212
224
  }
213
225
 
214
- getPositionSymbols() {
215
- return Object.keys(this._symbols);
226
+ getPositionSymbols(display) {
227
+ const symbols = this._items.reduce((symbols, item) => {
228
+ const position = item.position;
229
+
230
+ let symbol;
231
+
232
+ if (display) {
233
+ symbol = extractSymbolForDisplay(position);
234
+ } else {
235
+ symbol = extractSymbolForBarchart(position);
236
+ }
237
+
238
+ if (symbol !== null) {
239
+ symbols.push(symbol);
240
+ }
241
+
242
+ return symbols;
243
+ }, [ ]);
244
+
245
+ return array.unique(symbols);
216
246
  }
217
247
 
218
248
  setPositionQuote(symbol, quote) {
@@ -225,22 +255,26 @@ module.exports = (() => {
225
255
  }
226
256
 
227
257
  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
- }
258
+ return this._forexSymbols;
259
+ }
234
260
 
235
- return symbols;
236
- }, [ ]);
261
+ getForexQuotes() {
262
+ return this._forexQuotes;
237
263
  }
238
264
 
239
265
  setForexQuote(symbol, quote) {
240
266
  assert.argumentIsRequired(symbol, 'symbol', String);
241
267
  assert.argumentIsRequired(quote, 'quote', Object);
242
268
 
243
- this._forex[symbol] = quote;
269
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
270
+
271
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
272
+
273
+ if (index < 0) {
274
+ this._forexQuotes.push(rate);
275
+ } else {
276
+ this._forexQuotes[index] = rate;
277
+ }
244
278
  }
245
279
 
246
280
  getGroup(name, keys) {
@@ -283,5 +317,22 @@ module.exports = (() => {
283
317
  return ranges.map(range => null);
284
318
  }
285
319
 
320
+ function extractSymbolForBarchart(position) {
321
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
322
+ return position.instrument.symbol.barchart;
323
+ } else {
324
+ return null;
325
+ }
326
+ }
327
+
328
+ function extractSymbolForDisplay(position) {
329
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.display) {
330
+ return position.instrument.symbol.display;
331
+ } else {
332
+ return null;
333
+ }
334
+ }
335
+
336
+
286
337
  return PositionContainer;
287
338
  })();
@@ -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(actual.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.125",
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
 
@@ -808,11 +811,9 @@ module.exports = (() => {
808
811
  }, [ ]);
809
812
 
810
813
  this._symbols = this._items.reduce((map, item) => {
811
- const position = item.position;
812
-
813
- if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
814
- const symbol = position.instrument.symbol.barchart;
814
+ const symbol = extractSymbolForBarchart(item.position);
815
815
 
816
+ if (symbol) {
816
817
  if (!map.hasOwnProperty(symbol)) {
817
818
  map[symbol] = [ ];
818
819
  }
@@ -828,18 +829,29 @@ module.exports = (() => {
828
829
 
829
830
  if (position.instrument && position.instrument.currency) {
830
831
  const currency = position.instrument.currency;
832
+ const code = currency.code;
831
833
 
832
- if (!map.hasOwnProperty(currency)) {
833
- map[currency] = [ ];
834
+ if (!map.hasOwnProperty(code)) {
835
+ map[code] = [ ];
834
836
  }
835
837
 
836
- map[currency].push(item);
838
+ map[code].push(item);
837
839
  }
838
840
 
839
841
  return map;
840
842
  }, { });
841
843
 
842
- this._forex = { };
844
+ this._forexSymbols = Object.keys(this._currencies).reduce((symbols, code) => {
845
+ if (code !== DEFAULT_CURRENCY.code) {
846
+ symbols.push(`^${DEFAULT_CURRENCY.code}${code}`);
847
+ }
848
+
849
+ return symbols;
850
+ }, [ ]);
851
+
852
+ this._forexQuotes = this._forexSymbols.map((symbol) => {
853
+ return Rate.fromPair(Decimal.ONE, symbol);
854
+ });
843
855
 
844
856
  this._trees = definitions.reduce((map, treeDefinition) => {
845
857
  const tree = new Tree();
@@ -927,8 +939,26 @@ module.exports = (() => {
927
939
  return this._defaultCurrency;
928
940
  }
929
941
 
930
- getPositionSymbols() {
931
- return Object.keys(this._symbols);
942
+ getPositionSymbols(display) {
943
+ const symbols = this._items.reduce((symbols, item) => {
944
+ const position = item.position;
945
+
946
+ let symbol;
947
+
948
+ if (display) {
949
+ symbol = extractSymbolForDisplay(position);
950
+ } else {
951
+ symbol = extractSymbolForBarchart(position);
952
+ }
953
+
954
+ if (symbol !== null) {
955
+ symbols.push(symbol);
956
+ }
957
+
958
+ return symbols;
959
+ }, [ ]);
960
+
961
+ return array.unique(symbols);
932
962
  }
933
963
 
934
964
  setPositionQuote(symbol, quote) {
@@ -941,22 +971,26 @@ module.exports = (() => {
941
971
  }
942
972
 
943
973
  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
- }
974
+ return this._forexSymbols;
975
+ }
950
976
 
951
- return symbols;
952
- }, [ ]);
977
+ getForexQuotes() {
978
+ return this._forexQuotes;
953
979
  }
954
980
 
955
981
  setForexQuote(symbol, quote) {
956
982
  assert.argumentIsRequired(symbol, 'symbol', String);
957
983
  assert.argumentIsRequired(quote, 'quote', Object);
958
984
 
959
- this._forex[symbol] = quote;
985
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
986
+
987
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
988
+
989
+ if (index < 0) {
990
+ this._forexQuotes.push(rate);
991
+ } else {
992
+ this._forexQuotes[index] = rate;
993
+ }
960
994
  }
961
995
 
962
996
  getGroup(name, keys) {
@@ -999,16 +1033,34 @@ module.exports = (() => {
999
1033
  return ranges.map(range => null);
1000
1034
  }
1001
1035
 
1036
+ function extractSymbolForBarchart(position) {
1037
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
1038
+ return position.instrument.symbol.barchart;
1039
+ } else {
1040
+ return null;
1041
+ }
1042
+ }
1043
+
1044
+ function extractSymbolForDisplay(position) {
1045
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.display) {
1046
+ return position.instrument.symbol.display;
1047
+ } else {
1048
+ return null;
1049
+ }
1050
+ }
1051
+
1052
+
1002
1053
  return PositionContainer;
1003
1054
  })();
1004
1055
 
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){
1056
+ },{"./../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
1057
  const assert = require('@barchart/common-js/lang/assert'),
1007
1058
  Currency = require('@barchart/common-js/lang/Currency'),
1008
1059
  Decimal = require('@barchart/common-js/lang/Decimal'),
1009
1060
  Event = require('@barchart/common-js/messaging/Event'),
1010
1061
  formatter = require('@barchart/common-js/lang/formatter'),
1011
- is = require('@barchart/common-js/lang/is');
1062
+ is = require('@barchart/common-js/lang/is'),
1063
+ Rate = require('@barchart/common-js/lang/Rate');
1012
1064
 
1013
1065
  module.exports = (() => {
1014
1066
  'use strict';
@@ -1117,7 +1169,7 @@ module.exports = (() => {
1117
1169
  this._dataFormat.currentPrice = null;
1118
1170
  }
1119
1171
 
1120
- calculatePriceData(this, sender, false);
1172
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
1121
1173
  });
1122
1174
  });
1123
1175
 
@@ -1160,6 +1212,10 @@ module.exports = (() => {
1160
1212
  return this._excluded;
1161
1213
  }
1162
1214
 
1215
+ setForexQuote(quote) {
1216
+
1217
+ }
1218
+
1163
1219
  setExcluded(value) {
1164
1220
  assert.argumentIsRequired(value, 'value', Boolean);
1165
1221
 
@@ -1183,12 +1239,14 @@ module.exports = (() => {
1183
1239
  }
1184
1240
 
1185
1241
  refresh() {
1186
- calculateStaticData(this);
1187
- calculatePriceData(this, null, true);
1242
+ const rates = this._container.getForexQuotes();
1243
+
1244
+ calculateStaticData(this, rates);
1245
+ calculatePriceData(this, rates, null, true);
1188
1246
  }
1189
1247
 
1190
1248
  refreshMarketPercent() {
1191
- calculateMarketPercent(this, true);
1249
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
1192
1250
  }
1193
1251
 
1194
1252
  registerMarketPercentChangeHandler(handler) {
@@ -1228,7 +1286,7 @@ module.exports = (() => {
1228
1286
  return formatDecimal(decimal, currency.precision);
1229
1287
  }
1230
1288
 
1231
- function calculateStaticData(group) {
1289
+ function calculateStaticData(group, rates) {
1232
1290
  if (group.suspended) {
1233
1291
  return;
1234
1292
  }
@@ -1240,13 +1298,25 @@ module.exports = (() => {
1240
1298
 
1241
1299
  const items = group._items;
1242
1300
 
1301
+ const translate = (item, value) => {
1302
+ let translated;
1303
+
1304
+ if (item.currency !== currency) {
1305
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1306
+ } else {
1307
+ translated = value;
1308
+ }
1309
+
1310
+ return translated;
1311
+ };
1312
+
1243
1313
  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);
1314
+ updates.basis = updates.basis.add(translate(item, item.data.basis));
1315
+ updates.realized = updates.realized.add(translate(item, item.data.realized));
1316
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1317
+ updates.income = updates.income.add(translate(item, item.data.income));
1318
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1319
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
1250
1320
 
1251
1321
  return updates;
1252
1322
  }, {
@@ -1283,7 +1353,7 @@ module.exports = (() => {
1283
1353
  }
1284
1354
  }
1285
1355
 
1286
- function calculatePriceData(group, item, forceRefresh) {
1356
+ function calculatePriceData(group, rates, item, forceRefresh) {
1287
1357
  if (group.suspended) {
1288
1358
  return;
1289
1359
  }
@@ -1295,6 +1365,18 @@ module.exports = (() => {
1295
1365
 
1296
1366
  const currency = group.currency;
1297
1367
 
1368
+ const translate = (item, value) => {
1369
+ let translated;
1370
+
1371
+ if (item.currency !== currency) {
1372
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1373
+ } else {
1374
+ translated = value;
1375
+ }
1376
+
1377
+ return translated;
1378
+ };
1379
+
1298
1380
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1299
1381
 
1300
1382
  let updates;
@@ -1303,10 +1385,10 @@ module.exports = (() => {
1303
1385
  const items = group._items;
1304
1386
 
1305
1387
  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);
1388
+ updates.market = updates.market.add(translate(item, item.data.market));
1389
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1390
+ updates.unrealizedToday = updates.unrealizedToday.add(translate(item, item.data.unrealizedToday));
1391
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1310
1392
 
1311
1393
  return updates;
1312
1394
  }, {
@@ -1319,11 +1401,11 @@ module.exports = (() => {
1319
1401
  });
1320
1402
  } else {
1321
1403
  updates = {
1322
- market: actual.market.add(item.data.marketChange),
1404
+ market: actual.market.add(translate(item, item.data.marketChange)),
1323
1405
  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)
1406
+ unrealized: actual.unrealized.add(translate(item, item.data.unrealizedChange)),
1407
+ unrealizedToday: actual.unrealizedToday.add(translate(item, item.data.unrealizedTodayChange)),
1408
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrentChange))
1327
1409
  };
1328
1410
  }
1329
1411
 
@@ -1364,11 +1446,11 @@ module.exports = (() => {
1364
1446
  format.total = formatCurrency(actual.total, currency);
1365
1447
  format.totalNegative = actual.total.getIsNegative();
1366
1448
 
1367
- calculateMarketPercent(group, false);
1449
+ calculateMarketPercent(group, rates, false);
1368
1450
  calculateUnrealizedPercent(group);
1369
1451
  }
1370
1452
 
1371
- function calculateMarketPercent(group, silent) {
1453
+ function calculateMarketPercent(group, rates, silent) {
1372
1454
  if (group.suspended) {
1373
1455
  return;
1374
1456
  }
@@ -1384,7 +1466,15 @@ module.exports = (() => {
1384
1466
  const parentData = parent._dataActual;
1385
1467
 
1386
1468
  if (parentData.market !== null && !parentData.market.getIsZero()) {
1387
- marketPercent = actual.market.divide(parentData.market);
1469
+ let numerator;
1470
+
1471
+ if (group.currency !== parent.currency) {
1472
+ numerator = Rate.convert(actual.market, group.currency, parent.currency, ...rates);
1473
+ } else {
1474
+ numerator = actual.market;
1475
+ }
1476
+
1477
+ marketPercent = numerator.divide(parentData.market);
1388
1478
  } else {
1389
1479
  marketPercent = null;
1390
1480
  }
@@ -1419,9 +1509,10 @@ module.exports = (() => {
1419
1509
  return PositionGroup;
1420
1510
  })();
1421
1511
 
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){
1512
+ },{"@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
1513
  const array = require('@barchart/common-js/lang/array'),
1424
1514
  assert = require('@barchart/common-js/lang/assert'),
1515
+ Currency = require('@barchart/common-js/lang/Currency'),
1425
1516
  Decimal = require('@barchart/common-js/lang/Decimal'),
1426
1517
  Event = require('@barchart/common-js/messaging/Event'),
1427
1518
  is = require('@barchart/common-js/lang/is');
@@ -1438,6 +1529,7 @@ module.exports = (() => {
1438
1529
  constructor(portfolio, position, currentSummary, previousSummaries) {
1439
1530
  this._portfolio = portfolio;
1440
1531
  this._position = position;
1532
+ this._currency = position.instrument.currency || Currency.CAD;
1441
1533
 
1442
1534
  this._currentSummary = currentSummary || null;
1443
1535
  this._previousSummaries = previousSummaries || [ ];
@@ -1487,6 +1579,10 @@ module.exports = (() => {
1487
1579
  return this._position;
1488
1580
  }
1489
1581
 
1582
+ get currency() {
1583
+ return this._currency;
1584
+ }
1585
+
1490
1586
  get currentSummary() {
1491
1587
  return this._currentSummary;
1492
1588
  }
@@ -1524,7 +1620,7 @@ module.exports = (() => {
1524
1620
  assert.argumentIsRequired(value, 'value', Boolean);
1525
1621
 
1526
1622
  if (this._excluded !== value) {
1527
- this._excludedChangeEvent.fire(this, this._excluded = value);
1623
+ this._excludedChangeEvent.fire(this._excluded = value);
1528
1624
  }
1529
1625
  }
1530
1626
 
@@ -1678,7 +1774,7 @@ module.exports = (() => {
1678
1774
  return PositionItem;
1679
1775
  })();
1680
1776
 
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){
1777
+ },{"./../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
1778
  const assert = require('@barchart/common-js/lang/assert'),
1683
1779
  is = require('@barchart/common-js/lang/is');
1684
1780
 
@@ -1834,7 +1930,7 @@ module.exports = (() => {
1834
1930
  return PositionLevelDefinition;
1835
1931
  })();
1836
1932
 
1837
- },{"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20}],8:[function(require,module,exports){
1933
+ },{"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21}],8:[function(require,module,exports){
1838
1934
  const assert = require('@barchart/common-js/lang/assert');
1839
1935
 
1840
1936
  const PositionLevelDefinition = require('./PositionLevelDefinition');
@@ -1888,7 +1984,7 @@ module.exports = (() => {
1888
1984
  return PositionTreeDefinitions;
1889
1985
  })();
1890
1986
 
1891
- },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":18}],9:[function(require,module,exports){
1987
+ },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":19}],9:[function(require,module,exports){
1892
1988
  'use strict';
1893
1989
 
1894
1990
  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 +2293,7 @@ module.exports = function () {
2197
2293
  return Tree;
2198
2294
  }();
2199
2295
 
2200
- },{"./../lang/is":20}],10:[function(require,module,exports){
2296
+ },{"./../lang/is":21}],10:[function(require,module,exports){
2201
2297
  'use strict';
2202
2298
 
2203
2299
  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 +2437,7 @@ module.exports = function () {
2341
2437
  return ComparatorBuilder;
2342
2438
  }();
2343
2439
 
2344
- },{"./../../lang/assert":18,"./comparators":11}],11:[function(require,module,exports){
2440
+ },{"./../../lang/assert":19,"./comparators":11}],11:[function(require,module,exports){
2345
2441
  'use strict';
2346
2442
 
2347
2443
  var assert = require('./../../lang/assert');
@@ -2416,7 +2512,7 @@ module.exports = function () {
2416
2512
  };
2417
2513
  }();
2418
2514
 
2419
- },{"./../../lang/assert":18}],12:[function(require,module,exports){
2515
+ },{"./../../lang/assert":19}],12:[function(require,module,exports){
2420
2516
  'use strict';
2421
2517
 
2422
2518
  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 +2655,7 @@ module.exports = function () {
2559
2655
  return Currency;
2560
2656
  }();
2561
2657
 
2562
- },{"./Enum":16,"./assert":18,"./is":20}],13:[function(require,module,exports){
2658
+ },{"./Enum":16,"./assert":19,"./is":21}],13:[function(require,module,exports){
2563
2659
  'use strict';
2564
2660
 
2565
2661
  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 +3208,7 @@ module.exports = function () {
3112
3208
  return Day;
3113
3209
  }();
3114
3210
 
3115
- },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":18,"./is":20}],14:[function(require,module,exports){
3211
+ },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":19,"./is":21}],14:[function(require,module,exports){
3116
3212
  'use strict';
3117
3213
 
3118
3214
  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 +3788,7 @@ module.exports = function () {
3692
3788
  return Decimal;
3693
3789
  }();
3694
3790
 
3695
- },{"./Enum":16,"./assert":18,"./is":20,"big.js":22}],15:[function(require,module,exports){
3791
+ },{"./Enum":16,"./assert":19,"./is":21,"big.js":24}],15:[function(require,module,exports){
3696
3792
  'use strict';
3697
3793
 
3698
3794
  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 +3937,7 @@ module.exports = function () {
3841
3937
  return Disposable;
3842
3938
  }();
3843
3939
 
3844
- },{"./assert":18}],16:[function(require,module,exports){
3940
+ },{"./assert":19}],16:[function(require,module,exports){
3845
3941
  'use strict';
3846
3942
 
3847
3943
  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 +4079,262 @@ module.exports = function () {
3983
4079
  return Enum;
3984
4080
  }();
3985
4081
 
3986
- },{"./assert":18}],17:[function(require,module,exports){
4082
+ },{"./assert":19}],17:[function(require,module,exports){
4083
+ 'use strict';
4084
+
4085
+ 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; }; }();
4086
+
4087
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4088
+
4089
+ var assert = require('./assert'),
4090
+ memoize = require('./memoize');
4091
+
4092
+ var Currency = require('./Currency'),
4093
+ Decimal = require('./Decimal');
4094
+
4095
+ module.exports = function () {
4096
+ 'use strict';
4097
+
4098
+ /**
4099
+ * A component that represents an exchange rate, composed of a {@link Decimal}
4100
+ * value and two currencies -- a quote (i.e. the numerator) currency and a
4101
+ * base (i.e. denominator) currency.
4102
+ *
4103
+ * @public
4104
+ * @param {Number|String|Decimal} value - The rate
4105
+ * @param {Currency} numerator - The quote currency
4106
+ * @param {Currency} denominator - The base currency
4107
+ */
4108
+
4109
+ var Rate = function () {
4110
+ function Rate(value, numerator, denominator) {
4111
+ _classCallCheck(this, Rate);
4112
+
4113
+ assert.argumentIsRequired(numerator, 'numerator', Currency, 'Currency');
4114
+ assert.argumentIsRequired(denominator, 'denominator', Currency, 'Currency');
4115
+
4116
+ if (numerator === denominator) {
4117
+ throw new Error('A rate cannot use two identical currencies.');
4118
+ }
4119
+
4120
+ var decimal = getDecimal(value);
4121
+
4122
+ if (!decimal.getIsPositive()) {
4123
+ throw new Error('Rate value must be positive.');
4124
+ }
4125
+
4126
+ this._decimal = decimal;
4127
+ this._numerator = numerator;
4128
+ this._denominator = denominator;
4129
+ }
4130
+
4131
+ /**
4132
+ * The rate.
4133
+ *
4134
+ * @public
4135
+ * @returns {Decimal}
4136
+ */
4137
+
4138
+
4139
+ _createClass(Rate, [{
4140
+ key: 'invert',
4141
+
4142
+
4143
+ /**
4144
+ * Returns the equivalent rate with the numerator and denominator (i.e. the qoute and base)
4145
+ * currencies.
4146
+ *
4147
+ * @public
4148
+ * @returns {Rate}
4149
+ */
4150
+ value: function invert() {
4151
+ return new Rate(Decimal.ONE.divide(this._decimal), this._denominator, this._numerator);
4152
+ }
4153
+
4154
+ /**
4155
+ * Formats the currency pair as a string (e.g. "EURUSD" or "^EURUSD").
4156
+ *
4157
+ * @public
4158
+ * @param {Boolean=} useCarat - If true, a carat is used as a prefix to the resulting string.
4159
+ * @returns {string}
4160
+ */
4161
+
4162
+ }, {
4163
+ key: 'formatPair',
4164
+ value: function formatPair(useCarat) {
4165
+ assert.argumentIsOptional(useCarat, 'useCarat', Boolean);
4166
+
4167
+ return '' + (useCarat ? '^' : '') + this._numerator + this._denominator;
4168
+ }
4169
+
4170
+ /**
4171
+ * Creates a {@link Rate} instance, when given a value
4172
+ *
4173
+ * @public
4174
+ * @param {Number|String|Decimal} value - The rate.
4175
+ * @param {String} symbol - A string that can be parsed as a currency pair.
4176
+ * @returns {Rate}
4177
+ */
4178
+
4179
+ }, {
4180
+ key: 'toString',
4181
+ value: function toString() {
4182
+ return '[Rate]';
4183
+ }
4184
+ }, {
4185
+ key: 'decimal',
4186
+ get: function get() {
4187
+ return this._decimal;
4188
+ }
4189
+
4190
+ /**
4191
+ * The numerator (i.e. quote) currency. In other words,
4192
+ * this is EUR of the EURUSD pair.
4193
+ *
4194
+ * @public
4195
+ * @returns {Currency}
4196
+ */
4197
+
4198
+ }, {
4199
+ key: 'numerator',
4200
+ get: function get() {
4201
+ return this._numerator;
4202
+ }
4203
+
4204
+ /**
4205
+ * The quote (i.e. numerator) currency. In other words,
4206
+ * this is EUR of the EURUSD pair.
4207
+ *
4208
+ * @public
4209
+ * @returns {Currency}
4210
+ */
4211
+
4212
+ }, {
4213
+ key: 'quote',
4214
+ get: function get() {
4215
+ return this._numerator;
4216
+ }
4217
+
4218
+ /**
4219
+ * The denominator (i.e. base) currency. In other words,
4220
+ * this is USD of the EURUSD pair.
4221
+ *
4222
+ * @public
4223
+ * @returns {Currency}
4224
+ */
4225
+
4226
+ }, {
4227
+ key: 'denominator',
4228
+ get: function get() {
4229
+ return this._denominator;
4230
+ }
4231
+
4232
+ /**
4233
+ * The base (i.e. denominator) currency. In other words,
4234
+ * this is USD of the EURUSD pair.
4235
+ *
4236
+ * @public
4237
+ * @returns {Currency}
4238
+ */
4239
+
4240
+ }, {
4241
+ key: 'base',
4242
+ get: function get() {
4243
+ return this._denominator;
4244
+ }
4245
+ }], [{
4246
+ key: 'fromPair',
4247
+ value: function fromPair(value, symbol) {
4248
+ assert.argumentIsRequired(symbol, 'symbol', String);
4249
+
4250
+ var pair = parsePair(symbol);
4251
+
4252
+ return new Rate(value, Currency.parse(pair.numerator), Currency.parse(pair.denominator));
4253
+ }
4254
+
4255
+ /**
4256
+ * Given a {@link Decimal} value in a known currency, output
4257
+ * a {@link Decimal} converted to an alternate currency.
4258
+ *
4259
+ * @public
4260
+ * @param {Decimal} amount - The amount to convert.
4261
+ * @param {Currency} currency - The currency of the amount.
4262
+ * @param {Currency} desiredCurrency - The currency to convert to.
4263
+ * @param {...Rate} rates - A list of exchange rates to be used for the conversion.
4264
+ * @returns {Decimal}
4265
+ */
4266
+
4267
+ }, {
4268
+ key: 'convert',
4269
+ value: function convert(amount, currency, desiredCurrency) {
4270
+ assert.argumentIsRequired(amount, 'amount', Decimal, 'Decimal');
4271
+ assert.argumentIsRequired(currency, 'currency', Currency, 'Currency');
4272
+ assert.argumentIsRequired(desiredCurrency, 'desiredCurrency', Currency, 'Currency');
4273
+ //assert.argumentIsArray(rates, 'rates', Rate, 'Rate');
4274
+
4275
+ var converted = void 0;
4276
+
4277
+ if (currency === desiredCurrency) {
4278
+ converted = amount;
4279
+ } else {
4280
+ var numerator = desiredCurrency;
4281
+ var denominator = currency;
4282
+
4283
+ for (var _len = arguments.length, rates = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
4284
+ rates[_key - 3] = arguments[_key];
4285
+ }
4286
+
4287
+ var rate = rates.find(function (r) {
4288
+ return r.numerator === numerator && r.denominator === denominator || r.numerator === denominator && r.denominator === numerator;
4289
+ });
4290
+
4291
+ if (rate) {
4292
+ if (rate.numerator === denominator) {
4293
+ rate = rate.invert();
4294
+ }
4295
+ }
4296
+
4297
+ if (!rate) {
4298
+ throw new Error('Unable to perform conversion, given the rates provided.');
4299
+ }
4300
+
4301
+ converted = amount.multiply(rate.decimal);
4302
+ }
4303
+
4304
+ return converted;
4305
+ }
4306
+ }]);
4307
+
4308
+ return Rate;
4309
+ }();
4310
+
4311
+ var pairExpression = /^\^?([A-Z]{3})([A-Z]{3})$/;
4312
+
4313
+ function getDecimal(value) {
4314
+ if (value instanceof Decimal) {
4315
+ return value;
4316
+ } else {
4317
+ return new Decimal(value);
4318
+ }
4319
+ }
4320
+
4321
+ var parsePair = memoize.simple(function (symbol) {
4322
+ var match = symbol.match(pairExpression);
4323
+
4324
+ if (match === null) {
4325
+ throw new Error('The "pair" argument cannot be parsed.');
4326
+ }
4327
+
4328
+ return {
4329
+ numerator: match[2],
4330
+ denominator: match[1]
4331
+ };
4332
+ });
4333
+
4334
+ return Rate;
4335
+ }();
4336
+
4337
+ },{"./Currency":12,"./Decimal":14,"./assert":19,"./memoize":22}],18:[function(require,module,exports){
3987
4338
  'use strict';
3988
4339
 
3989
4340
  var assert = require('./assert'),
@@ -4364,7 +4715,7 @@ module.exports = function () {
4364
4715
  };
4365
4716
  }();
4366
4717
 
4367
- },{"./assert":18,"./is":20}],18:[function(require,module,exports){
4718
+ },{"./assert":19,"./is":21}],19:[function(require,module,exports){
4368
4719
  'use strict';
4369
4720
 
4370
4721
  var is = require('./is');
@@ -4512,7 +4863,7 @@ module.exports = function () {
4512
4863
  };
4513
4864
  }();
4514
4865
 
4515
- },{"./is":20}],19:[function(require,module,exports){
4866
+ },{"./is":21}],20:[function(require,module,exports){
4516
4867
  'use strict';
4517
4868
 
4518
4869
  module.exports = function () {
@@ -4577,7 +4928,7 @@ module.exports = function () {
4577
4928
  };
4578
4929
  }();
4579
4930
 
4580
- },{}],20:[function(require,module,exports){
4931
+ },{}],21:[function(require,module,exports){
4581
4932
  'use strict';
4582
4933
 
4583
4934
  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 +5151,80 @@ module.exports = function () {
4800
5151
  };
4801
5152
  }();
4802
5153
 
4803
- },{}],21:[function(require,module,exports){
5154
+ },{}],22:[function(require,module,exports){
5155
+ 'use strict';
5156
+
5157
+ var assert = require('./assert'),
5158
+ is = require('./is');
5159
+
5160
+ module.exports = function () {
5161
+ 'use strict';
5162
+
5163
+ /**
5164
+ * Utilities for caching results of function invocations (a.k.a. memoization).
5165
+ *
5166
+ * @public
5167
+ * @module lang/memoize
5168
+ */
5169
+
5170
+ return {
5171
+ /**
5172
+ * Memoizes a function that accepts a single argument only. Furthermore,
5173
+ * the parameter's toString function must return a unique value.
5174
+ *
5175
+ * @static
5176
+ * @public
5177
+ * @param {Function} fn - The function to memoize. This function should accept one parameters whose "toString" function outputs a unique value.
5178
+ */
5179
+ simple: function simple(fn) {
5180
+ var cache = {};
5181
+
5182
+ return function (x) {
5183
+ if (cache.hasOwnProperty(x)) {
5184
+ return cache[x];
5185
+ } else {
5186
+ return cache[x] = fn(x);
5187
+ }
5188
+ };
5189
+ },
5190
+
5191
+
5192
+ /**
5193
+ * Wraps a function. The resulting function will call the wrapped function
5194
+ * once and cache the result. If a specific duration is supplied, the
5195
+ * cache will be dropped after the duration expires and the wrapped
5196
+ * function will be invoked again.
5197
+ *
5198
+ * @public
5199
+ * @param {Function} fn
5200
+ * @param {Number} duration
5201
+ * @returns {Function}
5202
+ */
5203
+ cache: function cache(fn, duration) {
5204
+ assert.argumentIsRequired(fn, 'fn', Function);
5205
+ assert.argumentIsOptional(duration, 'duration', Number);
5206
+
5207
+ var durationToUse = duration || 0;
5208
+
5209
+ var executionTime = null;
5210
+ var cacheResult = null;
5211
+
5212
+ return function () {
5213
+ var currentTime = new Date().getTime();
5214
+
5215
+ if (executionTime === null || durationToUse > 0 && currentTime > executionTime + durationToUse) {
5216
+ executionTime = currentTime;
5217
+
5218
+ cacheResult = fn();
5219
+ }
5220
+
5221
+ return cacheResult;
5222
+ };
5223
+ }
5224
+ };
5225
+ }();
5226
+
5227
+ },{"./assert":19,"./is":21}],23:[function(require,module,exports){
4804
5228
  'use strict';
4805
5229
 
4806
5230
  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 +5396,7 @@ module.exports = function () {
4972
5396
  return Event;
4973
5397
  }();
4974
5398
 
4975
- },{"./../lang/Disposable":15,"./../lang/assert":18}],22:[function(require,module,exports){
5399
+ },{"./../lang/Disposable":15,"./../lang/assert":19}],24:[function(require,module,exports){
4976
5400
  /*
4977
5401
  * big.js v5.0.3
4978
5402
  * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
@@ -5913,7 +6337,7 @@ module.exports = function () {
5913
6337
  }
5914
6338
  })(this);
5915
6339
 
5916
- },{}],23:[function(require,module,exports){
6340
+ },{}],25:[function(require,module,exports){
5917
6341
  const Day = require('@barchart/common-js/lang/Day'),
5918
6342
  Decimal = require('@barchart/common-js/lang/Decimal');
5919
6343
 
@@ -6270,7 +6694,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
6270
6694
  });
6271
6695
  });
6272
6696
 
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){
6697
+ },{"./../../../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
6698
  const Currency = require('@barchart/common-js/lang/Currency'),
6275
6699
  Decimal = require('@barchart/common-js/lang/Decimal');
6276
6700
 
@@ -6379,4 +6803,4 @@ describe('When a position container data is gathered', () => {
6379
6803
  });
6380
6804
  });
6381
6805
 
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]);
6806
+ },{"./../../../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]);