@vuu-ui/vuu-data-test 4.0.0-alpha.21 → 4.0.0-alpha.23
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.
- package/README.md +36 -0
- package/package.json +7 -7
- package/src/basket/BasketModule.js +105 -40
- package/src/basket/basket-schemas.js +16 -0
- package/src/basket/reference-data/constituents.js +8 -76
- package/src/basket/reference-data/prices.js +9 -3
- package/src/core/table/TableContainer.js +51 -8
- package/types/basket/BasketModule.d.ts +2 -0
- package/types/basket/reference-data/constituents.d.ts +3 -3
- package/types/basket/reference-data/prices.d.ts +2 -1
- package/types/core/table/TableContainer.d.ts +1 -1
- package/src/basket/reference-data/ftse100.js +0 -686
- package/src/basket/reference-data/hsi.js +0 -1047
- package/src/basket/reference-data/nasdaq100.js +0 -812
- package/src/basket/reference-data/sp500.js +0 -315
- package/types/src/ArrayProxy.d.ts +0 -8
- package/types/src/RuntimeVisualLink.d.ts +0 -9
- package/types/src/Table.d.ts +0 -34
- package/types/src/TickingArrayDataSource.d.ts +0 -44
- package/types/src/UpdateGenerator.d.ts +0 -18
- package/types/src/basket/BasketModule.d.ts +0 -55
- package/types/src/basket/basket-schemas.d.ts +0 -9
- package/types/src/basket/index.d.ts +0 -2
- package/types/src/basket/reference-data/constituents.d.ts +0 -3
- package/types/src/basket/reference-data/ftse100.d.ts +0 -2
- package/types/src/basket/reference-data/hsi.d.ts +0 -2
- package/types/src/basket/reference-data/nasdaq100.d.ts +0 -2
- package/types/src/basket/reference-data/prices.d.ts +0 -24
- package/types/src/basket/reference-data/sp500.d.ts +0 -2
- package/types/src/core/module/ModuleContainer.d.ts +0 -11
- package/types/src/core/module/VuuModule.d.ts +0 -81
- package/types/src/core/table/TableContainer.d.ts +0 -16
- package/types/src/data-utils.d.ts +0 -7
- package/types/src/default-column-definitions.d.ts +0 -2
- package/types/src/index.d.ts +0 -12
- package/types/src/local-datasource-provider/LocalDatasourceProvider.d.ts +0 -4
- package/types/src/makeSuggestions.d.ts +0 -3
- package/types/src/rowUpdates.d.ts +0 -15
- package/types/src/schemas.d.ts +0 -8
- package/types/src/session-table-utils.d.ts +0 -6
- package/types/src/simul/SimulModule.d.ts +0 -24
- package/types/src/simul/index.d.ts +0 -2
- package/types/src/simul/reference-data/accounts.d.ts +0 -1
- package/types/src/simul/reference-data/algos.d.ts +0 -1
- package/types/src/simul/reference-data/currencies.d.ts +0 -1
- package/types/src/simul/reference-data/index.d.ts +0 -5
- package/types/src/simul/reference-data/instrument-prices.d.ts +0 -60
- package/types/src/simul/reference-data/instruments-extended.d.ts +0 -1
- package/types/src/simul/reference-data/instruments.d.ts +0 -35
- package/types/src/simul/reference-data/isin-generator/convert-string-to-base-ten-number.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/fixtures/alphabet.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/fixtures/alphanumeric-values.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/fixtures/base-ten-numbers.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-cusip-check-code.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-cusip-without-check-code.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-cusip.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-random-alphanumeric.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-random-base-ten-number.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-random-string-of-alphanumeric-chars.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/generate-random-string-of-base-ten-chars.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/index.d.ts +0 -1
- package/types/src/simul/reference-data/isin-generator/is-odd.d.ts +0 -1
- package/types/src/simul/reference-data/locations.d.ts +0 -4
- package/types/src/simul/reference-data/lotsizes.d.ts +0 -1
- package/types/src/simul/reference-data/orderStatus.d.ts +0 -1
- package/types/src/simul/reference-data/orders.d.ts +0 -36
- package/types/src/simul/reference-data/parent-child-orders.d.ts +0 -4
- package/types/src/simul/reference-data/priceStrategies.d.ts +0 -1
- package/types/src/simul/reference-data/prices.d.ts +0 -34
- package/types/src/simul/reference-data/sides.d.ts +0 -1
- package/types/src/simul/simul-schemas.d.ts +0 -9
- package/types/src/test/TestModule.d.ts +0 -16
- package/types/src/test/index.d.ts +0 -1
- package/types/src/vuu-row-generator.d.ts +0 -17
package/README.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# `@vuu-ui/vuu-data-test`
|
|
2
2
|
|
|
3
|
+
## Local basket trading
|
|
4
|
+
|
|
5
|
+
Constituent reference data is generated from the server's four CSV files in
|
|
6
|
+
`example/main/src/main/resources/static/`. From `vuu-ui`, run
|
|
7
|
+
`npm run generate:basket-data` after editing those files and commit the resulting
|
|
8
|
+
`src/basket/reference-data/constituents.json`. Use
|
|
9
|
+
`npm run generate:basket-data -- --check` to verify it is up to date.
|
|
10
|
+
The converter preserves source weights (without normalizing their units),
|
|
11
|
+
maps the differing price/change column names, and rejects invalid CSV records.
|
|
12
|
+
The browser loads only the generated JSON, not the CSV parser.
|
|
13
|
+
|
|
14
|
+
The `BASKET` module provides its own simulated constituent prices, including
|
|
15
|
+
updates for all basket instruments. Its constituent join retains
|
|
16
|
+
`instanceIdRic` as the row key, so multiple trading baskets can contain the
|
|
17
|
+
same instrument. Direct edits through the join update the underlying
|
|
18
|
+
constituent table; subsequent price ticks preserve those edits.
|
|
19
|
+
Changing the basket side flips each constituent's current side, preserving
|
|
20
|
+
mixed BUY/SELL positions, as on the Scala server. Unchanged side edits do
|
|
21
|
+
nothing, and other basket instances are unaffected.
|
|
22
|
+
Editing basket units recalculates its constituent quantities as
|
|
23
|
+
`weighting * units`, truncated to whole units, matching the Scala service.
|
|
24
|
+
|
|
25
|
+
New baskets retain the `basketTradeName` supplied by the creation dialog.
|
|
26
|
+
Constituents default to the Limit price strategy (`priceStrategyId = 2`),
|
|
27
|
+
matching the Scala server.
|
|
28
|
+
Dropping an instrument from the Add constituent context panel adds it to the
|
|
29
|
+
requested basket instance. Manually added constituents start with weight `0.1`,
|
|
30
|
+
BUY side and Limit strategy; quantity is calculated from the current basket
|
|
31
|
+
units. Unknown instruments, duplicates, missing baskets and on-market baskets
|
|
32
|
+
are rejected without changing existing rows.
|
|
33
|
+
The Add constituent list excludes RICs already in the active basket using a
|
|
34
|
+
separate full-membership subscription, including rows outside the visible grid.
|
|
35
|
+
Sending a basket to market and taking it off market update its constituent
|
|
36
|
+
statuses; live rows include `orderStatus` and an initially zero `filledQty`.
|
|
37
|
+
Execution fills are not simulated.
|
|
38
|
+
|
|
3
39
|
## Admin test module dependencies
|
|
4
40
|
|
|
5
41
|
The `USER_ADMIN` and `MODULE_DISCOVERY` test modules use the published
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.0.0-alpha.
|
|
2
|
+
"version": "4.0.0-alpha.23",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "heswell",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@heswell/module-admin": "1.1.0",
|
|
14
14
|
"@heswell/user-admin": "1.0.1",
|
|
15
|
-
"@vuu-ui/vuu-data-editing": "4.0.0-alpha.
|
|
16
|
-
"@vuu-ui/vuu-data-local": "4.0.0-alpha.
|
|
17
|
-
"@vuu-ui/vuu-utils": "4.0.0-alpha.
|
|
15
|
+
"@vuu-ui/vuu-data-editing": "4.0.0-alpha.23",
|
|
16
|
+
"@vuu-ui/vuu-data-local": "4.0.0-alpha.23",
|
|
17
|
+
"@vuu-ui/vuu-utils": "4.0.0-alpha.23"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@vuu-ui/vuu-
|
|
21
|
-
"@vuu-ui/vuu-
|
|
22
|
-
"@vuu-ui/vuu-table-types": "4.0.0-alpha.
|
|
20
|
+
"@vuu-ui/vuu-protocol-types": "4.0.0-alpha.23",
|
|
21
|
+
"@vuu-ui/vuu-data-types": "4.0.0-alpha.23",
|
|
22
|
+
"@vuu-ui/vuu-table-types": "4.0.0-alpha.23"
|
|
23
23
|
},
|
|
24
24
|
"sideEffects": false,
|
|
25
25
|
"files": [
|
|
@@ -2,6 +2,7 @@ import { VuuModule } from "../core/module/VuuModule.js";
|
|
|
2
2
|
import TableContainer from "../core/table/TableContainer.js";
|
|
3
3
|
import { schemas } from "./basket-schemas.js";
|
|
4
4
|
import reference_data_constituents from "./reference-data/constituents.js";
|
|
5
|
+
import prices from "./reference-data/prices.js";
|
|
5
6
|
const { createTable: createTable } = TableContainer;
|
|
6
7
|
let basketIncrement = 1;
|
|
7
8
|
const createBasketTradingRow = (basketId, basketName, side = "BUY", status = "OFF MARKET")=>[
|
|
@@ -98,10 +99,7 @@ class BasketModule extends VuuModule {
|
|
|
98
99
|
}, {
|
|
99
100
|
module: "BASKET",
|
|
100
101
|
table: "basketTradingConstituent"
|
|
101
|
-
},
|
|
102
|
-
module: "SIMUL",
|
|
103
|
-
table: "prices"
|
|
104
|
-
}, "ric"),
|
|
102
|
+
}, prices, "ric"),
|
|
105
103
|
priceStrategyType: createTable(schemas.priceStrategyType, [
|
|
106
104
|
[
|
|
107
105
|
"Peg to Near Touch",
|
|
@@ -123,6 +121,22 @@ class BasketModule extends VuuModule {
|
|
|
123
121
|
};
|
|
124
122
|
constructor(){
|
|
125
123
|
super("BASKET");
|
|
124
|
+
const table = this.tables.basketTrading;
|
|
125
|
+
const update = table.update.bind(table);
|
|
126
|
+
table.update = (key, column, value)=>{
|
|
127
|
+
if ("side" !== column && "units" !== column) return update(key, column, value);
|
|
128
|
+
const basket = table.findByKey(key);
|
|
129
|
+
if (!basket) throw Error(`[BasketModule] basket ${key} not found`);
|
|
130
|
+
if (basket[table.map[column]] === value) return;
|
|
131
|
+
if ("units" === column && ("number" != typeof value || !Number.isInteger(value))) throw Error("[BasketModule] units must be an integer");
|
|
132
|
+
update(key, column, value);
|
|
133
|
+
const constituents = this.tables.basketTradingConstituent;
|
|
134
|
+
for (const row of constituents.data)if (row[constituents.map.instanceId] === key) {
|
|
135
|
+
const constituentKey = String(row[constituents.map.instanceIdRic]);
|
|
136
|
+
if ("side" === column) constituents.update(constituentKey, "side", "BUY" === row[constituents.map.side] ? "SELL" : "BUY");
|
|
137
|
+
else if ("number" == typeof value) constituents.update(constituentKey, "quantity", Math.trunc(Number(row[constituents.map.weighting]) * value));
|
|
138
|
+
}
|
|
139
|
+
};
|
|
126
140
|
}
|
|
127
141
|
get menus() {
|
|
128
142
|
return {
|
|
@@ -196,45 +210,55 @@ class BasketModule extends VuuModule {
|
|
|
196
210
|
const { basketId: key } = buildDataColumnMap("basketConstituent");
|
|
197
211
|
const constituents = this.tables.basketConstituent.data.filter((c)=>c[key] === basketId);
|
|
198
212
|
const { instanceId } = tableMaps.basketTrading;
|
|
199
|
-
constituents.forEach(([, , description, , ric, , ,
|
|
200
|
-
|
|
201
|
-
const algoParams = "";
|
|
202
|
-
const limitPrice = 95;
|
|
203
|
-
const notionalLocal = 0;
|
|
204
|
-
const notionalUsd = 0;
|
|
205
|
-
const pctFilled = 0;
|
|
206
|
-
const priceSpread = 0;
|
|
207
|
-
const priceStrategyId = "";
|
|
208
|
-
const side = "BUY";
|
|
209
|
-
const venue = "venue";
|
|
210
|
-
const basketInstanceId = basketTradingRow[instanceId];
|
|
211
|
-
const basketTradingConstituentRow = [
|
|
212
|
-
algo,
|
|
213
|
-
algoParams,
|
|
214
|
-
basketId,
|
|
215
|
-
description,
|
|
216
|
-
basketInstanceId,
|
|
217
|
-
`${basketInstanceId}-${ric}`,
|
|
218
|
-
limitPrice,
|
|
219
|
-
notionalLocal,
|
|
220
|
-
notionalUsd,
|
|
221
|
-
pctFilled,
|
|
222
|
-
priceSpread,
|
|
223
|
-
priceStrategyId,
|
|
224
|
-
quantity,
|
|
225
|
-
ric,
|
|
226
|
-
side,
|
|
227
|
-
venue,
|
|
228
|
-
weighting
|
|
229
|
-
];
|
|
230
|
-
basketTradingConstituent.insert(basketTradingConstituentRow);
|
|
213
|
+
constituents.forEach(([, , description, , ric, , , , weighting])=>{
|
|
214
|
+
this.insertTradingConstituent(basketTradingRow, String(ric), String(description), Number(weighting));
|
|
231
215
|
});
|
|
232
216
|
return basketTradingRow[instanceId];
|
|
233
217
|
}
|
|
218
|
+
insertTradingConstituent(basketTradingRow, ric, description, weighting) {
|
|
219
|
+
const { basketId, instanceId } = tableMaps.basketTrading;
|
|
220
|
+
const quantity = Math.trunc(Number(weighting) * Number(basketTradingRow[tableMaps.basketTrading.units]));
|
|
221
|
+
const algo = "";
|
|
222
|
+
const algoParams = "";
|
|
223
|
+
const limitPrice = 95;
|
|
224
|
+
const notionalLocal = 0;
|
|
225
|
+
const notionalUsd = 0;
|
|
226
|
+
const pctFilled = 0;
|
|
227
|
+
const priceSpread = 0;
|
|
228
|
+
const priceStrategyId = 2;
|
|
229
|
+
const side = "BUY";
|
|
230
|
+
const status = "OFF-MARKET";
|
|
231
|
+
const venue = "venue";
|
|
232
|
+
const basketInstanceId = basketTradingRow[instanceId];
|
|
233
|
+
const basketTradingConstituentRow = [
|
|
234
|
+
algo,
|
|
235
|
+
algoParams,
|
|
236
|
+
basketTradingRow[basketId],
|
|
237
|
+
description,
|
|
238
|
+
basketInstanceId,
|
|
239
|
+
`${basketInstanceId}-${ric}`,
|
|
240
|
+
limitPrice,
|
|
241
|
+
notionalLocal,
|
|
242
|
+
notionalUsd,
|
|
243
|
+
pctFilled,
|
|
244
|
+
priceSpread,
|
|
245
|
+
priceStrategyId,
|
|
246
|
+
quantity,
|
|
247
|
+
ric,
|
|
248
|
+
side,
|
|
249
|
+
status,
|
|
250
|
+
venue,
|
|
251
|
+
weighting,
|
|
252
|
+
"PENDING",
|
|
253
|
+
0
|
|
254
|
+
];
|
|
255
|
+
basketTradingConstituent.insert(basketTradingConstituentRow);
|
|
256
|
+
return `${basketInstanceId}-${ric}`;
|
|
257
|
+
}
|
|
234
258
|
createNewBasket = async (rpcRequest)=>{
|
|
235
259
|
if ("VIEWPORT_CONTEXT" === rpcRequest.context.type) {
|
|
236
|
-
const { sourceBasketId,
|
|
237
|
-
const key = this.createTradingBasket(sourceBasketId,
|
|
260
|
+
const { sourceBasketId, basketTradeName } = rpcRequest.params;
|
|
261
|
+
const key = this.createTradingBasket(sourceBasketId, basketTradeName);
|
|
238
262
|
return {
|
|
239
263
|
type: "SUCCESS_RESULT",
|
|
240
264
|
data: key
|
|
@@ -246,6 +270,7 @@ class BasketModule extends VuuModule {
|
|
|
246
270
|
if ("VIEWPORT_CONTEXT" === rpcRequest.context.type) {
|
|
247
271
|
const { basketInstanceId } = rpcRequest.params;
|
|
248
272
|
this.tables.basketTrading.update(basketInstanceId, "status", "ON_MARKET");
|
|
273
|
+
this.updateConstituentStatus(basketInstanceId, "ON_MARKET", "ACKED");
|
|
249
274
|
return {
|
|
250
275
|
type: "SUCCESS_RESULT",
|
|
251
276
|
data: void 0
|
|
@@ -257,6 +282,7 @@ class BasketModule extends VuuModule {
|
|
|
257
282
|
if ("VIEWPORT_CONTEXT" === rpcRequest.context.type) {
|
|
258
283
|
const { basketInstanceId } = rpcRequest.params;
|
|
259
284
|
this.tables.basketTrading.update(basketInstanceId, "status", "OFF-MARKET");
|
|
285
|
+
this.updateConstituentStatus(basketInstanceId, "OFF-MARKET", "CANCELLED");
|
|
260
286
|
return {
|
|
261
287
|
type: "SUCCESS_RESULT",
|
|
262
288
|
data: void 0
|
|
@@ -264,9 +290,48 @@ class BasketModule extends VuuModule {
|
|
|
264
290
|
}
|
|
265
291
|
throw Error("[BasketModule] createNewBasket invalid request type");
|
|
266
292
|
};
|
|
267
|
-
addConstituent = async ()=>{
|
|
268
|
-
|
|
293
|
+
addConstituent = async (request)=>{
|
|
294
|
+
const { params } = request;
|
|
295
|
+
const ric = "ric" in params ? params.ric : void 0;
|
|
296
|
+
const basketInstanceId = "basketInstanceId" in params ? params.basketInstanceId : void 0;
|
|
297
|
+
if ("VIEWPORT_CONTEXT" !== request.context.type || "string" != typeof ric || "string" != typeof basketInstanceId) return {
|
|
298
|
+
type: "ERROR_RESULT",
|
|
299
|
+
errorMessage: "Invalid add constituent request"
|
|
300
|
+
};
|
|
301
|
+
const basket = this.tables.basketTrading.findByKey(basketInstanceId);
|
|
302
|
+
if (!basket) return {
|
|
303
|
+
type: "ERROR_RESULT",
|
|
304
|
+
errorMessage: "Basket not found"
|
|
305
|
+
};
|
|
306
|
+
if ("ON_MARKET" === basket[tableMaps.basketTrading.status]) return {
|
|
307
|
+
type: "ERROR_RESULT",
|
|
308
|
+
errorMessage: "Take the basket off market before adding constituents"
|
|
309
|
+
};
|
|
310
|
+
const source = this.tables.basketConstituent;
|
|
311
|
+
const reference = source.data.find((row)=>row[source.map.ric] === ric);
|
|
312
|
+
if (!reference) return {
|
|
313
|
+
type: "ERROR_RESULT",
|
|
314
|
+
errorMessage: `Unknown constituent ${ric}`
|
|
315
|
+
};
|
|
316
|
+
const key = `${basketInstanceId}-${ric}`;
|
|
317
|
+
if (this.tables.basketTradingConstituent.findByKey(key)) return {
|
|
318
|
+
type: "ERROR_RESULT",
|
|
319
|
+
errorMessage: `${ric} is already in this basket`
|
|
320
|
+
};
|
|
321
|
+
this.insertTradingConstituent(basket, ric, String(reference[source.map.description]), 0.1);
|
|
322
|
+
return {
|
|
323
|
+
type: "SUCCESS_RESULT",
|
|
324
|
+
data: key
|
|
325
|
+
};
|
|
269
326
|
};
|
|
327
|
+
updateConstituentStatus(basketInstanceId, status, orderStatus) {
|
|
328
|
+
const table = this.tables.basketTradingConstituent;
|
|
329
|
+
for (const row of table.data)if (row[table.map.instanceId] === basketInstanceId) {
|
|
330
|
+
const key = String(row[table.map.instanceIdRic]);
|
|
331
|
+
table.update(key, "status", status);
|
|
332
|
+
table.update(key, "orderStatus", orderStatus);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
270
335
|
}
|
|
271
336
|
const basketModule = new BasketModule();
|
|
272
337
|
export { BasketModule, basketModule, createBasketTradingRow };
|
|
@@ -216,6 +216,14 @@ const schemas = {
|
|
|
216
216
|
{
|
|
217
217
|
name: "weighting",
|
|
218
218
|
serverDataType: "double"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: "orderStatus",
|
|
222
|
+
serverDataType: "string"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "filledQty",
|
|
226
|
+
serverDataType: "long"
|
|
219
227
|
}
|
|
220
228
|
],
|
|
221
229
|
key: "instanceIdRic",
|
|
@@ -334,6 +342,14 @@ const schemas = {
|
|
|
334
342
|
{
|
|
335
343
|
name: "weighting",
|
|
336
344
|
serverDataType: "double"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
name: "orderStatus",
|
|
348
|
+
serverDataType: "string"
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: "filledQty",
|
|
352
|
+
serverDataType: "long"
|
|
337
353
|
}
|
|
338
354
|
],
|
|
339
355
|
key: "instanceIdRic",
|
|
@@ -1,76 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const side = "BUY";
|
|
10
|
-
const weighting = 1;
|
|
11
|
-
basketConstituentData.push([
|
|
12
|
-
basketId,
|
|
13
|
-
change,
|
|
14
|
-
name,
|
|
15
|
-
lastTrade,
|
|
16
|
-
ric,
|
|
17
|
-
`${ric}-${basketId}`,
|
|
18
|
-
side,
|
|
19
|
-
volume,
|
|
20
|
-
weighting
|
|
21
|
-
]);
|
|
22
|
-
}
|
|
23
|
-
for (const row of hsi){
|
|
24
|
-
const [name, ric, lastTrade, change, , volume] = row;
|
|
25
|
-
const basketId = ".HSI";
|
|
26
|
-
const side = "BUY";
|
|
27
|
-
const weighting = 1;
|
|
28
|
-
basketConstituentData.push([
|
|
29
|
-
basketId,
|
|
30
|
-
change,
|
|
31
|
-
name,
|
|
32
|
-
lastTrade,
|
|
33
|
-
ric,
|
|
34
|
-
`${ric}-${basketId}`,
|
|
35
|
-
side,
|
|
36
|
-
volume,
|
|
37
|
-
weighting
|
|
38
|
-
]);
|
|
39
|
-
}
|
|
40
|
-
for (const row of nasdaq100){
|
|
41
|
-
const [name, ric, weighting, lastTrade, change] = row;
|
|
42
|
-
const basketId = ".NASDAQ100";
|
|
43
|
-
const side = "BUY";
|
|
44
|
-
const volume = 1000;
|
|
45
|
-
basketConstituentData.push([
|
|
46
|
-
basketId,
|
|
47
|
-
change,
|
|
48
|
-
name,
|
|
49
|
-
lastTrade,
|
|
50
|
-
ric,
|
|
51
|
-
`${ric}-${basketId}`,
|
|
52
|
-
side,
|
|
53
|
-
volume,
|
|
54
|
-
weighting
|
|
55
|
-
]);
|
|
56
|
-
}
|
|
57
|
-
for (const row of sp500){
|
|
58
|
-
const [name, ric, weighting, , change] = row;
|
|
59
|
-
const basketId = ".SP500";
|
|
60
|
-
const side = "BUY";
|
|
61
|
-
const volume = 1000;
|
|
62
|
-
const lastTrade = 0;
|
|
63
|
-
basketConstituentData.push([
|
|
64
|
-
basketId,
|
|
65
|
-
change,
|
|
66
|
-
name,
|
|
67
|
-
lastTrade,
|
|
68
|
-
ric,
|
|
69
|
-
`${ric}-${basketId}`,
|
|
70
|
-
side,
|
|
71
|
-
volume,
|
|
72
|
-
weighting
|
|
73
|
-
]);
|
|
74
|
-
}
|
|
75
|
-
var constituents = basketConstituentData;
|
|
76
|
-
export default constituents;
|
|
1
|
+
import constituents from "./constituents.js";
|
|
2
|
+
import { schemas } from "../basket-schemas.js";
|
|
3
|
+
const basketConstituentData = constituents.map((constituent)=>{
|
|
4
|
+
const values = constituent;
|
|
5
|
+
return schemas.basketConstituent.columns.map(({ name })=>values[name]);
|
|
6
|
+
});
|
|
7
|
+
var reference_data_constituents = basketConstituentData;
|
|
8
|
+
export default reference_data_constituents;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { buildDataColumnMap } from "../../Table.js";
|
|
1
|
+
import { Table, buildDataColumnMap } from "../../Table.js";
|
|
2
2
|
import { BaseUpdateGenerator } from "../../UpdateGenerator.js";
|
|
3
3
|
import { schemas } from "../../simul/simul-schemas.js";
|
|
4
4
|
import constituents from "./constituents.js";
|
|
5
5
|
import { initBidAsk, nextRandomDouble, random } from "../../data-utils.js";
|
|
6
|
-
import TableContainer from "../../core/table/TableContainer.js";
|
|
7
6
|
const { bid: prices_bid, bidSize: prices_bidSize, ask: prices_ask, askSize: prices_askSize, last: prices_last } = buildDataColumnMap(schemas, "prices");
|
|
8
7
|
const pricesUpdateGenerator = new BaseUpdateGenerator({
|
|
9
8
|
bid: prices_bid,
|
|
@@ -13,9 +12,12 @@ const pricesUpdateGenerator = new BaseUpdateGenerator({
|
|
|
13
12
|
last: prices_last
|
|
14
13
|
});
|
|
15
14
|
const prices = [];
|
|
15
|
+
const seen = new Set();
|
|
16
16
|
for (const [, , , lastTrade, ric] of constituents){
|
|
17
|
+
if (seen.has(String(ric))) continue;
|
|
17
18
|
const priceSeed = parseFloat(String(lastTrade));
|
|
18
19
|
if (!isNaN(priceSeed)) {
|
|
20
|
+
seen.add(String(ric));
|
|
19
21
|
const [bid, ask] = initBidAsk(5, nextRandomDouble);
|
|
20
22
|
const askSize = random(1000, 3000);
|
|
21
23
|
const bidSize = random(1000, 3000);
|
|
@@ -38,6 +40,10 @@ for (const [, , , lastTrade, ric] of constituents){
|
|
|
38
40
|
]);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
const pricesTable =
|
|
43
|
+
const pricesTable = new Table(schemas.prices, prices, buildDataColumnMap(schemas, "prices"), pricesUpdateGenerator);
|
|
44
|
+
pricesUpdateGenerator.setRange({
|
|
45
|
+
from: 0,
|
|
46
|
+
to: prices.length
|
|
47
|
+
});
|
|
42
48
|
var reference_data_prices = pricesTable;
|
|
43
49
|
export default reference_data_prices;
|
|
@@ -15,9 +15,9 @@ class TableContainer {
|
|
|
15
15
|
this.addTable(table);
|
|
16
16
|
return table;
|
|
17
17
|
};
|
|
18
|
-
createJoinTable(joinTable,
|
|
19
|
-
const table1 = this.getTable(
|
|
20
|
-
const table2 = this.getTable(
|
|
18
|
+
createJoinTable(joinTable, source1, source2, joinColumn) {
|
|
19
|
+
const table1 = source1 instanceof Table ? source1 : this.getTable(source1.table);
|
|
20
|
+
const table2 = source2 instanceof Table ? source2 : this.getTable(source2.table);
|
|
21
21
|
const { map: m1, schema: schema1 } = table1;
|
|
22
22
|
const { map: m2, schema: schema2 } = table2;
|
|
23
23
|
const k1 = m1[joinColumn];
|
|
@@ -27,7 +27,7 @@ class TableContainer {
|
|
|
27
27
|
...schema2.columns
|
|
28
28
|
].map((col)=>col.name).sort());
|
|
29
29
|
const combinedSchema = {
|
|
30
|
-
key:
|
|
30
|
+
key: schema1.key,
|
|
31
31
|
table: joinTable,
|
|
32
32
|
rangeLimits: DEFAULT_RANGE_LIMITS,
|
|
33
33
|
columns: Array.from(combinedColumns).map((columnName)=>({
|
|
@@ -53,6 +53,18 @@ class TableContainer {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
const newTable = new Table(combinedSchema, data, combinedColumnMap);
|
|
56
|
+
const joinedKeys = new Map();
|
|
57
|
+
const indexJoinedRow = (row)=>{
|
|
58
|
+
const value = String(row[combinedColumnMap[joinColumn]]);
|
|
59
|
+
const key = String(row[combinedColumnMap[schema1.key]]);
|
|
60
|
+
let keys = joinedKeys.get(value);
|
|
61
|
+
if (!keys) {
|
|
62
|
+
keys = new Set();
|
|
63
|
+
joinedKeys.set(value, keys);
|
|
64
|
+
}
|
|
65
|
+
keys.add(key);
|
|
66
|
+
};
|
|
67
|
+
data.forEach(indexJoinedRow);
|
|
56
68
|
table1.on("insert", (row)=>{
|
|
57
69
|
const row2 = table2.findByKey(String(row[k1]));
|
|
58
70
|
if (row2) {
|
|
@@ -65,18 +77,49 @@ class TableContainer {
|
|
|
65
77
|
const value = row2[m2[column.name]];
|
|
66
78
|
out[combinedColumnMap[column.name]] = value;
|
|
67
79
|
}
|
|
80
|
+
indexJoinedRow(out);
|
|
68
81
|
newTable.insert(out);
|
|
69
82
|
}
|
|
70
83
|
});
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
const targetRow = newTable.findByKey(
|
|
84
|
+
table1.on("update", (row)=>{
|
|
85
|
+
const key = String(row[m1[schema1.key]]);
|
|
86
|
+
const targetRow = newTable.findByKey(key);
|
|
74
87
|
if (targetRow) {
|
|
75
88
|
const updatedRow = targetRow.slice();
|
|
76
|
-
for (const { name } of
|
|
89
|
+
for (const { name } of schema1.columns)updatedRow[combinedColumnMap[name]] = row[m1[name]];
|
|
90
|
+
newTable.updateRow(updatedRow);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
table1.on("delete", (key)=>{
|
|
94
|
+
const row = newTable.findByKey(key);
|
|
95
|
+
if (row) {
|
|
96
|
+
const value = String(row[combinedColumnMap[joinColumn]]);
|
|
97
|
+
const keys = joinedKeys.get(value);
|
|
98
|
+
keys?.delete(key);
|
|
99
|
+
if (keys?.size === 0) joinedKeys.delete(value);
|
|
100
|
+
newTable.delete(key);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
table2.on("update", (row)=>{
|
|
104
|
+
const keyValue = String(row[k2]);
|
|
105
|
+
for (const key of joinedKeys.get(keyValue) ?? []){
|
|
106
|
+
const targetRow = newTable.findByKey(key);
|
|
107
|
+
if (!targetRow) continue;
|
|
108
|
+
const updatedRow = targetRow.slice();
|
|
109
|
+
for (const { name } of table2.schema.columns)if (!(name in m1)) {
|
|
110
|
+
if (row[m2[name]] !== updatedRow[combinedColumnMap[name]]) updatedRow[combinedColumnMap[name]] = row[m2[name]];
|
|
111
|
+
}
|
|
77
112
|
newTable.updateRow(updatedRow);
|
|
78
113
|
}
|
|
79
114
|
});
|
|
115
|
+
newTable.update = (key, columnName, value)=>{
|
|
116
|
+
const row = newTable.findByKey(key);
|
|
117
|
+
if (!row) throw Error(`[TableContainer] join row ${key} not found`);
|
|
118
|
+
if (columnName === schema1.key || columnName === joinColumn) throw Error(`[TableContainer] cannot edit join key ${columnName}`);
|
|
119
|
+
if (columnName in m1) table1.update(key, columnName, value);
|
|
120
|
+
else if (columnName in m2) table2.update(String(row[combinedColumnMap[schema2.key]]), columnName, value);
|
|
121
|
+
else throw Error(`[TableContainer] unknown join column ${columnName}`);
|
|
122
|
+
};
|
|
80
123
|
this.addTable(newTable);
|
|
81
124
|
return newTable;
|
|
82
125
|
}
|
|
@@ -47,9 +47,11 @@ export declare class BasketModule extends VuuModule<BasketsTableName> {
|
|
|
47
47
|
}[];
|
|
48
48
|
};
|
|
49
49
|
private createTradingBasket;
|
|
50
|
+
private insertTradingConstituent;
|
|
50
51
|
private createNewBasket;
|
|
51
52
|
private sendToMarket;
|
|
52
53
|
private takeOffMarket;
|
|
53
54
|
private addConstituent;
|
|
55
|
+
private updateConstituentStatus;
|
|
54
56
|
}
|
|
55
57
|
export declare const basketModule: BasketModule;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
-
declare const
|
|
3
|
-
export default
|
|
1
|
+
import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
declare const basketConstituentData: VuuRowDataItemType[][];
|
|
3
|
+
export default basketConstituentData;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Table } from "../../Table";
|
|
1
2
|
export type ask = number;
|
|
2
3
|
export type askSize = number;
|
|
3
4
|
export type bid = number;
|
|
@@ -20,5 +21,5 @@ export type PricesDataRow = [
|
|
|
20
21
|
ric,
|
|
21
22
|
scenario
|
|
22
23
|
];
|
|
23
|
-
declare const pricesTable:
|
|
24
|
+
declare const pricesTable: Table;
|
|
24
25
|
export default pricesTable;
|
|
@@ -8,7 +8,7 @@ declare class TableContainer {
|
|
|
8
8
|
private constructor();
|
|
9
9
|
static get instance(): TableContainer;
|
|
10
10
|
createTable: (schema: TableSchema, data?: Array<Array<VuuRowDataItemType | bigint>>, dataMap?: ColumnMap, updateGenerator?: UpdateGenerator) => Table;
|
|
11
|
-
createJoinTable(joinTable: VuuTable,
|
|
11
|
+
createJoinTable(joinTable: VuuTable, source1: VuuTable | Table, source2: VuuTable | Table, joinColumn: string): Table;
|
|
12
12
|
addTable(table: Table): void;
|
|
13
13
|
getTable<T = Table>(tableName: string): NonNullable<T>;
|
|
14
14
|
}
|