@yuants/vendor-okx 0.23.9 → 0.23.10

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.
@@ -9,7 +9,27 @@ export const accountUid$ = accountConfig$.pipe(map((x) => x.data[0].uid), filter
9
9
  export const strategyAccountId$ = accountUid$.pipe(map((uid) => `okx/${uid}/strategy`), shareReplay(1));
10
10
  defer(async () => {
11
11
  const strategyAccountId = await firstValueFrom(strategyAccountId$);
12
+ terminal.server.provideService(`OKX/QueryGridPositions`, {
13
+ required: ['account_id', 'algoId'],
14
+ properties: {
15
+ account_id: { type: 'string', const: strategyAccountId },
16
+ algoId: { type: 'string' },
17
+ },
18
+ }, async (msg) => {
19
+ //
20
+ return {
21
+ res: {
22
+ code: 0,
23
+ message: 'OK',
24
+ data: await client.getGridPositions({ algoOrdType: 'contract_grid', algoId: msg.req.algoId }),
25
+ },
26
+ };
27
+ }, {
28
+ egress_token_capacity: 20,
29
+ egress_token_refill_interval: 4000, // 每 4 秒恢复 20 个令牌 (双倍冗余限流)
30
+ });
12
31
  provideAccountInfoService(terminal, strategyAccountId, async () => {
32
+ // TODO: 需要分页获取所有的网格订单 (每页 100 条)
13
33
  const [gridAlgoOrders] = await Promise.all([
14
34
  client.getGridOrdersAlgoPending({
15
35
  algoOrdType: 'contract_grid',
@@ -17,7 +37,10 @@ defer(async () => {
17
37
  ]);
18
38
  let totalEquity = 0;
19
39
  const positions = [];
20
- const gridPositionsRes = await Promise.all(gridAlgoOrders.data.map((item) => client.getGridPositions({ algoOrdType: 'contract_grid', algoId: item.algoId })));
40
+ const gridPositionsRes = await Promise.all(gridAlgoOrders.data.map((item) => terminal.client.requestForResponseData('OKX/QueryGridPositions', {
41
+ account_id: strategyAccountId,
42
+ algoId: item.algoId,
43
+ })));
21
44
  gridPositionsRes.forEach((gridPositions, index) => {
22
45
  var _a, _b, _c, _d;
23
46
  let positionValuation = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"strategy-account.js","sourceRoot":"","sources":["../src/strategy-account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAa,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CACvE,MAAM,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACzB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,CAAC,CAAC,CACf,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAClB,WAAW,CAAC,CAAC,CAAC,CACf,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC,IAAI,CAChD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,WAAW,CAAC,EACnC,WAAW,CAAC,CAAC,CAAC,CACf,CAAC;AACF,KAAK,CAAC,KAAK,IAAI,EAAE;IACf,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC,kBAAkB,CAAC,CAAC;IAEnE,yBAAyB,CACvB,QAAQ,EACR,iBAAiB,EACjB,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACzC,MAAM,CAAC,wBAAwB,CAAC;gBAC9B,WAAW,EAAE,eAAe;aAC7B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,MAAM,SAAS,GAAgB,EAAE,CAAC;QAElC,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,GAAG,CACxC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/B,MAAM,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAC/E,CACF,CAAC;QAEF,gBAAgB,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE;;YAChD,IAAI,iBAAiB,GAAG,CAAC,CAAC;YAC1B,MAAM,QAAQ,GAAG,CAAC,CAAA,MAAA,cAAc,CAAC,IAAI,0CAAG,KAAK,EAAE,WAAW,CAAA,CAAC;YAC3D,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,IAAI,0CAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;;gBACxC,IAAI,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,EAAE;oBACvB,MAAM,YAAY,GAAG,MAAA,MAAA,MAAA,cAAc,CAAC,IAAI,0CAAG,KAAK,CAAC,0CAAE,SAAS,mCAAI,EAAE,CAAC;oBACnE,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;oBACrE,SAAS,CAAC,IAAI,CAAC;wBACb,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;wBACzD,aAAa,EAAE,KAAK;wBACpB,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC;wBAC1D,SAAS;wBACT,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;wBAC/B,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG;wBAC1B,cAAc,EAAE,CAAC,QAAQ,CAAC,KAAK;wBAC/B,eAAe,EAAE,CAAC,QAAQ,CAAC,GAAG;wBAC9B,cAAc,EAAE,CAAC,QAAQ,CAAC,IAAI;wBAC9B,SAAS,EAAE,CAAC,QAAQ,CAAC,WAAW;qBACjC,CAAC,CAAC;oBACH,iBAAiB,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;iBAC5C;YACH,CAAC,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,CAAC,EAAE;gBAClB,mCAAmC;gBACnC,WAAW,IAAI,CAAC,CAAA,MAAA,cAAc,CAAC,IAAI,0CAAG,KAAK,EAAE,UAAU,CAAA,GAAG,CAAC,CAAA,MAAA,cAAc,CAAC,IAAI,0CAAG,KAAK,EAAE,QAAQ,CAAA,CAAC;aAClG;iBAAM;gBACL,oCAAoC;gBACpC,yBAAyB;gBACzB,WAAW,IAAI,iBAAiB,GAAG,QAAQ,CAAC;aAC7C;QACH,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,WAAW;gBACnB,0BAA0B;gBAC1B,IAAI,EAAE,CAAC;aACR;YACD,SAAS;SACV,CAAC;IACJ,CAAC,EACD,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAChC,CAAC;AACJ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAEf,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC;KACjC,IAAI,CAAC,KAAK,EAAE,CAAC;KACb,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,gBAAgB,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,OAAO,GAAG,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC;AACL,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC","sourcesContent":["import { addAccountMarket, IPosition, provideAccountInfoService } from '@yuants/data-account';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { defer, filter, first, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\nimport { client } from './api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nexport const accountConfig$ = defer(() => client.getAccountConfig()).pipe(\n repeat({ delay: 10_000 }),\n retry({ delay: 10_000 }),\n shareReplay(1),\n);\n\nexport const accountUid$ = accountConfig$.pipe(\n map((x) => x.data[0].uid),\n filter((x) => !!x),\n shareReplay(1),\n);\n\nexport const strategyAccountId$ = accountUid$.pipe(\n map((uid) => `okx/${uid}/strategy`),\n shareReplay(1),\n);\ndefer(async () => {\n const strategyAccountId = await firstValueFrom(strategyAccountId$);\n\n provideAccountInfoService(\n terminal,\n strategyAccountId,\n async () => {\n const [gridAlgoOrders] = await Promise.all([\n client.getGridOrdersAlgoPending({\n algoOrdType: 'contract_grid',\n }),\n ]);\n\n let totalEquity = 0;\n const positions: IPosition[] = [];\n\n const gridPositionsRes = await Promise.all(\n gridAlgoOrders.data.map((item) =>\n client.getGridPositions({ algoOrdType: 'contract_grid', algoId: item.algoId }),\n ),\n );\n\n gridPositionsRes.forEach((gridPositions, index) => {\n let positionValuation = 0;\n const leverage = +gridAlgoOrders.data?.[index].actualLever;\n gridPositions?.data?.forEach((position) => {\n if (+position.pos !== 0) {\n const directionRaw = gridAlgoOrders.data?.[index]?.direction ?? '';\n const direction = directionRaw ? directionRaw.toUpperCase() : 'LONG';\n positions.push({\n position_id: encodePath(position.algoId, position.instId),\n datasource_id: 'OKX',\n product_id: encodePath(position.instType, position.instId),\n direction,\n volume: Math.abs(+position.pos),\n free_volume: +position.pos,\n position_price: +position.avgPx,\n floating_profit: +position.upl,\n closable_price: +position.last,\n valuation: +position.notionalUsd,\n });\n positionValuation += +position.notionalUsd;\n }\n });\n if (leverage === 0) {\n // 实际杠杆为 0,说明没有持仓,直接把投资金额和累计盈亏算到净值里\n totalEquity += +gridAlgoOrders.data?.[index].investment + +gridAlgoOrders.data?.[index].totalPnl;\n } else {\n // 历史提取金额不会从 investment, totalPnl 扣减\n // 计算净值需要通过仓位的名义价值和实际杠杆计算\n totalEquity += positionValuation / leverage;\n }\n });\n\n return {\n money: {\n currency: 'USDT',\n equity: totalEquity,\n // TODO: 累计策略的可提取资金作为 free\n free: 0,\n },\n positions,\n };\n },\n { auto_refresh_interval: 5000 },\n );\n}).subscribe();\n\nconst sub = defer(() => accountUid$)\n .pipe(first())\n .subscribe((uid) => {\n addAccountMarket(terminal, { account_id: `okx/${uid}/strategy`, market_id: 'OKX' });\n });\ndefer(() => terminal.dispose$).subscribe(() => sub.unsubscribe());\n"]}
1
+ {"version":3,"file":"strategy-account.js","sourceRoot":"","sources":["../src/strategy-account.ts"],"names":[],"mappings":"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","sourcesContent":["import { addAccountMarket, IPosition, provideAccountInfoService } from '@yuants/data-account';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { defer, filter, first, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\nimport { client } from './api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nexport const accountConfig$ = defer(() => client.getAccountConfig()).pipe(\n repeat({ delay: 10_000 }),\n retry({ delay: 10_000 }),\n shareReplay(1),\n);\n\nexport const accountUid$ = accountConfig$.pipe(\n map((x) => x.data[0].uid),\n filter((x) => !!x),\n shareReplay(1),\n);\n\nexport const strategyAccountId$ = accountUid$.pipe(\n map((uid) => `okx/${uid}/strategy`),\n shareReplay(1),\n);\n\ndefer(async () => {\n const strategyAccountId = await firstValueFrom(strategyAccountId$);\n\n type InferPromise<T> = T extends Promise<infer U> ? U : T;\n\n terminal.server.provideService<\n { account_id: string; algoId: string },\n InferPromise<ReturnType<typeof client.getGridPositions>>\n >(\n `OKX/QueryGridPositions`,\n {\n required: ['account_id', 'algoId'],\n properties: {\n account_id: { type: 'string', const: strategyAccountId },\n algoId: { type: 'string' },\n },\n },\n async (msg) => {\n //\n return {\n res: {\n code: 0,\n message: 'OK',\n data: await client.getGridPositions({ algoOrdType: 'contract_grid', algoId: msg.req.algoId }),\n },\n };\n },\n {\n egress_token_capacity: 20,\n egress_token_refill_interval: 4000, // 每 4 秒恢复 20 个令牌 (双倍冗余限流)\n },\n );\n\n provideAccountInfoService(\n terminal,\n strategyAccountId,\n async () => {\n // TODO: 需要分页获取所有的网格订单 (每页 100 条)\n const [gridAlgoOrders] = await Promise.all([\n client.getGridOrdersAlgoPending({\n algoOrdType: 'contract_grid',\n }),\n ]);\n\n let totalEquity = 0;\n const positions: IPosition[] = [];\n\n const gridPositionsRes = await Promise.all(\n gridAlgoOrders.data.map((item) =>\n terminal.client.requestForResponseData<\n { account_id: string; algoId: string },\n InferPromise<ReturnType<typeof client.getGridPositions>>\n >('OKX/QueryGridPositions', {\n account_id: strategyAccountId,\n algoId: item.algoId,\n }),\n ),\n );\n\n gridPositionsRes.forEach((gridPositions, index) => {\n let positionValuation = 0;\n const leverage = +gridAlgoOrders.data?.[index].actualLever;\n gridPositions?.data?.forEach((position) => {\n if (+position.pos !== 0) {\n const directionRaw = gridAlgoOrders.data?.[index]?.direction ?? '';\n const direction = directionRaw ? directionRaw.toUpperCase() : 'LONG';\n positions.push({\n position_id: encodePath(position.algoId, position.instId),\n datasource_id: 'OKX',\n product_id: encodePath(position.instType, position.instId),\n direction,\n volume: Math.abs(+position.pos),\n free_volume: +position.pos,\n position_price: +position.avgPx,\n floating_profit: +position.upl,\n closable_price: +position.last,\n valuation: +position.notionalUsd,\n });\n positionValuation += +position.notionalUsd;\n }\n });\n if (leverage === 0) {\n // 实际杠杆为 0,说明没有持仓,直接把投资金额和累计盈亏算到净值里\n totalEquity += +gridAlgoOrders.data?.[index].investment + +gridAlgoOrders.data?.[index].totalPnl;\n } else {\n // 历史提取金额不会从 investment, totalPnl 扣减\n // 计算净值需要通过仓位的名义价值和实际杠杆计算\n totalEquity += positionValuation / leverage;\n }\n });\n\n return {\n money: {\n currency: 'USDT',\n equity: totalEquity,\n // TODO: 累计策略的可提取资金作为 free\n free: 0,\n },\n positions,\n };\n },\n { auto_refresh_interval: 5000 },\n );\n}).subscribe();\n\nconst sub = defer(() => accountUid$)\n .pipe(first())\n .subscribe((uid) => {\n addAccountMarket(terminal, { account_id: `okx/${uid}/strategy`, market_id: 'OKX' });\n });\ndefer(() => terminal.dispose$).subscribe(() => sub.unsubscribe());\n"]}
@@ -12,7 +12,27 @@ exports.accountUid$ = exports.accountConfig$.pipe((0, rxjs_1.map)((x) => x.data[
12
12
  exports.strategyAccountId$ = exports.accountUid$.pipe((0, rxjs_1.map)((uid) => `okx/${uid}/strategy`), (0, rxjs_1.shareReplay)(1));
13
13
  (0, rxjs_1.defer)(async () => {
14
14
  const strategyAccountId = await (0, rxjs_1.firstValueFrom)(exports.strategyAccountId$);
15
+ terminal.server.provideService(`OKX/QueryGridPositions`, {
16
+ required: ['account_id', 'algoId'],
17
+ properties: {
18
+ account_id: { type: 'string', const: strategyAccountId },
19
+ algoId: { type: 'string' },
20
+ },
21
+ }, async (msg) => {
22
+ //
23
+ return {
24
+ res: {
25
+ code: 0,
26
+ message: 'OK',
27
+ data: await api_1.client.getGridPositions({ algoOrdType: 'contract_grid', algoId: msg.req.algoId }),
28
+ },
29
+ };
30
+ }, {
31
+ egress_token_capacity: 20,
32
+ egress_token_refill_interval: 4000, // 每 4 秒恢复 20 个令牌 (双倍冗余限流)
33
+ });
15
34
  (0, data_account_1.provideAccountInfoService)(terminal, strategyAccountId, async () => {
35
+ // TODO: 需要分页获取所有的网格订单 (每页 100 条)
16
36
  const [gridAlgoOrders] = await Promise.all([
17
37
  api_1.client.getGridOrdersAlgoPending({
18
38
  algoOrdType: 'contract_grid',
@@ -20,7 +40,10 @@ exports.strategyAccountId$ = exports.accountUid$.pipe((0, rxjs_1.map)((uid) => `
20
40
  ]);
21
41
  let totalEquity = 0;
22
42
  const positions = [];
23
- const gridPositionsRes = await Promise.all(gridAlgoOrders.data.map((item) => api_1.client.getGridPositions({ algoOrdType: 'contract_grid', algoId: item.algoId })));
43
+ const gridPositionsRes = await Promise.all(gridAlgoOrders.data.map((item) => terminal.client.requestForResponseData('OKX/QueryGridPositions', {
44
+ account_id: strategyAccountId,
45
+ algoId: item.algoId,
46
+ })));
24
47
  gridPositionsRes.forEach((gridPositions, index) => {
25
48
  var _a, _b, _c, _d;
26
49
  let positionValuation = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"strategy-account.js","sourceRoot":"","sources":["../src/strategy-account.ts"],"names":[],"mappings":"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","sourcesContent":["import { addAccountMarket, IPosition, provideAccountInfoService } from '@yuants/data-account';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { defer, filter, first, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\nimport { client } from './api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nexport const accountConfig$ = defer(() => client.getAccountConfig()).pipe(\n repeat({ delay: 10_000 }),\n retry({ delay: 10_000 }),\n shareReplay(1),\n);\n\nexport const accountUid$ = accountConfig$.pipe(\n map((x) => x.data[0].uid),\n filter((x) => !!x),\n shareReplay(1),\n);\n\nexport const strategyAccountId$ = accountUid$.pipe(\n map((uid) => `okx/${uid}/strategy`),\n shareReplay(1),\n);\ndefer(async () => {\n const strategyAccountId = await firstValueFrom(strategyAccountId$);\n\n provideAccountInfoService(\n terminal,\n strategyAccountId,\n async () => {\n const [gridAlgoOrders] = await Promise.all([\n client.getGridOrdersAlgoPending({\n algoOrdType: 'contract_grid',\n }),\n ]);\n\n let totalEquity = 0;\n const positions: IPosition[] = [];\n\n const gridPositionsRes = await Promise.all(\n gridAlgoOrders.data.map((item) =>\n client.getGridPositions({ algoOrdType: 'contract_grid', algoId: item.algoId }),\n ),\n );\n\n gridPositionsRes.forEach((gridPositions, index) => {\n let positionValuation = 0;\n const leverage = +gridAlgoOrders.data?.[index].actualLever;\n gridPositions?.data?.forEach((position) => {\n if (+position.pos !== 0) {\n const directionRaw = gridAlgoOrders.data?.[index]?.direction ?? '';\n const direction = directionRaw ? directionRaw.toUpperCase() : 'LONG';\n positions.push({\n position_id: encodePath(position.algoId, position.instId),\n datasource_id: 'OKX',\n product_id: encodePath(position.instType, position.instId),\n direction,\n volume: Math.abs(+position.pos),\n free_volume: +position.pos,\n position_price: +position.avgPx,\n floating_profit: +position.upl,\n closable_price: +position.last,\n valuation: +position.notionalUsd,\n });\n positionValuation += +position.notionalUsd;\n }\n });\n if (leverage === 0) {\n // 实际杠杆为 0,说明没有持仓,直接把投资金额和累计盈亏算到净值里\n totalEquity += +gridAlgoOrders.data?.[index].investment + +gridAlgoOrders.data?.[index].totalPnl;\n } else {\n // 历史提取金额不会从 investment, totalPnl 扣减\n // 计算净值需要通过仓位的名义价值和实际杠杆计算\n totalEquity += positionValuation / leverage;\n }\n });\n\n return {\n money: {\n currency: 'USDT',\n equity: totalEquity,\n // TODO: 累计策略的可提取资金作为 free\n free: 0,\n },\n positions,\n };\n },\n { auto_refresh_interval: 5000 },\n );\n}).subscribe();\n\nconst sub = defer(() => accountUid$)\n .pipe(first())\n .subscribe((uid) => {\n addAccountMarket(terminal, { account_id: `okx/${uid}/strategy`, market_id: 'OKX' });\n });\ndefer(() => terminal.dispose$).subscribe(() => sub.unsubscribe());\n"]}
1
+ {"version":3,"file":"strategy-account.js","sourceRoot":"","sources":["../src/strategy-account.ts"],"names":[],"mappings":"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","sourcesContent":["import { addAccountMarket, IPosition, provideAccountInfoService } from '@yuants/data-account';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { defer, filter, first, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\nimport { client } from './api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nexport const accountConfig$ = defer(() => client.getAccountConfig()).pipe(\n repeat({ delay: 10_000 }),\n retry({ delay: 10_000 }),\n shareReplay(1),\n);\n\nexport const accountUid$ = accountConfig$.pipe(\n map((x) => x.data[0].uid),\n filter((x) => !!x),\n shareReplay(1),\n);\n\nexport const strategyAccountId$ = accountUid$.pipe(\n map((uid) => `okx/${uid}/strategy`),\n shareReplay(1),\n);\n\ndefer(async () => {\n const strategyAccountId = await firstValueFrom(strategyAccountId$);\n\n type InferPromise<T> = T extends Promise<infer U> ? U : T;\n\n terminal.server.provideService<\n { account_id: string; algoId: string },\n InferPromise<ReturnType<typeof client.getGridPositions>>\n >(\n `OKX/QueryGridPositions`,\n {\n required: ['account_id', 'algoId'],\n properties: {\n account_id: { type: 'string', const: strategyAccountId },\n algoId: { type: 'string' },\n },\n },\n async (msg) => {\n //\n return {\n res: {\n code: 0,\n message: 'OK',\n data: await client.getGridPositions({ algoOrdType: 'contract_grid', algoId: msg.req.algoId }),\n },\n };\n },\n {\n egress_token_capacity: 20,\n egress_token_refill_interval: 4000, // 每 4 秒恢复 20 个令牌 (双倍冗余限流)\n },\n );\n\n provideAccountInfoService(\n terminal,\n strategyAccountId,\n async () => {\n // TODO: 需要分页获取所有的网格订单 (每页 100 条)\n const [gridAlgoOrders] = await Promise.all([\n client.getGridOrdersAlgoPending({\n algoOrdType: 'contract_grid',\n }),\n ]);\n\n let totalEquity = 0;\n const positions: IPosition[] = [];\n\n const gridPositionsRes = await Promise.all(\n gridAlgoOrders.data.map((item) =>\n terminal.client.requestForResponseData<\n { account_id: string; algoId: string },\n InferPromise<ReturnType<typeof client.getGridPositions>>\n >('OKX/QueryGridPositions', {\n account_id: strategyAccountId,\n algoId: item.algoId,\n }),\n ),\n );\n\n gridPositionsRes.forEach((gridPositions, index) => {\n let positionValuation = 0;\n const leverage = +gridAlgoOrders.data?.[index].actualLever;\n gridPositions?.data?.forEach((position) => {\n if (+position.pos !== 0) {\n const directionRaw = gridAlgoOrders.data?.[index]?.direction ?? '';\n const direction = directionRaw ? directionRaw.toUpperCase() : 'LONG';\n positions.push({\n position_id: encodePath(position.algoId, position.instId),\n datasource_id: 'OKX',\n product_id: encodePath(position.instType, position.instId),\n direction,\n volume: Math.abs(+position.pos),\n free_volume: +position.pos,\n position_price: +position.avgPx,\n floating_profit: +position.upl,\n closable_price: +position.last,\n valuation: +position.notionalUsd,\n });\n positionValuation += +position.notionalUsd;\n }\n });\n if (leverage === 0) {\n // 实际杠杆为 0,说明没有持仓,直接把投资金额和累计盈亏算到净值里\n totalEquity += +gridAlgoOrders.data?.[index].investment + +gridAlgoOrders.data?.[index].totalPnl;\n } else {\n // 历史提取金额不会从 investment, totalPnl 扣减\n // 计算净值需要通过仓位的名义价值和实际杠杆计算\n totalEquity += positionValuation / leverage;\n }\n });\n\n return {\n money: {\n currency: 'USDT',\n equity: totalEquity,\n // TODO: 累计策略的可提取资金作为 free\n free: 0,\n },\n positions,\n };\n },\n { auto_refresh_interval: 5000 },\n );\n}).subscribe();\n\nconst sub = defer(() => accountUid$)\n .pipe(first())\n .subscribe((uid) => {\n addAccountMarket(terminal, { account_id: `okx/${uid}/strategy`, market_id: 'OKX' });\n });\ndefer(() => terminal.dispose$).subscribe(() => sub.unsubscribe());\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuants/vendor-okx",
3
- "version": "0.23.9",
3
+ "version": "0.23.10",
4
4
  "bin": "lib/cli.js",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -1,13 +1,13 @@
1
1
  {
2
- "apps/vendor-okx/CHANGELOG.json": "35cddf491321ab817ce9366304824cdbb2b0af13",
3
- "apps/vendor-okx/CHANGELOG.md": "42c022a8cd36c0917eab9827830627912aca4886",
2
+ "apps/vendor-okx/CHANGELOG.json": "948b848b5b56b883f70e43dbb6daa1cae1a5a820",
3
+ "apps/vendor-okx/CHANGELOG.md": "f1e3dedde2cbda8c2afd2d032ed6f2ca86563e31",
4
4
  "apps/vendor-okx/README.md": "ac3d1f6c4c8d73066664699b0bb1b01db02e67a2",
5
5
  "apps/vendor-okx/api-extractor.json": "62f4fd324425b9a235f0c117975967aab09ced0c",
6
6
  "apps/vendor-okx/config/jest.config.json": "4bb17bde3ee911163a3edb36a6eb71491d80b1bd",
7
7
  "apps/vendor-okx/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
8
8
  "apps/vendor-okx/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
9
9
  "apps/vendor-okx/etc/vendor-okx.api.md": "92c54ccd547d2ad81ca6088158ca193e85c208df",
10
- "apps/vendor-okx/package.json": "c0e4124f1a4c20ed74076101ebf4e2c6603b8a8c",
10
+ "apps/vendor-okx/package.json": "93702e9eac5126b43ba7c9adc3affa441c31d723",
11
11
  "apps/vendor-okx/src/account.ts": "ecfbe5017d6b5d4d1bc833de9f48fe72db76bdb7",
12
12
  "apps/vendor-okx/src/api.ts": "1ed5d9e4a758523e5f97183a1e6377bed0d75493",
13
13
  "apps/vendor-okx/src/cli.ts": "9bf6b5559a6c6f33da20e74cc6c5d702c60ec891",
@@ -25,7 +25,7 @@
25
25
  "apps/vendor-okx/src/provideSeriesFromTimeBackwardService.ts": "daf3c793eb4fc20e59a740bb69e50fadab5f62f0",
26
26
  "apps/vendor-okx/src/quote.ts": "e289161a274db61505efcdecfafb817e7376742f",
27
27
  "apps/vendor-okx/src/services.ts": "7b7df830a6d78b6de5cee44bbcec66f282ab53ab",
28
- "apps/vendor-okx/src/strategy-account.ts": "900f7cf7707023b52d164b9c9a6935ab57bee4ab",
28
+ "apps/vendor-okx/src/strategy-account.ts": "48e1533b6fd42ff621a789eb991cf094a4a9ee64",
29
29
  "apps/vendor-okx/src/trade.ts": "5265a7215b803c5f357842e1ece7ddca53f7e7fc",
30
30
  "apps/vendor-okx/src/websocket.ts": "6c0199bbb9db714ec96b59d90b35b3c801975194",
31
31
  "apps/vendor-okx/src/ws.ts": "7aa1561c8c524dee838817eaeda5031d389ec877",