@barchart/portfolio-api-common 1.0.71 → 1.0.72

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.
@@ -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
  }
@@ -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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barchart/portfolio-api-common",
3
- "version": "1.0.71",
3
+ "version": "1.0.72",
4
4
  "description": "Common classes used by the Portfolio system",
5
5
  "author": {
6
6
  "name": "Bryan Ingle",
@@ -786,13 +786,13 @@ module.exports = (() => {
786
786
  const populatedGroups = Object.keys(populatedObjects).map(key => populatedObjects[key]).map((items) => {
787
787
  const first = items[0];
788
788
 
789
- return new PositionGroup(parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
789
+ return new PositionGroup(this, parent, items, currentDefinition.currencySelector(first), currentDefinition.descriptionSelector(first), currentDefinition.single && items.length === 1);
790
790
  });
791
791
 
792
792
  const missingGroups = array.difference(currentDefinition.requiredGroups.map(group => group.description), populatedGroups.map(group => group.description));
793
793
 
794
794
  const empty = missingGroups.map((description) => {
795
- return new PositionGroup(parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
795
+ return new PositionGroup(this, parent, [ ], currentDefinition.requiredGroups.find(group => group.description === description).currency, description);
796
796
  });
797
797
 
798
798
  const compositeGroups = populatedGroups.concat(empty);
@@ -863,10 +863,20 @@ module.exports = (() => {
863
863
  }, [ ]);
864
864
  }
865
865
 
866
- setExchangeRage(symbol, price) {
866
+ setExchangeRate(symbol, price) {
867
867
 
868
868
  }
869
869
 
870
+ startTransaction(executor) {
871
+ assert.argumentIsRequired(executor, 'executor', Function);
872
+
873
+ this._tree.walk(group => group.setSuspended(true), false, false);
874
+
875
+ executor(this);
876
+
877
+ this._tree.walk(group => group.setSuspended(false), false, false);
878
+ }
879
+
870
880
  getGroup(keys) {
871
881
  const node = keys.reduce((tree, key) => {
872
882
  tree = tree.findChild(group => group.description === key);
@@ -913,7 +923,8 @@ module.exports = (() => {
913
923
  * @public
914
924
  */
915
925
  class PositionGroup {
916
- constructor(parent, items, currency, description, single) {
926
+ constructor(container, parent, items, currency, description, single) {
927
+ this._container = container;
917
928
  this._parent = parent || null;
918
929
 
919
930
  this._items = items;
@@ -923,6 +934,9 @@ module.exports = (() => {
923
934
 
924
935
  this._single = is.boolean(single) && single;
925
936
 
937
+ this._excluded = false;
938
+ this._suspended = false;
939
+
926
940
  this._dataFormat = { };
927
941
  this._dataActual = { };
928
942
 
@@ -964,12 +978,11 @@ module.exports = (() => {
964
978
  this._dataFormat.currentPrice = null;
965
979
  }
966
980
 
967
- calculatePriceData(this, sender);
981
+ calculatePriceData(this, sender, false);
968
982
  });
969
983
  });
970
984
 
971
- calculateStaticData(this);
972
- calculatePriceData(this);
985
+ this.refresh();
973
986
  }
974
987
 
975
988
  get items() {
@@ -992,6 +1005,41 @@ module.exports = (() => {
992
1005
  return this._single;
993
1006
  }
994
1007
 
1008
+ get suspended() {
1009
+ return this._suspended;
1010
+ }
1011
+
1012
+ get excluded() {
1013
+ return this._excluded;
1014
+ }
1015
+
1016
+ setExcluded(value) {
1017
+ assert.argumentIsRequired(value, 'value', Boolean);
1018
+
1019
+ if (this._excluded !== value) {
1020
+ this._container.startTransaction(() => {
1021
+ this._items.forEach((item) => {
1022
+ item.setExcluded(value);
1023
+ });
1024
+ });
1025
+ }
1026
+ }
1027
+
1028
+ setSuspended(value) {
1029
+ assert.argumentIsRequired(value, 'value', Boolean);
1030
+
1031
+ if (this._suspended !== value) {
1032
+ if (this._suspended = value) {
1033
+ this.refresh();
1034
+ }
1035
+ }
1036
+ }
1037
+
1038
+ refresh() {
1039
+ calculateStaticData(this);
1040
+ calculatePriceData(this, null, true);
1041
+ }
1042
+
995
1043
  toString() {
996
1044
  return '[PositionGroup]';
997
1045
  }
@@ -1018,6 +1066,10 @@ module.exports = (() => {
1018
1066
  }
1019
1067
 
1020
1068
  function calculateStaticData(group) {
1069
+ if (group.suspended) {
1070
+ return;
1071
+ }
1072
+
1021
1073
  const actual = group._dataActual;
1022
1074
  const format = group._dataFormat;
1023
1075
 
@@ -1054,7 +1106,11 @@ module.exports = (() => {
1054
1106
  format.summaryTwoTotal = formatCurrency(updates.summaryTwoTotal, currency);
1055
1107
  }
1056
1108
 
1057
- function calculatePriceData(group, item) {
1109
+ function calculatePriceData(group, item, forceRefresh) {
1110
+ if (group.suspended) {
1111
+ return;
1112
+ }
1113
+
1058
1114
  const parent = group._parent;
1059
1115
 
1060
1116
  const actual = group._dataActual;
@@ -1062,14 +1118,11 @@ module.exports = (() => {
1062
1118
 
1063
1119
  const currency = group.currency;
1064
1120
 
1121
+ const refresh = (is.boolean(forceRefresh) && forceRefresh) || (actual.market === null || actual.unrealizedToday === null || actual.total === null);
1122
+
1065
1123
  let updates;
1066
1124
 
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 {
1125
+ if (refresh) {
1073
1126
  const items = group._items;
1074
1127
 
1075
1128
  updates = items.reduce((updates, item) => {
@@ -1079,8 +1132,14 @@ module.exports = (() => {
1079
1132
  return updates;
1080
1133
  }, {
1081
1134
  market: Decimal.ZERO,
1135
+
1082
1136
  unrealizedToday: Decimal.ZERO
1083
1137
  });
1138
+ } else {
1139
+ updates = {
1140
+ market: actual.market.add(item.data.marketChange),
1141
+ unrealizedToday: actual.unrealizedToday.add(item.data.unrealizedTodayChange)
1142
+ };
1084
1143
  }
1085
1144
 
1086
1145
  if (parent !== null) {
@@ -1196,10 +1255,13 @@ module.exports = (() => {
1196
1255
  this._data.realized = null;
1197
1256
  this._data.income = null;
1198
1257
 
1258
+ this._excluded = false;
1259
+
1199
1260
  calculateStaticData(this);
1200
1261
  calculatePriceData(this, null);
1201
1262
 
1202
1263
  this._priceChangeEvent = new Event(this);
1264
+ this._excludedChangeEvent = new Event(this);
1203
1265
  }
1204
1266
 
1205
1267
  get portfolio() {
@@ -1218,7 +1280,13 @@ module.exports = (() => {
1218
1280
  return this._data;
1219
1281
  }
1220
1282
 
1283
+ get excluded() {
1284
+ return this._excluded;
1285
+ }
1286
+
1221
1287
  setPrice(price) {
1288
+ assert.argumentIsRequired(price, 'price', Number);
1289
+
1222
1290
  if (this._data.price !== price) {
1223
1291
  calculatePriceData(this, this._data.currentPrice = price);
1224
1292
 
@@ -1226,12 +1294,22 @@ module.exports = (() => {
1226
1294
  }
1227
1295
  }
1228
1296
 
1229
- registerPriceChangeHandler(handler) {
1230
- assert.argumentIsRequired(handler, 'handler', Function);
1297
+ setExcluded(value) {
1298
+ assert.argumentIsRequired(value, 'value', Boolean);
1231
1299
 
1300
+ if (this._excluded !== value) {
1301
+ this._excludedChangeEvent.fire(this, this._excluded = value);
1302
+ }
1303
+ }
1304
+
1305
+ registerPriceChangeHandler(handler) {
1232
1306
  this._priceChangeEvent.register(handler);
1233
1307
  }
1234
1308
 
1309
+ registerExcludedChangeHandler(handler) {
1310
+ this._excludedChangeEvent.register(handler);
1311
+ }
1312
+
1235
1313
  toString() {
1236
1314
  return '[PositionItem]';
1237
1315
  }