@yuants/app-virtual-exchange 0.17.0 → 0.18.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/series-collector/backwards-interest-rate.js +4 -4
- package/dist/series-collector/backwards-interest-rate.js.map +1 -1
- package/dist/series-collector/backwards-ohlc.js +33 -68
- package/dist/series-collector/backwards-ohlc.js.map +1 -1
- package/dist/series-collector/discovery.js +30 -1
- package/dist/series-collector/discovery.js.map +1 -1
- package/dist/series-collector/forwards-interest-rate.js +5 -5
- package/dist/series-collector/forwards-interest-rate.js.map +1 -1
- package/dist/series-collector/forwards-ohlc.js +33 -68
- package/dist/series-collector/forwards-ohlc.js.map +1 -1
- package/dist/series-collector/index.js +1 -2
- package/dist/series-collector/index.js.map +1 -1
- package/dist/series-collector/interest-rate.js +11 -5
- package/dist/series-collector/interest-rate.js.map +1 -1
- package/dist/series-collector/ohlc.js +49 -0
- package/dist/series-collector/ohlc.js.map +1 -0
- package/dist/series-collector/patch-interest-rate.js +4 -0
- package/dist/series-collector/patch-interest-rate.js.map +1 -1
- package/dist/series-collector/patch-ohlc.js +67 -0
- package/dist/series-collector/patch-ohlc.js.map +1 -0
- package/lib/series-collector/backwards-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/backwards-interest-rate.js +4 -4
- package/lib/series-collector/backwards-interest-rate.js.map +1 -1
- package/lib/series-collector/backwards-ohlc.d.ts +2 -1
- package/lib/series-collector/backwards-ohlc.d.ts.map +1 -1
- package/lib/series-collector/backwards-ohlc.js +34 -67
- package/lib/series-collector/backwards-ohlc.js.map +1 -1
- package/lib/series-collector/discovery.d.ts +5 -0
- package/lib/series-collector/discovery.d.ts.map +1 -1
- package/lib/series-collector/discovery.js +31 -1
- package/lib/series-collector/discovery.js.map +1 -1
- package/lib/series-collector/forwards-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/forwards-interest-rate.js +5 -5
- package/lib/series-collector/forwards-interest-rate.js.map +1 -1
- package/lib/series-collector/forwards-ohlc.d.ts +2 -1
- package/lib/series-collector/forwards-ohlc.d.ts.map +1 -1
- package/lib/series-collector/forwards-ohlc.js +34 -67
- package/lib/series-collector/forwards-ohlc.js.map +1 -1
- package/lib/series-collector/index.d.ts +1 -2
- package/lib/series-collector/index.d.ts.map +1 -1
- package/lib/series-collector/index.js +1 -2
- package/lib/series-collector/index.js.map +1 -1
- package/lib/series-collector/interest-rate.js +9 -3
- package/lib/series-collector/interest-rate.js.map +1 -1
- package/lib/series-collector/ohlc.d.ts +2 -0
- package/lib/series-collector/ohlc.d.ts.map +1 -0
- package/lib/series-collector/ohlc.js +51 -0
- package/lib/series-collector/ohlc.js.map +1 -0
- package/lib/series-collector/patch-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/patch-interest-rate.js +4 -0
- package/lib/series-collector/patch-interest-rate.js.map +1 -1
- package/lib/series-collector/patch-ohlc.d.ts +3 -0
- package/lib/series-collector/patch-ohlc.d.ts.map +1 -0
- package/lib/series-collector/patch-ohlc.js +71 -0
- package/lib/series-collector/patch-ohlc.js.map +1 -0
- package/package.json +1 -1
|
@@ -6,6 +6,9 @@ import { Terminal } from '@yuants/protocol';
|
|
|
6
6
|
import { decodePath, formatTime, tokenBucket } from '@yuants/utils';
|
|
7
7
|
import { findInterestRateStartTimeBackward } from './sql-helpers';
|
|
8
8
|
const terminal = Terminal.fromNodeEnv();
|
|
9
|
+
const ingestCounter = terminal.metrics
|
|
10
|
+
.counter('series_collector_ingest_count', '')
|
|
11
|
+
.labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'backward' });
|
|
9
12
|
export const handleIngestInterestRateBackward = async (product_id, meta, signal) => {
|
|
10
13
|
var _a, _b, _c, _d;
|
|
11
14
|
const [datasource_id] = decodePath(product_id);
|
|
@@ -30,10 +33,7 @@ export const handleIngestInterestRateBackward = async (product_id, meta, signal)
|
|
|
30
33
|
}
|
|
31
34
|
console.info(formatTime(Date.now()), '[SeriesCollector][InterestRate][Backward]', 'Request', `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`);
|
|
32
35
|
const res = await terminal.client.requestForResponseData('IngestInterestRate', req);
|
|
33
|
-
|
|
34
|
-
.counter('series_collector_ingest_count', '')
|
|
35
|
-
.labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'backward' })
|
|
36
|
-
.inc(res.wrote_count || 0);
|
|
36
|
+
ingestCounter.inc(res.wrote_count || 0);
|
|
37
37
|
console.info(formatTime(Date.now()), '[SeriesCollector][InterestRate][Backward]', 'Result', `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
38
38
|
};
|
|
39
39
|
//# sourceMappingURL=backwards-interest-rate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/backwards-interest-rate.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,yDAAyD;AACzD,qCAAqC;AAOrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"backwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/backwards-interest-rate.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,yDAAyD;AACzD,qCAAqC;AAOrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAE1F,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,EACnD,UAAkB,EAClB,IAAkC,EAClC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,sBAAsB;IACtB,MAAM,WAAW,CAAC,0BAA0B,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAChF,IAAI,GAA+B,CAAC;IACpC,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU,EAAE;QACjC,MAAM,SAAS,GAAG,MAAM,iCAAiC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAE1E,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,UAAU;SACjB,CAAC;KACH;SAAM;QACL,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,CAAC;SACR,CAAC;KACH;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,2CAA2C,EAC3C,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,2CAA2C,EAC3C,QAAQ,EACR,aAAa,UAAU,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CAClF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// 解决 Backwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Backwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestInterestRate Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport {\n IIngestInterestRateRequest,\n IInterestRateServiceMetadata,\n ISeriesIngestResult,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { decodePath, formatTime, tokenBucket } from '@yuants/utils';\nimport { findInterestRateStartTimeBackward } from './sql-helpers';\n\nconst terminal = Terminal.fromNodeEnv();\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'backward' });\n\nexport const handleIngestInterestRateBackward = async (\n product_id: string,\n meta: IInterestRateServiceMetadata,\n signal: AbortSignal,\n) => {\n const [datasource_id] = decodePath(product_id);\n // 控制速率:每个数据源每秒钟只能请求一次\n await tokenBucket(`interest_rate:backward:${datasource_id}`).acquire(1, signal);\n let req: IIngestInterestRateRequest;\n if (meta.direction === 'backward') {\n const startTime = await findInterestRateStartTimeBackward(terminal, product_id);\n const start_time = startTime ? new Date(startTime).getTime() : Date.now();\n\n req = {\n product_id: product_id,\n direction: 'backward',\n time: start_time,\n };\n } else {\n req = {\n product_id: product_id,\n direction: 'forward',\n time: 0,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Backward]',\n 'Request',\n `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Backward]',\n 'Result',\n `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -2,78 +2,43 @@
|
|
|
2
2
|
// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Backwards 拉取的序列。
|
|
3
3
|
// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。
|
|
4
4
|
// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。
|
|
5
|
-
import { decodeOHLCSeriesId
|
|
6
|
-
import { parseOHLCServiceMetadataFromSchema, } from '@yuants/exchange';
|
|
5
|
+
import { decodeOHLCSeriesId } from '@yuants/data-ohlc';
|
|
7
6
|
import { Terminal } from '@yuants/protocol';
|
|
8
7
|
import { escapeSQL, requestSQL } from '@yuants/sql';
|
|
9
8
|
import { decodePath, formatTime, tokenBucket } from '@yuants/utils';
|
|
10
|
-
import { defer, repeat, retry } from 'rxjs';
|
|
11
9
|
const terminal = Terminal.fromNodeEnv();
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
finally {
|
|
34
|
-
}
|
|
35
|
-
}
|
|
10
|
+
const ingestCounter = terminal.metrics
|
|
11
|
+
.counter('series_collector_ingest_count', '')
|
|
12
|
+
.labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'backward' });
|
|
13
|
+
export const handleIngestOHLCBackward = async (series_id, direction, signal) => {
|
|
14
|
+
var _a, _b, _c, _d;
|
|
15
|
+
const { product_id, duration } = decodeOHLCSeriesId(series_id);
|
|
16
|
+
const [datasource_id] = decodePath(product_id);
|
|
17
|
+
// 控制速率:每个数据源每秒钟只能请求一次
|
|
18
|
+
await tokenBucket(`ohlc:backward:${datasource_id}`).acquire(1, signal);
|
|
19
|
+
let req;
|
|
20
|
+
if (direction === 'backward') {
|
|
21
|
+
const [record] = await requestSQL(terminal, `select start_time from series_data_range where series_id = ${escapeSQL(series_id)} and table_name = 'ohlc_v2' order by start_time limit 1`);
|
|
22
|
+
const start_time = record ? new Date(record.start_time).getTime() : Date.now();
|
|
23
|
+
req = {
|
|
24
|
+
product_id,
|
|
25
|
+
duration,
|
|
26
|
+
direction: 'backward',
|
|
27
|
+
time: start_time,
|
|
28
|
+
};
|
|
36
29
|
}
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
else {
|
|
31
|
+
// forward
|
|
32
|
+
req = {
|
|
33
|
+
product_id,
|
|
34
|
+
duration,
|
|
35
|
+
direction,
|
|
36
|
+
time: 0,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
console.info(formatTime(Date.now()), '[SeriesCollector][OHLC][Backward]', 'Request', `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(req.time)}`);
|
|
40
|
+
const res = await terminal.client.requestForResponseData('IngestOHLC', req);
|
|
41
|
+
ingestCounter.inc(res.wrote_count || 0);
|
|
42
|
+
console.info(formatTime(Date.now()), '[SeriesCollector][OHLC][Backward]', 'Response', `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
39
43
|
};
|
|
40
|
-
defer(async () => {
|
|
41
|
-
const time = Date.now();
|
|
42
|
-
const series_ids = await listBackwardSeriesIds();
|
|
43
|
-
console.log(`[SeriesCollector][Backwards] Found ${series_ids.size} series to collect backwards data for. (${formatTime(Date.now() - time)})`);
|
|
44
|
-
await Promise.all([...series_ids].map(async (series_id) => {
|
|
45
|
-
var _a, _b, _c, _d;
|
|
46
|
-
try {
|
|
47
|
-
const { product_id, duration } = decodeOHLCSeriesId(series_id);
|
|
48
|
-
const [datasource_id] = decodePath(product_id);
|
|
49
|
-
// 控制速率:每个数据源每秒钟只能请求一次
|
|
50
|
-
await tokenBucket(`backwards_target_${datasource_id}`, {
|
|
51
|
-
refillInterval: 1000,
|
|
52
|
-
capacity: 1,
|
|
53
|
-
}).acquire();
|
|
54
|
-
{
|
|
55
|
-
const [record] = await requestSQL(terminal, `select start_time from series_data_range where series_id = ${escapeSQL(series_id)} and table_name = 'ohlc_v2' order by start_time limit 1`);
|
|
56
|
-
const start_time = record ? new Date(record.start_time).getTime() : Date.now();
|
|
57
|
-
const req = {
|
|
58
|
-
product_id,
|
|
59
|
-
duration,
|
|
60
|
-
direction: 'backward',
|
|
61
|
-
time: start_time,
|
|
62
|
-
};
|
|
63
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLC', `product_id=${product_id}, duration=${duration}, time=${formatTime(start_time)}`);
|
|
64
|
-
const res = await terminal.client.requestForResponseData('IngestOHLC', req);
|
|
65
|
-
terminal.metrics
|
|
66
|
-
.counter('series_collector_backwards_ingest_count', '')
|
|
67
|
-
.labels({ terminal_id: terminal.terminal_id, type: 'ohlc' })
|
|
68
|
-
.inc(res.wrote_count || 0);
|
|
69
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLCResult', `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLCError', `series_id=${series_id}`, e);
|
|
74
|
-
}
|
|
75
|
-
}));
|
|
76
|
-
})
|
|
77
|
-
.pipe(retry({ delay: 1000 }), repeat({ delay: 1000 }))
|
|
78
|
-
.subscribe();
|
|
79
44
|
//# sourceMappingURL=backwards-ohlc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/backwards-ohlc.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"backwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/backwards-ohlc.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC/D,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,sBAAsB;IACtB,MAAM,WAAW,CAAC,iBAAiB,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEvE,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,UAAU,EAAE;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAK/B,QAAQ,EACR,8DAA8D,SAAS,CACrE,SAAS,CACV,yDAAyD,CAC3D,CAAC;QACF,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAE/E,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,UAAU;SACjB,CAAC;KACH;SAAM;QACL,UAAU;QACV,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS;YACT,IAAI,EAAE,CAAC;SACR,CAAC;KACH;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,mCAAmC,EACnC,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,cAAc,GAAG,CAAC,QAAQ,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CACpG,GAAG,CAAC,IAAI,CACT,EAAE,CACJ,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,YAAY,EACZ,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,mCAAmC,EACnC,UAAU,EACV,aAAa,SAAS,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACjF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// 解决 Backwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Backwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport { decodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport { IIngestOHLCRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { decodePath, formatTime, tokenBucket } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'backward' });\n\nexport const handleIngestOHLCBackward = async (\n series_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const { product_id, duration } = decodeOHLCSeriesId(series_id);\n const [datasource_id] = decodePath(product_id);\n // 控制速率:每个数据源每秒钟只能请求一次\n await tokenBucket(`ohlc:backward:${datasource_id}`).acquire(1, signal);\n\n let req: IIngestOHLCRequest;\n if (direction === 'backward') {\n const [record] = await requestSQL<\n {\n start_time: string;\n }[]\n >(\n terminal,\n `select start_time from series_data_range where series_id = ${escapeSQL(\n series_id,\n )} and table_name = 'ohlc_v2' order by start_time limit 1`,\n );\n const start_time = record ? new Date(record.start_time).getTime() : Date.now();\n\n req = {\n product_id,\n duration,\n direction: 'backward',\n time: start_time,\n };\n } else {\n // forward\n req = {\n product_id,\n duration,\n direction,\n time: 0,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Backward]',\n 'Request',\n `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(\n req.time,\n )}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>(\n 'IngestOHLC',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Backward]',\n 'Response',\n `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// 发现所有支持利率的品种系列ID
|
|
2
|
-
import {
|
|
2
|
+
import { encodeOHLCSeriesId } from '@yuants/data-ohlc';
|
|
3
|
+
import { parseInterestRateServiceMetadataFromSchema, parseOHLCServiceMetadataFromSchema, } from '@yuants/exchange';
|
|
3
4
|
import { Terminal } from '@yuants/protocol';
|
|
4
5
|
import { requestSQL } from '@yuants/sql';
|
|
5
6
|
const terminal = Terminal.fromNodeEnv();
|
|
@@ -30,4 +31,32 @@ export const listInterestRateSeriesIds = async () => {
|
|
|
30
31
|
}
|
|
31
32
|
return series_ids;
|
|
32
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
export const listOHLCSeriesIds = async () => {
|
|
39
|
+
const product_ids = await requestSQL(terminal, `select product_id from product`);
|
|
40
|
+
const series_ids = new Map();
|
|
41
|
+
for (const terminalInfo of terminal.terminalInfos) {
|
|
42
|
+
for (const serviceInfo of Object.values(terminalInfo.serviceInfo || {})) {
|
|
43
|
+
if (serviceInfo.method !== 'IngestOHLC')
|
|
44
|
+
continue;
|
|
45
|
+
try {
|
|
46
|
+
const meta = parseOHLCServiceMetadataFromSchema(serviceInfo.schema);
|
|
47
|
+
for (const { product_id } of product_ids) {
|
|
48
|
+
if (!product_id.startsWith(meta.product_id_prefix))
|
|
49
|
+
continue;
|
|
50
|
+
for (const duration of meta.duration_list) {
|
|
51
|
+
const series_id = encodeOHLCSeriesId(product_id, duration);
|
|
52
|
+
series_ids.set(series_id, meta.direction);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return series_ids;
|
|
61
|
+
};
|
|
33
62
|
//# sourceMappingURL=discovery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/series-collector/discovery.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/series-collector/discovery.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAEL,0CAA0C,EAC1C,kCAAkC,GACnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,IAAI,EAAE;IAClD,MAAM,WAAW,GAAG,MAAM,UAAU,CAClC,QAAQ;IACR,aAAa;IACb,+DAA+D,CAChE,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAwC,CAAC;IACnE,KAAK,MAAM,YAAY,IAAI,QAAQ,CAAC,aAAa,EAAE;QACjD,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE;YACvE,IAAI,WAAW,CAAC,MAAM,KAAK,oBAAoB;gBAAE,SAAS;YAC1D,IAAI;gBACF,MAAM,IAAI,GAAG,0CAA0C,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAE5E,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,WAAW,EAAE;oBACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC;wBAAE,SAAS;oBAC7D,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;iBAClC;aACF;oBAAS;aACT;SACF;KACF;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;IAC1C,MAAM,WAAW,GAAG,MAAM,UAAU,CAA2B,QAAQ,EAAE,gCAAgC,CAAC,CAAC;IAE3G,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC7D,KAAK,MAAM,YAAY,IAAI,QAAQ,CAAC,aAAa,EAAE;QACjD,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE;YACvE,IAAI,WAAW,CAAC,MAAM,KAAK,YAAY;gBAAE,SAAS;YAClD,IAAI;gBACF,MAAM,IAAI,GAAG,kCAAkC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAEpE,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,WAAW,EAAE;oBACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC;wBAAE,SAAS;oBAC7D,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,aAAa,EAAE;wBACzC,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;wBAC3D,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;qBAC3C;iBACF;aACF;oBAAS;aACT;SACF;KACF;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC","sourcesContent":["// 发现所有支持利率的品种系列ID\n\nimport { encodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport {\n IInterestRateServiceMetadata,\n parseInterestRateServiceMetadataFromSchema,\n parseOHLCServiceMetadataFromSchema,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { requestSQL } from '@yuants/sql';\n\nconst terminal = Terminal.fromNodeEnv();\n\n/**\n * 列出所有支持利率的品种系列ID以及对应的 Service Metadata\n * @returns\n */\nexport const listInterestRateSeriesIds = async () => {\n const product_ids = await requestSQL<{ product_id: string }[]>(\n terminal,\n // 必须是支持利率的品种\n `select product_id from product where no_interest_rate = false`,\n );\n\n const series_ids = new Map<string, IInterestRateServiceMetadata>();\n for (const terminalInfo of terminal.terminalInfos) {\n for (const serviceInfo of Object.values(terminalInfo.serviceInfo || {})) {\n if (serviceInfo.method !== 'IngestInterestRate') continue;\n try {\n const meta = parseInterestRateServiceMetadataFromSchema(serviceInfo.schema);\n\n for (const { product_id } of product_ids) {\n if (!product_id.startsWith(meta.product_id_prefix)) continue;\n series_ids.set(product_id, meta);\n }\n } finally {\n }\n }\n }\n\n return series_ids;\n};\n\n/**\n *\n * @returns\n */\nexport const listOHLCSeriesIds = async () => {\n const product_ids = await requestSQL<{ product_id: string }[]>(terminal, `select product_id from product`);\n\n const series_ids = new Map<string, 'forward' | 'backward'>();\n for (const terminalInfo of terminal.terminalInfos) {\n for (const serviceInfo of Object.values(terminalInfo.serviceInfo || {})) {\n if (serviceInfo.method !== 'IngestOHLC') continue;\n try {\n const meta = parseOHLCServiceMetadataFromSchema(serviceInfo.schema);\n\n for (const { product_id } of product_ids) {\n if (!product_id.startsWith(meta.product_id_prefix)) continue;\n for (const duration of meta.duration_list) {\n const series_id = encodeOHLCSeriesId(product_id, duration);\n series_ids.set(series_id, meta.direction);\n }\n }\n } finally {\n }\n }\n }\n\n return series_ids;\n};\n"]}
|
|
@@ -6,11 +6,14 @@ import { Terminal } from '@yuants/protocol';
|
|
|
6
6
|
import { decodePath, formatTime, tokenBucket } from '@yuants/utils';
|
|
7
7
|
import { findInterestRateEndTimeForward } from './sql-helpers';
|
|
8
8
|
const terminal = Terminal.fromNodeEnv();
|
|
9
|
+
const ingestCounter = terminal.metrics
|
|
10
|
+
.counter('series_collector_ingest_count', '')
|
|
11
|
+
.labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'forward' });
|
|
9
12
|
export const handleIngestInterestRateForward = async (product_id, meta, signal) => {
|
|
10
13
|
var _a, _b, _c, _d;
|
|
11
14
|
const [datasource_id] = decodePath(product_id);
|
|
12
15
|
// 控制速率:每个数据源每秒钟只能请求一次
|
|
13
|
-
await tokenBucket(`
|
|
16
|
+
await tokenBucket(`interest_rate:forwards:${datasource_id}`).acquire(1, signal);
|
|
14
17
|
{
|
|
15
18
|
let req;
|
|
16
19
|
if (meta.direction === 'forward') {
|
|
@@ -32,10 +35,7 @@ export const handleIngestInterestRateForward = async (product_id, meta, signal)
|
|
|
32
35
|
}
|
|
33
36
|
console.info(formatTime(Date.now()), '[SeriesCollector][InterestRate][Forward]', 'Request', `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`);
|
|
34
37
|
const res = await terminal.client.requestForResponseData('IngestInterestRate', req);
|
|
35
|
-
|
|
36
|
-
.counter('series_collector_forwards_ingest_count', '')
|
|
37
|
-
.labels({ terminal_id: terminal.terminal_id, type: 'interest_rate' })
|
|
38
|
-
.inc(res.wrote_count || 0);
|
|
38
|
+
ingestCounter.inc(res.wrote_count || 0);
|
|
39
39
|
console.info(formatTime(Date.now()), '[SeriesCollector][InterestRate][Forward]', 'Result', `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
40
40
|
}
|
|
41
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/forwards-interest-rate.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,yDAAyD;AACzD,qCAAqC;AAOrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,EAClD,UAAkB,EAClB,IAAkC,EAClC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,sBAAsB;IACtB,MAAM,WAAW,CAAC,0BAA0B,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEhF;QACE,IAAI,GAA+B,CAAC;QACpC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE;YAChC,MAAM,OAAO,GAAG,MAAM,8BAA8B,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvD,GAAG,GAAG;gBACJ,UAAU,EAAE,UAAU;gBACtB,SAAS,EAAE,SAAS;gBACpB,IAAI;aACL,CAAC;SACH;aAAM;YACL,WAAW;YACX,GAAG,GAAG;gBACJ,UAAU;gBACV,SAAS,EAAE,UAAU;gBACrB,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;aACjB,CAAC;SACH;QAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,0CAA0C,EAC1C,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;QAEF,
|
|
1
|
+
{"version":3,"file":"forwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/forwards-interest-rate.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,yDAAyD;AACzD,qCAAqC;AAOrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,EAClD,UAAkB,EAClB,IAAkC,EAClC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,sBAAsB;IACtB,MAAM,WAAW,CAAC,0BAA0B,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEhF;QACE,IAAI,GAA+B,CAAC;QACpC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE;YAChC,MAAM,OAAO,GAAG,MAAM,8BAA8B,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvD,GAAG,GAAG;gBACJ,UAAU,EAAE,UAAU;gBACtB,SAAS,EAAE,SAAS;gBACpB,IAAI;aACL,CAAC;SACH;aAAM;YACL,WAAW;YACX,GAAG,GAAG;gBACJ,UAAU;gBACV,SAAS,EAAE,UAAU;gBACrB,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;aACjB,CAAC;SACH;QAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,0CAA0C,EAC1C,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;QAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;QAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,0CAA0C,EAC1C,QAAQ,EACR,aAAa,UAAU,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CAClF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;KACH;AACH,CAAC,CAAC","sourcesContent":["// 解决 Forwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Forwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestInterestRate Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport {\n IIngestInterestRateRequest,\n IInterestRateServiceMetadata,\n ISeriesIngestResult,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { decodePath, formatTime, tokenBucket } from '@yuants/utils';\nimport { findInterestRateEndTimeForward } from './sql-helpers';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'forward' });\n\nexport const handleIngestInterestRateForward = async (\n product_id: string,\n meta: IInterestRateServiceMetadata,\n signal: AbortSignal,\n) => {\n const [datasource_id] = decodePath(product_id);\n // 控制速率:每个数据源每秒钟只能请求一次\n await tokenBucket(`interest_rate:forwards:${datasource_id}`).acquire(1, signal);\n\n {\n let req: IIngestInterestRateRequest;\n if (meta.direction === 'forward') {\n const endTime = await findInterestRateEndTimeForward(terminal, product_id);\n const time = endTime ? new Date(endTime).getTime() : 0;\n\n req = {\n product_id: product_id,\n direction: 'forward',\n time,\n };\n } else {\n // backward\n req = {\n product_id,\n direction: 'backward',\n time: Date.now(),\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Forward]',\n 'Request',\n `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n const res = await terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Forward]',\n 'Result',\n `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n }\n};\n"]}
|
|
@@ -2,78 +2,43 @@
|
|
|
2
2
|
// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Forwards 拉取的序列。
|
|
3
3
|
// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。
|
|
4
4
|
// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。
|
|
5
|
-
import { decodeOHLCSeriesId
|
|
6
|
-
import { parseOHLCServiceMetadataFromSchema, } from '@yuants/exchange';
|
|
5
|
+
import { decodeOHLCSeriesId } from '@yuants/data-ohlc';
|
|
7
6
|
import { Terminal } from '@yuants/protocol';
|
|
8
7
|
import { escapeSQL, requestSQL } from '@yuants/sql';
|
|
9
8
|
import { decodePath, formatTime, tokenBucket } from '@yuants/utils';
|
|
10
|
-
import { defer, repeat, retry } from 'rxjs';
|
|
11
9
|
const terminal = Terminal.fromNodeEnv();
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
finally {
|
|
34
|
-
}
|
|
35
|
-
}
|
|
10
|
+
const ingestCounter = terminal.metrics
|
|
11
|
+
.counter('series_collector_ingest_count', '')
|
|
12
|
+
.labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'forward' });
|
|
13
|
+
export const handleIngestOHLCForward = async (series_id, direction, signal) => {
|
|
14
|
+
var _a, _b, _c, _d;
|
|
15
|
+
const { product_id, duration } = decodeOHLCSeriesId(series_id);
|
|
16
|
+
const [datasource_id] = decodePath(product_id);
|
|
17
|
+
// 控制速率:每个数据源每秒钟只能请求一次
|
|
18
|
+
await tokenBucket(`ohlc:forward:${datasource_id}`).acquire();
|
|
19
|
+
let req;
|
|
20
|
+
if (direction === 'forward') {
|
|
21
|
+
const [record] = await requestSQL(terminal, `select end_time from series_data_range where series_id = ${escapeSQL(series_id)} and table_name = 'ohlc_v2' order by end_time desc limit 1`);
|
|
22
|
+
const time = record ? new Date(record.end_time).getTime() : 0;
|
|
23
|
+
req = {
|
|
24
|
+
product_id,
|
|
25
|
+
duration,
|
|
26
|
+
direction: 'forward',
|
|
27
|
+
time,
|
|
28
|
+
};
|
|
36
29
|
}
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
else {
|
|
31
|
+
// backward
|
|
32
|
+
req = {
|
|
33
|
+
product_id,
|
|
34
|
+
duration,
|
|
35
|
+
direction,
|
|
36
|
+
time: Date.now(),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
console.info(formatTime(Date.now()), '[SeriesCollector][OHLC][Forward]', 'Request', `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(req.time)}`);
|
|
40
|
+
const res = await terminal.client.requestForResponseData('IngestOHLC', req);
|
|
41
|
+
ingestCounter.inc(res.wrote_count || 0);
|
|
42
|
+
console.info(formatTime(Date.now()), '[SeriesCollector][OHLC][Forward]', 'Response', `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
39
43
|
};
|
|
40
|
-
defer(async () => {
|
|
41
|
-
const time = Date.now();
|
|
42
|
-
const series_ids = await listForwardSeriesIds();
|
|
43
|
-
console.log(`[SeriesCollector][OHLC][Forwards] Found ${series_ids.size} series to collect forwards data for. (${formatTime(Date.now() - time)})`);
|
|
44
|
-
await Promise.all([...series_ids].map(async (series_id) => {
|
|
45
|
-
var _a, _b, _c, _d;
|
|
46
|
-
try {
|
|
47
|
-
const { product_id, duration } = decodeOHLCSeriesId(series_id);
|
|
48
|
-
const [datasource_id] = decodePath(product_id);
|
|
49
|
-
// 控制速率:每个数据源每秒钟只能请求一次
|
|
50
|
-
await tokenBucket(`ohlc_forwards_target_${datasource_id}`, {
|
|
51
|
-
refillInterval: 1000,
|
|
52
|
-
capacity: 1,
|
|
53
|
-
}).acquire();
|
|
54
|
-
{
|
|
55
|
-
const [record] = await requestSQL(terminal, `select end_time from series_data_range where series_id = ${escapeSQL(series_id)} and table_name = 'ohlc_v2' order by end_time desc limit 1`);
|
|
56
|
-
const time = record ? new Date(record.end_time).getTime() : 0;
|
|
57
|
-
const req = {
|
|
58
|
-
product_id,
|
|
59
|
-
duration,
|
|
60
|
-
direction: 'forward',
|
|
61
|
-
time,
|
|
62
|
-
};
|
|
63
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLC_Forwards', `product_id=${product_id}, duration=${duration}, time=${formatTime(time)}`);
|
|
64
|
-
const res = await terminal.client.requestForResponseData('IngestOHLC', req);
|
|
65
|
-
terminal.metrics
|
|
66
|
-
.counter('series_collector_forwards_ingest_count', '')
|
|
67
|
-
.labels({ terminal_id: terminal.terminal_id, type: 'ohlc' })
|
|
68
|
-
.inc(res.wrote_count || 0);
|
|
69
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLCResult_Forwards', `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime((_b = (_a = res.range) === null || _a === void 0 ? void 0 : _a.start_time) !== null && _b !== void 0 ? _b : NaN)}, end_time=${formatTime((_d = (_c = res.range) === null || _c === void 0 ? void 0 : _c.end_time) !== null && _d !== void 0 ? _d : NaN)}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
console.info(formatTime(Date.now()), 'DispatchIngestOHLCError_Forwards', `series_id=${series_id}`, e);
|
|
74
|
-
}
|
|
75
|
-
}));
|
|
76
|
-
})
|
|
77
|
-
.pipe(retry({ delay: 1000 }), repeat({ delay: 1000 }))
|
|
78
|
-
.subscribe();
|
|
79
44
|
//# sourceMappingURL=forwards-ohlc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/forwards-ohlc.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"forwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/forwards-ohlc.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEhF,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC/D,MAAM,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,sBAAsB;IACtB,MAAM,WAAW,CAAC,gBAAgB,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAC7D,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,SAAS,EAAE;QAC3B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAK/B,QAAQ,EACR,4DAA4D,SAAS,CACnE,SAAS,CACV,4DAA4D,CAC9D,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS,EAAE,SAAS;YACpB,IAAI;SACL,CAAC;KACH;SAAM;QACL,WAAW;QACX,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS;YACT,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;SACjB,CAAC;KACH;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,kCAAkC,EAClC,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,cAAc,GAAG,CAAC,QAAQ,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CACpG,GAAG,CAAC,IAAI,CACT,EAAE,CACJ,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,YAAY,EACZ,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,kCAAkC,EAClC,UAAU,EACV,aAAa,SAAS,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACjF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// 解决 Forwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Forwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport { decodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport { IIngestOHLCRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { decodePath, formatTime, tokenBucket } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'forward' });\n\nexport const handleIngestOHLCForward = async (\n series_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const { product_id, duration } = decodeOHLCSeriesId(series_id);\n const [datasource_id] = decodePath(product_id);\n // 控制速率:每个数据源每秒钟只能请求一次\n await tokenBucket(`ohlc:forward:${datasource_id}`).acquire();\n let req: IIngestOHLCRequest;\n if (direction === 'forward') {\n const [record] = await requestSQL<\n {\n end_time: string;\n }[]\n >(\n terminal,\n `select end_time from series_data_range where series_id = ${escapeSQL(\n series_id,\n )} and table_name = 'ohlc_v2' order by end_time desc limit 1`,\n );\n\n const time = record ? new Date(record.end_time).getTime() : 0;\n\n req = {\n product_id,\n duration,\n direction: 'forward',\n time,\n };\n } else {\n // backward\n req = {\n product_id,\n duration,\n direction,\n time: Date.now(),\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Forward]',\n 'Request',\n `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(\n req.time,\n )}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>(\n 'IngestOHLC',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Forward]',\n 'Response',\n `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/series-collector/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/series-collector/index.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC;AACzB,OAAO,QAAQ,CAAC","sourcesContent":["import './interest-rate';\nimport './ohlc';\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { listWatch } from '@yuants/utils';
|
|
2
|
-
import { defer, map, Observable, repeat, retry } from 'rxjs';
|
|
1
|
+
import { formatTime, listWatch } from '@yuants/utils';
|
|
2
|
+
import { defer, map, Observable, repeat, retry, tap } from 'rxjs';
|
|
3
3
|
import { handleIngestInterestRateBackward } from './backwards-interest-rate';
|
|
4
4
|
import { listInterestRateSeriesIds } from './discovery';
|
|
5
5
|
import { handleIngestInterestRateForward } from './forwards-interest-rate';
|
|
@@ -15,7 +15,9 @@ defer(() => listInterestRateSeriesIds())
|
|
|
15
15
|
const forwardTask = defer(async () => {
|
|
16
16
|
await handleIngestInterestRateForward(product_id, meta, abortController.signal);
|
|
17
17
|
})
|
|
18
|
-
.pipe(
|
|
18
|
+
.pipe(tap({
|
|
19
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][InterestRate][Forward]`, 'Error', err),
|
|
20
|
+
}), retry(), repeat())
|
|
19
21
|
.subscribe();
|
|
20
22
|
sub.add(() => {
|
|
21
23
|
forwardTask.unsubscribe();
|
|
@@ -24,7 +26,9 @@ defer(() => listInterestRateSeriesIds())
|
|
|
24
26
|
const backwardTask = defer(async () => {
|
|
25
27
|
await handleIngestInterestRateBackward(product_id, meta, abortController.signal);
|
|
26
28
|
})
|
|
27
|
-
.pipe(
|
|
29
|
+
.pipe(tap({
|
|
30
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][InterestRate][Backward]`, 'Error', err),
|
|
31
|
+
}), retry(), repeat())
|
|
28
32
|
.subscribe();
|
|
29
33
|
sub.add(() => {
|
|
30
34
|
backwardTask.unsubscribe();
|
|
@@ -33,7 +37,9 @@ defer(() => listInterestRateSeriesIds())
|
|
|
33
37
|
const patchTask = defer(async () => {
|
|
34
38
|
await handleInterestRatePatch(product_id, meta, abortController.signal);
|
|
35
39
|
})
|
|
36
|
-
.pipe(
|
|
40
|
+
.pipe(tap({
|
|
41
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][InterestRate][Patch]`, 'Error', err),
|
|
42
|
+
}), retry(), repeat())
|
|
37
43
|
.subscribe();
|
|
38
44
|
sub.add(() => {
|
|
39
45
|
patchTask.unsubscribe();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/interest-rate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/interest-rate.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatTime, listWatch } from '@yuants/utils';\nimport { defer, map, Observable, repeat, retry, tap } from 'rxjs';\nimport { handleIngestInterestRateBackward } from './backwards-interest-rate';\nimport { listInterestRateSeriesIds } from './discovery';\nimport { handleIngestInterestRateForward } from './forwards-interest-rate';\nimport { handleInterestRatePatch } from './patch-interest-rate';\n\ndefer(() => listInterestRateSeriesIds())\n .pipe(\n retry({ delay: 1000 }),\n repeat({ delay: 60000 }),\n map((x) => Array.from(x.entries())),\n listWatch(\n (x) => x[0],\n ([product_id, meta]) =>\n new Observable((sub) => {\n // 处理每个利率品种任务: (forward / backward / patch),都需要独立调度\n const abortController = new AbortController();\n\n sub.add(() => {\n abortController.abort();\n });\n\n // 先处理前向任务\n const forwardTask = defer(async () => {\n await handleIngestInterestRateForward(product_id, meta, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(\n formatTime(Date.now()),\n `[SeriesCollector][InterestRate][Forward]`,\n 'Error',\n err,\n ),\n }),\n\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n forwardTask.unsubscribe();\n });\n\n // 设置后向任务\n const backwardTask = defer(async () => {\n await handleIngestInterestRateBackward(product_id, meta, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(\n formatTime(Date.now()),\n `[SeriesCollector][InterestRate][Backward]`,\n 'Error',\n err,\n ),\n }),\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n backwardTask.unsubscribe();\n });\n\n // 设置补齐任务\n const patchTask = defer(async () => {\n await handleInterestRatePatch(product_id, meta, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(\n formatTime(Date.now()),\n `[SeriesCollector][InterestRate][Patch]`,\n 'Error',\n err,\n ),\n }),\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n patchTask.unsubscribe();\n });\n }),\n ),\n )\n .subscribe();\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { formatTime, listWatch } from '@yuants/utils';
|
|
2
|
+
import { defer, map, Observable, repeat, retry, tap } from 'rxjs';
|
|
3
|
+
import { listOHLCSeriesIds } from './discovery';
|
|
4
|
+
import { handleIngestOHLCForward } from './forwards-ohlc';
|
|
5
|
+
import { handleIngestOHLCBackward } from './backwards-ohlc';
|
|
6
|
+
import { handleOHLCPatch } from './patch-ohlc';
|
|
7
|
+
defer(() => listOHLCSeriesIds())
|
|
8
|
+
.pipe(retry({ delay: 1000 }), repeat({ delay: 60000 }), map((x) => Array.from(x.entries())), listWatch((x) => x[0], ([product_id, direction]) => new Observable((sub) => {
|
|
9
|
+
// 处理每个利率品种任务: (forward / backward / patch),都需要独立调度
|
|
10
|
+
const abortController = new AbortController();
|
|
11
|
+
sub.add(() => {
|
|
12
|
+
abortController.abort();
|
|
13
|
+
});
|
|
14
|
+
// 先处理前向任务
|
|
15
|
+
const forwardTask = defer(async () => {
|
|
16
|
+
await handleIngestOHLCForward(product_id, direction, abortController.signal);
|
|
17
|
+
})
|
|
18
|
+
.pipe(tap({
|
|
19
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Forward]`, 'Error', err),
|
|
20
|
+
}), retry(), repeat())
|
|
21
|
+
.subscribe();
|
|
22
|
+
sub.add(() => {
|
|
23
|
+
forwardTask.unsubscribe();
|
|
24
|
+
});
|
|
25
|
+
// 设置后向任务
|
|
26
|
+
const backwardTask = defer(async () => {
|
|
27
|
+
await handleIngestOHLCBackward(product_id, direction, abortController.signal);
|
|
28
|
+
})
|
|
29
|
+
.pipe(tap({
|
|
30
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Backward]`, 'Error', err),
|
|
31
|
+
}), retry(), repeat())
|
|
32
|
+
.subscribe();
|
|
33
|
+
sub.add(() => {
|
|
34
|
+
backwardTask.unsubscribe();
|
|
35
|
+
});
|
|
36
|
+
// 设置补齐任务
|
|
37
|
+
const patchTask = defer(async () => {
|
|
38
|
+
await handleOHLCPatch(product_id, direction, abortController.signal);
|
|
39
|
+
})
|
|
40
|
+
.pipe(tap({
|
|
41
|
+
error: (err) => console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Patch]`, 'Error', err),
|
|
42
|
+
}), retry(), repeat())
|
|
43
|
+
.subscribe();
|
|
44
|
+
sub.add(() => {
|
|
45
|
+
patchTask.unsubscribe();
|
|
46
|
+
});
|
|
47
|
+
})))
|
|
48
|
+
.subscribe();
|
|
49
|
+
//# sourceMappingURL=ohlc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../../src/series-collector/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatTime, listWatch } from '@yuants/utils';\nimport { defer, map, Observable, repeat, retry, tap } from 'rxjs';\nimport { handleIngestInterestRateBackward } from './backwards-interest-rate';\nimport { listOHLCSeriesIds } from './discovery';\nimport { handleIngestInterestRateForward } from './forwards-interest-rate';\nimport { handleInterestRatePatch } from './patch-interest-rate';\nimport { handleIngestOHLCForward } from './forwards-ohlc';\nimport { handleIngestOHLCBackward } from './backwards-ohlc';\nimport { handleOHLCPatch } from './patch-ohlc';\n\ndefer(() => listOHLCSeriesIds())\n .pipe(\n retry({ delay: 1000 }),\n repeat({ delay: 60000 }),\n map((x) => Array.from(x.entries())),\n listWatch(\n (x) => x[0],\n ([product_id, direction]) =>\n new Observable((sub) => {\n // 处理每个利率品种任务: (forward / backward / patch),都需要独立调度\n const abortController = new AbortController();\n\n sub.add(() => {\n abortController.abort();\n });\n\n // 先处理前向任务\n const forwardTask = defer(async () => {\n await handleIngestOHLCForward(product_id, direction, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Forward]`, 'Error', err),\n }),\n\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n forwardTask.unsubscribe();\n });\n\n // 设置后向任务\n const backwardTask = defer(async () => {\n await handleIngestOHLCBackward(product_id, direction, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Backward]`, 'Error', err),\n }),\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n backwardTask.unsubscribe();\n });\n\n // 设置补齐任务\n const patchTask = defer(async () => {\n await handleOHLCPatch(product_id, direction, abortController.signal);\n })\n .pipe(\n tap({\n error: (err) =>\n console.info(formatTime(Date.now()), `[SeriesCollector][OHLC][Patch]`, 'Error', err),\n }),\n retry(),\n repeat(),\n )\n .subscribe();\n\n sub.add(() => {\n patchTask.unsubscribe();\n });\n }),\n ),\n )\n .subscribe();\n"]}
|