@barchart/portfolio-api-common 1.0.120 → 1.0.124

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();
@@ -211,8 +225,26 @@ module.exports = (() => {
211
225
  return this._defaultCurrency;
212
226
  }
213
227
 
214
- getPositionSymbols() {
215
- return Object.keys(this._symbols);
228
+ getPositionSymbols(display) {
229
+ const symbols = this._items.reduce((symbols, item) => {
230
+ const position = item.position;
231
+
232
+ let symbol;
233
+
234
+ if (display) {
235
+ symbol = extractSymbolForDisplay(position);
236
+ } else {
237
+ symbol = extractSymbolForBarchart(position);
238
+ }
239
+
240
+ if (symbol !== null) {
241
+ symbols.push(symbol);
242
+ }
243
+
244
+ return symbols;
245
+ }, [ ]);
246
+
247
+ return array.unique(symbols);
216
248
  }
217
249
 
218
250
  setPositionQuote(symbol, quote) {
@@ -225,22 +257,26 @@ module.exports = (() => {
225
257
  }
226
258
 
227
259
  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
- }
260
+ return this._forexSymbols;
261
+ }
234
262
 
235
- return symbols;
236
- }, [ ]);
263
+ getForexQuotes() {
264
+ return this._forexQuotes;
237
265
  }
238
266
 
239
267
  setForexQuote(symbol, quote) {
240
268
  assert.argumentIsRequired(symbol, 'symbol', String);
241
269
  assert.argumentIsRequired(quote, 'quote', Object);
242
270
 
243
- this._forex[symbol] = quote;
271
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
272
+
273
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
274
+
275
+ if (index < 0) {
276
+ this._forexQuotes.push(rate);
277
+ } else {
278
+ this._forexQuotes[index] = rate;
279
+ }
244
280
  }
245
281
 
246
282
  getGroup(name, keys) {
@@ -283,5 +319,22 @@ module.exports = (() => {
283
319
  return ranges.map(range => null);
284
320
  }
285
321
 
322
+ function extractSymbolForBarchart(position) {
323
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
324
+ return position.instrument.symbol.barchart;
325
+ } else {
326
+ return null;
327
+ }
328
+ }
329
+
330
+ function extractSymbolForDisplay(position) {
331
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.display) {
332
+ return position.instrument.symbol.display;
333
+ } else {
334
+ return null;
335
+ }
336
+ }
337
+
338
+
286
339
  return PositionContainer;
287
340
  })();
@@ -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';
@@ -96,7 +97,7 @@ module.exports = (() => {
96
97
  if (this._single) {
97
98
  const precision = sender.position.instrument.currency.precision;
98
99
 
99
- this._dataActual.currentPrice = sender.data.currentPrice;
100
+ this._dataActual.currentPrice = quote.lastPrice;
100
101
  this._dataFormat.currentPrice = formatNumber(this._dataActual.currentPrice, precision);
101
102
 
102
103
  this._dataFormat.quoteLast = formatNumber(quote.previousPrice, precision);
@@ -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
  }
@@ -94,9 +100,6 @@ module.exports = (() => {
94
100
  this._previousQuote = this._currentQuote;
95
101
  this._currentQuote = quote;
96
102
 
97
- this._data.previousPrice = this._data.currentPrice;
98
- this._data.currentPrice = quote.lastPrice;
99
-
100
103
  this._quoteChangedEvent.fire(this._currentQuote);
101
104
  }
102
105
  }
@@ -105,7 +108,7 @@ module.exports = (() => {
105
108
  assert.argumentIsRequired(value, 'value', Boolean);
106
109
 
107
110
  if (this._excluded !== value) {
108
- this._excludedChangeEvent.fire(this, this._excluded = value);
111
+ this._excludedChangeEvent.fire(this._excluded = value);
109
112
  }
110
113
  }
111
114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.120",
3
+ "version": "1.0.124",
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();
@@ -927,8 +941,26 @@ module.exports = (() => {
927
941
  return this._defaultCurrency;
928
942
  }
929
943
 
930
- getPositionSymbols() {
931
- return Object.keys(this._symbols);
944
+ getPositionSymbols(display) {
945
+ const symbols = this._items.reduce((symbols, item) => {
946
+ const position = item.position;
947
+
948
+ let symbol;
949
+
950
+ if (display) {
951
+ symbol = extractSymbolForDisplay(position);
952
+ } else {
953
+ symbol = extractSymbolForBarchart(position);
954
+ }
955
+
956
+ if (symbol !== null) {
957
+ symbols.push(symbol);
958
+ }
959
+
960
+ return symbols;
961
+ }, [ ]);
962
+
963
+ return array.unique(symbols);
932
964
  }
933
965
 
934
966
  setPositionQuote(symbol, quote) {
@@ -941,22 +973,26 @@ module.exports = (() => {
941
973
  }
942
974
 
943
975
  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
- }
976
+ return this._forexSymbols;
977
+ }
950
978
 
951
- return symbols;
952
- }, [ ]);
979
+ getForexQuotes() {
980
+ return this._forexQuotes;
953
981
  }
954
982
 
955
983
  setForexQuote(symbol, quote) {
956
984
  assert.argumentIsRequired(symbol, 'symbol', String);
957
985
  assert.argumentIsRequired(quote, 'quote', Object);
958
986
 
959
- this._forex[symbol] = quote;
987
+ const rate = Rate.fromPair(quote.lastPrice, symbol);
988
+
989
+ const index = this._forexQuotes.findIndex(existing => existing.formatPair() === rate.formatPair());
990
+
991
+ if (index < 0) {
992
+ this._forexQuotes.push(rate);
993
+ } else {
994
+ this._forexQuotes[index] = rate;
995
+ }
960
996
  }
961
997
 
962
998
  getGroup(name, keys) {
@@ -999,16 +1035,34 @@ module.exports = (() => {
999
1035
  return ranges.map(range => null);
1000
1036
  }
1001
1037
 
1038
+ function extractSymbolForBarchart(position) {
1039
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
1040
+ return position.instrument.symbol.barchart;
1041
+ } else {
1042
+ return null;
1043
+ }
1044
+ }
1045
+
1046
+ function extractSymbolForDisplay(position) {
1047
+ if (position.instrument && position.instrument.symbol && position.instrument.symbol.display) {
1048
+ return position.instrument.symbol.display;
1049
+ } else {
1050
+ return null;
1051
+ }
1052
+ }
1053
+
1054
+
1002
1055
  return PositionContainer;
1003
1056
  })();
1004
1057
 
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){
1058
+ },{"./../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
1059
  const assert = require('@barchart/common-js/lang/assert'),
1007
1060
  Currency = require('@barchart/common-js/lang/Currency'),
1008
1061
  Decimal = require('@barchart/common-js/lang/Decimal'),
1009
1062
  Event = require('@barchart/common-js/messaging/Event'),
1010
1063
  formatter = require('@barchart/common-js/lang/formatter'),
1011
- is = require('@barchart/common-js/lang/is');
1064
+ is = require('@barchart/common-js/lang/is'),
1065
+ Rate = require('@barchart/common-js/lang/Rate');
1012
1066
 
1013
1067
  module.exports = (() => {
1014
1068
  'use strict';
@@ -1101,7 +1155,7 @@ module.exports = (() => {
1101
1155
  if (this._single) {
1102
1156
  const precision = sender.position.instrument.currency.precision;
1103
1157
 
1104
- this._dataActual.currentPrice = sender.data.currentPrice;
1158
+ this._dataActual.currentPrice = quote.lastPrice;
1105
1159
  this._dataFormat.currentPrice = formatNumber(this._dataActual.currentPrice, precision);
1106
1160
 
1107
1161
  this._dataFormat.quoteLast = formatNumber(quote.previousPrice, precision);
@@ -1117,7 +1171,7 @@ module.exports = (() => {
1117
1171
  this._dataFormat.currentPrice = null;
1118
1172
  }
1119
1173
 
1120
- calculatePriceData(this, sender, false);
1174
+ calculatePriceData(this, this._container.getForexQuotes(), sender, false);
1121
1175
  });
1122
1176
  });
1123
1177
 
@@ -1160,6 +1214,10 @@ module.exports = (() => {
1160
1214
  return this._excluded;
1161
1215
  }
1162
1216
 
1217
+ setForexQuote(quote) {
1218
+
1219
+ }
1220
+
1163
1221
  setExcluded(value) {
1164
1222
  assert.argumentIsRequired(value, 'value', Boolean);
1165
1223
 
@@ -1183,12 +1241,14 @@ module.exports = (() => {
1183
1241
  }
1184
1242
 
1185
1243
  refresh() {
1186
- calculateStaticData(this);
1187
- calculatePriceData(this, null, true);
1244
+ const rates = this._container.getForexQuotes();
1245
+
1246
+ calculateStaticData(this, rates);
1247
+ calculatePriceData(this, rates, null, true);
1188
1248
  }
1189
1249
 
1190
1250
  refreshMarketPercent() {
1191
- calculateMarketPercent(this, true);
1251
+ calculateMarketPercent(this, this._container.getForexQuotes(), true);
1192
1252
  }
1193
1253
 
1194
1254
  registerMarketPercentChangeHandler(handler) {
@@ -1228,7 +1288,7 @@ module.exports = (() => {
1228
1288
  return formatDecimal(decimal, currency.precision);
1229
1289
  }
1230
1290
 
1231
- function calculateStaticData(group) {
1291
+ function calculateStaticData(group, rates) {
1232
1292
  if (group.suspended) {
1233
1293
  return;
1234
1294
  }
@@ -1240,13 +1300,25 @@ module.exports = (() => {
1240
1300
 
1241
1301
  const items = group._items;
1242
1302
 
1303
+ const translate = (item, value) => {
1304
+ let translated;
1305
+
1306
+ if (item.currency !== currency) {
1307
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1308
+ } else {
1309
+ translated = value;
1310
+ }
1311
+
1312
+ return translated;
1313
+ };
1314
+
1243
1315
  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);
1316
+ updates.basis = updates.basis.add(translate(item, item.data.basis));
1317
+ updates.realized = updates.realized.add(translate(item, item.data.realized));
1318
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1319
+ updates.income = updates.income.add(translate(item, item.data.income));
1320
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1321
+ updates.summaryTotalPrevious = updates.summaryTotalPrevious.add(translate(item, item.data.summaryTotalPrevious));
1250
1322
 
1251
1323
  return updates;
1252
1324
  }, {
@@ -1283,7 +1355,7 @@ module.exports = (() => {
1283
1355
  }
1284
1356
  }
1285
1357
 
1286
- function calculatePriceData(group, item, forceRefresh) {
1358
+ function calculatePriceData(group, rates, item, forceRefresh) {
1287
1359
  if (group.suspended) {
1288
1360
  return;
1289
1361
  }
@@ -1295,6 +1367,18 @@ module.exports = (() => {
1295
1367
 
1296
1368
  const currency = group.currency;
1297
1369
 
1370
+ const translate = (item, value) => {
1371
+ let translated;
1372
+
1373
+ if (item.currency !== currency) {
1374
+ translated = Rate.convert(value, item.currency, currency, ...rates);
1375
+ } else {
1376
+ translated = value;
1377
+ }
1378
+
1379
+ return translated;
1380
+ };
1381
+
1298
1382
  const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1299
1383
 
1300
1384
  let updates;
@@ -1303,10 +1387,10 @@ module.exports = (() => {
1303
1387
  const items = group._items;
1304
1388
 
1305
1389
  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);
1390
+ updates.market = updates.market.add(translate(item, item.data.market));
1391
+ updates.unrealized = updates.unrealized.add(translate(item, item.data.unrealized));
1392
+ updates.unrealizedToday = updates.unrealizedToday.add(translate(item, item.data.unrealizedToday));
1393
+ updates.summaryTotalCurrent = updates.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrent));
1310
1394
 
1311
1395
  return updates;
1312
1396
  }, {
@@ -1319,11 +1403,11 @@ module.exports = (() => {
1319
1403
  });
1320
1404
  } else {
1321
1405
  updates = {
1322
- market: actual.market.add(item.data.marketChange),
1406
+ market: actual.market.add(translate(item, item.data.marketChange)),
1323
1407
  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)
1408
+ unrealized: actual.unrealized.add(translate(item, item.data.unrealizedChange)),
1409
+ unrealizedToday: actual.unrealizedToday.add(translate(item, item.data.unrealizedTodayChange)),
1410
+ summaryTotalCurrent: actual.summaryTotalCurrent.add(translate(item, item.data.summaryTotalCurrentChange))
1327
1411
  };
1328
1412
  }
1329
1413
 
@@ -1364,11 +1448,11 @@ module.exports = (() => {
1364
1448
  format.total = formatCurrency(actual.total, currency);
1365
1449
  format.totalNegative = actual.total.getIsNegative();
1366
1450
 
1367
- calculateMarketPercent(group, false);
1451
+ calculateMarketPercent(group, rates, false);
1368
1452
  calculateUnrealizedPercent(group);
1369
1453
  }
1370
1454
 
1371
- function calculateMarketPercent(group, silent) {
1455
+ function calculateMarketPercent(group, rates, silent) {
1372
1456
  if (group.suspended) {
1373
1457
  return;
1374
1458
  }
@@ -1384,7 +1468,15 @@ module.exports = (() => {
1384
1468
  const parentData = parent._dataActual;
1385
1469
 
1386
1470
  if (parentData.market !== null && !parentData.market.getIsZero()) {
1387
- marketPercent = actual.market.divide(parentData.market);
1471
+ let numerator;
1472
+
1473
+ if (group.currency !== parent.currency) {
1474
+ numerator = Rate.convert(actual.market, group.currency, parent.currency, ...rates);
1475
+ } else {
1476
+ numerator = actual.market;
1477
+ }
1478
+
1479
+ marketPercent = numerator.divide(parentData.market);
1388
1480
  } else {
1389
1481
  marketPercent = null;
1390
1482
  }
@@ -1419,9 +1511,10 @@ module.exports = (() => {
1419
1511
  return PositionGroup;
1420
1512
  })();
1421
1513
 
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){
1514
+ },{"@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
1515
  const array = require('@barchart/common-js/lang/array'),
1424
1516
  assert = require('@barchart/common-js/lang/assert'),
1517
+ Currency = require('@barchart/common-js/lang/Currency'),
1425
1518
  Decimal = require('@barchart/common-js/lang/Decimal'),
1426
1519
  Event = require('@barchart/common-js/messaging/Event'),
1427
1520
  is = require('@barchart/common-js/lang/is');
@@ -1438,6 +1531,7 @@ module.exports = (() => {
1438
1531
  constructor(portfolio, position, currentSummary, previousSummaries) {
1439
1532
  this._portfolio = portfolio;
1440
1533
  this._position = position;
1534
+ this._currency = position.instrument.currency || Currency.CAD;
1441
1535
 
1442
1536
  this._currentSummary = currentSummary || null;
1443
1537
  this._previousSummaries = previousSummaries || [ ];
@@ -1487,6 +1581,10 @@ module.exports = (() => {
1487
1581
  return this._position;
1488
1582
  }
1489
1583
 
1584
+ get currency() {
1585
+ return this._currency;
1586
+ }
1587
+
1490
1588
  get currentSummary() {
1491
1589
  return this._currentSummary;
1492
1590
  }
@@ -1516,9 +1614,6 @@ module.exports = (() => {
1516
1614
  this._previousQuote = this._currentQuote;
1517
1615
  this._currentQuote = quote;
1518
1616
 
1519
- this._data.previousPrice = this._data.currentPrice;
1520
- this._data.currentPrice = quote.lastPrice;
1521
-
1522
1617
  this._quoteChangedEvent.fire(this._currentQuote);
1523
1618
  }
1524
1619
  }
@@ -1527,7 +1622,7 @@ module.exports = (() => {
1527
1622
  assert.argumentIsRequired(value, 'value', Boolean);
1528
1623
 
1529
1624
  if (this._excluded !== value) {
1530
- this._excludedChangeEvent.fire(this, this._excluded = value);
1625
+ this._excludedChangeEvent.fire(this._excluded = value);
1531
1626
  }
1532
1627
  }
1533
1628
 
@@ -1681,7 +1776,7 @@ module.exports = (() => {
1681
1776
  return PositionItem;
1682
1777
  })();
1683
1778
 
1684
- },{"./../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){
1779
+ },{"./../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){
1685
1780
  const assert = require('@barchart/common-js/lang/assert'),
1686
1781
  is = require('@barchart/common-js/lang/is');
1687
1782
 
@@ -1837,7 +1932,7 @@ module.exports = (() => {
1837
1932
  return PositionLevelDefinition;
1838
1933
  })();
1839
1934
 
1840
- },{"@barchart/common-js/lang/assert":18,"@barchart/common-js/lang/is":20}],8:[function(require,module,exports){
1935
+ },{"@barchart/common-js/lang/assert":19,"@barchart/common-js/lang/is":21}],8:[function(require,module,exports){
1841
1936
  const assert = require('@barchart/common-js/lang/assert');
1842
1937
 
1843
1938
  const PositionLevelDefinition = require('./PositionLevelDefinition');
@@ -1891,7 +1986,7 @@ module.exports = (() => {
1891
1986
  return PositionTreeDefinitions;
1892
1987
  })();
1893
1988
 
1894
- },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":18}],9:[function(require,module,exports){
1989
+ },{"./PositionLevelDefinition":7,"@barchart/common-js/lang/assert":19}],9:[function(require,module,exports){
1895
1990
  'use strict';
1896
1991
 
1897
1992
  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; }; }();
@@ -2200,7 +2295,7 @@ module.exports = function () {
2200
2295
  return Tree;
2201
2296
  }();
2202
2297
 
2203
- },{"./../lang/is":20}],10:[function(require,module,exports){
2298
+ },{"./../lang/is":21}],10:[function(require,module,exports){
2204
2299
  'use strict';
2205
2300
 
2206
2301
  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; }; }();
@@ -2344,7 +2439,7 @@ module.exports = function () {
2344
2439
  return ComparatorBuilder;
2345
2440
  }();
2346
2441
 
2347
- },{"./../../lang/assert":18,"./comparators":11}],11:[function(require,module,exports){
2442
+ },{"./../../lang/assert":19,"./comparators":11}],11:[function(require,module,exports){
2348
2443
  'use strict';
2349
2444
 
2350
2445
  var assert = require('./../../lang/assert');
@@ -2419,7 +2514,7 @@ module.exports = function () {
2419
2514
  };
2420
2515
  }();
2421
2516
 
2422
- },{"./../../lang/assert":18}],12:[function(require,module,exports){
2517
+ },{"./../../lang/assert":19}],12:[function(require,module,exports){
2423
2518
  'use strict';
2424
2519
 
2425
2520
  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; }; }();
@@ -2562,7 +2657,7 @@ module.exports = function () {
2562
2657
  return Currency;
2563
2658
  }();
2564
2659
 
2565
- },{"./Enum":16,"./assert":18,"./is":20}],13:[function(require,module,exports){
2660
+ },{"./Enum":16,"./assert":19,"./is":21}],13:[function(require,module,exports){
2566
2661
  'use strict';
2567
2662
 
2568
2663
  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; }; }();
@@ -3115,7 +3210,7 @@ module.exports = function () {
3115
3210
  return Day;
3116
3211
  }();
3117
3212
 
3118
- },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":18,"./is":20}],14:[function(require,module,exports){
3213
+ },{"./../collections/sorting/ComparatorBuilder":10,"./../collections/sorting/comparators":11,"./assert":19,"./is":21}],14:[function(require,module,exports){
3119
3214
  'use strict';
3120
3215
 
3121
3216
  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; }; }();
@@ -3695,7 +3790,7 @@ module.exports = function () {
3695
3790
  return Decimal;
3696
3791
  }();
3697
3792
 
3698
- },{"./Enum":16,"./assert":18,"./is":20,"big.js":22}],15:[function(require,module,exports){
3793
+ },{"./Enum":16,"./assert":19,"./is":21,"big.js":24}],15:[function(require,module,exports){
3699
3794
  'use strict';
3700
3795
 
3701
3796
  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; }; }();
@@ -3844,7 +3939,7 @@ module.exports = function () {
3844
3939
  return Disposable;
3845
3940
  }();
3846
3941
 
3847
- },{"./assert":18}],16:[function(require,module,exports){
3942
+ },{"./assert":19}],16:[function(require,module,exports){
3848
3943
  'use strict';
3849
3944
 
3850
3945
  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; }; }();
@@ -3986,7 +4081,262 @@ module.exports = function () {
3986
4081
  return Enum;
3987
4082
  }();
3988
4083
 
3989
- },{"./assert":18}],17:[function(require,module,exports){
4084
+ },{"./assert":19}],17:[function(require,module,exports){
4085
+ 'use strict';
4086
+
4087
+ 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; }; }();
4088
+
4089
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4090
+
4091
+ var assert = require('./assert'),
4092
+ memoize = require('./memoize');
4093
+
4094
+ var Currency = require('./Currency'),
4095
+ Decimal = require('./Decimal');
4096
+
4097
+ module.exports = function () {
4098
+ 'use strict';
4099
+
4100
+ /**
4101
+ * A component that represents an exchange rate, composed of a {@link Decimal}
4102
+ * value and two currencies -- a quote (i.e. the numerator) currency and a
4103
+ * base (i.e. denominator) currency.
4104
+ *
4105
+ * @public
4106
+ * @param {Number|String|Decimal} value - The rate
4107
+ * @param {Currency} numerator - The quote currency
4108
+ * @param {Currency} denominator - The base currency
4109
+ */
4110
+
4111
+ var Rate = function () {
4112
+ function Rate(value, numerator, denominator) {
4113
+ _classCallCheck(this, Rate);
4114
+
4115
+ assert.argumentIsRequired(numerator, 'numerator', Currency, 'Currency');
4116
+ assert.argumentIsRequired(denominator, 'denominator', Currency, 'Currency');
4117
+
4118
+ if (numerator === denominator) {
4119
+ throw new Error('A rate cannot use two identical currencies.');
4120
+ }
4121
+
4122
+ var decimal = getDecimal(value);
4123
+
4124
+ if (!decimal.getIsPositive()) {
4125
+ throw new Error('Rate value must be positive.');
4126
+ }
4127
+
4128
+ this._decimal = decimal;
4129
+ this._numerator = numerator;
4130
+ this._denominator = denominator;
4131
+ }
4132
+
4133
+ /**
4134
+ * The rate.
4135
+ *
4136
+ * @public
4137
+ * @returns {Decimal}
4138
+ */
4139
+
4140
+
4141
+ _createClass(Rate, [{
4142
+ key: 'invert',
4143
+
4144
+
4145
+ /**
4146
+ * Returns the equivalent rate with the numerator and denominator (i.e. the qoute and base)
4147
+ * currencies.
4148
+ *
4149
+ * @public
4150
+ * @returns {Rate}
4151
+ */
4152
+ value: function invert() {
4153
+ return new Rate(Decimal.ONE.divide(this._decimal), this._denominator, this._numerator);
4154
+ }
4155
+
4156
+ /**
4157
+ * Formats the currency pair as a string (e.g. "EURUSD" or "^EURUSD").
4158
+ *
4159
+ * @public
4160
+ * @param {Boolean=} useCarat - If true, a carat is used as a prefix to the resulting string.
4161
+ * @returns {string}
4162
+ */
4163
+
4164
+ }, {
4165
+ key: 'formatPair',
4166
+ value: function formatPair(useCarat) {
4167
+ assert.argumentIsOptional(useCarat, 'useCarat', Boolean);
4168
+
4169
+ return '' + (useCarat ? '^' : '') + this._numerator + this._denominator;
4170
+ }
4171
+
4172
+ /**
4173
+ * Creates a {@link Rate} instance, when given a value
4174
+ *
4175
+ * @public
4176
+ * @param {Number|String|Decimal} value - The rate.
4177
+ * @param {String} symbol - A string that can be parsed as a currency pair.
4178
+ * @returns {Rate}
4179
+ */
4180
+
4181
+ }, {
4182
+ key: 'toString',
4183
+ value: function toString() {
4184
+ return '[Rate]';
4185
+ }
4186
+ }, {
4187
+ key: 'decimal',
4188
+ get: function get() {
4189
+ return this._decimal;
4190
+ }
4191
+
4192
+ /**
4193
+ * The numerator (i.e. quote) currency. In other words,
4194
+ * this is EUR of the EURUSD pair.
4195
+ *
4196
+ * @public
4197
+ * @returns {Currency}
4198
+ */
4199
+
4200
+ }, {
4201
+ key: 'numerator',
4202
+ get: function get() {
4203
+ return this._numerator;
4204
+ }
4205
+
4206
+ /**
4207
+ * The quote (i.e. numerator) currency. In other words,
4208
+ * this is EUR of the EURUSD pair.
4209
+ *
4210
+ * @public
4211
+ * @returns {Currency}
4212
+ */
4213
+
4214
+ }, {
4215
+ key: 'quote',
4216
+ get: function get() {
4217
+ return this._numerator;
4218
+ }
4219
+
4220
+ /**
4221
+ * The denominator (i.e. base) currency. In other words,
4222
+ * this is USD of the EURUSD pair.
4223
+ *
4224
+ * @public
4225
+ * @returns {Currency}
4226
+ */
4227
+
4228
+ }, {
4229
+ key: 'denominator',
4230
+ get: function get() {
4231
+ return this._denominator;
4232
+ }
4233
+
4234
+ /**
4235
+ * The base (i.e. denominator) currency. In other words,
4236
+ * this is USD of the EURUSD pair.
4237
+ *
4238
+ * @public
4239
+ * @returns {Currency}
4240
+ */
4241
+
4242
+ }, {
4243
+ key: 'base',
4244
+ get: function get() {
4245
+ return this._denominator;
4246
+ }
4247
+ }], [{
4248
+ key: 'fromPair',
4249
+ value: function fromPair(value, symbol) {
4250
+ assert.argumentIsRequired(symbol, 'symbol', String);
4251
+
4252
+ var pair = parsePair(symbol);
4253
+
4254
+ return new Rate(value, Currency.parse(pair.numerator), Currency.parse(pair.denominator));
4255
+ }
4256
+
4257
+ /**
4258
+ * Given a {@link Decimal} value in a known currency, output
4259
+ * a {@link Decimal} converted to an alternate currency.
4260
+ *
4261
+ * @public
4262
+ * @param {Decimal} amount - The amount to convert.
4263
+ * @param {Currency} currency - The currency of the amount.
4264
+ * @param {Currency} desiredCurrency - The currency to convert to.
4265
+ * @param {...Rate} rates - A list of exchange rates to be used for the conversion.
4266
+ * @returns {Decimal}
4267
+ */
4268
+
4269
+ }, {
4270
+ key: 'convert',
4271
+ value: function convert(amount, currency, desiredCurrency) {
4272
+ assert.argumentIsRequired(amount, 'amount', Decimal, 'Decimal');
4273
+ assert.argumentIsRequired(currency, 'currency', Currency, 'Currency');
4274
+ assert.argumentIsRequired(desiredCurrency, 'desiredCurrency', Currency, 'Currency');
4275
+ //assert.argumentIsArray(rates, 'rates', Rate, 'Rate');
4276
+
4277
+ var converted = void 0;
4278
+
4279
+ if (currency === desiredCurrency) {
4280
+ converted = amount;
4281
+ } else {
4282
+ var numerator = desiredCurrency;
4283
+ var denominator = currency;
4284
+
4285
+ for (var _len = arguments.length, rates = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
4286
+ rates[_key - 3] = arguments[_key];
4287
+ }
4288
+
4289
+ var rate = rates.find(function (r) {
4290
+ return r.numerator === numerator && r.denominator === denominator || r.numerator === denominator && r.denominator === numerator;
4291
+ });
4292
+
4293
+ if (rate) {
4294
+ if (rate.numerator === denominator) {
4295
+ rate = rate.invert();
4296
+ }
4297
+ }
4298
+
4299
+ if (!rate) {
4300
+ throw new Error('Unable to perform conversion, given the rates provided.');
4301
+ }
4302
+
4303
+ converted = amount.multiply(rate.decimal);
4304
+ }
4305
+
4306
+ return converted;
4307
+ }
4308
+ }]);
4309
+
4310
+ return Rate;
4311
+ }();
4312
+
4313
+ var pairExpression = /^\^?([A-Z]{3})([A-Z]{3})$/;
4314
+
4315
+ function getDecimal(value) {
4316
+ if (value instanceof Decimal) {
4317
+ return value;
4318
+ } else {
4319
+ return new Decimal(value);
4320
+ }
4321
+ }
4322
+
4323
+ var parsePair = memoize.simple(function (symbol) {
4324
+ var match = symbol.match(pairExpression);
4325
+
4326
+ if (match === null) {
4327
+ throw new Error('The "pair" argument cannot be parsed.');
4328
+ }
4329
+
4330
+ return {
4331
+ numerator: match[2],
4332
+ denominator: match[1]
4333
+ };
4334
+ });
4335
+
4336
+ return Rate;
4337
+ }();
4338
+
4339
+ },{"./Currency":12,"./Decimal":14,"./assert":19,"./memoize":22}],18:[function(require,module,exports){
3990
4340
  'use strict';
3991
4341
 
3992
4342
  var assert = require('./assert'),
@@ -4367,7 +4717,7 @@ module.exports = function () {
4367
4717
  };
4368
4718
  }();
4369
4719
 
4370
- },{"./assert":18,"./is":20}],18:[function(require,module,exports){
4720
+ },{"./assert":19,"./is":21}],19:[function(require,module,exports){
4371
4721
  'use strict';
4372
4722
 
4373
4723
  var is = require('./is');
@@ -4515,7 +4865,7 @@ module.exports = function () {
4515
4865
  };
4516
4866
  }();
4517
4867
 
4518
- },{"./is":20}],19:[function(require,module,exports){
4868
+ },{"./is":21}],20:[function(require,module,exports){
4519
4869
  'use strict';
4520
4870
 
4521
4871
  module.exports = function () {
@@ -4580,7 +4930,7 @@ module.exports = function () {
4580
4930
  };
4581
4931
  }();
4582
4932
 
4583
- },{}],20:[function(require,module,exports){
4933
+ },{}],21:[function(require,module,exports){
4584
4934
  'use strict';
4585
4935
 
4586
4936
  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; };
@@ -4803,7 +5153,80 @@ module.exports = function () {
4803
5153
  };
4804
5154
  }();
4805
5155
 
4806
- },{}],21:[function(require,module,exports){
5156
+ },{}],22:[function(require,module,exports){
5157
+ 'use strict';
5158
+
5159
+ var assert = require('./assert'),
5160
+ is = require('./is');
5161
+
5162
+ module.exports = function () {
5163
+ 'use strict';
5164
+
5165
+ /**
5166
+ * Utilities for caching results of function invocations (a.k.a. memoization).
5167
+ *
5168
+ * @public
5169
+ * @module lang/memoize
5170
+ */
5171
+
5172
+ return {
5173
+ /**
5174
+ * Memoizes a function that accepts a single argument only. Furthermore,
5175
+ * the parameter's toString function must return a unique value.
5176
+ *
5177
+ * @static
5178
+ * @public
5179
+ * @param {Function} fn - The function to memoize. This function should accept one parameters whose "toString" function outputs a unique value.
5180
+ */
5181
+ simple: function simple(fn) {
5182
+ var cache = {};
5183
+
5184
+ return function (x) {
5185
+ if (cache.hasOwnProperty(x)) {
5186
+ return cache[x];
5187
+ } else {
5188
+ return cache[x] = fn(x);
5189
+ }
5190
+ };
5191
+ },
5192
+
5193
+
5194
+ /**
5195
+ * Wraps a function. The resulting function will call the wrapped function
5196
+ * once and cache the result. If a specific duration is supplied, the
5197
+ * cache will be dropped after the duration expires and the wrapped
5198
+ * function will be invoked again.
5199
+ *
5200
+ * @public
5201
+ * @param {Function} fn
5202
+ * @param {Number} duration
5203
+ * @returns {Function}
5204
+ */
5205
+ cache: function cache(fn, duration) {
5206
+ assert.argumentIsRequired(fn, 'fn', Function);
5207
+ assert.argumentIsOptional(duration, 'duration', Number);
5208
+
5209
+ var durationToUse = duration || 0;
5210
+
5211
+ var executionTime = null;
5212
+ var cacheResult = null;
5213
+
5214
+ return function () {
5215
+ var currentTime = new Date().getTime();
5216
+
5217
+ if (executionTime === null || durationToUse > 0 && currentTime > executionTime + durationToUse) {
5218
+ executionTime = currentTime;
5219
+
5220
+ cacheResult = fn();
5221
+ }
5222
+
5223
+ return cacheResult;
5224
+ };
5225
+ }
5226
+ };
5227
+ }();
5228
+
5229
+ },{"./assert":19,"./is":21}],23:[function(require,module,exports){
4807
5230
  'use strict';
4808
5231
 
4809
5232
  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; }; }();
@@ -4975,7 +5398,7 @@ module.exports = function () {
4975
5398
  return Event;
4976
5399
  }();
4977
5400
 
4978
- },{"./../lang/Disposable":15,"./../lang/assert":18}],22:[function(require,module,exports){
5401
+ },{"./../lang/Disposable":15,"./../lang/assert":19}],24:[function(require,module,exports){
4979
5402
  /*
4980
5403
  * big.js v5.0.3
4981
5404
  * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
@@ -5916,7 +6339,7 @@ module.exports = function () {
5916
6339
  }
5917
6340
  })(this);
5918
6341
 
5919
- },{}],23:[function(require,module,exports){
6342
+ },{}],25:[function(require,module,exports){
5920
6343
  const Day = require('@barchart/common-js/lang/Day'),
5921
6344
  Decimal = require('@barchart/common-js/lang/Decimal');
5922
6345
 
@@ -6273,7 +6696,7 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
6273
6696
  });
6274
6697
  });
6275
6698
 
6276
- },{"./../../../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){
6699
+ },{"./../../../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){
6277
6700
  const Currency = require('@barchart/common-js/lang/Currency'),
6278
6701
  Decimal = require('@barchart/common-js/lang/Decimal');
6279
6702
 
@@ -6382,4 +6805,4 @@ describe('When a position container data is gathered', () => {
6382
6805
  });
6383
6806
  });
6384
6807
 
6385
- },{"./../../../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]);
6808
+ },{"./../../../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]);