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
This commit is contained in:
Rekey
2026-06-14 18:45:01 +08:00
parent a9c45cce39
commit 9351dec226
15 changed files with 311 additions and 27 deletions
+26 -5
View File
@@ -11,7 +11,7 @@
// const ds = new DataSource({ ...pgsql });
// const redisClient = new Redis(redis.url);
//
// 配置文件位置:<project_root>/env.yaml
// 配置文件位置:data/env.yaml(软链接 → 项目根目录 env.yaml)
// TypeScript / Python 模块共享同一份配置。
// ============================================================
@@ -39,12 +39,14 @@ function getProjectRoot(): string {
}
/**
* 项目根目录读取 env.yaml 并解析为原始对象。
* 读取 data/env.yaml(软链接指向项目根目录 env.yaml并解析为原始对象。
* 文件不存在时抛出明确错误,不做静默降级。
*/
function loadYamlConfig(): unknown {
const root = getProjectRoot();
const yamlPath = resolve(root, "env.yaml");
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// config/index.ts → config/ → data/env.yaml
const yamlPath = resolve(__dirname, "../env.yaml");
let content: string;
try {
@@ -52,7 +54,7 @@ function loadYamlConfig(): unknown {
} catch {
throw new Error(
`[config] 无法读取配置文件: ${yamlPath}\n` +
`请确保项目根目录存在 env.yaml(可参考 data/.env.example 的结构)`,
`请确保 data/env.yaml 软链接指向项目根目录的 env.yaml`,
);
}
@@ -131,6 +133,19 @@ export const logging = {
pretty: rawConfig.logging.node_env === "development",
} as const;
/**
* 交易所 API 密钥配置
*
* 按交易所 ID 索引,目前仅 binance。
* 新增交易所时在 env.yaml 的 exchange 段添加对应子配置即可。
*/
export const exchange = {
binance: {
apiKey: rawConfig.exchange.binance.api_key,
apiSecret: rawConfig.exchange.binance.api_secret,
},
} as const;
// ============================================================
// 4. 工具:运行时打印配置概要(不含敏感信息)
// ============================================================
@@ -150,6 +165,12 @@ export function printConfigSummary(): void {
url: redis.url.replace(/\/\/.*@/, "//***@"), // 隐藏密码
publishEnabled: redis.publishEnabled,
},
exchange: {
binance: {
apiKey: exchange.binance.apiKey.slice(0, 6) + "***",
apiSecret: "***",
},
},
logging: {
level: logging.level,
nodeEnv: logging.nodeEnv,