38 Commits

Author SHA1 Message Date
Rekey 6292c63b7c fix: 聚合刷新改为按 pair 计数精确触发(方案 C)
问题:同一分钟多个 pair 的 1m K 线先后入库,旧代码每个 pair
各自触发 checkAndRefresh,先到达的 pair 刷新时其他 pair 数据
未入库,导致聚合视图不完整。

方案:用 Map<openTime, Set<pairKey>> 收集同分钟所有 pair,
全部到齐后统一触发一次 checkAndRefresh。

- start.ts: kline:saved 改为收集模式,readyCount 到齐才触发
- start.ts: backfillComplete 门控避免启动期 readyCount 不稳定
- start.ts: pairKey = exchange:type:symbol,与 pair:ready 对齐
- aggregate.ts: 删除 refreshLocks 去重锁,编排层已保证单次调用
2026-06-19 08:26:11 +08:00
Rekey 9d1955e0a0 feat: checkAndRefresh 聚合刷新实现,含完整 DB 写入链路
- 接入 AppDataSource,执行 CALL refresh_continuous_aggregate
- 扩展周期到 12 个(3m → 1mon),对齐 03-continuous-aggregates.sql
- 回溯公式 lookbackPeriods: 100 / √(ms/5min),下限 3
- 精确计算 windowEnd/windowStart,不碰未闭合桶
- 失败收集后 throw AggregateError,阻止 aggregate:refreshed 误发
- 文档同步更新:步骤 9 从暂缓 → 完成
2026-06-19 01:06:41 +08:00
Rekey 10e2364cf1 fix(aggregate): 修正聚合刷新触发时机 — 桶闭合时触发而非桶首
- aggregate.ts: openTime % ms === 0 → (openTime + 60_000) % ms === 0
  确保桶内最后一根1m K线到达(桶已闭合)时才触发聚合刷新
- AGENTS.md: 新增 K线 time 字段与 time_bucket 边界说明
- ARCHITECTURE.md: 新增 §4.3 聚合时间边界与刷新时机 小节
- websocket-realtime.md: 同步更新 checkAndRefresh 判定公式和表格
2026-06-19 00:27:02 +08:00
Rekey ab3904f627 chore: #7 kline:tick 微回补文档同步 + ws.ts 显式判断
- ws.ts: !msg.kline.final → msg.kline.final === false 更清晰
- websocket-realtime.md: 事件表/启动流程/角色表补上 kline:tick,#7 标记已修复
- tech-debt.md: #10 kline:tick 标记已完成
2026-06-18 23:23:50 +08:00
Rekey 6374159e53 feat(ws): kline:tick 微回补机制消除回补→WS衔接缺口 (#7)
- bus.ts: 新增 kline:tick 事件类型
- ws.ts: toKline() 提取;final=false 时 emit kline:tick
- start.ts: 监听 kline:tick,首次 tick 触发 backfillKline 微回补
- backfill.ts: 回溯10分钟注释说明
2026-06-18 23:14:13 +08:00
Rekey 2c7d993049 feat(data): 回补回溯10分钟避免K线缺口 + 新增 getPairBySymbol 查询函数 2026-06-18 22:51:03 +08:00
Rekey 4809ff7c23 docs: 更新 ARCHITECTURE.md 对齐实际代码,融入合约 type 字段设计
- §4.3: 5列复合PK含type、type vs .P后缀设计决策对比表
- §4.5: 替换远期设计为实际 BinanceRestClient/FuturesRestClient + rest-registry 自动路由
- §4.6: 对齐实际 backfill.ts 增量回补 + start.ts bus 事件编排
- §6.1: conflictPaths 4列→5列含type
- §6.3: 替换自动迁移为 synchronize:false + init-db SQL脚本
- 移除不存在的符号实体、虚假CLI参数、ccxt/rxjs等远期内容
- 删除 PLAN-add-futures-data.md(内容已全部融入)
- rest.ts: 补充 exchange 字段行为注释
2026-06-18 21:47:10 +08:00
Rekey 0a6198b0a2 chore: 清偿技术债务 P2 区 #8 #9 #11 #12 #13 #14
- exchanges/index.ts 拆分为 rest-registry + ws-manager,降级为 re-export hub
- 移除 fetchMarkets() 及 MarketInfo 类型(交易对人工筛选,无需自动注册)
- 移除 ConnectionState 死代码
- aggregate.ts: console.log → logger.debug 统一日志
- 删除 data/test.ts(SDK 临时调试脚本)
- ARCHITECTURE.md 更新反映当前简化架构
- #12 写入缓冲暂不实施:8 交易对瞬时 8 tps,无压力
2026-06-18 20:33:23 +08:00
Rekey 34632b6c33 refactor: #5 catch 块收敛至 RestError.from() 2026-06-18 19:20:32 +08:00
Rekey ca9952f621 feat: #5 REST 请求异常分类,RestError + try/catch + 错误码注释 2026-06-18 19:13:50 +08:00
Rekey 66e0689cfb docs: #6 标记不修复并新增负载模型
- tech-debt.md: #6 日志 resolveCaller 标记为不修复,理由:日志量由 K 线间隔锁定,
  500 交易对仅 ~8 条/秒,caller 字段对生产排障有价值
- ARCHITECTURE.md §10.4: 新增负载模型(日志量/DB 写入/内存),
  为后续优化决策提供量化参照
2026-06-18 18:38:41 +08:00
Rekey 77ffc67a25 fix(data): P1 #4 WS 异常事件监听 + #7 tradingPairs 类型修复
- #4: ws.ts 新增 exception 事件监听,logger.error + system:error
- #7: exchange.entity.ts 使用 import type 破循环依赖,unknown[] → TradingPair[]
2026-06-18 18:20:42 +08:00
Rekey 0e449d3c5f fix(backfill): 修复回补超时竞态 + 首批单元测试 + 技术债务文档
- backfill.ts: clearTimeout 移入 try/catch 分支内部,防止 upsert 慢被超时误杀
- backfill.ts: setTimeout 回调和 catch 块各加 status 先到先得守卫
- backfill.ts: 注释补充容错策略(Binance SDK 僵死 → exit 重启)
- tests: 新增 4 文件 63 用例(utils/bus/convert-kline/config)
- docs: tech-debt.md 技术债务清单, testing.md 测试方案
2026-06-18 15:34:02 +08:00
Rekey ff4c66aee9 fix(ws): kline 处理链添加 .catch() 错误处理 + system:error 事件
- kline:update / kline:saved 两处 handler 添加 .catch()
- 失败时 logger.error + bus.emit('system:error'),供 Telegram 等通知
- utils/bus.ts 新增 system:error 事件类型
- docs/websocket-realtime.md 同步更新:已知问题 #1 → 已修复
2026-06-18 14:52:28 +08:00
Rekey 3b363bf95a fix(ws): pair:ready/pair:failed 事件 type 字段改为 PairType
- bus.ts 中 pair:ready / pair:failed 的 type 从 string 收窄为 PairType
- start.ts 去掉 type as 'spot'|'um'|'cm' 类型断言
2026-06-18 14:22:19 +08:00
Rekey 555f9345f1 feat(ws): WebSocket 实时管线基础设施
- BaseWsClient 抽象基类 + BinanceWsClient 实现
- watchKline / watchKlines / unWatchKline 订阅管理
- start.ts 编排入口:三层事件链 kline:update → saved → aggregate:refreshed
- backfill / pair / aggregate service 模块(被动调用)
- bus 事件类型扩展(kline:saved, aggregate:refreshed, ws:stale)
- 文档:WebSocket 实时行情技术方案 + kline:tick 事件设计(#7)
2026-06-18 14:17:41 +08:00
Rekey 524299ac8e feat(ws): 消息总线提升 + last_ws_time 迁移 + WS 方案更新
- utils/bus.ts: 消息总线提升到公共层,新增 kline:update 事件
- migration: trading_pairs 新增 last_ws_time 列
- exchanges: convertBinanceKline 导出供 WS 复用
- docs: WS 方案更新为 bus 驱动架构 + exchanges 层封装设计
- AGENTS.md: 新增"倾向于 ≠ 执行"约定

实施进度(11 步中完成 4 步):
   1. last_ws_time 字段 + 迁移
   2. utils/bus.ts 消息总线
   3. updatePairWsTime()
   4. backfill 服务 + emit pair:ready
   5. BaseWsClient 抽象类
   6. BinanceWsClient
   7. watchKlines() 注册表
   8. run/ws.ts
   9. aggregate.ts
   10. package.json ws 脚本
2026-06-18 11:00:58 +08:00
Rekey cda8786320 refactor(exchange): 回补逻辑抽离为 backfill service,exchange 驱动化
- exchange.ts 精简为入口:调用 backfillKlines + 监听 event-bus
- backfill.ts/pair.ts: exchange 从硬编码改为 pair.exchange.name
- utils/index.ts: 新增 wait() 工具
- 清理调试代码
2026-06-18 09:37:46 +08:00
Rekey 8c93354f4f feat(ws): 回补服务抽取 + 消息总线 + WebSocket 技术方案
- service/backfill.ts: 回补逻辑从 exchange.ts 独立为可复用服务,集成 event-bus
- service/event-bus.ts: TypedEventBus 进程内消息总线,解耦回补与 WS 订阅
- utils/index.ts: getNowMinuteMS/getPrevMinuteMS 公共工具函数
- docs/websocket-realtime.md: WebSocket 实时行情完整技术方案
- 删除 service/bnkline.ts: 冗余封装已废弃
2026-06-18 08:57:10 +08:00
Rekey e252cbca9b feat(logger): 日志系统升级 — 双通道输出 + caller/traceId + 脱敏
- 开发环境 pino-pretty 彩色输出,生产环境 pino-roll 滚动写入 /var/log/trade/data
- mixin 自动附加调用位置(caller)和 traceId 到每条日志
- redact 自动脱敏 api_key/api_secret 等敏感字段
- 新增 withTrace() 支持异步上下文 traceId 传递
- 新增 pino-roll 依赖
2026-06-17 12:05:48 +08:00
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
Rekey ebaef5042e refactor(exchanges): fetchKlines 改为 params 对象签名,新增 type/exchange 参数
- 新增 FetchKlinesParams 接口统一 fetchKlines 参数(exchange/type/symbol/startTime/limit/endTime)
- BaseRestClient 抽象方法 + MarketDataFeed 接口改为 params 对象签名
- BinanceRestClient / BinanceFuturesRestClient 由调用方传入 type,不再硬编码 spot/um
- index.ts 新增静态 fetchKlines(params) 便捷函数,按 exchange+type 自动路由
- exchange.ts / bnkline.ts 调用方适配新签名
- 初始化 SQL 补充 BNBUSDT/SOLUSDT 合约交易对
2026-06-16 19:02:16 +08:00
Rekey 705a2f6ea0 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 空函数
2026-06-16 18:39:40 +08:00
Rekey 1adb093100 refactor(data/exchanges): 多子类架构 + 工厂入口
- 每个交易所独立子类:BinanceRestClient extends BaseRestClient
- 统一入口 createRestClient(exchangeId) 工厂函数
- KLINE_INTERVAL_MS 移至 constants.ts
- fetchKlines 签名统一为 (symbol, startTime, limit?, endTime?)
- throttle 限流实际生效
- convertBinanceKline interval 参数化
- 删除 filterConsecutive 死代码
- 更新 run/exchange.ts 和 service/bnkline.ts 调用方
2026-06-16 17:53:36 +08:00
Rekey b540b7611c chore: 合并 AGENTS 配置为单文件 AGENTS.md,精简 reasonix.toml
- 删除 AGENTS/ 目录下 8 个拆分 .md 文件,统一为根目录 AGENTS.md
- 删除 .reasonix.toml,配置合并到 reasonix.toml
- reasonix.toml 精简为仅保留实际生效的 3 项配置
- KlineInterval 类型导出源从 kline.entity 改到 ../../types
2026-06-16 13:32:05 +08:00
Rekey d8a2f4bb52 refactor: 统一 TypeORM CLI 数据源配置,执行废弃列清理迁移
- data/db/data-source-cli.cjs → .ts,复用 config 模块的 pgsql 配置
- 新增迁移 CleanupTradingPairDeprecatedColumns,删除 trading_pairs 表三个废弃列
- reasonix.toml: model 升级 deepseek-pro,启用中文
2026-06-16 12:29:23 +08:00
Rekey f755f76ed1 补充 pair.ts 函数 JSDoc 注释 2026-06-15 23:25:06 +08:00
Rekey b4c7636731 添加 USDT-M 合约数据支持(配置层 + 清理多余字段)
- 配置层:env.yaml 新增 binance_futures API Key 段,validators + config 同步
- 清理 TradingPair 实体:删除 kline_interval、kline_intervals、kline_synthesis_enabled
- 删除 fetchKlines 系列函数的 interval 参数,硬编码为 1m
- 更新 SQL seed 数据、example、base_rest 接口、types 接口
- 新增 AGENTS/08-boundaries.md 执行纪律
- 新增 PLAN-add-futures-data.md 方案文档
2026-06-15 23:24:21 +08:00
Rekey 6708abaf56 feat(data/service): add bnkline.ts — Binance REST client K-line wrapper
封装 Client(多交易所 REST 客户端)的 binance 实现,
提供 fetchKlines 服务层函数,复用限流、数据转换、
连续性过滤等既有逻辑,参数顺序更自然(endTime 在 limit 前)。
2026-06-14 18:50:42 +08:00
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
Rekey a9c45cce39 chore: add Reasonix config files and env.yaml symlink
- .reasonix.toml / reasonix.toml — Reasonix 工具配置
- data/env.yaml — 软链接指向项目根目录 env.yaml(统一配置加载路径)
2026-06-14 18:44:43 +08:00
Rekey edc50e8809 feat: 新增2h/6h时间框架支持,策略重构为增量指标计算
- 数据层: build_aggregates_sql 新增 2h/6h 聚合视图,默认起始时间调整为 2017-05
- 模型层: KlineInterval 类型扩展 2h/6h,DataService 新增对应表名和毫秒映射
- 指标层: 新增 incremental.py 增量指标模块 (EmaInc/AtrInc/RsiInc/BbInc),O(1) per bar
- 策略重构: long_short.py 和 regime_all.py 从批量 ema/atr 迁移至增量指标,避免每 bar 重复全量计算
- regime 探测器: RegimeDetector3 改为增量 EMA200,detect() 接口简化
- 回测扩展: regime_timeframe_comparison 从 4h/1d 扩展至 2h/4h/6h/1d
- 新增示例: multi_strategy_report, vol_break_compare/periods, intraday_explore, top3_trades 等分析脚本
2026-06-13 19:30:25 +08:00
Rekey 72a53cc86d feat(data): TimescaleDB 连续聚合逐月刷新脚本 & 基础设施改进
- 新增 build_aggregates_sql.ts:按月粒度刷新 klines 聚合视图链 (5m→1w),支持 dry-run/execute 模式

- 新增 run_exchange.sh 交易所数据拉取脚本

- DataSource 启动时输出配置概要,Binance REST 客户端添加超时配置

- 开发依赖新增 ts-node,env.yaml 更新数据库地址
2026-06-11 15:48:29 +08:00
Rekey 309b11ae30 fix(db): TypeORM 压缩配置对齐 SQL DDL,新增 TimescaleDB 初始化脚本
- kline.entity.ts: compress_segmentby 移除 interval(基表固定 1m 无需分段),schedule_interval 365d→30d 与 init-db SQL 一致
- data-source.ts: 生产环境关闭 synchronize,以 init-db SQL 脚本为建表唯一来源
- 新增 data/db/init-db/ 初始化 SQL 链:
  01-timescaledb.sql — 启用 TimescaleDB 扩展
  02-init-tables.sql — 核心业务表 + klines hypertable(7d chunk / 30d 压缩)
  03-continuous-aggregates.sql — 分层连续聚合视图(5m→15m→30m→1h→4h→1d→1w)
2026-06-10 20:03:00 +08:00
Rekey 5e385547c7 refactor(data): 重构交易所适配器,修复 Kline 实体复合主键
- 废弃旧 adapter 体系 (base/binance/types.ts),新增 base_rest/rest.ts
  基于 Binance 官方 SDK 实现 REST K 线拉取
- Kline 实体改为四列复合主键 (exchange/symbol/interval/time),
  修复单列 time PK 导致的跨 symbol 写入冲突
- 新增 filterConsecutive():K 线连续性过滤,首缺口截断策略
- 新增 service/kline.ts:批量 UPSERT K 线入库
- 新增 types/ 共享类型定义、example/ 示例、run/ 运行脚本
2026-06-08 18:18:16 +08:00
Rekey 85a0031a78 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 依赖
2026-06-08 01:24:48 +08:00
Rekey e91cad79e6 feat(data): 实现配置表 CRUD 与 Schema 初始化拆分
- 新增 data/db/ 数据库访问层:pool 管理、类型定义、Zod 校验、参数化 SQL 查询
- 新增 data/db/config-crud.ts:MonitoredSymbolsRepo / ExchangeConfigRepo / AppConfigRepo 三个 CRUD 服务类
- 新增 data/config.ts:中心化配置模块,零依赖 .env 解析 + Zod 校验
- 新增 data/schema/:klines.sql + config.sql 参考 DDL
- 新增 data/exchanges/:交易所类型定义与 Binance WebSocket 封装
- 新增 data/run/:交易所连接启动入口
- 重构 data/init-db/:001_init.sql 仅保留 TimescaleDB + klines,配置表拆分至 002_config.sql
- 更新 docker-compose.yml:挂载 init-db 初始化脚本
2026-06-07 20:46:35 +08:00
Rekey 10e13ae8da chore: 初始化项目骨架 — 数据模块依赖配置、TimescaleDB 建表脚本、Docker Compose 编排 2026-06-06 19:56:01 +08:00