# tradehk 系统架构总览 > 返回:[tradehk 文档中心](./README.md) ## 技术栈 | 层次 | 技术 | 说明 | |------|------|------| | 前端框架 | React + TypeScript + Vite | 单页应用,实时更新 | | UI 组件 | TailwindCSS + shadcn/ui | 深色专业交易终端风格 | | 图表库 | lightweight-charts | TradingView 同款 K 线图库 | | 后端框架 | Node.js + tRPC | 类型安全的 API 层 | | 数据库 | MySQL(Drizzle ORM) | 信号持久化、用户配置 | | 实时数据 | Binance WebSocket + REST API | K 线、行情、账户数据 | | 通知推送 | 飞书 Webhook(Lark) | EWO 转换通知、信号通知 | | 部署 | Docker Compose + Nginx | Node.js + MySQL + 反向代理 | | 字体 | JetBrains Mono + Inter | 数字等宽字体 + 界面字体 | ## 目录结构 ``` tradehk/ ├── client/ # 前端代码 │ └── src/ │ ├── lib/ │ │ ├── indicators.ts # ★ 核心:所有技术指标计算 + 信号引擎 │ │ ├── types.ts # ★ 核心:所有 TypeScript 类型定义 │ │ ├── binanceApi.ts # Binance API 封装(前端) │ │ ├── tradeService.ts # 交易服务(下单、持仓管理) │ │ └── store.ts # 全局状态管理 │ ├── components/ # UI 组件 │ └── pages/ # 页面(Home、Login、NotFound) ├── server/ │ ├── _core/ │ │ ├── marketEngine.ts # ★ 核心:市场引擎(轮询、信号、EWO通知) │ │ ├── marketData.ts # Binance API 封装(服务端) │ │ ├── notification.ts # 通知服务基础层 │ │ ├── lark.ts # 飞书 Webhook 推送 │ │ └── dataApi.ts # 数据 API 路由 │ ├── db.ts # 数据库操作层 │ └── storage.ts # 存储抽象层 ├── shared/ │ └── types.ts # 共享类型(数据库 schema 导出) ├── drizzle/ │ ├── schema.ts # ★ 数据库表结构定义 │ └── *.sql # 迁移文件 ├── deploy/ │ ├── deploy.sh # 一键部署脚本 │ ├── nginx.conf # Nginx 反向代理配置 │ └── mysql/my.cnf # MySQL 配置 └── docker-compose.yml # 生产环境容器编排 ``` ## 数据流向 ### 1. 实时行情流(前端) ``` Binance WebSocket ↓ 订阅 K 线流(kline_10m 等) useMarketData Hook ↓ 更新 K 线缓存(最新300根) K 线图组件(lightweight-charts) ↓ 同步渲染 指标子图(EWO / MACD / AO / RSI 等) ``` ### 2. 信号检测流(服务端) ``` setInterval(每30秒,可配置 MARKET_ENGINE_POLL_MS) ↓ buildUserRuntimeConfigs() ← 从 MySQL 读取用户配置和监控列表 ↓ refreshCacheForPairs() ← 从 Binance REST API 拉取最新220根K线 ↓ evaluateSignalsForUser() ← 调用 generateSignal() 计算信号 ↓ hasSignalRecord() ← 去重检查(同币同方向同时间戳) ↓ saveSignal() ← 持久化到 MySQL signals 表 ↓ maybePushSignalLark() ← 频控后推送飞书通知 ``` ### 3. EWO 转换检测流(服务端) ``` 每次引擎轮询 ↓ evaluateEwoTurnForUser() ↓ 取最后两根已收线K线的 EWO 值 ↓ 比较颜色(red/green)是否发生变化 ↓ 计算上一阶段持续时间和K线根数 ↓ consumeSharedEwoTurnDedupeSlot() ← 去重(同币同方向同时间戳只推一次) ↓ pushLarkWebhookMessage() ← 推送飞书通知 ``` ## 关键配置参数 | 参数 | 默认值 | 说明 | |------|--------|------| | `MARKET_ENGINE_POLL_MS` | 30000 | 引擎轮询间隔(毫秒),最小10秒 | | `MARKET_SUMMARY_INTERVAL_HOURS` | 4 | 定期汇总推送间隔(小时) | | `CACHE_CANDLE_LIMIT` | 300 | 每对缓存K线数量上限 | | `DEFAULT_SYMBOL_INTERVAL` | 10m | 默认K线周期 | | `signalLarkThrottleMinutes` | 10 | 信号推送频控(分钟) | ## 设计风格 tradehk 采用**精英深色仪表盘**风格(Elite Dark Dashboard): - **主背景**:`#0A0E17`(深海蓝黑) - **主色调**:`#F0B90B`(Binance 黄金) - **涨势色**:`#0ECB81`(清新绿) - **跌势色**:`#F6465D`(警示红) - **数字字体**:JetBrains Mono(等宽,确保对齐) - **界面字体**:Inter(清晰易读) ## 相关文档 - [指标引擎详解](./指标引擎详解.md) - [信号评分引擎](./信号评分引擎.md) - [EWO转换检测机制](./EWO转换检测机制.md) - [部署运维指南](./部署运维指南.md) --- ## 附录:数据说明与补充 本文档旨在对 tradehk 系统的核心概念、数据结构及关键参数进行深入阐述,以补充系统架构概览中的信息。内容涵盖了关键指标的量化定义、实际应用场景、数据格式规范、参数配置建议以及常见的设计与实践误区,旨在为开发者和使用者提供更全面的参考。 ### 1. 核心指标量化详解 系统中的技术指标是信号生成与市场分析的基础。下表对核心指标的计算方法、数据属性及应用进行了详细说明。 | 指标名称 | 计算公式 (LaTeX) | 数据范围 | 单位 | 精度要求 | 数据来源 | | :--- | :--- | :--- | :--- | :--- | :--- | | **EWO** | $$ EWO = SMA(Close, 5) - SMA(Close, 34) $$ | (-∞, +∞) | 计价货币 | 4位小数 | 原始 K 线收盘价 | | **MACD** | $$ MACD = EMA(Close, 12) - EMA(Close, 26) $$ | (-∞, +∞) | 计价货币 | 8位小数 | 原始 K 线收盘价 | | **AO** | $$ AO = SMA(\frac{H+L}{2}, 5) - SMA(\frac{H+L}{2}, 34) $$ | (-∞, +∞) | 计价货币 | 8位小数 | 原始 K 线高低价 | | **RSI** | $$ RSI = 100 - \frac{100}{1 + \frac{AvgGain}{AvgLoss}} $$ | [0, 100] | / | 2位小数 | 原始 K 线收盘价 | #### 1.1 指标应用场景 - **EWO (艾略特波浪振荡器)** 1. **趋势识别**:EWO 值持续为正且不断增大,通常预示着强劲的上升趋势;反之,持续为负且不断减小,则预示着下降趋势。可用于构建[趋势跟踪](../../wiki/名词解释/趋势跟踪.md)策略的入场过滤器。 2. **背离交易**:当价格创出新高而 EWO 未能创出新高时,形成“顶背离”,是潜在的卖出信号。反之,价格新低而 EWO 未创新低,形成“底背离”,是潜在的买入信号。 - **MACD (平滑异同移动平均线)** 1. **金叉/死叉交易**:快线(DIF)由下向上穿越慢线(DEA)形成“金叉”,为买入信号;由上向下穿越形成“死叉”,为卖出信号。这是最经典的[动量策略](../../wiki/名词解释/动量策略.md)之一。 2. **零轴穿越**:MACD 柱状图(Histogram)由负转正(穿越零轴),表明市场情绪由空转多,可作为多头开仓的辅助判断;反之则为空头信号。 ### 2. 关键数据结构定义 系统的数据流始于标准化的 K 线数据,并最终生成结构化的交易信号。明确其数据格式对于系统对接与二次开发至关重要。 #### 2.1 K线数据 (Candlestick Data) K 线数据是所有技术分析的基础,系统直接采用 Binance API 的标准格式。 - **数据格式**: `Array` - **示例**: `[ 1499040000000, "4261.48000000", "4261.48000000", "4261.48000000", "4261.48000000", "1.48630000", 1499644799999, ... ]` - **字段说明**: | 索引 | 字段名 | 数据类型 | 描述 | | :--- | :--- | :--- | :--- | | 0 | Open time | `number` | K 线开盘时间戳 (毫秒, UTC) | | 1 | Open | `string` | 开盘价 | | 2 | High | `string` | 最高价 | | 3 | Low | `string` | 最低价 | | 4 | Close | `string` | 收盘价 | | 5 | Volume | `string` | 成交量 (基础资产) | | 6 | Close time | `number` | K 线收盘时间戳 (毫秒, UTC) | #### 2.2 交易信号 (Signal) 当指标满足特定条件时,信号引擎会生成一条记录,并持久化至数据库。 - **数据格式**: `JSON Object` - **字段说明**: | 字段名 | 数据类型 | 描述 | 示例 | | :--- | :--- | :--- | :--- | | `id` | `number` | 唯一标识符 | `101` | | `userId` | `number` | 关联的用户 ID | `1` | | `symbol` | `string` | 交易对 | `"BTCUSDT"` | | `interval` | `string` | K 线周期 | `"10m"` | | `direction` | `"LONG" \| "SHORT"` | 信号方向 | `"LONG"` | | `timestamp` | `string` | 信号触发时间 (ISO 8601) | `"2026-03-06T12:30:00.000Z"` | | `createdAt` | `string` | 记录创建时间 (ISO 8601) | `"2026-03-06T12:30:03.123Z"` | ### 3. 系统参数配置参考 合理的参数配置是确保系统稳定、高效运行的关键。下表提供了对 `docker-compose.yml` 中核心环境变量的配置建议。 | 参数 | 推荐值 | 取值范围 | 说明 | | :--- | :--- | :--- | :--- | | `MARKET_ENGINE_POLL_MS` | 15000 | `10000` - `60000` | 引擎轮询间隔。过短会增加 API 请求频率,可能触发风控;过长则降低信号时效性。15秒是时效性与资源消耗的良好平衡点。 | | `MARKET_SUMMARY_INTERVAL_HOURS` | 6 | `1` - `24` | 定期市场总结推送的间隔。对于活跃交易者,可缩短至 2-4 小时;对于长期观察者,可延长至 8-12 小时。 | | `CACHE_CANDLE_LIMIT` | 300 | `250` - `1000` | K 线缓存数量。该值需覆盖所有指标计算所需的最大周期(如 MACD 的 26周期、EWO 的 34周期)。300根可满足大部分常用指标计算。 | | `signalLarkThrottleMinutes` | 5 | `0` - `60` | 同一交易对同方向信号的推送冷却时间。设为 0 表示不节流。建议设为 5-10 分钟,避免因市场震荡导致重复的[信号轰炸](../../wiki/名词解释/信号轰炸.md)。 | ### 4. 常见误区与正确理解 1. **误区:轮询间隔越短,信号越及时。** **正确理解**:信号的及时性受限于 K 线周期。对于 `10m` 周期的 K 线,只有在当前 K 线收盘后,其指标值才能最终确定。因此,将轮询间隔设为远小于 K 线周期的值(如1秒)并无实际意义,反而会因请求未收盘 K 线而产生大量无效计算和 API 调用。轮询间隔应与[交易策略](../../wiki/名词解释/交易策略.md)的反应速度相匹配。 2. **误区:前端计算的指标与服务端完全一致。** **正确理解**:前端和服务端在 K 线数据的获取和更新机制上存在差异。前端通过 [WebSocket](../../wiki/名词解释/WebSocket.md) 实时更新最新价格,导致当前 K 线不断变化;而服务端在固定时间间隔通过 [REST API](../../wiki/名词解释/REST API.md) 拉取已收盘的 K 线快照。因此,只有对于已完全收盘的 K 线,两者的指标计算结果才能保证一致。 3. **误区:EWO 颜色转换即是反转信号。** **正确理解**:EWO 由绿转红或由红转绿,仅表示短期动能(5周期均线)与长期动能(34周期均线)的相对强弱发生了变化,可视为潜在的趋势转折“警示”,而非确定的反转信号。它需要结合价格行为、成交量或其他指标进行综合判断,以过滤掉盘整行情中的大量“毛刺”信号。