@barchart/portfolio-api-common 1.0.62 → 1.0.66
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.
|
@@ -6,6 +6,8 @@ const array = require('@barchart/common-js/lang/array'),
|
|
|
6
6
|
is = require('@barchart/common-js/lang/is'),
|
|
7
7
|
Tree = require('@barchart/common-js/collections/Tree');
|
|
8
8
|
|
|
9
|
+
const InstrumentType = require('./../data/InstrumentType');
|
|
10
|
+
|
|
9
11
|
const PositionGroup = require('./PositionGroup'),
|
|
10
12
|
PositionItem = require('./PositionItem');
|
|
11
13
|
|
|
@@ -16,7 +18,10 @@ module.exports = (() => {
|
|
|
16
18
|
* @public
|
|
17
19
|
*/
|
|
18
20
|
class PositionContainer {
|
|
19
|
-
constructor(portfolios, positions, summaries, definitions) {
|
|
21
|
+
constructor(portfolios, positions, summaries, definitions, defaultCurrency) {
|
|
22
|
+
this._definitions = definitions;
|
|
23
|
+
this._defaultCurrency = defaultCurrency || Currency.CAD;
|
|
24
|
+
|
|
20
25
|
this._portfolios = portfolios.reduce((map, portfolio) => {
|
|
21
26
|
map[portfolio.portfolio] = portfolio;
|
|
22
27
|
|
|
@@ -48,11 +53,10 @@ module.exports = (() => {
|
|
|
48
53
|
}, [ ]);
|
|
49
54
|
|
|
50
55
|
this._symbols = this._items.reduce((map, item) => {
|
|
51
|
-
|
|
52
|
-
let symbol = null;
|
|
56
|
+
const position = item.position;
|
|
53
57
|
|
|
54
58
|
if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
|
|
55
|
-
symbol = position.instrument.symbol.barchart;
|
|
59
|
+
const symbol = position.instrument.symbol.barchart;
|
|
56
60
|
|
|
57
61
|
if (!map.hasOwnProperty(symbol)) {
|
|
58
62
|
map[symbol] = [ ];
|
|
@@ -64,7 +68,21 @@ module.exports = (() => {
|
|
|
64
68
|
return map;
|
|
65
69
|
}, { });
|
|
66
70
|
|
|
67
|
-
this.
|
|
71
|
+
this._currencies = this._items.reduce((map, item) => {
|
|
72
|
+
const position = item.position;
|
|
73
|
+
|
|
74
|
+
if (position.instrument && position.instrument.currency) {
|
|
75
|
+
const currency = position.instrument.currency;
|
|
76
|
+
|
|
77
|
+
if (!map.hasOwnProperty(currency)) {
|
|
78
|
+
map[currency] = [ ];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
map[currency].push(item);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return map;
|
|
85
|
+
}, { });
|
|
68
86
|
|
|
69
87
|
this._tree = new Tree();
|
|
70
88
|
|
|
@@ -73,6 +91,8 @@ module.exports = (() => {
|
|
|
73
91
|
return;
|
|
74
92
|
}
|
|
75
93
|
|
|
94
|
+
const parent = tree.getValue() || null;
|
|
95
|
+
|
|
76
96
|
const currentDefinition = definitions[0];
|
|
77
97
|
const additionalDefinitions = array.dropLeft(definitions);
|
|
78
98
|
|
|
@@ -80,13 +100,13 @@ module.exports = (() => {
|
|
|
80
100
|
const populatedGroups = Object.keys(populatedObjects).map(key => populatedObjects[key]).map((items) => {
|
|
81
101
|
const first = items[0];
|
|
82
102
|
|
|
83
|
-
return new PositionGroup(items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
|
|
103
|
+
return new PositionGroup(parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
|
|
84
104
|
});
|
|
85
105
|
|
|
86
106
|
const missingGroups = array.difference(currentDefinition.requiredGroups.map(group => group.description), populatedGroups.map(group => group.description));
|
|
87
107
|
|
|
88
108
|
const empty = missingGroups.map((description) => {
|
|
89
|
-
return new PositionGroup([ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
|
|
109
|
+
return new PositionGroup(parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
|
|
90
110
|
});
|
|
91
111
|
|
|
92
112
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -131,6 +151,10 @@ module.exports = (() => {
|
|
|
131
151
|
createGroups(this._tree, this._items, this._definitions);
|
|
132
152
|
}
|
|
133
153
|
|
|
154
|
+
get defaultCurrency() {
|
|
155
|
+
return this._defaultCurrency;
|
|
156
|
+
}
|
|
157
|
+
|
|
134
158
|
getSymbols() {
|
|
135
159
|
return Object.keys(this._symbols);
|
|
136
160
|
}
|
|
@@ -141,6 +165,22 @@ module.exports = (() => {
|
|
|
141
165
|
}
|
|
142
166
|
}
|
|
143
167
|
|
|
168
|
+
getCurrencySymbols() {
|
|
169
|
+
const codes = Object.keys(this._currencies);
|
|
170
|
+
|
|
171
|
+
return codes.reduce((symbols, code) => {
|
|
172
|
+
if (code !== this._defaultCurrency) {
|
|
173
|
+
symbols.push(`^${this._defaultCurrency}${code}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return symbols;
|
|
177
|
+
}, [ ]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
setExchangeRage(symbol, price) {
|
|
181
|
+
|
|
182
|
+
}
|
|
183
|
+
|
|
144
184
|
getGroup(keys) {
|
|
145
185
|
const node = keys.reduce((tree, key) => {
|
|
146
186
|
tree = tree.findChild(group => group.description === key);
|
|
@@ -11,7 +11,9 @@ module.exports = (() => {
|
|
|
11
11
|
* @public
|
|
12
12
|
*/
|
|
13
13
|
class PositionGroup {
|
|
14
|
-
constructor(items, currency, description, single) {
|
|
14
|
+
constructor(parent, items, currency, description, single) {
|
|
15
|
+
this._parent = parent || null;
|
|
16
|
+
|
|
15
17
|
this._items = items;
|
|
16
18
|
this._currency = currency;
|
|
17
19
|
|
|
@@ -20,33 +22,37 @@ module.exports = (() => {
|
|
|
20
22
|
this._single = is.boolean(single) && single;
|
|
21
23
|
|
|
22
24
|
this._dataFormat = { };
|
|
23
|
-
this.
|
|
25
|
+
this._dataActual = { };
|
|
24
26
|
|
|
25
27
|
this._dataFormat.description = this._description;
|
|
26
28
|
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
this._dataRaw.basis = null;
|
|
34
|
-
this._dataRaw.market = null;
|
|
29
|
+
this._dataActual.currentPrice = null;
|
|
30
|
+
this._dataActual.previousPrice = null;
|
|
31
|
+
this._dataActual.basis = null;
|
|
32
|
+
this._dataActual.market = null;
|
|
33
|
+
this._dataActual.marketPercent = null;
|
|
34
|
+
this._dataActual.unrealizedToday = null;
|
|
35
35
|
|
|
36
|
+
this._dataFormat.currentPrice = null;
|
|
37
|
+
this._dataFormat.previousPrice = null;
|
|
36
38
|
this._dataFormat.basis = null;
|
|
37
39
|
this._dataFormat.market = null;
|
|
40
|
+
this._dataFormat.marketPercent = null;
|
|
41
|
+
this._dataFormat.unrealizedToday = null;
|
|
42
|
+
|
|
43
|
+
this._dataFormat.unrealizedTodayNegative = false;
|
|
38
44
|
|
|
39
45
|
this._items.forEach((item) => {
|
|
40
46
|
item.registerPriceChangeHandler((data, sender) => {
|
|
41
47
|
if (this._single) {
|
|
42
|
-
this.
|
|
43
|
-
this._dataFormat.
|
|
48
|
+
this._dataActual.currentPrice = data.currentPrice;
|
|
49
|
+
this._dataFormat.currentPrice = format(data.currentPrice, sender.position.instrument.currency);
|
|
44
50
|
} else {
|
|
45
|
-
this.
|
|
46
|
-
this._dataFormat.
|
|
51
|
+
this._dataActual.currentPrice = null;
|
|
52
|
+
this._dataFormat.currentPrice = null;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
calculatePriceData(this,
|
|
55
|
+
calculatePriceData(this, sender);
|
|
50
56
|
});
|
|
51
57
|
});
|
|
52
58
|
|
|
@@ -79,64 +85,92 @@ module.exports = (() => {
|
|
|
79
85
|
}
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
function
|
|
83
|
-
|
|
88
|
+
function formatNumber(decimal, precision) {
|
|
89
|
+
if (decimal !== null) {
|
|
90
|
+
return formatter.numberToString(decimal.toFloat(), precision, ',', false);
|
|
91
|
+
} else {
|
|
92
|
+
return '--';
|
|
93
|
+
}
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
function formatPercent(decimal, precision) {
|
|
97
|
+
if (decimal !== null) {
|
|
98
|
+
return formatNumber(decimal.multiply(100));
|
|
99
|
+
} else {
|
|
100
|
+
return '--';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
90
103
|
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
function formatCurrency(decimal, currency) {
|
|
105
|
+
return formatNumber(decimal, currency.precision);
|
|
106
|
+
}
|
|
93
107
|
|
|
94
|
-
|
|
108
|
+
function calculateStaticData(group) {
|
|
109
|
+
const actual = group._dataActual;
|
|
110
|
+
const format = group._dataFormat;
|
|
95
111
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
updates.basis = updates.basis.add(item.data.basis);
|
|
112
|
+
const currency = group.currency;
|
|
113
|
+
|
|
114
|
+
const items = group._items;
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
basis: Decimal.ZERO
|
|
104
|
-
});
|
|
105
|
-
}
|
|
116
|
+
let updates = items.reduce((updates, item) => {
|
|
117
|
+
updates.basis = updates.basis.add(item.data.basis);
|
|
106
118
|
|
|
107
|
-
|
|
108
|
-
|
|
119
|
+
return updates;
|
|
120
|
+
}, {
|
|
121
|
+
basis: Decimal.ZERO
|
|
122
|
+
});
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
|
|
124
|
+
actual.basis = updates.basis;
|
|
125
|
+
|
|
126
|
+
format.basis = formatCurrency(updates.basis, currency);
|
|
112
127
|
}
|
|
113
128
|
|
|
114
|
-
function calculatePriceData(group) {
|
|
115
|
-
const
|
|
129
|
+
function calculatePriceData(group, item) {
|
|
130
|
+
const parent = group._parent;
|
|
116
131
|
|
|
117
|
-
|
|
132
|
+
const actual = group._dataActual;
|
|
133
|
+
const format = group._dataFormat;
|
|
134
|
+
|
|
135
|
+
const currency = group.currency;
|
|
118
136
|
|
|
119
|
-
|
|
120
|
-
updates = { };
|
|
137
|
+
let updates;
|
|
121
138
|
|
|
122
|
-
|
|
139
|
+
if (actual.market === null || actual.unrealizedToday === null) {
|
|
140
|
+
const items = group._items;
|
|
123
141
|
|
|
124
|
-
updates
|
|
125
|
-
} else {
|
|
126
|
-
updates = items.reduce(function(updates, item) {
|
|
142
|
+
updates = items.reduce((updates, item) => {
|
|
127
143
|
updates.market = updates.market.add(item.data.market);
|
|
144
|
+
updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
|
|
128
145
|
|
|
129
146
|
return updates;
|
|
130
147
|
}, {
|
|
131
|
-
market: Decimal.ZERO
|
|
148
|
+
market: Decimal.ZERO,
|
|
149
|
+
unrealizedToday: Decimal.ZERO
|
|
132
150
|
});
|
|
151
|
+
} else {
|
|
152
|
+
updates = {
|
|
153
|
+
market: actual.market.add(item.data.marketChange),
|
|
154
|
+
unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
|
|
155
|
+
};
|
|
133
156
|
}
|
|
157
|
+
|
|
158
|
+
if (parent !== null) {
|
|
159
|
+
const parentData = parent._dataActual;
|
|
134
160
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
161
|
+
if (parentData.market !== null && !parentData.market.getIsZero()) {
|
|
162
|
+
updates.marketPercent = updates.market.divide(parentData.market);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
actual.market = updates.market;
|
|
167
|
+
actual.marketPercent = updates.marketPercent;
|
|
168
|
+
actual.unrealizedToday = updates.unrealizedToday;
|
|
169
|
+
|
|
170
|
+
format.market = formatCurrency(updates.market, currency);
|
|
171
|
+
format.marketPercent = formatPercent(updates.unrealizedToday, 2);
|
|
172
|
+
format.unrealizedToday = formatCurrency(updates.unrealizedToday, currency);
|
|
173
|
+
format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
|
|
140
174
|
}
|
|
141
175
|
|
|
142
176
|
return PositionGroup;
|
|
@@ -19,10 +19,17 @@ module.exports = (() => {
|
|
|
19
19
|
|
|
20
20
|
this._data = { };
|
|
21
21
|
|
|
22
|
-
this._data.current = null;
|
|
23
|
-
this._data.previous = null;
|
|
24
22
|
this._data.basis = null;
|
|
25
23
|
|
|
24
|
+
this._data.currentPrice = null;
|
|
25
|
+
this._data.previousPrice = null;
|
|
26
|
+
|
|
27
|
+
this._data.market = null;
|
|
28
|
+
this._data.marketChange = null;
|
|
29
|
+
|
|
30
|
+
this._data.unrealizedToday = null;
|
|
31
|
+
this._data.unrealizedTodayChange = null;
|
|
32
|
+
|
|
26
33
|
calculateStaticData(this);
|
|
27
34
|
calculatePriceData(this, null);
|
|
28
35
|
|
|
@@ -47,7 +54,7 @@ module.exports = (() => {
|
|
|
47
54
|
|
|
48
55
|
setPrice(price) {
|
|
49
56
|
if (this._data.price !== price) {
|
|
50
|
-
calculatePriceData(this, this._data.
|
|
57
|
+
calculatePriceData(this, this._data.currentPrice = price);
|
|
51
58
|
|
|
52
59
|
this._priceChangeEvent.fire(this._data);
|
|
53
60
|
}
|
|
@@ -70,7 +77,7 @@ module.exports = (() => {
|
|
|
70
77
|
|
|
71
78
|
const data = item._data;
|
|
72
79
|
|
|
73
|
-
data.
|
|
80
|
+
data.previousPrice = position.previousPrice || null;
|
|
74
81
|
|
|
75
82
|
let basis;
|
|
76
83
|
|
|
@@ -103,7 +110,35 @@ module.exports = (() => {
|
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
|
|
113
|
+
let marketChange;
|
|
114
|
+
|
|
115
|
+
if (data.market === null) {
|
|
116
|
+
marketChange = market;
|
|
117
|
+
} else {
|
|
118
|
+
marketChange = market.subtract(data.market);
|
|
119
|
+
}
|
|
120
|
+
|
|
106
121
|
data.market = market;
|
|
122
|
+
data.marketChange = marketChange;
|
|
123
|
+
|
|
124
|
+
let unrealizedToday;
|
|
125
|
+
let unrealizedTodayChange;
|
|
126
|
+
|
|
127
|
+
if (data.previousPrice && price) {
|
|
128
|
+
unrealizedToday = market.subtract(snapshot.open.multiply(data.previousPrice));
|
|
129
|
+
|
|
130
|
+
if (data.unrealizedToday !== null) {
|
|
131
|
+
unrealizedTodayChange = unrealizedToday.subtract(data.unrealizedToday);
|
|
132
|
+
} else {
|
|
133
|
+
unrealizedTodayChange = unrealizedToday;
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
unrealizedToday = Decimal.ZERO;
|
|
137
|
+
unrealizedTodayChange = Decimal.ZERO;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
data.unrealizedToday = unrealizedToday;
|
|
141
|
+
data.unrealizedTodayChange = unrealizedTodayChange;
|
|
107
142
|
}
|
|
108
143
|
|
|
109
144
|
return PositionItem;
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -612,6 +612,8 @@ const array = require('@barchart/common-js/lang/array'),
|
|
|
612
612
|
is = require('@barchart/common-js/lang/is'),
|
|
613
613
|
Tree = require('@barchart/common-js/collections/Tree');
|
|
614
614
|
|
|
615
|
+
const InstrumentType = require('./../data/InstrumentType');
|
|
616
|
+
|
|
615
617
|
const PositionGroup = require('./PositionGroup'),
|
|
616
618
|
PositionItem = require('./PositionItem');
|
|
617
619
|
|
|
@@ -622,7 +624,10 @@ module.exports = (() => {
|
|
|
622
624
|
* @public
|
|
623
625
|
*/
|
|
624
626
|
class PositionContainer {
|
|
625
|
-
constructor(portfolios, positions, summaries, definitions) {
|
|
627
|
+
constructor(portfolios, positions, summaries, definitions, defaultCurrency) {
|
|
628
|
+
this._definitions = definitions;
|
|
629
|
+
this._defaultCurrency = defaultCurrency || Currency.CAD;
|
|
630
|
+
|
|
626
631
|
this._portfolios = portfolios.reduce((map, portfolio) => {
|
|
627
632
|
map[portfolio.portfolio] = portfolio;
|
|
628
633
|
|
|
@@ -654,11 +659,10 @@ module.exports = (() => {
|
|
|
654
659
|
}, [ ]);
|
|
655
660
|
|
|
656
661
|
this._symbols = this._items.reduce((map, item) => {
|
|
657
|
-
|
|
658
|
-
let symbol = null;
|
|
662
|
+
const position = item.position;
|
|
659
663
|
|
|
660
664
|
if (position.instrument && position.instrument.symbol && position.instrument.symbol.barchart) {
|
|
661
|
-
symbol = position.instrument.symbol.barchart;
|
|
665
|
+
const symbol = position.instrument.symbol.barchart;
|
|
662
666
|
|
|
663
667
|
if (!map.hasOwnProperty(symbol)) {
|
|
664
668
|
map[symbol] = [ ];
|
|
@@ -670,7 +674,21 @@ module.exports = (() => {
|
|
|
670
674
|
return map;
|
|
671
675
|
}, { });
|
|
672
676
|
|
|
673
|
-
this.
|
|
677
|
+
this._currencies = this._items.reduce((map, item) => {
|
|
678
|
+
const position = item.position;
|
|
679
|
+
|
|
680
|
+
if (position.instrument && position.instrument.currency) {
|
|
681
|
+
const currency = position.instrument.currency;
|
|
682
|
+
|
|
683
|
+
if (!map.hasOwnProperty(currency)) {
|
|
684
|
+
map[currency] = [ ];
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
map[currency].push(item);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return map;
|
|
691
|
+
}, { });
|
|
674
692
|
|
|
675
693
|
this._tree = new Tree();
|
|
676
694
|
|
|
@@ -679,6 +697,8 @@ module.exports = (() => {
|
|
|
679
697
|
return;
|
|
680
698
|
}
|
|
681
699
|
|
|
700
|
+
const parent = tree.getValue() || null;
|
|
701
|
+
|
|
682
702
|
const currentDefinition = definitions[0];
|
|
683
703
|
const additionalDefinitions = array.dropLeft(definitions);
|
|
684
704
|
|
|
@@ -686,13 +706,13 @@ module.exports = (() => {
|
|
|
686
706
|
const populatedGroups = Object.keys(populatedObjects).map(key => populatedObjects[key]).map((items) => {
|
|
687
707
|
const first = items[0];
|
|
688
708
|
|
|
689
|
-
return new PositionGroup(items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
|
|
709
|
+
return new PositionGroup(parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
|
|
690
710
|
});
|
|
691
711
|
|
|
692
712
|
const missingGroups = array.difference(currentDefinition.requiredGroups.map(group => group.description), populatedGroups.map(group => group.description));
|
|
693
713
|
|
|
694
714
|
const empty = missingGroups.map((description) => {
|
|
695
|
-
return new PositionGroup([ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
|
|
715
|
+
return new PositionGroup(parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
|
|
696
716
|
});
|
|
697
717
|
|
|
698
718
|
const compositeGroups = populatedGroups.concat(empty);
|
|
@@ -737,6 +757,10 @@ module.exports = (() => {
|
|
|
737
757
|
createGroups(this._tree, this._items, this._definitions);
|
|
738
758
|
}
|
|
739
759
|
|
|
760
|
+
get defaultCurrency() {
|
|
761
|
+
return this._defaultCurrency;
|
|
762
|
+
}
|
|
763
|
+
|
|
740
764
|
getSymbols() {
|
|
741
765
|
return Object.keys(this._symbols);
|
|
742
766
|
}
|
|
@@ -747,6 +771,22 @@ module.exports = (() => {
|
|
|
747
771
|
}
|
|
748
772
|
}
|
|
749
773
|
|
|
774
|
+
getCurrencySymbols() {
|
|
775
|
+
const codes = Object.keys(this._currencies);
|
|
776
|
+
|
|
777
|
+
return codes.reduce((symbols, code) => {
|
|
778
|
+
if (code !== this._defaultCurrency) {
|
|
779
|
+
symbols.push(`^${this._defaultCurrency}${code}`);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return symbols;
|
|
783
|
+
}, [ ]);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
setExchangeRage(symbol, price) {
|
|
787
|
+
|
|
788
|
+
}
|
|
789
|
+
|
|
750
790
|
getGroup(keys) {
|
|
751
791
|
const node = keys.reduce((tree, key) => {
|
|
752
792
|
tree = tree.findChild(group => group.description === key);
|
|
@@ -775,7 +815,7 @@ module.exports = (() => {
|
|
|
775
815
|
return PositionContainer;
|
|
776
816
|
})();
|
|
777
817
|
|
|
778
|
-
},{"./PositionGroup":5,"./PositionItem":7,"@barchart/common-js/collections/Tree":8,"@barchart/common-js/collections/sorting/ComparatorBuilder":9,"@barchart/common-js/collections/sorting/comparators":10,"@barchart/common-js/lang/Currency":11,"@barchart/common-js/lang/array":16,"@barchart/common-js/lang/assert":17,"@barchart/common-js/lang/is":19}],5:[function(require,module,exports){
|
|
818
|
+
},{"./../data/InstrumentType":1,"./PositionGroup":5,"./PositionItem":7,"@barchart/common-js/collections/Tree":8,"@barchart/common-js/collections/sorting/ComparatorBuilder":9,"@barchart/common-js/collections/sorting/comparators":10,"@barchart/common-js/lang/Currency":11,"@barchart/common-js/lang/array":16,"@barchart/common-js/lang/assert":17,"@barchart/common-js/lang/is":19}],5:[function(require,module,exports){
|
|
779
819
|
const assert = require('@barchart/common-js/lang/assert'),
|
|
780
820
|
Currency = require('@barchart/common-js/lang/Currency'),
|
|
781
821
|
Decimal = require('@barchart/common-js/lang/Decimal'),
|
|
@@ -789,7 +829,9 @@ module.exports = (() => {
|
|
|
789
829
|
* @public
|
|
790
830
|
*/
|
|
791
831
|
class PositionGroup {
|
|
792
|
-
constructor(items, currency, description, single) {
|
|
832
|
+
constructor(parent, items, currency, description, single) {
|
|
833
|
+
this._parent = parent || null;
|
|
834
|
+
|
|
793
835
|
this._items = items;
|
|
794
836
|
this._currency = currency;
|
|
795
837
|
|
|
@@ -798,33 +840,37 @@ module.exports = (() => {
|
|
|
798
840
|
this._single = is.boolean(single) && single;
|
|
799
841
|
|
|
800
842
|
this._dataFormat = { };
|
|
801
|
-
this.
|
|
843
|
+
this._dataActual = { };
|
|
802
844
|
|
|
803
845
|
this._dataFormat.description = this._description;
|
|
804
846
|
|
|
805
|
-
this.
|
|
806
|
-
this.
|
|
807
|
-
|
|
808
|
-
this.
|
|
809
|
-
this.
|
|
810
|
-
|
|
811
|
-
this._dataRaw.basis = null;
|
|
812
|
-
this._dataRaw.market = null;
|
|
847
|
+
this._dataActual.currentPrice = null;
|
|
848
|
+
this._dataActual.previousPrice = null;
|
|
849
|
+
this._dataActual.basis = null;
|
|
850
|
+
this._dataActual.market = null;
|
|
851
|
+
this._dataActual.marketPercent = null;
|
|
852
|
+
this._dataActual.unrealizedToday = null;
|
|
813
853
|
|
|
854
|
+
this._dataFormat.currentPrice = null;
|
|
855
|
+
this._dataFormat.previousPrice = null;
|
|
814
856
|
this._dataFormat.basis = null;
|
|
815
857
|
this._dataFormat.market = null;
|
|
858
|
+
this._dataFormat.marketPercent = null;
|
|
859
|
+
this._dataFormat.unrealizedToday = null;
|
|
860
|
+
|
|
861
|
+
this._dataFormat.unrealizedTodayNegative = false;
|
|
816
862
|
|
|
817
863
|
this._items.forEach((item) => {
|
|
818
864
|
item.registerPriceChangeHandler((data, sender) => {
|
|
819
865
|
if (this._single) {
|
|
820
|
-
this.
|
|
821
|
-
this._dataFormat.
|
|
866
|
+
this._dataActual.currentPrice = data.currentPrice;
|
|
867
|
+
this._dataFormat.currentPrice = format(data.currentPrice, sender.position.instrument.currency);
|
|
822
868
|
} else {
|
|
823
|
-
this.
|
|
824
|
-
this._dataFormat.
|
|
869
|
+
this._dataActual.currentPrice = null;
|
|
870
|
+
this._dataFormat.currentPrice = null;
|
|
825
871
|
}
|
|
826
872
|
|
|
827
|
-
calculatePriceData(this,
|
|
873
|
+
calculatePriceData(this, sender);
|
|
828
874
|
});
|
|
829
875
|
});
|
|
830
876
|
|
|
@@ -857,64 +903,92 @@ module.exports = (() => {
|
|
|
857
903
|
}
|
|
858
904
|
}
|
|
859
905
|
|
|
860
|
-
function
|
|
861
|
-
|
|
906
|
+
function formatNumber(decimal, precision) {
|
|
907
|
+
if (decimal !== null) {
|
|
908
|
+
return formatter.numberToString(decimal.toFloat(), precision, ',', false);
|
|
909
|
+
} else {
|
|
910
|
+
return '--';
|
|
911
|
+
}
|
|
862
912
|
}
|
|
863
913
|
|
|
864
|
-
function
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
914
|
+
function formatPercent(decimal, precision) {
|
|
915
|
+
if (decimal !== null) {
|
|
916
|
+
return formatNumber(decimal.multiply(100));
|
|
917
|
+
} else {
|
|
918
|
+
return '--';
|
|
919
|
+
}
|
|
920
|
+
}
|
|
868
921
|
|
|
869
|
-
|
|
870
|
-
|
|
922
|
+
function formatCurrency(decimal, currency) {
|
|
923
|
+
return formatNumber(decimal, currency.precision);
|
|
924
|
+
}
|
|
871
925
|
|
|
872
|
-
|
|
926
|
+
function calculateStaticData(group) {
|
|
927
|
+
const actual = group._dataActual;
|
|
928
|
+
const format = group._dataFormat;
|
|
873
929
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
updates.basis = updates.basis.add(item.data.basis);
|
|
930
|
+
const currency = group.currency;
|
|
931
|
+
|
|
932
|
+
const items = group._items;
|
|
878
933
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
basis: Decimal.ZERO
|
|
882
|
-
});
|
|
883
|
-
}
|
|
934
|
+
let updates = items.reduce((updates, item) => {
|
|
935
|
+
updates.basis = updates.basis.add(item.data.basis);
|
|
884
936
|
|
|
885
|
-
|
|
886
|
-
|
|
937
|
+
return updates;
|
|
938
|
+
}, {
|
|
939
|
+
basis: Decimal.ZERO
|
|
940
|
+
});
|
|
887
941
|
|
|
888
|
-
|
|
889
|
-
|
|
942
|
+
actual.basis = updates.basis;
|
|
943
|
+
|
|
944
|
+
format.basis = formatCurrency(updates.basis, currency);
|
|
890
945
|
}
|
|
891
946
|
|
|
892
|
-
function calculatePriceData(group) {
|
|
893
|
-
const
|
|
947
|
+
function calculatePriceData(group, item) {
|
|
948
|
+
const parent = group._parent;
|
|
894
949
|
|
|
895
|
-
|
|
950
|
+
const actual = group._dataActual;
|
|
951
|
+
const format = group._dataFormat;
|
|
896
952
|
|
|
897
|
-
|
|
898
|
-
updates = { };
|
|
953
|
+
const currency = group.currency;
|
|
899
954
|
|
|
900
|
-
|
|
955
|
+
let updates;
|
|
901
956
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
957
|
+
if (actual.market === null || actual.unrealizedToday === null) {
|
|
958
|
+
const items = group._items;
|
|
959
|
+
|
|
960
|
+
updates = items.reduce((updates, item) => {
|
|
905
961
|
updates.market = updates.market.add(item.data.market);
|
|
962
|
+
updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
|
|
906
963
|
|
|
907
964
|
return updates;
|
|
908
965
|
}, {
|
|
909
|
-
market: Decimal.ZERO
|
|
966
|
+
market: Decimal.ZERO,
|
|
967
|
+
unrealizedToday: Decimal.ZERO
|
|
910
968
|
});
|
|
969
|
+
} else {
|
|
970
|
+
updates = {
|
|
971
|
+
market: actual.market.add(item.data.marketChange),
|
|
972
|
+
unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
|
|
973
|
+
};
|
|
911
974
|
}
|
|
975
|
+
|
|
976
|
+
if (parent !== null) {
|
|
977
|
+
const parentData = parent._dataActual;
|
|
912
978
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
979
|
+
if (parentData.market !== null && !parentData.market.getIsZero()) {
|
|
980
|
+
updates.marketPercent = updates.market.divide(parentData.market);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
actual.market = updates.market;
|
|
985
|
+
actual.marketPercent = updates.marketPercent;
|
|
986
|
+
actual.unrealizedToday = updates.unrealizedToday;
|
|
987
|
+
|
|
988
|
+
format.market = formatCurrency(updates.market, currency);
|
|
989
|
+
format.marketPercent = formatPercent(updates.unrealizedToday, 2);
|
|
990
|
+
format.unrealizedToday = formatCurrency(updates.unrealizedToday, currency);
|
|
991
|
+
format.unrealizedTodayNegative = actual.unrealizedToday.getIsNegative();
|
|
918
992
|
}
|
|
919
993
|
|
|
920
994
|
return PositionGroup;
|
|
@@ -992,10 +1066,17 @@ module.exports = (() => {
|
|
|
992
1066
|
|
|
993
1067
|
this._data = { };
|
|
994
1068
|
|
|
995
|
-
this._data.current = null;
|
|
996
|
-
this._data.previous = null;
|
|
997
1069
|
this._data.basis = null;
|
|
998
1070
|
|
|
1071
|
+
this._data.currentPrice = null;
|
|
1072
|
+
this._data.previousPrice = null;
|
|
1073
|
+
|
|
1074
|
+
this._data.market = null;
|
|
1075
|
+
this._data.marketChange = null;
|
|
1076
|
+
|
|
1077
|
+
this._data.unrealizedToday = null;
|
|
1078
|
+
this._data.unrealizedTodayChange = null;
|
|
1079
|
+
|
|
999
1080
|
calculateStaticData(this);
|
|
1000
1081
|
calculatePriceData(this, null);
|
|
1001
1082
|
|
|
@@ -1020,7 +1101,7 @@ module.exports = (() => {
|
|
|
1020
1101
|
|
|
1021
1102
|
setPrice(price) {
|
|
1022
1103
|
if (this._data.price !== price) {
|
|
1023
|
-
calculatePriceData(this, this._data.
|
|
1104
|
+
calculatePriceData(this, this._data.currentPrice = price);
|
|
1024
1105
|
|
|
1025
1106
|
this._priceChangeEvent.fire(this._data);
|
|
1026
1107
|
}
|
|
@@ -1043,7 +1124,7 @@ module.exports = (() => {
|
|
|
1043
1124
|
|
|
1044
1125
|
const data = item._data;
|
|
1045
1126
|
|
|
1046
|
-
data.
|
|
1127
|
+
data.previousPrice = position.previousPrice || null;
|
|
1047
1128
|
|
|
1048
1129
|
let basis;
|
|
1049
1130
|
|
|
@@ -1076,7 +1157,35 @@ module.exports = (() => {
|
|
|
1076
1157
|
}
|
|
1077
1158
|
}
|
|
1078
1159
|
|
|
1160
|
+
let marketChange;
|
|
1161
|
+
|
|
1162
|
+
if (data.market === null) {
|
|
1163
|
+
marketChange = market;
|
|
1164
|
+
} else {
|
|
1165
|
+
marketChange = market.subtract(data.market);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1079
1168
|
data.market = market;
|
|
1169
|
+
data.marketChange = marketChange;
|
|
1170
|
+
|
|
1171
|
+
let unrealizedToday;
|
|
1172
|
+
let unrealizedTodayChange;
|
|
1173
|
+
|
|
1174
|
+
if (data.previousPrice && price) {
|
|
1175
|
+
unrealizedToday = market.subtract(snapshot.open.multiply(data.previousPrice));
|
|
1176
|
+
|
|
1177
|
+
if (data.unrealizedToday !== null) {
|
|
1178
|
+
unrealizedTodayChange = unrealizedToday.subtract(data.unrealizedToday);
|
|
1179
|
+
} else {
|
|
1180
|
+
unrealizedTodayChange = unrealizedToday;
|
|
1181
|
+
}
|
|
1182
|
+
} else {
|
|
1183
|
+
unrealizedToday = Decimal.ZERO;
|
|
1184
|
+
unrealizedTodayChange = Decimal.ZERO;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
data.unrealizedToday = unrealizedToday;
|
|
1188
|
+
data.unrealizedTodayChange = unrealizedTodayChange;
|
|
1080
1189
|
}
|
|
1081
1190
|
|
|
1082
1191
|
return PositionItem;
|