Files
trade/data/run/exchange.ts
T
Rekey 626acb20d3 feat: 全链路新增 type 字段支持 + exchange.ts 超时退出优化
- TS: exit 函数统一管理进程退出与 DB 连接关闭;10s 超时 + 异常路径 clearTimeout
- Python: PairType(spot/um/cm) 贯穿 Kline 模型、策略配置、数据查询
- 回测脚本升级: 9策略 × 4币种 × 6时间级别 × 2交易类型
- 新增 generate_report.py 回测报告生成工具
2026-06-17 10:01:52 +08:00

62 lines
2.1 KiB
TypeScript

import { logger } from "../utils/logger";
import { getAllPairs, updatePairLastBackfillTime } from '../service/pair';
import { upsertOrUpdateKlines } from "../service/kline";
import { fetchKlines } from '../exchanges';
import { AppDataSource } from '../db/data-source';
async function exit() {
AppDataSource.destroy().finally(() => {
process.exit(0);
});
}
function getNowMinuteMS() {
const minuteMS = 1000 * 60;
return Math.floor(Date.now() / minuteMS) * minuteMS
}
const allPairs = await getAllPairs();
for (const pair of allPairs) {
let lastBackfillTime = pair.last_backfill_time.getTime();
while (lastBackfillTime < getNowMinuteMS()) {
const timer = setTimeout(exit, 10000);
try {
logger.info({ lastBackfillTime }, '回补进度');
const klines = await fetchKlines({
exchange: 'binance',
type: pair.type,
symbol: pair.symbol,
startTime: lastBackfillTime,
limit: 1000,
});
clearTimeout(timer);
logger.info(`拉取到 ${klines.length} 条 K 线`);
if (klines.length > 0) {
await upsertOrUpdateKlines(klines);
const lastK = klines[klines.length - 1];
if (lastK) {
await updatePairLastBackfillTime(lastK?.symbol, new Date(lastK.openTime), pair.type);
if (lastBackfillTime === lastK.openTime) {
break;
}
lastBackfillTime = lastK.openTime;
}
}
} catch (err) {
clearTimeout(timer);
logger.error({ err }, "拉取失败");
}
await new Promise((resolve) => {
setTimeout(resolve, Math.random() * 1000);
});
}
}
// 所有交易对均已完成回补,等待 10~40 秒再退出,
// 避免外部进程管理立即重启导致高频空查触发 API 限流。
await new Promise((resolve) => {
setTimeout(resolve, Math.random() * 30 * 1000 + 10000);
});
exit();