@yuants/app-virtual-exchange 0.7.1 → 0.8.0

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/dist/general.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';
2
2
  import { Terminal } from '@yuants/protocol';
3
3
  import { getCredentialBySecretId } from './credential';
4
- import { polyfillPosition } from './position';
4
+ import { polyfillOrders, polyfillPosition } from './position';
5
5
  const terminal = Terminal.fromNodeEnv();
6
6
  terminal.server.provideService('VEX/GetPositions', {
7
7
  type: 'object',
@@ -16,6 +16,9 @@ terminal.server.provideService('VEX/GetPositions', {
16
16
  if (!res.data)
17
17
  return { res };
18
18
  const positions = await polyfillPosition(res.data);
19
+ positions.forEach((pos) => {
20
+ pos.account_id = credential.credentialId;
21
+ });
19
22
  return { res: { code: 0, message: 'OK', data: positions } };
20
23
  });
21
24
  terminal.server.provideService('VEX/GetOrders', {
@@ -26,13 +29,16 @@ terminal.server.provideService('VEX/GetOrders', {
26
29
  product_id: { type: 'string' },
27
30
  },
28
31
  }, async (msg) => {
29
- var _a;
30
32
  const credential = await getCredentialBySecretId(msg.req.secret_id);
31
33
  const res = await getOrders(terminal, credential.credential, msg.req.product_id);
32
- (_a = res.data) === null || _a === void 0 ? void 0 : _a.forEach((order) => {
34
+ if (!res.data)
35
+ return { res };
36
+ const orders = res.data;
37
+ orders.forEach((order) => {
33
38
  order.account_id = credential.credentialId;
34
39
  });
35
- return { res };
40
+ await polyfillOrders(orders);
41
+ return { res: { code: 0, message: 'OK', data: orders } };
36
42
  });
37
43
  // 10. Proxy Orders
38
44
  // SubmitOrder
@@ -45,7 +51,8 @@ terminal.server.provideService('VEX/SubmitOrder', {
45
51
  },
46
52
  }, async (msg) => {
47
53
  const credential = await getCredentialBySecretId(msg.req.secret_id);
48
- const res = await submitOrder(terminal, credential.credential, msg.req.order);
54
+ const [order] = await polyfillOrders([msg.req.order]);
55
+ const res = await submitOrder(terminal, credential.credential, order);
49
56
  return { res };
50
57
  });
51
58
  // ModifyOrder
@@ -58,7 +65,8 @@ terminal.server.provideService('VEX/ModifyOrder', {
58
65
  },
59
66
  }, async (msg) => {
60
67
  const credential = await getCredentialBySecretId(msg.req.secret_id);
61
- const res = await modifyOrder(terminal, credential.credential, msg.req.order);
68
+ const [order] = await polyfillOrders([msg.req.order]);
69
+ const res = await modifyOrder(terminal, credential.credential, order);
62
70
  return { res };
63
71
  });
64
72
  // CancelOrder
@@ -71,7 +79,8 @@ terminal.server.provideService('VEX/CancelOrder', {
71
79
  },
72
80
  }, async (msg) => {
73
81
  const credential = await getCredentialBySecretId(msg.req.secret_id);
74
- const res = await cancelOrder(terminal, credential.credential, msg.req.order);
82
+ const [order] = await polyfillOrders([msg.req.order]);
83
+ const res = await cancelOrder(terminal, credential.credential, order);
75
84
  return { res };
76
85
  });
77
86
  //# sourceMappingURL=general.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"general.js","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":"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","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { getCredentialBySecretId } from './credential';\nimport { polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IPosition[]>(\n 'VEX/GetPositions',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getPositions(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const positions = await polyfillPosition(res.data);\n return { res: { code: 0, message: 'OK', data: positions } };\n },\n);\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IOrder[]>(\n 'VEX/GetOrders',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getOrders(terminal, credential.credential, msg.req.product_id);\n res.data?.forEach((order) => {\n order.account_id = credential.credentialId;\n });\n return { res };\n },\n);\n\n// 10. Proxy Orders\n// SubmitOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, { order_id: string }>(\n 'VEX/SubmitOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await submitOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n\n// ModifyOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/ModifyOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await modifyOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n\n// CancelOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/CancelOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await cancelOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n"]}
1
+ {"version":3,"file":"general.js","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":"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","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { getCredentialBySecretId } from './credential';\nimport { polyfillOrders, polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IPosition[]>(\n 'VEX/GetPositions',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getPositions(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const positions = await polyfillPosition(res.data);\n positions.forEach((pos) => {\n pos.account_id = credential.credentialId;\n });\n return { res: { code: 0, message: 'OK', data: positions } };\n },\n);\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IOrder[]>(\n 'VEX/GetOrders',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getOrders(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const orders = res.data;\n orders.forEach((order) => {\n order.account_id = credential.credentialId;\n });\n await polyfillOrders(orders);\n return { res: { code: 0, message: 'OK', data: orders } };\n },\n);\n\n// 10. Proxy Orders\n// SubmitOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, { order_id: string }>(\n 'VEX/SubmitOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await submitOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n\n// ModifyOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/ModifyOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await modifyOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n\n// CancelOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/CancelOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await cancelOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n"]}
@@ -5,7 +5,7 @@ import { Terminal } from '@yuants/protocol';
5
5
  import { listWatch, newError } from '@yuants/utils';
6
6
  import { map, Observable } from 'rxjs';
7
7
  import { validCredentials$ } from './credential';
8
- import { polyfillPosition } from './position';
8
+ import { polyfillOrders, polyfillPosition } from './position';
9
9
  const terminal = Terminal.fromNodeEnv();
10
10
  validCredentials$
11
11
  .pipe(map((x) => Array.from(x.entries())), listWatch(([id]) => id, ([credential_id, credential]) => new Observable((sub) => {
@@ -17,6 +17,9 @@ validCredentials$
17
17
  if (!res.data)
18
18
  throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });
19
19
  const polyfilledPositions = await polyfillPosition(res.data);
20
+ polyfilledPositions.forEach((pos) => {
21
+ pos.account_id = credential_id;
22
+ });
20
23
  return polyfilledPositions;
21
24
  }, {
22
25
  auto_refresh_interval: 1000,
@@ -34,6 +37,7 @@ validCredentials$
34
37
  res.data.forEach((order) => {
35
38
  order.account_id = credential_id;
36
39
  });
40
+ await polyfillOrders(res.data);
37
41
  return res.data;
38
42
  }, {
39
43
  auto_refresh_interval: 10000,
@@ -51,7 +55,8 @@ validCredentials$
51
55
  account_id: { type: 'string', const: credential_id },
52
56
  },
53
57
  }, async (msg) => {
54
- const res = await submitOrder(terminal, credential, msg.req);
58
+ const [order] = await polyfillOrders([msg.req]);
59
+ const res = await submitOrder(terminal, credential, order);
55
60
  return { res };
56
61
  });
57
62
  sub.add(() => {
@@ -67,7 +72,8 @@ validCredentials$
67
72
  account_id: { type: 'string', const: credential_id },
68
73
  },
69
74
  }, async (msg) => {
70
- const res = await modifyOrder(terminal, credential, msg.req);
75
+ const [order] = await polyfillOrders([msg.req]);
76
+ const res = await modifyOrder(terminal, credential, order);
71
77
  return { res };
72
78
  });
73
79
  sub.add(() => {
@@ -83,7 +89,8 @@ validCredentials$
83
89
  account_id: { type: 'string', const: credential_id },
84
90
  },
85
91
  }, async (msg) => {
86
- const res = await cancelOrder(terminal, credential, msg.req);
92
+ const [order] = await polyfillOrders([msg.req]);
93
+ const res = await cancelOrder(terminal, credential, order);
87
94
  return { res };
88
95
  });
89
96
  sub.add(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { listWatch, newError } from '@yuants/utils';\nimport { map, Observable } from 'rxjs';\nimport { validCredentials$ } from './credential';\nimport { polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nvalidCredentials$\n .pipe(\n map((x) => Array.from(x.entries())),\n listWatch(\n ([id]) => id,\n ([credential_id, credential]) =>\n new Observable((sub) => {\n console.info(`Setting up VEX services for credential: ${credential_id}`);\n // Setup AccountInfo Service\n {\n const service = provideAccountInfoService(\n terminal,\n credential_id,\n async () => {\n const res = await getPositions(terminal, credential);\n if (!res.data) throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });\n const polyfilledPositions = await polyfillPosition(res.data);\n return polyfilledPositions;\n },\n {\n auto_refresh_interval: 1000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup Pending Orders Service\n {\n const service = providePendingOrdersService(\n terminal,\n credential_id,\n async () => {\n const res = await getOrders(terminal, credential);\n if (!res.data) throw newError('FETCH_ORDERS_FAILED', { credential_id, res });\n\n res.data.forEach((order) => {\n order.account_id = credential_id;\n });\n\n return res.data;\n },\n {\n auto_refresh_interval: 10000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup SubmitOrder Service\n {\n const service = terminal.server.provideService<IOrder, { order_id: string }>(\n 'SubmitOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await submitOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup ModifyOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'ModifyOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await modifyOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup CancelOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'CancelOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await cancelOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n }),\n ),\n )\n .subscribe();\n"]}
1
+ {"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { listWatch, newError } from '@yuants/utils';\nimport { map, Observable } from 'rxjs';\nimport { validCredentials$ } from './credential';\nimport { polyfillOrders, polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nvalidCredentials$\n .pipe(\n map((x) => Array.from(x.entries())),\n listWatch(\n ([id]) => id,\n ([credential_id, credential]) =>\n new Observable((sub) => {\n console.info(`Setting up VEX services for credential: ${credential_id}`);\n // Setup AccountInfo Service\n {\n const service = provideAccountInfoService(\n terminal,\n credential_id,\n async () => {\n const res = await getPositions(terminal, credential);\n if (!res.data) throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });\n const polyfilledPositions = await polyfillPosition(res.data);\n polyfilledPositions.forEach((pos) => {\n pos.account_id = credential_id;\n });\n return polyfilledPositions;\n },\n {\n auto_refresh_interval: 1000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup Pending Orders Service\n {\n const service = providePendingOrdersService(\n terminal,\n credential_id,\n async () => {\n const res = await getOrders(terminal, credential);\n if (!res.data) throw newError('FETCH_ORDERS_FAILED', { credential_id, res });\n\n res.data.forEach((order) => {\n order.account_id = credential_id;\n });\n\n await polyfillOrders(res.data);\n\n return res.data;\n },\n {\n auto_refresh_interval: 10000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup SubmitOrder Service\n {\n const service = terminal.server.provideService<IOrder, { order_id: string }>(\n 'SubmitOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await submitOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup ModifyOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'ModifyOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await modifyOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup CancelOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'CancelOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await cancelOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n }),\n ),\n )\n .subscribe();\n"]}
package/dist/position.js CHANGED
@@ -2,6 +2,7 @@ import { createCache } from '@yuants/cache';
2
2
  import { createClientProductCache } from '@yuants/data-product';
3
3
  import { Terminal } from '@yuants/protocol';
4
4
  import { escapeSQL, requestSQL } from '@yuants/sql';
5
+ import { newError } from '@yuants/utils';
5
6
  const terminal = Terminal.fromNodeEnv();
6
7
  const productCache = createClientProductCache(terminal);
7
8
  const quoteCache = createCache(async (product_id) => {
@@ -14,8 +15,15 @@ const interestRateIntervalCache = createCache(async (product_id) => {
14
15
  const rates = await requestSQL(terminal, sql);
15
16
  if (rates.length < 2)
16
17
  return undefined;
17
- return new Date(rates[0].created_at).getTime() - new Date(rates[1].created_at).getTime();
18
- });
18
+ const prev = new Date(rates[0].created_at).getTime();
19
+ const prevOfPrev = new Date(rates[1].created_at).getTime();
20
+ const interval = prev - prevOfPrev;
21
+ return {
22
+ prev,
23
+ prevOfPrev,
24
+ interval,
25
+ };
26
+ }, { swrAfter: 3600000, expire: 8 * 3600000 });
19
27
  export const polyfillPosition = async (positions) => {
20
28
  // TODO: 使用 batch query SQL 优化 product / quote 查询性能
21
29
  for (const pos of positions) {
@@ -44,8 +52,15 @@ export const polyfillPosition = async (positions) => {
44
52
  // 利率相关信息的追加
45
53
  if (quote) {
46
54
  if (quote.interest_rate_next_settled_at !== null) {
55
+ // 优先使用行情数据中的下一个结算时间
47
56
  pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();
48
57
  }
58
+ else if (quote.interest_rate_next_settled_at === null && interestRateInterval !== undefined) {
59
+ // 估算下一个结算时间
60
+ // 找到 prev + k * interval > now 的最小 k,则下一个结算时间为 prev + k * interval
61
+ const k = Math.ceil((Date.now() - interestRateInterval.prev) / interestRateInterval.interval);
62
+ pos.settlement_scheduled_at = interestRateInterval.prev + k * interestRateInterval.interval;
63
+ }
49
64
  if (pos.direction === 'LONG') {
50
65
  if (quote.interest_rate_long !== null) {
51
66
  pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;
@@ -58,9 +73,39 @@ export const polyfillPosition = async (positions) => {
58
73
  }
59
74
  }
60
75
  if (interestRateInterval) {
61
- pos.settlement_interval = interestRateInterval;
76
+ pos.settlement_interval = interestRateInterval.interval;
62
77
  }
63
78
  }
64
79
  return positions;
65
80
  };
81
+ export const polyfillOrders = async (orders) => {
82
+ for (const order of orders) {
83
+ const theProduct = await productCache.query(order.product_id);
84
+ if (theProduct) {
85
+ if (order.size !== undefined) {
86
+ const sizeNum = +order.size;
87
+ const sizeStep = theProduct.volume_step * theProduct.value_scale;
88
+ if (!(sizeStep > 0))
89
+ throw newError('INVALID_SIZE_STEP', { product: theProduct, sizeStep });
90
+ // check size is multiple of sizeStep
91
+ if (Math.abs(sizeNum - Math.round(sizeNum / sizeStep) * sizeStep) > 1e-16) {
92
+ throw newError('INVALID_ORDER_SIZE_NOT_MULTIPLE_OF_SIZE_STEP', {
93
+ order,
94
+ sizeStep,
95
+ sizeNum,
96
+ product: theProduct,
97
+ });
98
+ }
99
+ if (sizeNum >= 0) {
100
+ order.order_direction = order.is_close ? 'CLOSE_SHORT' : 'OPEN_LONG';
101
+ }
102
+ else {
103
+ order.order_direction = order.is_close ? 'CLOSE_LONG' : 'OPEN_SHORT';
104
+ }
105
+ order.volume = Math.abs(sizeNum) / theProduct.value_scale;
106
+ }
107
+ }
108
+ }
109
+ return orders;
110
+ };
66
111
  //# sourceMappingURL=position.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"position.js","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IPosition } from '@yuants/data-account';\nimport { createClientProductCache } from '@yuants/data-product';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\n\nconst terminal = Terminal.fromNodeEnv();\nconst productCache = createClientProductCache(terminal);\nconst quoteCache = createCache<IQuote>(\n async (product_id) => {\n const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;\n const [quote] = await requestSQL<IQuote[]>(terminal, sql);\n return quote;\n },\n { expire: 30_000 },\n);\n\nconst interestRateIntervalCache = createCache(async (product_id: string) => {\n const sql = `select created_at from interest_rate where series_id = ${escapeSQL(\n product_id,\n )} order by created_at desc limit 2`;\n const rates = await requestSQL<{ created_at: string }[]>(terminal, sql);\n if (rates.length < 2) return undefined;\n return new Date(rates[0].created_at).getTime() - new Date(rates[1].created_at).getTime();\n});\n\nexport const polyfillPosition = async (positions: IPosition[]): Promise<IPosition[]> => {\n // TODO: 使用 batch query SQL 优化 product / quote 查询性能\n for (const pos of positions) {\n const [theProduct, quote, interestRateInterval] = await Promise.all([\n productCache.query(pos.product_id),\n quoteCache.query(pos.product_id),\n interestRateIntervalCache.query(pos.product_id),\n ]);\n\n // 估值 = value_scale * volume * closable_price\n if (theProduct) {\n if (theProduct.base_currency) {\n pos.base_currency = theProduct.base_currency;\n }\n if (theProduct.quote_currency) {\n pos.quote_currency = theProduct.quote_currency;\n }\n if (pos.size === undefined && pos.volume !== undefined && pos.direction !== undefined) {\n pos.size = (pos.direction === 'LONG' ? 1 : -1) * pos.volume * (theProduct.value_scale || 1) + '';\n }\n if (pos.free_size === undefined && pos.free_volume !== undefined && pos.direction !== undefined) {\n pos.free_size =\n (pos.direction === 'LONG' ? 1 : -1) * pos.free_volume * (theProduct.value_scale || 1) + '';\n }\n pos.valuation = Math.abs((theProduct.value_scale || 1) * pos.volume * pos.closable_price);\n }\n\n // 利率相关信息的追加\n if (quote) {\n if (quote.interest_rate_next_settled_at !== null) {\n pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();\n }\n if (pos.direction === 'LONG') {\n if (quote.interest_rate_long !== null) {\n pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;\n }\n }\n if (pos.direction === 'SHORT') {\n if (quote.interest_rate_short !== null) {\n pos.interest_to_settle = +quote.interest_rate_short * pos.valuation;\n }\n }\n }\n\n if (interestRateInterval) {\n pos.settlement_interval = interestRateInterval;\n }\n }\n return positions;\n};\n"]}
1
+ {"version":3,"file":"position.js","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { createClientProductCache } from '@yuants/data-product';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { newError } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\nconst productCache = createClientProductCache(terminal);\nconst quoteCache = createCache<IQuote>(\n async (product_id) => {\n const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;\n const [quote] = await requestSQL<IQuote[]>(terminal, sql);\n return quote;\n },\n { expire: 30_000 },\n);\n\nconst interestRateIntervalCache = createCache(\n async (product_id: string) => {\n const sql = `select created_at from interest_rate where series_id = ${escapeSQL(\n product_id,\n )} order by created_at desc limit 2`;\n const rates = await requestSQL<{ created_at: string }[]>(terminal, sql);\n if (rates.length < 2) return undefined;\n const prev = new Date(rates[0].created_at).getTime();\n const prevOfPrev = new Date(rates[1].created_at).getTime();\n const interval = prev - prevOfPrev;\n return {\n prev,\n prevOfPrev,\n interval,\n };\n },\n { swrAfter: 3600_000, expire: 8 * 3600_000 },\n);\n\nexport const polyfillPosition = async (positions: IPosition[]): Promise<IPosition[]> => {\n // TODO: 使用 batch query SQL 优化 product / quote 查询性能\n for (const pos of positions) {\n const [theProduct, quote, interestRateInterval] = await Promise.all([\n productCache.query(pos.product_id),\n quoteCache.query(pos.product_id),\n interestRateIntervalCache.query(pos.product_id),\n ]);\n\n // 估值 = value_scale * volume * closable_price\n if (theProduct) {\n if (theProduct.base_currency) {\n pos.base_currency = theProduct.base_currency;\n }\n if (theProduct.quote_currency) {\n pos.quote_currency = theProduct.quote_currency;\n }\n if (pos.size === undefined && pos.volume !== undefined && pos.direction !== undefined) {\n pos.size = (pos.direction === 'LONG' ? 1 : -1) * pos.volume * (theProduct.value_scale || 1) + '';\n }\n if (pos.free_size === undefined && pos.free_volume !== undefined && pos.direction !== undefined) {\n pos.free_size =\n (pos.direction === 'LONG' ? 1 : -1) * pos.free_volume * (theProduct.value_scale || 1) + '';\n }\n pos.valuation = Math.abs((theProduct.value_scale || 1) * pos.volume * pos.closable_price);\n }\n\n // 利率相关信息的追加\n if (quote) {\n if (quote.interest_rate_next_settled_at !== null) {\n // 优先使用行情数据中的下一个结算时间\n pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();\n } else if (quote.interest_rate_next_settled_at === null && interestRateInterval !== undefined) {\n // 估算下一个结算时间\n // 找到 prev + k * interval > now 的最小 k,则下一个结算时间为 prev + k * interval\n const k = Math.ceil((Date.now() - interestRateInterval.prev) / interestRateInterval.interval);\n pos.settlement_scheduled_at = interestRateInterval.prev + k * interestRateInterval.interval;\n }\n\n if (pos.direction === 'LONG') {\n if (quote.interest_rate_long !== null) {\n pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;\n }\n }\n if (pos.direction === 'SHORT') {\n if (quote.interest_rate_short !== null) {\n pos.interest_to_settle = +quote.interest_rate_short * pos.valuation;\n }\n }\n }\n\n if (interestRateInterval) {\n pos.settlement_interval = interestRateInterval.interval;\n }\n }\n return positions;\n};\n\nexport const polyfillOrders = async (orders: IOrder[]): Promise<IOrder[]> => {\n for (const order of orders) {\n const theProduct = await productCache.query(order.product_id);\n if (theProduct) {\n if (order.size !== undefined) {\n const sizeNum = +order.size;\n const sizeStep = theProduct.volume_step * theProduct.value_scale;\n if (!(sizeStep > 0)) throw newError('INVALID_SIZE_STEP', { product: theProduct, sizeStep });\n // check size is multiple of sizeStep\n if (Math.abs(sizeNum - Math.round(sizeNum / sizeStep) * sizeStep) > 1e-16) {\n throw newError('INVALID_ORDER_SIZE_NOT_MULTIPLE_OF_SIZE_STEP', {\n order,\n sizeStep,\n sizeNum,\n product: theProduct,\n });\n }\n\n if (sizeNum >= 0) {\n order.order_direction = order.is_close ? 'CLOSE_SHORT' : 'OPEN_LONG';\n } else {\n order.order_direction = order.is_close ? 'CLOSE_LONG' : 'OPEN_SHORT';\n }\n order.volume = Math.abs(sizeNum) / theProduct.value_scale;\n }\n }\n }\n return orders;\n};\n"]}
package/lib/general.js CHANGED
@@ -18,6 +18,9 @@ terminal.server.provideService('VEX/GetPositions', {
18
18
  if (!res.data)
19
19
  return { res };
20
20
  const positions = await (0, position_1.polyfillPosition)(res.data);
21
+ positions.forEach((pos) => {
22
+ pos.account_id = credential.credentialId;
23
+ });
21
24
  return { res: { code: 0, message: 'OK', data: positions } };
22
25
  });
23
26
  terminal.server.provideService('VEX/GetOrders', {
@@ -28,13 +31,16 @@ terminal.server.provideService('VEX/GetOrders', {
28
31
  product_id: { type: 'string' },
29
32
  },
30
33
  }, async (msg) => {
31
- var _a;
32
34
  const credential = await (0, credential_1.getCredentialBySecretId)(msg.req.secret_id);
33
35
  const res = await (0, exchange_1.getOrders)(terminal, credential.credential, msg.req.product_id);
34
- (_a = res.data) === null || _a === void 0 ? void 0 : _a.forEach((order) => {
36
+ if (!res.data)
37
+ return { res };
38
+ const orders = res.data;
39
+ orders.forEach((order) => {
35
40
  order.account_id = credential.credentialId;
36
41
  });
37
- return { res };
42
+ await (0, position_1.polyfillOrders)(orders);
43
+ return { res: { code: 0, message: 'OK', data: orders } };
38
44
  });
39
45
  // 10. Proxy Orders
40
46
  // SubmitOrder
@@ -47,7 +53,8 @@ terminal.server.provideService('VEX/SubmitOrder', {
47
53
  },
48
54
  }, async (msg) => {
49
55
  const credential = await (0, credential_1.getCredentialBySecretId)(msg.req.secret_id);
50
- const res = await (0, exchange_1.submitOrder)(terminal, credential.credential, msg.req.order);
56
+ const [order] = await (0, position_1.polyfillOrders)([msg.req.order]);
57
+ const res = await (0, exchange_1.submitOrder)(terminal, credential.credential, order);
51
58
  return { res };
52
59
  });
53
60
  // ModifyOrder
@@ -60,7 +67,8 @@ terminal.server.provideService('VEX/ModifyOrder', {
60
67
  },
61
68
  }, async (msg) => {
62
69
  const credential = await (0, credential_1.getCredentialBySecretId)(msg.req.secret_id);
63
- const res = await (0, exchange_1.modifyOrder)(terminal, credential.credential, msg.req.order);
70
+ const [order] = await (0, position_1.polyfillOrders)([msg.req.order]);
71
+ const res = await (0, exchange_1.modifyOrder)(terminal, credential.credential, order);
64
72
  return { res };
65
73
  });
66
74
  // CancelOrder
@@ -73,7 +81,8 @@ terminal.server.provideService('VEX/CancelOrder', {
73
81
  },
74
82
  }, async (msg) => {
75
83
  const credential = await (0, credential_1.getCredentialBySecretId)(msg.req.secret_id);
76
- const res = await (0, exchange_1.cancelOrder)(terminal, credential.credential, msg.req.order);
84
+ const [order] = await (0, position_1.polyfillOrders)([msg.req.order]);
85
+ const res = await (0, exchange_1.cancelOrder)(terminal, credential.credential, order);
77
86
  return { res };
78
87
  });
79
88
  //# sourceMappingURL=general.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"general.js","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":"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","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { getCredentialBySecretId } from './credential';\nimport { polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IPosition[]>(\n 'VEX/GetPositions',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getPositions(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const positions = await polyfillPosition(res.data);\n return { res: { code: 0, message: 'OK', data: positions } };\n },\n);\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IOrder[]>(\n 'VEX/GetOrders',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getOrders(terminal, credential.credential, msg.req.product_id);\n res.data?.forEach((order) => {\n order.account_id = credential.credentialId;\n });\n return { res };\n },\n);\n\n// 10. Proxy Orders\n// SubmitOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, { order_id: string }>(\n 'VEX/SubmitOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await submitOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n\n// ModifyOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/ModifyOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await modifyOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n\n// CancelOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/CancelOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await cancelOrder(terminal, credential.credential, msg.req.order);\n return { res };\n },\n);\n"]}
1
+ {"version":3,"file":"general.js","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":"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","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { getCredentialBySecretId } from './credential';\nimport { polyfillOrders, polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IPosition[]>(\n 'VEX/GetPositions',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getPositions(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const positions = await polyfillPosition(res.data);\n positions.forEach((pos) => {\n pos.account_id = credential.credentialId;\n });\n return { res: { code: 0, message: 'OK', data: positions } };\n },\n);\n\nterminal.server.provideService<{ secret_id: string; product_id?: string }, IOrder[]>(\n 'VEX/GetOrders',\n {\n type: 'object',\n required: ['secret_id'],\n properties: {\n secret_id: { type: 'string' },\n product_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const res = await getOrders(terminal, credential.credential, msg.req.product_id);\n if (!res.data) return { res };\n const orders = res.data;\n orders.forEach((order) => {\n order.account_id = credential.credentialId;\n });\n await polyfillOrders(orders);\n return { res: { code: 0, message: 'OK', data: orders } };\n },\n);\n\n// 10. Proxy Orders\n// SubmitOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, { order_id: string }>(\n 'VEX/SubmitOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await submitOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n\n// ModifyOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/ModifyOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await modifyOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n\n// CancelOrder\nterminal.server.provideService<{ order: IOrder; secret_id: string }, void>(\n 'VEX/CancelOrder',\n {\n type: 'object',\n required: ['order', 'secret_id'],\n properties: {\n order: { type: 'object' },\n secret_id: { type: 'string' },\n },\n },\n async (msg) => {\n const credential = await getCredentialBySecretId(msg.req.secret_id);\n const [order] = await polyfillOrders([msg.req.order]);\n const res = await cancelOrder(terminal, credential.credential, order);\n return { res };\n },\n);\n"]}
@@ -19,6 +19,9 @@ credential_1.validCredentials$
19
19
  if (!res.data)
20
20
  throw (0, utils_1.newError)('FETCH_POSITIONS_FAILED', { credential_id, res });
21
21
  const polyfilledPositions = await (0, position_1.polyfillPosition)(res.data);
22
+ polyfilledPositions.forEach((pos) => {
23
+ pos.account_id = credential_id;
24
+ });
22
25
  return polyfilledPositions;
23
26
  }, {
24
27
  auto_refresh_interval: 1000,
@@ -36,6 +39,7 @@ credential_1.validCredentials$
36
39
  res.data.forEach((order) => {
37
40
  order.account_id = credential_id;
38
41
  });
42
+ await (0, position_1.polyfillOrders)(res.data);
39
43
  return res.data;
40
44
  }, {
41
45
  auto_refresh_interval: 10000,
@@ -53,7 +57,8 @@ credential_1.validCredentials$
53
57
  account_id: { type: 'string', const: credential_id },
54
58
  },
55
59
  }, async (msg) => {
56
- const res = await (0, exchange_1.submitOrder)(terminal, credential, msg.req);
60
+ const [order] = await (0, position_1.polyfillOrders)([msg.req]);
61
+ const res = await (0, exchange_1.submitOrder)(terminal, credential, order);
57
62
  return { res };
58
63
  });
59
64
  sub.add(() => {
@@ -69,7 +74,8 @@ credential_1.validCredentials$
69
74
  account_id: { type: 'string', const: credential_id },
70
75
  },
71
76
  }, async (msg) => {
72
- const res = await (0, exchange_1.modifyOrder)(terminal, credential, msg.req);
77
+ const [order] = await (0, position_1.polyfillOrders)([msg.req]);
78
+ const res = await (0, exchange_1.modifyOrder)(terminal, credential, order);
73
79
  return { res };
74
80
  });
75
81
  sub.add(() => {
@@ -85,7 +91,8 @@ credential_1.validCredentials$
85
91
  account_id: { type: 'string', const: credential_id },
86
92
  },
87
93
  }, async (msg) => {
88
- const res = await (0, exchange_1.cancelOrder)(terminal, credential, msg.req);
94
+ const [order] = await (0, position_1.polyfillOrders)([msg.req]);
95
+ const res = await (0, exchange_1.cancelOrder)(terminal, credential, order);
89
96
  return { res };
90
97
  });
91
98
  sub.add(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { listWatch, newError } from '@yuants/utils';\nimport { map, Observable } from 'rxjs';\nimport { validCredentials$ } from './credential';\nimport { polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nvalidCredentials$\n .pipe(\n map((x) => Array.from(x.entries())),\n listWatch(\n ([id]) => id,\n ([credential_id, credential]) =>\n new Observable((sub) => {\n console.info(`Setting up VEX services for credential: ${credential_id}`);\n // Setup AccountInfo Service\n {\n const service = provideAccountInfoService(\n terminal,\n credential_id,\n async () => {\n const res = await getPositions(terminal, credential);\n if (!res.data) throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });\n const polyfilledPositions = await polyfillPosition(res.data);\n return polyfilledPositions;\n },\n {\n auto_refresh_interval: 1000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup Pending Orders Service\n {\n const service = providePendingOrdersService(\n terminal,\n credential_id,\n async () => {\n const res = await getOrders(terminal, credential);\n if (!res.data) throw newError('FETCH_ORDERS_FAILED', { credential_id, res });\n\n res.data.forEach((order) => {\n order.account_id = credential_id;\n });\n\n return res.data;\n },\n {\n auto_refresh_interval: 10000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup SubmitOrder Service\n {\n const service = terminal.server.provideService<IOrder, { order_id: string }>(\n 'SubmitOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await submitOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup ModifyOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'ModifyOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await modifyOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup CancelOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'CancelOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const res = await cancelOrder(terminal, credential, msg.req);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n }),\n ),\n )\n .subscribe();\n"]}
1
+ {"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { listWatch, newError } from '@yuants/utils';\nimport { map, Observable } from 'rxjs';\nimport { validCredentials$ } from './credential';\nimport { polyfillOrders, polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nvalidCredentials$\n .pipe(\n map((x) => Array.from(x.entries())),\n listWatch(\n ([id]) => id,\n ([credential_id, credential]) =>\n new Observable((sub) => {\n console.info(`Setting up VEX services for credential: ${credential_id}`);\n // Setup AccountInfo Service\n {\n const service = provideAccountInfoService(\n terminal,\n credential_id,\n async () => {\n const res = await getPositions(terminal, credential);\n if (!res.data) throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });\n const polyfilledPositions = await polyfillPosition(res.data);\n polyfilledPositions.forEach((pos) => {\n pos.account_id = credential_id;\n });\n return polyfilledPositions;\n },\n {\n auto_refresh_interval: 1000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup Pending Orders Service\n {\n const service = providePendingOrdersService(\n terminal,\n credential_id,\n async () => {\n const res = await getOrders(terminal, credential);\n if (!res.data) throw newError('FETCH_ORDERS_FAILED', { credential_id, res });\n\n res.data.forEach((order) => {\n order.account_id = credential_id;\n });\n\n await polyfillOrders(res.data);\n\n return res.data;\n },\n {\n auto_refresh_interval: 10000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup SubmitOrder Service\n {\n const service = terminal.server.provideService<IOrder, { order_id: string }>(\n 'SubmitOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await submitOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup ModifyOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'ModifyOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await modifyOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup CancelOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'CancelOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await cancelOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n }),\n ),\n )\n .subscribe();\n"]}
package/lib/position.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  import { IPosition } from '@yuants/data-account';
2
+ import { IOrder } from '@yuants/data-order';
2
3
  export declare const polyfillPosition: (positions: IPosition[]) => Promise<IPosition[]>;
4
+ export declare const polyfillOrders: (orders: IOrder[]) => Promise<IOrder[]>;
3
5
  //# sourceMappingURL=position.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA0BjD,eAAO,MAAM,gBAAgB,cAAqB,SAAS,EAAE,KAAG,QAAQ,SAAS,EAAE,CAiDlF,CAAC"}
1
+ {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAqC5C,eAAO,MAAM,gBAAgB,cAAqB,SAAS,EAAE,KAAG,QAAQ,SAAS,EAAE,CAwDlF,CAAC;AAEF,eAAO,MAAM,cAAc,WAAkB,MAAM,EAAE,KAAG,QAAQ,MAAM,EAAE,CA4BvE,CAAC"}
package/lib/position.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.polyfillPosition = void 0;
3
+ exports.polyfillOrders = exports.polyfillPosition = void 0;
4
4
  const cache_1 = require("@yuants/cache");
5
5
  const data_product_1 = require("@yuants/data-product");
6
6
  const protocol_1 = require("@yuants/protocol");
7
7
  const sql_1 = require("@yuants/sql");
8
+ const utils_1 = require("@yuants/utils");
8
9
  const terminal = protocol_1.Terminal.fromNodeEnv();
9
10
  const productCache = (0, data_product_1.createClientProductCache)(terminal);
10
11
  const quoteCache = (0, cache_1.createCache)(async (product_id) => {
@@ -17,8 +18,15 @@ const interestRateIntervalCache = (0, cache_1.createCache)(async (product_id) =>
17
18
  const rates = await (0, sql_1.requestSQL)(terminal, sql);
18
19
  if (rates.length < 2)
19
20
  return undefined;
20
- return new Date(rates[0].created_at).getTime() - new Date(rates[1].created_at).getTime();
21
- });
21
+ const prev = new Date(rates[0].created_at).getTime();
22
+ const prevOfPrev = new Date(rates[1].created_at).getTime();
23
+ const interval = prev - prevOfPrev;
24
+ return {
25
+ prev,
26
+ prevOfPrev,
27
+ interval,
28
+ };
29
+ }, { swrAfter: 3600000, expire: 8 * 3600000 });
22
30
  const polyfillPosition = async (positions) => {
23
31
  // TODO: 使用 batch query SQL 优化 product / quote 查询性能
24
32
  for (const pos of positions) {
@@ -47,8 +55,15 @@ const polyfillPosition = async (positions) => {
47
55
  // 利率相关信息的追加
48
56
  if (quote) {
49
57
  if (quote.interest_rate_next_settled_at !== null) {
58
+ // 优先使用行情数据中的下一个结算时间
50
59
  pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();
51
60
  }
61
+ else if (quote.interest_rate_next_settled_at === null && interestRateInterval !== undefined) {
62
+ // 估算下一个结算时间
63
+ // 找到 prev + k * interval > now 的最小 k,则下一个结算时间为 prev + k * interval
64
+ const k = Math.ceil((Date.now() - interestRateInterval.prev) / interestRateInterval.interval);
65
+ pos.settlement_scheduled_at = interestRateInterval.prev + k * interestRateInterval.interval;
66
+ }
52
67
  if (pos.direction === 'LONG') {
53
68
  if (quote.interest_rate_long !== null) {
54
69
  pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;
@@ -61,10 +76,41 @@ const polyfillPosition = async (positions) => {
61
76
  }
62
77
  }
63
78
  if (interestRateInterval) {
64
- pos.settlement_interval = interestRateInterval;
79
+ pos.settlement_interval = interestRateInterval.interval;
65
80
  }
66
81
  }
67
82
  return positions;
68
83
  };
69
84
  exports.polyfillPosition = polyfillPosition;
85
+ const polyfillOrders = async (orders) => {
86
+ for (const order of orders) {
87
+ const theProduct = await productCache.query(order.product_id);
88
+ if (theProduct) {
89
+ if (order.size !== undefined) {
90
+ const sizeNum = +order.size;
91
+ const sizeStep = theProduct.volume_step * theProduct.value_scale;
92
+ if (!(sizeStep > 0))
93
+ throw (0, utils_1.newError)('INVALID_SIZE_STEP', { product: theProduct, sizeStep });
94
+ // check size is multiple of sizeStep
95
+ if (Math.abs(sizeNum - Math.round(sizeNum / sizeStep) * sizeStep) > 1e-16) {
96
+ throw (0, utils_1.newError)('INVALID_ORDER_SIZE_NOT_MULTIPLE_OF_SIZE_STEP', {
97
+ order,
98
+ sizeStep,
99
+ sizeNum,
100
+ product: theProduct,
101
+ });
102
+ }
103
+ if (sizeNum >= 0) {
104
+ order.order_direction = order.is_close ? 'CLOSE_SHORT' : 'OPEN_LONG';
105
+ }
106
+ else {
107
+ order.order_direction = order.is_close ? 'CLOSE_LONG' : 'OPEN_SHORT';
108
+ }
109
+ order.volume = Math.abs(sizeNum) / theProduct.value_scale;
110
+ }
111
+ }
112
+ }
113
+ return orders;
114
+ };
115
+ exports.polyfillOrders = polyfillOrders;
70
116
  //# sourceMappingURL=position.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"position.js","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":";;;AAAA,yCAA4C;AAE5C,uDAAgE;AAEhE,+CAA4C;AAC5C,qCAAoD;AAEpD,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,YAAY,GAAG,IAAA,uCAAwB,EAAC,QAAQ,CAAC,CAAC;AACxD,MAAM,UAAU,GAAG,IAAA,mBAAW,EAC5B,KAAK,EAAE,UAAU,EAAE,EAAE;IACnB,MAAM,GAAG,GAAG,0CAA0C,IAAA,eAAS,EAAC,UAAU,CAAC,EAAE,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAA,gBAAU,EAAW,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC,EACD,EAAE,MAAM,EAAE,KAAM,EAAE,CACnB,CAAC;AAEF,MAAM,yBAAyB,GAAG,IAAA,mBAAW,EAAC,KAAK,EAAE,UAAkB,EAAE,EAAE;IACzE,MAAM,GAAG,GAAG,0DAA0D,IAAA,eAAS,EAC7E,UAAU,CACX,mCAAmC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,IAAA,gBAAU,EAA2B,QAAQ,EAAE,GAAG,CAAC,CAAC;IACxE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;AAC3F,CAAC,CAAC,CAAC;AAEI,MAAM,gBAAgB,GAAG,KAAK,EAAE,SAAsB,EAAwB,EAAE;IACrF,mDAAmD;IACnD,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE;QAC3B,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,oBAAoB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAClE,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;YAClC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;YAChC,yBAAyB,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;SAChD,CAAC,CAAC;QAEH,6CAA6C;QAC7C,IAAI,UAAU,EAAE;YACd,IAAI,UAAU,CAAC,aAAa,EAAE;gBAC5B,GAAG,CAAC,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC;aAC9C;YACD,IAAI,UAAU,CAAC,cAAc,EAAE;gBAC7B,GAAG,CAAC,cAAc,GAAG,UAAU,CAAC,cAAc,CAAC;aAChD;YACD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE;gBACrF,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;aAClG;YACD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE;gBAC/F,GAAG,CAAC,SAAS;oBACX,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,WAAW,GAAG,CAAC,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;aAC9F;YACD,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;SAC3F;QAED,YAAY;QACZ,IAAI,KAAK,EAAE;YACT,IAAI,KAAK,CAAC,6BAA6B,KAAK,IAAI,EAAE;gBAChD,GAAG,CAAC,uBAAuB,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC,OAAO,EAAE,CAAC;aACvF;YACD,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,EAAE;gBAC5B,IAAI,KAAK,CAAC,kBAAkB,KAAK,IAAI,EAAE;oBACrC,GAAG,CAAC,kBAAkB,GAAG,CAAC,KAAK,CAAC,kBAAkB,GAAG,GAAG,CAAC,SAAS,CAAC;iBACpE;aACF;YACD,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO,EAAE;gBAC7B,IAAI,KAAK,CAAC,mBAAmB,KAAK,IAAI,EAAE;oBACtC,GAAG,CAAC,kBAAkB,GAAG,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,CAAC,SAAS,CAAC;iBACrE;aACF;SACF;QAED,IAAI,oBAAoB,EAAE;YACxB,GAAG,CAAC,mBAAmB,GAAG,oBAAoB,CAAC;SAChD;KACF;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAjDW,QAAA,gBAAgB,oBAiD3B","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IPosition } from '@yuants/data-account';\nimport { createClientProductCache } from '@yuants/data-product';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\n\nconst terminal = Terminal.fromNodeEnv();\nconst productCache = createClientProductCache(terminal);\nconst quoteCache = createCache<IQuote>(\n async (product_id) => {\n const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;\n const [quote] = await requestSQL<IQuote[]>(terminal, sql);\n return quote;\n },\n { expire: 30_000 },\n);\n\nconst interestRateIntervalCache = createCache(async (product_id: string) => {\n const sql = `select created_at from interest_rate where series_id = ${escapeSQL(\n product_id,\n )} order by created_at desc limit 2`;\n const rates = await requestSQL<{ created_at: string }[]>(terminal, sql);\n if (rates.length < 2) return undefined;\n return new Date(rates[0].created_at).getTime() - new Date(rates[1].created_at).getTime();\n});\n\nexport const polyfillPosition = async (positions: IPosition[]): Promise<IPosition[]> => {\n // TODO: 使用 batch query SQL 优化 product / quote 查询性能\n for (const pos of positions) {\n const [theProduct, quote, interestRateInterval] = await Promise.all([\n productCache.query(pos.product_id),\n quoteCache.query(pos.product_id),\n interestRateIntervalCache.query(pos.product_id),\n ]);\n\n // 估值 = value_scale * volume * closable_price\n if (theProduct) {\n if (theProduct.base_currency) {\n pos.base_currency = theProduct.base_currency;\n }\n if (theProduct.quote_currency) {\n pos.quote_currency = theProduct.quote_currency;\n }\n if (pos.size === undefined && pos.volume !== undefined && pos.direction !== undefined) {\n pos.size = (pos.direction === 'LONG' ? 1 : -1) * pos.volume * (theProduct.value_scale || 1) + '';\n }\n if (pos.free_size === undefined && pos.free_volume !== undefined && pos.direction !== undefined) {\n pos.free_size =\n (pos.direction === 'LONG' ? 1 : -1) * pos.free_volume * (theProduct.value_scale || 1) + '';\n }\n pos.valuation = Math.abs((theProduct.value_scale || 1) * pos.volume * pos.closable_price);\n }\n\n // 利率相关信息的追加\n if (quote) {\n if (quote.interest_rate_next_settled_at !== null) {\n pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();\n }\n if (pos.direction === 'LONG') {\n if (quote.interest_rate_long !== null) {\n pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;\n }\n }\n if (pos.direction === 'SHORT') {\n if (quote.interest_rate_short !== null) {\n pos.interest_to_settle = +quote.interest_rate_short * pos.valuation;\n }\n }\n }\n\n if (interestRateInterval) {\n pos.settlement_interval = interestRateInterval;\n }\n }\n return positions;\n};\n"]}
1
+ {"version":3,"file":"position.js","sourceRoot":"","sources":["../src/position.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { createClientProductCache } from '@yuants/data-product';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { newError } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\nconst productCache = createClientProductCache(terminal);\nconst quoteCache = createCache<IQuote>(\n async (product_id) => {\n const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;\n const [quote] = await requestSQL<IQuote[]>(terminal, sql);\n return quote;\n },\n { expire: 30_000 },\n);\n\nconst interestRateIntervalCache = createCache(\n async (product_id: string) => {\n const sql = `select created_at from interest_rate where series_id = ${escapeSQL(\n product_id,\n )} order by created_at desc limit 2`;\n const rates = await requestSQL<{ created_at: string }[]>(terminal, sql);\n if (rates.length < 2) return undefined;\n const prev = new Date(rates[0].created_at).getTime();\n const prevOfPrev = new Date(rates[1].created_at).getTime();\n const interval = prev - prevOfPrev;\n return {\n prev,\n prevOfPrev,\n interval,\n };\n },\n { swrAfter: 3600_000, expire: 8 * 3600_000 },\n);\n\nexport const polyfillPosition = async (positions: IPosition[]): Promise<IPosition[]> => {\n // TODO: 使用 batch query SQL 优化 product / quote 查询性能\n for (const pos of positions) {\n const [theProduct, quote, interestRateInterval] = await Promise.all([\n productCache.query(pos.product_id),\n quoteCache.query(pos.product_id),\n interestRateIntervalCache.query(pos.product_id),\n ]);\n\n // 估值 = value_scale * volume * closable_price\n if (theProduct) {\n if (theProduct.base_currency) {\n pos.base_currency = theProduct.base_currency;\n }\n if (theProduct.quote_currency) {\n pos.quote_currency = theProduct.quote_currency;\n }\n if (pos.size === undefined && pos.volume !== undefined && pos.direction !== undefined) {\n pos.size = (pos.direction === 'LONG' ? 1 : -1) * pos.volume * (theProduct.value_scale || 1) + '';\n }\n if (pos.free_size === undefined && pos.free_volume !== undefined && pos.direction !== undefined) {\n pos.free_size =\n (pos.direction === 'LONG' ? 1 : -1) * pos.free_volume * (theProduct.value_scale || 1) + '';\n }\n pos.valuation = Math.abs((theProduct.value_scale || 1) * pos.volume * pos.closable_price);\n }\n\n // 利率相关信息的追加\n if (quote) {\n if (quote.interest_rate_next_settled_at !== null) {\n // 优先使用行情数据中的下一个结算时间\n pos.settlement_scheduled_at = new Date(quote.interest_rate_next_settled_at).getTime();\n } else if (quote.interest_rate_next_settled_at === null && interestRateInterval !== undefined) {\n // 估算下一个结算时间\n // 找到 prev + k * interval > now 的最小 k,则下一个结算时间为 prev + k * interval\n const k = Math.ceil((Date.now() - interestRateInterval.prev) / interestRateInterval.interval);\n pos.settlement_scheduled_at = interestRateInterval.prev + k * interestRateInterval.interval;\n }\n\n if (pos.direction === 'LONG') {\n if (quote.interest_rate_long !== null) {\n pos.interest_to_settle = +quote.interest_rate_long * pos.valuation;\n }\n }\n if (pos.direction === 'SHORT') {\n if (quote.interest_rate_short !== null) {\n pos.interest_to_settle = +quote.interest_rate_short * pos.valuation;\n }\n }\n }\n\n if (interestRateInterval) {\n pos.settlement_interval = interestRateInterval.interval;\n }\n }\n return positions;\n};\n\nexport const polyfillOrders = async (orders: IOrder[]): Promise<IOrder[]> => {\n for (const order of orders) {\n const theProduct = await productCache.query(order.product_id);\n if (theProduct) {\n if (order.size !== undefined) {\n const sizeNum = +order.size;\n const sizeStep = theProduct.volume_step * theProduct.value_scale;\n if (!(sizeStep > 0)) throw newError('INVALID_SIZE_STEP', { product: theProduct, sizeStep });\n // check size is multiple of sizeStep\n if (Math.abs(sizeNum - Math.round(sizeNum / sizeStep) * sizeStep) > 1e-16) {\n throw newError('INVALID_ORDER_SIZE_NOT_MULTIPLE_OF_SIZE_STEP', {\n order,\n sizeStep,\n sizeNum,\n product: theProduct,\n });\n }\n\n if (sizeNum >= 0) {\n order.order_direction = order.is_close ? 'CLOSE_SHORT' : 'OPEN_LONG';\n } else {\n order.order_direction = order.is_close ? 'CLOSE_LONG' : 'OPEN_SHORT';\n }\n order.volume = Math.abs(sizeNum) / theProduct.value_scale;\n }\n }\n }\n return orders;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuants/app-virtual-exchange",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "main": "lib/index.js",
5
5
  "files": [
6
6
  "dist",
@@ -11,12 +11,12 @@
11
11
  "@yuants/protocol": "0.53.2",
12
12
  "@yuants/utils": "0.14.0",
13
13
  "@yuants/data-product": "0.5.0",
14
- "@yuants/data-account": "0.10.0",
15
- "@yuants/data-order": "0.6.6",
14
+ "@yuants/data-account": "0.10.1",
15
+ "@yuants/data-order": "0.7.0",
16
16
  "@yuants/data-quote": "0.2.43",
17
17
  "@yuants/secret": "0.3.13",
18
18
  "@yuants/sql": "0.9.30",
19
- "@yuants/exchange": "0.5.0",
19
+ "@yuants/exchange": "0.5.1",
20
20
  "@yuants/cache": "0.3.3",
21
21
  "rxjs": "~7.5.6",
22
22
  "ajv": "~8.12.0"
@@ -1,29 +1,29 @@
1
1
  {
2
- "apps/virtual-exchange/CHANGELOG.json": "e97010395e2916eeb7047426c7d217dd2b1405df",
3
- "apps/virtual-exchange/CHANGELOG.md": "8bb205ea50a3c711d70c6dde68a1ef7a41d14d2c",
2
+ "apps/virtual-exchange/CHANGELOG.json": "2eff996425f4f7ead9024824f7bb4fb7717ddbe5",
3
+ "apps/virtual-exchange/CHANGELOG.md": "cd989fdca5e96c0629ad50740eb60c9781b852ad",
4
4
  "apps/virtual-exchange/api-extractor.json": "62f4fd324425b9a235f0c117975967aab09ced0c",
5
5
  "apps/virtual-exchange/config/jest.config.json": "4bb17bde3ee911163a3edb36a6eb71491d80b1bd",
6
6
  "apps/virtual-exchange/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
7
7
  "apps/virtual-exchange/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
8
8
  "apps/virtual-exchange/etc/app-virtual-exchange.api.md": "6cb40ec1fa2d40a31a7b0dd3f02b8b24a4d7c4de",
9
- "apps/virtual-exchange/package.json": "7aa18dbb6758249c32aa918ddb21dab95f5fdbb2",
9
+ "apps/virtual-exchange/package.json": "0ed67aa66e97585d7cb5c19344320e1f9b76d917",
10
10
  "apps/virtual-exchange/src/credential.ts": "f839246750fcbddd9a6a29bf3de54631a92c88b7",
11
- "apps/virtual-exchange/src/general.ts": "16a234c6ddbdf33490339272579cbcbac17e048c",
11
+ "apps/virtual-exchange/src/general.ts": "b3d0cd8c57975b9711008beaa05ad7f6812bd57e",
12
12
  "apps/virtual-exchange/src/index.ts": "8d7f19a07e6be09c4d8fd4a49ddb3127d3fbf3de",
13
- "apps/virtual-exchange/src/legacy-services.ts": "73f57566054e8cae899dc20f4d1547184e2c2e71",
14
- "apps/virtual-exchange/src/position.ts": "19b4c6ff99b13a3bc2fc0de70ba5352a3ae9f499",
13
+ "apps/virtual-exchange/src/legacy-services.ts": "a9f6b6c61b7a0efc909a443e6fde88c2766562bf",
14
+ "apps/virtual-exchange/src/position.ts": "41aba2456041b80074801e110b0becf58bf4cc7e",
15
15
  "apps/virtual-exchange/src/product-collector.ts": "15ba0a692d694d20b607eaad0287a864577ef30c",
16
16
  "apps/virtual-exchange/tsconfig.json": "22f94ca28b507f8ddcc21b9053158eefd3f726a9",
17
17
  "apps/virtual-exchange/.rush/temp/shrinkwrap-deps.json": "2c8344167a574161e8a89138bc1eb686bf6339de",
18
18
  "libraries/protocol/temp/package-deps.json": "0bd43721e96039b52d7b59c834dc6df45cf75e3f",
19
19
  "libraries/utils/temp/package-deps.json": "6d58e9b325e8d16de8a878c32010f626b12a01da",
20
20
  "libraries/data-product/temp/package-deps.json": "a03f08f30800d5fb52c5d019bda4f8e7ec04e344",
21
- "libraries/data-account/temp/package-deps.json": "3ee766acef866410612b60dfc1012082c9c24556",
22
- "libraries/data-order/temp/package-deps.json": "2adac9fc0423f9b1b7ddaa8946ab7af374cc22e1",
21
+ "libraries/data-account/temp/package-deps.json": "e6ba0067a1b68f17266564f15987936ab2672eb9",
22
+ "libraries/data-order/temp/package-deps.json": "ccdc9819f254f37a3591bb37876a86c703df33a6",
23
23
  "libraries/data-quote/temp/package-deps.json": "34d079eab44d2bf65e07b112ac2099c6e92a015e",
24
24
  "libraries/secret/temp/package-deps.json": "d7bea10938c76e2e654781b013cc7be5eaa04ede",
25
25
  "libraries/sql/temp/package-deps.json": "4a9a7ec55f04b20459e664e81e76fa74b6c77b39",
26
- "libraries/exchange/temp/package-deps.json": "d40288d0530bc7e63246f234bdffa10a497776b1",
26
+ "libraries/exchange/temp/package-deps.json": "2679f6d65ffd785cbca43cfbe5b6b9a13c7c003d",
27
27
  "libraries/cache/temp/package-deps.json": "a4afa15e6462983f9d3735d31dc1ed8a683fb4dc",
28
28
  "tools/toolkit/temp/package-deps.json": "23e053490eb8feade23e4d45de4e54883e322711"
29
29
  }