Files
trade/data/run/exchange.ts
T
Rekey 9351dec226 refactor: migrate API keys to config, extend Kline intervals, add DB extensions
Security:
- Move hardcoded Binance API key/secret from rest.ts to env.yaml (exchange config segment)
- Add ExchangeConfig validation in config/validators.ts
- Export typed exchange config from config/index.ts
- Update AGENTS/07-caveats.md to reflect the new policy

Kline intervals (add 3m / 2h / 6h / 8h / 1mon):
- TypeScript: update KlineInterval type, KLINE_INTERVAL_MS mapping, build_aggregates_sql refresh chain
- Python: sync KlineInterval Literal type, INTERVAL_TO_TABLE and INTERVAL_MS mappings, db_test table list
- SQL: add 5 continuous aggregate materialized views (klines_3m/2h/6h/8h/1mon) with indexes
- SQL: extend default kline_intervals in trading_pairs table
- SQL: add cross-sectional query indexes for klines_1d and klines_1w

DB:
- Enable pg_prewarm extension (backtest warmup)
- Enable pg_stat_statements extension (slow query monitoring)

Other:
- data/run/exchange.ts: graceful pgsql shutdown after backfill completes
- Config path: load from data/env.yaml (symlink) instead of project root
2026-06-14 18:45:01 +08:00

53 lines
1.9 KiB
TypeScript

import { logger } from "../utils/logger";
import { getAllPairs, updatePairLastBackfillTime } from '../service/pair';
import { upsertOrUpdateKlines } from "../service/kline";
import { Client } from '../exchanges/rest';
function getNowMinuteMS() {
const minuteMS = 1000 * 60;
return Math.floor(Date.now() / minuteMS) * minuteMS
}
const allPairs = await getAllPairs();
for (const pair of allPairs) {
const client = new Client("binance");
let lastBackfillTime = pair.last_backfill_time.getTime();
try {
while (lastBackfillTime < getNowMinuteMS()) {
console.log('lastBackfillTime', lastBackfillTime);
const klines = await client.fetchKlines(
pair.symbol,
pair.kline_interval,
lastBackfillTime,
500
);
console.log(`拉取到 ${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));
if (lastBackfillTime === lastK.openTime) {
break;
}
lastBackfillTime = lastK.openTime;
}
}
await new Promise((resolve) => {
setTimeout(resolve, Math.random() * 1000);
});
}
} catch (err) {
console.error("拉取失败:", err);
}
}
// 所有币种回补完成以后等待1秒关闭pgsql连接退出此进程
await new Promise((resolve) => setTimeout(resolve, 1000));
const { AppDataSource } = await import("../db/data-source");
if (AppDataSource.isInitialized) {
await AppDataSource.destroy();
console.log("pgsql 连接已关闭");
}
process.exit(0);