@barchart/portfolio-api-common 1.0.61 → 1.0.65
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,37 +22,42 @@ 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.unrealizedTodayPositive = true;
|
|
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
|
|
|
53
59
|
calculateStaticData(this);
|
|
60
|
+
calculatePriceData(this);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
get items() {
|
|
@@ -78,64 +85,92 @@ module.exports = (() => {
|
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
function
|
|
82
|
-
|
|
88
|
+
function formatNumber(decimal, precision) {
|
|
89
|
+
if (decimal !== null) {
|
|
90
|
+
return formatter.numberToString(decimal.toFloat(), precision, ',', false);
|
|
91
|
+
} else {
|
|
92
|
+
return '--';
|
|
93
|
+
}
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
function formatPercent(decimal, precision) {
|
|
97
|
+
if (decimal !== null) {
|
|
98
|
+
return formatNumber(decimal.multiply(100));
|
|
99
|
+
} else {
|
|
100
|
+
return '--';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
function formatCurrency(decimal, currency) {
|
|
105
|
+
return formatNumber(decimal, currency.precision);
|
|
106
|
+
}
|
|
92
107
|
|
|
93
|
-
|
|
108
|
+
function calculateStaticData(group) {
|
|
109
|
+
const actual = group._dataActual;
|
|
110
|
+
const format = group._dataFormat;
|
|
94
111
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
updates.basis = updates.basis.add(item.data.basis);
|
|
112
|
+
const currency = group.currency;
|
|
113
|
+
|
|
114
|
+
const items = group._items;
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
basis: Decimal.ZERO
|
|
103
|
-
});
|
|
104
|
-
}
|
|
116
|
+
let updates = items.reduce((updates, item) => {
|
|
117
|
+
updates.basis = updates.basis.add(item.data.basis);
|
|
105
118
|
|
|
106
|
-
|
|
107
|
-
|
|
119
|
+
return updates;
|
|
120
|
+
}, {
|
|
121
|
+
basis: Decimal.ZERO
|
|
122
|
+
});
|
|
108
123
|
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
actual.basis = updates.basis;
|
|
125
|
+
|
|
126
|
+
format.basis = formatCurrency(updates.basis, currency);
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
function calculatePriceData(group) {
|
|
114
|
-
const
|
|
129
|
+
function calculatePriceData(group, item) {
|
|
130
|
+
const parent = group._parent;
|
|
115
131
|
|
|
116
|
-
|
|
132
|
+
const actual = group._dataActual;
|
|
133
|
+
const format = group._dataFormat;
|
|
134
|
+
|
|
135
|
+
const currency = group.currency;
|
|
117
136
|
|
|
118
|
-
|
|
119
|
-
updates = { };
|
|
137
|
+
let updates;
|
|
120
138
|
|
|
121
|
-
|
|
139
|
+
if (actual.market === null || actual.unrealizedToday === null) {
|
|
140
|
+
const items = group._items;
|
|
122
141
|
|
|
123
|
-
updates
|
|
124
|
-
} else {
|
|
125
|
-
updates = items.reduce(function(updates, item) {
|
|
142
|
+
updates = items.reduce((updates, item) => {
|
|
126
143
|
updates.market = updates.market.add(item.data.market);
|
|
144
|
+
updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
|
|
127
145
|
|
|
128
146
|
return updates;
|
|
129
147
|
}, {
|
|
130
|
-
market: Decimal.ZERO
|
|
148
|
+
market: Decimal.ZERO,
|
|
149
|
+
unrealizedToday: Decimal.ZERO
|
|
131
150
|
});
|
|
151
|
+
} else {
|
|
152
|
+
updates = {
|
|
153
|
+
market: actual.market.add(item.data.marketChange),
|
|
154
|
+
unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
|
|
155
|
+
};
|
|
132
156
|
}
|
|
157
|
+
|
|
158
|
+
if (parent !== null) {
|
|
159
|
+
const parentData = parent._dataActual;
|
|
133
160
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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.unrealizedTodayPositive = actual.unrealizedToday.getIsPositive();
|
|
139
174
|
}
|
|
140
175
|
|
|
141
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,37 +840,42 @@ 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.unrealizedTodayPositive = true;
|
|
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
|
|
|
831
877
|
calculateStaticData(this);
|
|
878
|
+
calculatePriceData(this);
|
|
832
879
|
}
|
|
833
880
|
|
|
834
881
|
get items() {
|
|
@@ -856,64 +903,92 @@ module.exports = (() => {
|
|
|
856
903
|
}
|
|
857
904
|
}
|
|
858
905
|
|
|
859
|
-
function
|
|
860
|
-
|
|
906
|
+
function formatNumber(decimal, precision) {
|
|
907
|
+
if (decimal !== null) {
|
|
908
|
+
return formatter.numberToString(decimal.toFloat(), precision, ',', false);
|
|
909
|
+
} else {
|
|
910
|
+
return '--';
|
|
911
|
+
}
|
|
861
912
|
}
|
|
862
913
|
|
|
863
|
-
function
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
914
|
+
function formatPercent(decimal, precision) {
|
|
915
|
+
if (decimal !== null) {
|
|
916
|
+
return formatNumber(decimal.multiply(100));
|
|
917
|
+
} else {
|
|
918
|
+
return '--';
|
|
919
|
+
}
|
|
920
|
+
}
|
|
867
921
|
|
|
868
|
-
|
|
869
|
-
|
|
922
|
+
function formatCurrency(decimal, currency) {
|
|
923
|
+
return formatNumber(decimal, currency.precision);
|
|
924
|
+
}
|
|
870
925
|
|
|
871
|
-
|
|
926
|
+
function calculateStaticData(group) {
|
|
927
|
+
const actual = group._dataActual;
|
|
928
|
+
const format = group._dataFormat;
|
|
872
929
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
updates.basis = updates.basis.add(item.data.basis);
|
|
930
|
+
const currency = group.currency;
|
|
931
|
+
|
|
932
|
+
const items = group._items;
|
|
877
933
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
basis: Decimal.ZERO
|
|
881
|
-
});
|
|
882
|
-
}
|
|
934
|
+
let updates = items.reduce((updates, item) => {
|
|
935
|
+
updates.basis = updates.basis.add(item.data.basis);
|
|
883
936
|
|
|
884
|
-
|
|
885
|
-
|
|
937
|
+
return updates;
|
|
938
|
+
}, {
|
|
939
|
+
basis: Decimal.ZERO
|
|
940
|
+
});
|
|
886
941
|
|
|
887
|
-
|
|
888
|
-
|
|
942
|
+
actual.basis = updates.basis;
|
|
943
|
+
|
|
944
|
+
format.basis = formatCurrency(updates.basis, currency);
|
|
889
945
|
}
|
|
890
946
|
|
|
891
|
-
function calculatePriceData(group) {
|
|
892
|
-
const
|
|
947
|
+
function calculatePriceData(group, item) {
|
|
948
|
+
const parent = group._parent;
|
|
893
949
|
|
|
894
|
-
|
|
950
|
+
const actual = group._dataActual;
|
|
951
|
+
const format = group._dataFormat;
|
|
895
952
|
|
|
896
|
-
|
|
897
|
-
updates = { };
|
|
953
|
+
const currency = group.currency;
|
|
898
954
|
|
|
899
|
-
|
|
955
|
+
let updates;
|
|
900
956
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
957
|
+
if (actual.market === null || actual.unrealizedToday === null) {
|
|
958
|
+
const items = group._items;
|
|
959
|
+
|
|
960
|
+
updates = items.reduce((updates, item) => {
|
|
904
961
|
updates.market = updates.market.add(item.data.market);
|
|
962
|
+
updates.unrealizedToday = updates.unrealizedToday.add(item.data.unrealizedToday);
|
|
905
963
|
|
|
906
964
|
return updates;
|
|
907
965
|
}, {
|
|
908
|
-
market: Decimal.ZERO
|
|
966
|
+
market: Decimal.ZERO,
|
|
967
|
+
unrealizedToday: Decimal.ZERO
|
|
909
968
|
});
|
|
969
|
+
} else {
|
|
970
|
+
updates = {
|
|
971
|
+
market: actual.market.add(item.data.marketChange),
|
|
972
|
+
unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
|
|
973
|
+
};
|
|
910
974
|
}
|
|
975
|
+
|
|
976
|
+
if (parent !== null) {
|
|
977
|
+
const parentData = parent._dataActual;
|
|
911
978
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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.unrealizedTodayPositive = actual.unrealizedToday.getIsPositive();
|
|
917
992
|
}
|
|
918
993
|
|
|
919
994
|
return PositionGroup;
|
|
@@ -991,10 +1066,17 @@ module.exports = (() => {
|
|
|
991
1066
|
|
|
992
1067
|
this._data = { };
|
|
993
1068
|
|
|
994
|
-
this._data.current = null;
|
|
995
|
-
this._data.previous = null;
|
|
996
1069
|
this._data.basis = null;
|
|
997
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
|
+
|
|
998
1080
|
calculateStaticData(this);
|
|
999
1081
|
calculatePriceData(this, null);
|
|
1000
1082
|
|
|
@@ -1019,7 +1101,7 @@ module.exports = (() => {
|
|
|
1019
1101
|
|
|
1020
1102
|
setPrice(price) {
|
|
1021
1103
|
if (this._data.price !== price) {
|
|
1022
|
-
calculatePriceData(this, this._data.
|
|
1104
|
+
calculatePriceData(this, this._data.currentPrice = price);
|
|
1023
1105
|
|
|
1024
1106
|
this._priceChangeEvent.fire(this._data);
|
|
1025
1107
|
}
|
|
@@ -1042,7 +1124,7 @@ module.exports = (() => {
|
|
|
1042
1124
|
|
|
1043
1125
|
const data = item._data;
|
|
1044
1126
|
|
|
1045
|
-
data.
|
|
1127
|
+
data.previousPrice = position.previousPrice || null;
|
|
1046
1128
|
|
|
1047
1129
|
let basis;
|
|
1048
1130
|
|
|
@@ -1075,7 +1157,35 @@ module.exports = (() => {
|
|
|
1075
1157
|
}
|
|
1076
1158
|
}
|
|
1077
1159
|
|
|
1160
|
+
let marketChange;
|
|
1161
|
+
|
|
1162
|
+
if (data.market === null) {
|
|
1163
|
+
marketChange = market;
|
|
1164
|
+
} else {
|
|
1165
|
+
marketChange = market.subtract(data.market);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1078
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;
|
|
1079
1189
|
}
|
|
1080
1190
|
|
|
1081
1191
|
return PositionItem;
|