@barchart/portfolio-api-common 1.0.70 → 1.0.74

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.
@@ -13,15 +13,23 @@ module.exports = (() => {
13
13
  * @param {String} alternateDescription
14
14
  * @param {String} code
15
15
  * @param {Boolean} canReinvest
16
+ * @param {Boolean} usesSymbols
16
17
  */
17
18
  class InstrumentType extends Enum {
18
- constructor(code, description, alternateDescription, canReinvest) {
19
+ constructor(code, description, alternateDescription, canReinvest, usesSymbols) {
19
20
  super(code, description);
20
21
 
21
22
  this._alternateDescription = alternateDescription;
22
23
  this._canReinvest = canReinvest;
24
+ this._usesSymbols = usesSymbols;
23
25
  }
24
26
 
27
+ /**
28
+ * A human-readable description.
29
+ *
30
+ * @public
31
+ * @return {String}
32
+ */
25
33
  get alternateDescription() {
26
34
  return this._alternateDescription;
27
35
  }
@@ -29,16 +37,28 @@ module.exports = (() => {
29
37
  /**
30
38
  * Indicates if the instrument type allows automatic reinvestment.
31
39
  *
40
+ * @public
32
41
  * @returns {Boolean}
33
42
  */
34
43
  get canReinvest() {
35
44
  return this._canReinvest;
36
45
  }
37
46
 
47
+ /**
48
+ * Indicates if an instrument of this type can be represented by a symbol.
49
+ *
50
+ * @public
51
+ * @returns {Boolean}
52
+ */
53
+ get usesSymbols() {
54
+ return this._usesSymbols;
55
+ }
56
+
38
57
  /**
39
58
  * Cash.
40
59
  *
41
60
  * @public
61
+ * @static
42
62
  * @returns {InstrumentType}
43
63
  */
44
64
  static get CASH() {
@@ -49,6 +69,7 @@ module.exports = (() => {
49
69
  * An equity issue.
50
70
  *
51
71
  * @public
72
+ * @static
52
73
  * @returns {InstrumentType}
53
74
  */
54
75
  static get EQUITY() {
@@ -59,6 +80,7 @@ module.exports = (() => {
59
80
  * A mutual fund.
60
81
  *
61
82
  * @public
83
+ * @static
62
84
  * @returns {InstrumentType}
63
85
  */
64
86
  static get FUND() {
@@ -69,6 +91,7 @@ module.exports = (() => {
69
91
  * An undefined asset (e.g. a house, or a collectible, or a salvaged alien spaceship).
70
92
  *
71
93
  * @public
94
+ * @static
72
95
  * @returns {InstrumentType}
73
96
  */
74
97
  static get OTHER() {
@@ -80,10 +103,10 @@ module.exports = (() => {
80
103
  }
81
104
  }
82
105
 
83
- const cash = new InstrumentType('CASH', 'cash', 'Cash', false);
84
- const equity = new InstrumentType('EQUITY', 'equity', 'Equities', true);
85
- const fund = new InstrumentType('FUND', 'mutual fund', 'Funds', true);
86
- const other = new InstrumentType('OTHER', 'other', 'Other', false);
106
+ const cash = new InstrumentType('CASH', 'cash', 'Cash', false, false);
107
+ const equity = new InstrumentType('EQUITY', 'equity', 'Equities', true, true);
108
+ const fund = new InstrumentType('FUND', 'mutual fund', 'Funds', true, true);
109
+ const other = new InstrumentType('OTHER', 'other', 'Other', false, false);
87
110
 
88
111
  return InstrumentType;
89
112
  })();
@@ -239,7 +239,7 @@ module.exports = (() => {
239
239
  }
240
240
 
241
241
  function getYearToDateRangeDescription(startDate, endDate) {
242
- return '';
242
+ return `${endDate.year.toString()} YTD`;
243
243
  }
244
244
 
245
245
  function getFilteredTransactions(transactions) {
@@ -109,13 +109,13 @@ module.exports = (() => {
109
109
  const populatedGroups = Object.keys(populatedObjects).map(key => populatedObjects[key]).map((items) => {
110
110
  const first = items[0];
111
111
 
112
- return new PositionGroup(parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
112
+ return new PositionGroup(this, parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
113
113
  });
114
114
 
115
115
  const missingGroups = array.difference(currentDefinition.requiredGroups.map(group => group.description), populatedGroups.map(group => group.description));
116
116
 
117
117
  const empty = missingGroups.map((description) => {
118
- return new PositionGroup(parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
118
+ return new PositionGroup(this, parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
119
119
  });
120
120
 
121
121
  const compositeGroups = populatedGroups.concat(empty);
@@ -186,10 +186,20 @@ module.exports = (() => {
186
186
  }, [ ]);
187
187
  }
188
188
 
189
- setExchangeRage(symbol, price) {
189
+ setExchangeRate(symbol, price) {
190
190
 
191
191
  }
192
192
 
193
+ startTransaction(executor) {
194
+ assert.argumentIsRequired(executor, 'executor', Function);
195
+
196
+ this._tree.walk(group => group.setSuspended(true), false, false);
197
+
198
+ executor(this);
199
+
200
+ this._tree.walk(group => group.setSuspended(false), false, false);
201
+ }
202
+
193
203
  getGroup(keys) {
194
204
  const node = keys.reduce((tree, key) => {
195
205
  tree = tree.findChild(group => group.description === key);
@@ -11,7 +11,8 @@ module.exports = (() => {
11
11
  * @public
12
12
  */
13
13
  class PositionGroup {
14
- constructor(parent, items, currency, description, single) {
14
+ constructor(container, parent, items, currency, description, single) {
15
+ this._container = container;
15
16
  this._parent = parent || null;
16
17
 
17
18
  this._items = items;
@@ -21,6 +22,9 @@ module.exports = (() => {
21
22
 
22
23
  this._single = is.boolean(single) && single;
23
24
 
25
+ this._excluded = false;
26
+ this._suspended = false;
27
+
24
28
  this._dataFormat = { };
25
29
  this._dataActual = { };
26
30
 
@@ -62,12 +66,11 @@ module.exports = (() => {
62
66
  this._dataFormat.currentPrice = null;
63
67
  }
64
68
 
65
- calculatePriceData(this, sender);
69
+ calculatePriceData(this, sender, false);
66
70
  });
67
71
  });
68
72
 
69
- calculateStaticData(this);
70
- calculatePriceData(this);
73
+ this.refresh();
71
74
  }
72
75
 
73
76
  get items() {
@@ -90,6 +93,41 @@ module.exports = (() => {
90
93
  return this._single;
91
94
  }
92
95
 
96
+ get suspended() {
97
+ return this._suspended;
98
+ }
99
+
100
+ get excluded() {
101
+ return this._excluded;
102
+ }
103
+
104
+ setExcluded(value) {
105
+ assert.argumentIsRequired(value, 'value', Boolean);
106
+
107
+ if (this._excluded !== value) {
108
+ this._container.startTransaction(() => {
109
+ this._items.forEach((item) => {
110
+ item.setExcluded(value);
111
+ });
112
+ });
113
+ }
114
+ }
115
+
116
+ setSuspended(value) {
117
+ assert.argumentIsRequired(value, 'value', Boolean);
118
+
119
+ if (this._suspended !== value) {
120
+ if (this._suspended = value) {
121
+ this.refresh();
122
+ }
123
+ }
124
+ }
125
+
126
+ refresh() {
127
+ calculateStaticData(this);
128
+ calculatePriceData(this, null, true);
129
+ }
130
+
93
131
  toString() {
94
132
  return '[PositionGroup]';
95
133
  }
@@ -116,6 +154,10 @@ module.exports = (() => {
116
154
  }
117
155
 
118
156
  function calculateStaticData(group) {
157
+ if (group.suspended) {
158
+ return;
159
+ }
160
+
119
161
  const actual = group._dataActual;
120
162
  const format = group._dataFormat;
121
163
 
@@ -152,7 +194,11 @@ module.exports = (() => {
152
194
  format.summaryTwoTotal = formatCurrency(updates.summaryTwoTotal, currency);
153
195
  }
154
196
 
155
- function calculatePriceData(group, item) {
197
+ function calculatePriceData(group, item, forceRefresh) {
198
+ if (group.suspended) {
199
+ return;
200
+ }
201
+
156
202
  const parent = group._parent;
157
203
 
158
204
  const actual = group._dataActual;
@@ -160,14 +206,11 @@ module.exports = (() => {
160
206
 
161
207
  const currency = group.currency;
162
208
 
209
+ const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
210
+
163
211
  let updates;
164
212
 
165
- if (actual.market !== null && actual.unrealizedToday !== null && actual.total !== null) {
166
- updates = {
167
- market: actual.market.add(item.data.marketChange),
168
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
169
- };
170
- } else {
213
+ if (refresh) {
171
214
  const items = group._items;
172
215
 
173
216
  updates = items.reduce((updates, item) => {
@@ -177,8 +220,14 @@ module.exports = (() => {
177
220
  return updates;
178
221
  }, {
179
222
  market: Decimal.ZERO,
223
+
180
224
  unrealizedToday: Decimal.ZERO
181
225
  });
226
+ } else {
227
+ updates = {
228
+ market: actual.market.add(item.data.marketChange),
229
+ unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
230
+ };
182
231
  }
183
232
 
184
233
  if (parent !== null) {
@@ -33,10 +33,13 @@ module.exports = (() => {
33
33
  this._data.realized = null;
34
34
  this._data.income = null;
35
35
 
36
+ this._excluded = false;
37
+
36
38
  calculateStaticData(this);
37
39
  calculatePriceData(this, null);
38
40
 
39
41
  this._priceChangeEvent = new Event(this);
42
+ this._excludedChangeEvent = new Event(this);
40
43
  }
41
44
 
42
45
  get portfolio() {
@@ -55,7 +58,13 @@ module.exports = (() => {
55
58
  return this._data;
56
59
  }
57
60
 
61
+ get excluded() {
62
+ return this._excluded;
63
+ }
64
+
58
65
  setPrice(price) {
66
+ assert.argumentIsRequired(price, 'price', Number);
67
+
59
68
  if (this._data.price !== price) {
60
69
  calculatePriceData(this, this._data.currentPrice = price);
61
70
 
@@ -63,12 +72,22 @@ module.exports = (() => {
63
72
  }
64
73
  }
65
74
 
66
- registerPriceChangeHandler(handler) {
67
- assert.argumentIsRequired(handler, 'handler', Function);
75
+ setExcluded(value) {
76
+ assert.argumentIsRequired(value, 'value', Boolean);
68
77
 
78
+ if (this._excluded !== value) {
79
+ this._excludedChangeEvent.fire(this, this._excluded = value);
80
+ }
81
+ }
82
+
83
+ registerPriceChangeHandler(handler) {
69
84
  this._priceChangeEvent.register(handler);
70
85
  }
71
86
 
87
+ registerExcludedChangeHandler(handler) {
88
+ this._excludedChangeEvent.register(handler);
89
+ }
90
+
72
91
  toString() {
73
92
  return '[PositionItem]';
74
93
  }
@@ -99,7 +118,7 @@ module.exports = (() => {
99
118
  const getSummaryTotal = (index) => {
100
119
  let summaryTotal;
101
120
 
102
- if (summaries.length > (index + 1) && summaries[index] !== null) {
121
+ if (summaries.length > index && summaries[index] !== null) {
103
122
  const period = summaries[index].period;
104
123
 
105
124
  summaryTotal = period.realized.add(period.unrealized).add(period.income);
@@ -155,6 +155,7 @@ module.exports = (() => {
155
155
  );
156
156
 
157
157
  const update = new PortfolioSchema(SchemaBuilder.withName('update')
158
+ .withField('portfolio', DataType.STRING)
158
159
  .withField('name', DataType.STRING)
159
160
  .withField('timezone', DataType.forEnum(Timezones, 'Timezone'), true)
160
161
  .withField('defaults.currency', DataType.forEnum(Currency, 'Currency'), true)
@@ -391,8 +391,6 @@ module.exports = (() => {
391
391
  .withField('instrument.name', DataType.STRING, true)
392
392
  .withField('instrument.type', DataType.STRING, true)
393
393
  .withField('instrument.currency', DataType.forEnum(Currency, 'Currency'), true)
394
- .withField('instrument.symbol.barchart', DataType.STRING, true)
395
- .withField('instrument.symbol.display', DataType.STRING, true)
396
394
  .withField('date', DataType.DAY)
397
395
  .withField('amount', DataType.DECIMAL)
398
396
  .withField('fee', DataType.DECIMAL, true)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.70",
3
+ "version": "1.0.74",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -14,15 +14,23 @@ module.exports = (() => {
14
14
  * @param {String} alternateDescription
15
15
  * @param {String} code
16
16
  * @param {Boolean} canReinvest
17
+ * @param {Boolean} usesSymbols
17
18
  */
18
19
  class InstrumentType extends Enum {
19
- constructor(code, description, alternateDescription, canReinvest) {
20
+ constructor(code, description, alternateDescription, canReinvest, usesSymbols) {
20
21
  super(code, description);
21
22
 
22
23
  this._alternateDescription = alternateDescription;
23
24
  this._canReinvest = canReinvest;
25
+ this._usesSymbols = usesSymbols;
24
26
  }
25
27
 
28
+ /**
29
+ * A human-readable description.
30
+ *
31
+ * @public
32
+ * @return {String}
33
+ */
26
34
  get alternateDescription() {
27
35
  return this._alternateDescription;
28
36
  }
@@ -30,16 +38,28 @@ module.exports = (() => {
30
38
  /**
31
39
  * Indicates if the instrument type allows automatic reinvestment.
32
40
  *
41
+ * @public
33
42
  * @returns {Boolean}
34
43
  */
35
44
  get canReinvest() {
36
45
  return this._canReinvest;
37
46
  }
38
47
 
48
+ /**
49
+ * Indicates if an instrument of this type can be represented by a symbol.
50
+ *
51
+ * @public
52
+ * @returns {Boolean}
53
+ */
54
+ get usesSymbols() {
55
+ return this._usesSymbols;
56
+ }
57
+
39
58
  /**
40
59
  * Cash.
41
60
  *
42
61
  * @public
62
+ * @static
43
63
  * @returns {InstrumentType}
44
64
  */
45
65
  static get CASH() {
@@ -50,6 +70,7 @@ module.exports = (() => {
50
70
  * An equity issue.
51
71
  *
52
72
  * @public
73
+ * @static
53
74
  * @returns {InstrumentType}
54
75
  */
55
76
  static get EQUITY() {
@@ -60,6 +81,7 @@ module.exports = (() => {
60
81
  * A mutual fund.
61
82
  *
62
83
  * @public
84
+ * @static
63
85
  * @returns {InstrumentType}
64
86
  */
65
87
  static get FUND() {
@@ -70,6 +92,7 @@ module.exports = (() => {
70
92
  * An undefined asset (e.g. a house, or a collectible, or a salvaged alien spaceship).
71
93
  *
72
94
  * @public
95
+ * @static
73
96
  * @returns {InstrumentType}
74
97
  */
75
98
  static get OTHER() {
@@ -81,10 +104,10 @@ module.exports = (() => {
81
104
  }
82
105
  }
83
106
 
84
- const cash = new InstrumentType('CASH', 'cash', 'Cash', false);
85
- const equity = new InstrumentType('EQUITY', 'equity', 'Equities', true);
86
- const fund = new InstrumentType('FUND', 'mutual fund', 'Funds', true);
87
- const other = new InstrumentType('OTHER', 'other', 'Other', false);
107
+ const cash = new InstrumentType('CASH', 'cash', 'Cash', false, false);
108
+ const equity = new InstrumentType('EQUITY', 'equity', 'Equities', true, true);
109
+ const fund = new InstrumentType('FUND', 'mutual fund', 'Funds', true, true);
110
+ const other = new InstrumentType('OTHER', 'other', 'Other', false, false);
88
111
 
89
112
  return InstrumentType;
90
113
  })();
@@ -331,7 +354,7 @@ module.exports = (() => {
331
354
  }
332
355
 
333
356
  function getYearToDateRangeDescription(startDate, endDate) {
334
- return '';
357
+ return `${endDate.year.toString()} YTD`;
335
358
  }
336
359
 
337
360
  function getFilteredTransactions(transactions) {
@@ -786,13 +809,13 @@ module.exports = (() => {
786
809
  const populatedGroups = Object.keys(populatedObjects).map(key => populatedObjects[key]).map((items) => {
787
810
  const first = items[0];
788
811
 
789
- return new PositionGroup(parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
812
+ return new PositionGroup(this, parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
790
813
  });
791
814
 
792
815
  const missingGroups = array.difference(currentDefinition.requiredGroups.map(group => group.description), populatedGroups.map(group => group.description));
793
816
 
794
817
  const empty = missingGroups.map((description) => {
795
- return new PositionGroup(parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
818
+ return new PositionGroup(this, parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
796
819
  });
797
820
 
798
821
  const compositeGroups = populatedGroups.concat(empty);
@@ -863,10 +886,20 @@ module.exports = (() => {
863
886
  }, [ ]);
864
887
  }
865
888
 
866
- setExchangeRage(symbol, price) {
889
+ setExchangeRate(symbol, price) {
867
890
 
868
891
  }
869
892
 
893
+ startTransaction(executor) {
894
+ assert.argumentIsRequired(executor, 'executor', Function);
895
+
896
+ this._tree.walk(group => group.setSuspended(true), false, false);
897
+
898
+ executor(this);
899
+
900
+ this._tree.walk(group => group.setSuspended(false), false, false);
901
+ }
902
+
870
903
  getGroup(keys) {
871
904
  const node = keys.reduce((tree, key) => {
872
905
  tree = tree.findChild(group => group.description === key);
@@ -913,7 +946,8 @@ module.exports = (() => {
913
946
  * @public
914
947
  */
915
948
  class PositionGroup {
916
- constructor(parent, items, currency, description, single) {
949
+ constructor(container, parent, items, currency, description, single) {
950
+ this._container = container;
917
951
  this._parent = parent || null;
918
952
 
919
953
  this._items = items;
@@ -923,6 +957,9 @@ module.exports = (() => {
923
957
 
924
958
  this._single = is.boolean(single) && single;
925
959
 
960
+ this._excluded = false;
961
+ this._suspended = false;
962
+
926
963
  this._dataFormat = { };
927
964
  this._dataActual = { };
928
965
 
@@ -964,12 +1001,11 @@ module.exports = (() => {
964
1001
  this._dataFormat.currentPrice = null;
965
1002
  }
966
1003
 
967
- calculatePriceData(this, sender);
1004
+ calculatePriceData(this, sender, false);
968
1005
  });
969
1006
  });
970
1007
 
971
- calculateStaticData(this);
972
- calculatePriceData(this);
1008
+ this.refresh();
973
1009
  }
974
1010
 
975
1011
  get items() {
@@ -992,6 +1028,41 @@ module.exports = (() => {
992
1028
  return this._single;
993
1029
  }
994
1030
 
1031
+ get suspended() {
1032
+ return this._suspended;
1033
+ }
1034
+
1035
+ get excluded() {
1036
+ return this._excluded;
1037
+ }
1038
+
1039
+ setExcluded(value) {
1040
+ assert.argumentIsRequired(value, 'value', Boolean);
1041
+
1042
+ if (this._excluded !== value) {
1043
+ this._container.startTransaction(() => {
1044
+ this._items.forEach((item) => {
1045
+ item.setExcluded(value);
1046
+ });
1047
+ });
1048
+ }
1049
+ }
1050
+
1051
+ setSuspended(value) {
1052
+ assert.argumentIsRequired(value, 'value', Boolean);
1053
+
1054
+ if (this._suspended !== value) {
1055
+ if (this._suspended = value) {
1056
+ this.refresh();
1057
+ }
1058
+ }
1059
+ }
1060
+
1061
+ refresh() {
1062
+ calculateStaticData(this);
1063
+ calculatePriceData(this, null, true);
1064
+ }
1065
+
995
1066
  toString() {
996
1067
  return '[PositionGroup]';
997
1068
  }
@@ -1018,6 +1089,10 @@ module.exports = (() => {
1018
1089
  }
1019
1090
 
1020
1091
  function calculateStaticData(group) {
1092
+ if (group.suspended) {
1093
+ return;
1094
+ }
1095
+
1021
1096
  const actual = group._dataActual;
1022
1097
  const format = group._dataFormat;
1023
1098
 
@@ -1054,7 +1129,11 @@ module.exports = (() => {
1054
1129
  format.summaryTwoTotal = formatCurrency(updates.summaryTwoTotal, currency);
1055
1130
  }
1056
1131
 
1057
- function calculatePriceData(group, item) {
1132
+ function calculatePriceData(group, item, forceRefresh) {
1133
+ if (group.suspended) {
1134
+ return;
1135
+ }
1136
+
1058
1137
  const parent = group._parent;
1059
1138
 
1060
1139
  const actual = group._dataActual;
@@ -1062,14 +1141,11 @@ module.exports = (() => {
1062
1141
 
1063
1142
  const currency = group.currency;
1064
1143
 
1144
+ const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1145
+
1065
1146
  let updates;
1066
1147
 
1067
- if (actual.market !== null && actual.unrealizedToday !== null && actual.total !== null) {
1068
- updates = {
1069
- market: actual.market.add(item.data.marketChange),
1070
- unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
1071
- };
1072
- } else {
1148
+ if (refresh) {
1073
1149
  const items = group._items;
1074
1150
 
1075
1151
  updates = items.reduce((updates, item) => {
@@ -1079,8 +1155,14 @@ module.exports = (() => {
1079
1155
  return updates;
1080
1156
  }, {
1081
1157
  market: Decimal.ZERO,
1158
+
1082
1159
  unrealizedToday: Decimal.ZERO
1083
1160
  });
1161
+ } else {
1162
+ updates = {
1163
+ market: actual.market.add(item.data.marketChange),
1164
+ unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
1165
+ };
1084
1166
  }
1085
1167
 
1086
1168
  if (parent !== null) {
@@ -1196,10 +1278,13 @@ module.exports = (() => {
1196
1278
  this._data.realized = null;
1197
1279
  this._data.income = null;
1198
1280
 
1281
+ this._excluded = false;
1282
+
1199
1283
  calculateStaticData(this);
1200
1284
  calculatePriceData(this, null);
1201
1285
 
1202
1286
  this._priceChangeEvent = new Event(this);
1287
+ this._excludedChangeEvent = new Event(this);
1203
1288
  }
1204
1289
 
1205
1290
  get portfolio() {
@@ -1218,7 +1303,13 @@ module.exports = (() => {
1218
1303
  return this._data;
1219
1304
  }
1220
1305
 
1306
+ get excluded() {
1307
+ return this._excluded;
1308
+ }
1309
+
1221
1310
  setPrice(price) {
1311
+ assert.argumentIsRequired(price, 'price', Number);
1312
+
1222
1313
  if (this._data.price !== price) {
1223
1314
  calculatePriceData(this, this._data.currentPrice = price);
1224
1315
 
@@ -1226,12 +1317,22 @@ module.exports = (() => {
1226
1317
  }
1227
1318
  }
1228
1319
 
1229
- registerPriceChangeHandler(handler) {
1230
- assert.argumentIsRequired(handler, 'handler', Function);
1320
+ setExcluded(value) {
1321
+ assert.argumentIsRequired(value, 'value', Boolean);
1322
+
1323
+ if (this._excluded !== value) {
1324
+ this._excludedChangeEvent.fire(this, this._excluded = value);
1325
+ }
1326
+ }
1231
1327
 
1328
+ registerPriceChangeHandler(handler) {
1232
1329
  this._priceChangeEvent.register(handler);
1233
1330
  }
1234
1331
 
1332
+ registerExcludedChangeHandler(handler) {
1333
+ this._excludedChangeEvent.register(handler);
1334
+ }
1335
+
1235
1336
  toString() {
1236
1337
  return '[PositionItem]';
1237
1338
  }
@@ -1262,7 +1363,7 @@ module.exports = (() => {
1262
1363
  const getSummaryTotal = (index) => {
1263
1364
  let summaryTotal;
1264
1365
 
1265
- if (summaries.length > (index + 1) && summaries[index] !== null) {
1366
+ if (summaries.length > index && summaries[index] !== null) {
1266
1367
  const period = summaries[index].period;
1267
1368
 
1268
1369
  summaryTotal = period.realized.add(period.unrealized).add(period.income);