feat: 接入 USDT-M 合约数据 — type 字段方案

- PairType 定义移至 types/kline.ts (spot/um/cm)
- Kline 接口新增 type 字段,全链路透传
- klines 5列复合主键 (exchange, symbol, type, interval, time)
- 拆出 BinanceFuturesRestClient (USDMClient)
- exchanges/index.ts 注册 binance_futures
- trading_pairs 唯一约束加 type,种子数据加合约对
- 12个连续聚合视图 SELECT/GROUP BY/INDEX 加 type
- 清理 bnkline.ts 废弃代码和 pair.ts 空函数
This commit is contained in:
Rekey
2026-06-16 18:39:40 +08:00
parent 1adb093100
commit 705a2f6ea0
15 changed files with 442 additions and 209 deletions
+69 -3
View File
@@ -1,9 +1,9 @@
import { MainClient, type Kline as BinanceRestKline } from "binance";
import { MainClient, USDMClient, type Kline as BinanceRestKline } from "binance";
import { logger } from "../../utils/logger";
import { exchange } from "../../config";
import { BaseRestClient } from "../base";
import type { Kline, MarketInfo, KlineInterval } from "../../types";
import type { Kline, MarketInfo, KlineInterval, PairType } from "../../types";
// ============================================================
// Binance REST K 线 → 本系统标准化 Kline 转换
@@ -32,6 +32,7 @@ function convertBinanceKline(
raw: BinanceRestKline,
symbol: string,
interval: KlineInterval,
type: PairType,
): Kline {
const [
openTime,
@@ -51,6 +52,7 @@ function convertBinanceKline(
return {
exchange: "binance",
symbol,
type,
interval,
openTime,
closeTime,
@@ -130,7 +132,7 @@ export class BinanceRestClient extends BaseRestClient {
// 按 openTime 升序排序(防御性),转换为标准化 Kline
return rawKlines
.map((k) => convertBinanceKline(k, symbol, "1m"))
.map((k) => convertBinanceKline(k, symbol, "1m", "spot"))
.sort((a, b) => a.openTime - b.openTime);
}
@@ -139,3 +141,67 @@ export class BinanceRestClient extends BaseRestClient {
return [];
}
}
// ============================================================
// BinanceFuturesRestClient — USDT-M 永续合约
// ============================================================
export class BinanceFuturesRestClient extends BaseRestClient {
readonly exchange = "binance_futures";
private client: USDMClient;
constructor() {
super();
this.client = new USDMClient(
{
api_key: exchange.binanceFutures.apiKey,
api_secret: exchange.binanceFutures.apiSecret,
},
{ timeout: 3000 },
);
}
/**
* 拉取 USDT-M 永续合约 1m K 线。
*
* USDMClient.getKlines() 返回与 MainClient 同构的 12 元组,
* convertBinanceKline 直接复用,type 固定为 'um'。
*/
async fetchKlines(
symbol: string,
startTime: number,
limit?: number,
endTime?: number,
): Promise<Kline[]> {
const effectiveLimit = limit ?? this.config.defaultLimit;
const safeLimit = Math.min(effectiveLimit, 1000);
await this.throttle(`${symbol}:1m`);
const rawKlines = await this.client.getKlines({
symbol,
interval: "1m",
startTime,
endTime,
limit: safeLimit,
});
logger.debug(
{ symbol, interval: "1m", startTime, endTime, limit: safeLimit },
"[binance_futures] fetchKlines 请求参数",
);
if (!rawKlines || rawKlines.length === 0) {
return [];
}
return rawKlines
.map((k) => convertBinanceKline(k, symbol, "1m", "um"))
.sort((a, b) => a.openTime - b.openTime);
}
async fetchMarkets(): Promise<MarketInfo[]> {
return [];
}
}