feat(data): 实现 Binance WebSocket 适配器与架构重构
- 新增 exchanges/ 模块:MarketDataFeed 统一接口、BaseExchangeAdapter 抽象基类、 BinanceAdapter 完整实现(WebSocket + REST) - WebSocket 层基于 binance 官方 SDK 的 WebsocketClient,自动多路复用与断线重连 - REST 层使用 MainClient(Spot),实现 fetchKlines 自动分页补拉 + fetchMarkets 元数据解析 - 数据标准化:Ticker/Trade/OrderBook/Kline 类型定义与 Binance 原生格式互转 - 引入 RxJS Subject 作为统一事件流管道,按 eventType 运行时路由分发 - 重构 config/:YAML 驱动配置加载 + 零依赖运行时校验(fail-fast) - 重构 db/:TypeORM DataSource 配置 + TimescaleDB K 线 Hypertable 实体 - 新增 utils/logger.ts:Pino 结构化日志(开发环境 pino-pretty 彩色输出) - 新增 env.yaml 作为 TS/Python 共享的统一环境配置源 - 删除旧版手写 SQL schema 与散落配置文件,收敛到 TypeORM 实体管理 - 安装 rxjs@7.8.2 依赖
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
// ============================================================
|
||||
// kline.entity.ts — TimescaleDB K 线 Hypertable 实体
|
||||
// ============================================================
|
||||
// 映射到 PostgreSQL klines 表(TimescaleDB hypertable)。
|
||||
// 不继承 CommonBaseEntity — 使用 @timescaledb/typeorm 的
|
||||
// @Hypertable / @TimeColumn 装饰器管理 TimescaleDB 特性。
|
||||
//
|
||||
// 关键 TimescaleDB 特性(由 @Hypertable 装饰器自动配置):
|
||||
// - 自动按 time 列做时间分区(by_range)
|
||||
// - 列式压缩(compress),7 天后自动执行
|
||||
// - 通过 ContinuousAggregate 生成高周期 K 线视图
|
||||
//
|
||||
// 注意:@timescaledb/typeorm v0.0.1 为实验版本,
|
||||
// 不支持空间分区(partitioning_column)。
|
||||
// 若需要空间分区,可通过 db/init-db/ 下的 SQL 脚本手动添加。
|
||||
// ============================================================
|
||||
|
||||
import { Hypertable, TimeColumn } from "@timescaledb/typeorm";
|
||||
import {
|
||||
Entity,
|
||||
PrimaryColumn,
|
||||
Column,
|
||||
Index,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from "typeorm";
|
||||
|
||||
/** K 线周期枚举 */
|
||||
export type KlineInterval =
|
||||
| "1m"
|
||||
| "5m"
|
||||
| "15m"
|
||||
| "30m"
|
||||
| "1h"
|
||||
| "4h"
|
||||
| "1d"
|
||||
| "1w";
|
||||
|
||||
/**
|
||||
* 1 分钟 K 线 Hypertable
|
||||
*
|
||||
* 存储交易所推送的 OHLCV 数据。写入使用 UPSERT
|
||||
* (ON CONFLICT DO UPDATE),已存在的 K 线只更新
|
||||
* high/low/close/volume 增量。
|
||||
*
|
||||
* 高周期 K 线(5m+)通过 TimescaleDB 连续聚合视图
|
||||
* 从 1m 表自动生成,无需单独建表。
|
||||
*/
|
||||
@Hypertable({
|
||||
compression: {
|
||||
compress: true,
|
||||
compress_orderby: "time DESC",
|
||||
compress_segmentby: "exchange, symbol, interval",
|
||||
policy: {
|
||||
schedule_interval: "365 days", // 365 天后自动压缩
|
||||
},
|
||||
},
|
||||
})
|
||||
@Index(["exchange", "symbol", "interval", "time"], { unique: true })
|
||||
@Entity("klines")
|
||||
export class Kline {
|
||||
/** K 线开盘时间(UTC)— @timescaledb/typeorm 自动标记为时间分区列 */
|
||||
@TimeColumn()
|
||||
@PrimaryColumn("timestamptz")
|
||||
time!: Date;
|
||||
|
||||
/** 交易所标识(binance / okx / bybit) */
|
||||
@Column("text")
|
||||
exchange!: string;
|
||||
|
||||
/** 交易对符号(如 BTCUSDT) */
|
||||
@Column("text")
|
||||
symbol!: string;
|
||||
|
||||
/** K 线周期(1m) */
|
||||
@Column("text")
|
||||
interval!: KlineInterval;
|
||||
|
||||
// ============================================================
|
||||
// OHLCV 价格数据(NUMERIC(20,8) 精度,与交易所对齐)
|
||||
// ============================================================
|
||||
|
||||
/** 开盘价 */
|
||||
@Column("numeric", { precision: 20, scale: 8 })
|
||||
open!: number;
|
||||
|
||||
/** 最高价 */
|
||||
@Column("numeric", { precision: 20, scale: 8 })
|
||||
high!: number;
|
||||
|
||||
/** 最低价 */
|
||||
@Column("numeric", { precision: 20, scale: 8 })
|
||||
low!: number;
|
||||
|
||||
/** 收盘价 */
|
||||
@Column("numeric", { precision: 20, scale: 8 })
|
||||
close!: number;
|
||||
|
||||
/** 成交量(base 币种) */
|
||||
@Column("numeric", { precision: 20, scale: 8 })
|
||||
volume!: number;
|
||||
|
||||
// ============================================================
|
||||
// 扩展字段(Binance 等交易所提供)
|
||||
// ============================================================
|
||||
|
||||
/** 成交额(quote 币种) */
|
||||
@Column("numeric", { precision: 20, scale: 8, nullable: true })
|
||||
quote_volume?: number;
|
||||
|
||||
/** 主动买入成交量(base 币种) */
|
||||
@Column("numeric", { precision: 20, scale: 8, nullable: true })
|
||||
taker_buy_base_vol?: number;
|
||||
|
||||
/** 主动买入成交额(quote 币种) */
|
||||
@Column("numeric", { precision: 20, scale: 8, nullable: true })
|
||||
taker_buy_quote_vol?: number;
|
||||
|
||||
/** 成交笔数 */
|
||||
@Column("integer", { nullable: true })
|
||||
trade_count?: number;
|
||||
|
||||
/** K 线是否已关闭(true = 该周期 K 线不再变化) */
|
||||
@Column("boolean", { default: true })
|
||||
is_closed!: boolean;
|
||||
|
||||
// ============================================================
|
||||
// 审计字段
|
||||
// ============================================================
|
||||
|
||||
/** 记录首次写入时间 */
|
||||
@CreateDateColumn({ type: "timestamptz", name: "created_at" })
|
||||
createdAt!: Date;
|
||||
|
||||
/** 记录最后更新时间 */
|
||||
@UpdateDateColumn({ type: "timestamptz", name: "updated_at" })
|
||||
updatedAt!: Date;
|
||||
}
|
||||
Reference in New Issue
Block a user