V5.4 Strategy Factory 数据合约文档
V5.4 策略工厂完整数据合约,包含所有表结构、API 接口、字段约束、迁移方案
V5.4 Strategy Factory 数据合约文档
版本:v1.0
日期:2026-03-11
作者:露露
状态:待范总 + 小范 + 小周 Review
原则:设计优先于实现;可扩展性优先于性能;字段语义必须清晰
1. 设计原则
- 数据优先:所有结构在编码前确定,不在编码过程中随意增减字段
- 可扩展:预留
schema_version,参数结构变更时向后兼容 - 可溯源:历史记录永久保留,所有状态变更记录时间戳
- 冗余快照:关键关联字段(如策略名)在写入时做快照,防止改名后历史数据断层
- 执行与展示分离:执行相关字段和展示/说明字段在表设计和代码中明确区分,避免相互干扰
2. 核心表结构
2.1 strategies 表(策略配置主表)
每一行代表一个策略实例(一个币种 × 一套参数配置)。
CREATE TABLE strategies (
-- ─── 标识 ──────────────────────────────────────────────────
strategy_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
display_name TEXT NOT NULL, -- 用户自定义名称,可改
-- ─── 版本控制 ────────────────────────────────────────────────
schema_version INT NOT NULL DEFAULT 1, -- 参数结构版本,升级时递增
-- ─── 状态 ────────────────────────────────────────────────────
status TEXT NOT NULL DEFAULT 'running'
CHECK (status IN ('running', 'paused', 'deprecated')),
status_changed_at TIMESTAMP, -- 最近一次状态变更时间
last_run_at TIMESTAMP, -- 最近一次 Worker 评估时间(心跳用)
deprecated_at TIMESTAMP, -- 废弃时间(nullable)
-- ─── 基础配置(执行层)────────────────────────────────────────
symbol TEXT NOT NULL
CHECK (symbol IN ('BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'XRPUSDT')),
direction TEXT NOT NULL DEFAULT 'both'
CHECK (direction IN ('long_only', 'short_only', 'both')),
-- ─── CVD 窗口(执行层)────────────────────────────────────────
cvd_fast_window TEXT NOT NULL DEFAULT '30m'
CHECK (cvd_fast_window IN ('5m', '15m', '30m')),
cvd_slow_window TEXT NOT NULL DEFAULT '4h'
CHECK (cvd_slow_window IN ('1h', '4h')),
-- ─── 四层权重(执行层,合计必须 = 100)────────────────────────
weight_direction INT NOT NULL DEFAULT 55
CHECK (weight_direction BETWEEN 10 AND 80),
weight_env INT NOT NULL DEFAULT 25
CHECK (weight_env BETWEEN 5 AND 60),
weight_aux INT NOT NULL DEFAULT 15
CHECK (weight_aux BETWEEN 0 AND 40),
weight_momentum INT NOT NULL DEFAULT 5
CHECK (weight_momentum BETWEEN 0 AND 20),
-- 应用层校验:weight_direction + weight_env + weight_aux + weight_momentum = 100
-- ─── 入场阈值(执行层)────────────────────────────────────────
entry_score INT NOT NULL DEFAULT 75
CHECK (entry_score BETWEEN 60 AND 95),
-- ─── 四道 Gate(执行层)───────────────────────────────────────
gate_obi_enabled BOOL NOT NULL DEFAULT TRUE,
obi_threshold FLOAT NOT NULL DEFAULT 0.3
CHECK (obi_threshold BETWEEN 0.1 AND 0.9),
gate_whale_enabled BOOL NOT NULL DEFAULT TRUE,
whale_cvd_threshold FLOAT NOT NULL DEFAULT 0.0
CHECK (whale_cvd_threshold BETWEEN -1.0 AND 1.0),
gate_vol_enabled BOOL NOT NULL DEFAULT TRUE,
atr_percentile_min INT NOT NULL DEFAULT 20
CHECK (atr_percentile_min BETWEEN 5 AND 80),
gate_spot_perp_enabled BOOL NOT NULL DEFAULT FALSE,
spot_perp_threshold FLOAT NOT NULL DEFAULT 0.002
CHECK (spot_perp_threshold BETWEEN 0.0005 AND 0.01),
-- ─── 风控参数(执行层)────────────────────────────────────────
sl_atr_multiplier FLOAT NOT NULL DEFAULT 1.5
CHECK (sl_atr_multiplier BETWEEN 0.5 AND 3.0),
tp1_ratio FLOAT NOT NULL DEFAULT 0.75
CHECK (tp1_ratio BETWEEN 0.3 AND 2.0),
tp2_ratio FLOAT NOT NULL DEFAULT 1.5
CHECK (tp2_ratio BETWEEN 0.5 AND 4.0),
timeout_minutes INT NOT NULL DEFAULT 240
CHECK (timeout_minutes BETWEEN 30 AND 1440),
flip_threshold INT NOT NULL DEFAULT 80
CHECK (flip_threshold BETWEEN 60 AND 95),
-- ─── 资金(执行层)────────────────────────────────────────────
initial_balance FLOAT NOT NULL DEFAULT 10000.0
CHECK (initial_balance >= 1000),
current_balance FLOAT NOT NULL DEFAULT 10000.0,
-- ─── 元数据(展示层,不影响执行)──────────────────────────────
description TEXT, -- 策略描述,可选
tags TEXT[], -- 标签,可选
-- ─── 时间戳 ──────────────────────────────────────────────────
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- 索引
CREATE INDEX idx_strategies_status ON strategies(status);
CREATE INDEX idx_strategies_symbol ON strategies(symbol);
CREATE INDEX idx_strategies_last_run ON strategies(last_run_at);字段约束说明:
| 分组 | 字段 | 是否影响执行 | 备注 |
|---|---|---|---|
| 执行层 | symbol, direction, cvd_, weight_, entry_score, gate_, sl_, tp_, timeout_, flip_* | ✅ 是 | Worker 每周期读取这些字段做决策 |
| 展示层 | display_name, description, tags | ❌ 否 | 仅前端展示,修改不影响运行 |
| 状态层 | status, *_at 时间戳 | 部分 | status 影响 Worker 是否运行;时间戳仅记录 |
2.2 paper_trades 表(模拟盘交易记录,修改项)
在现有基础上新增/修改以下字段:
ALTER TABLE paper_trades
-- 新增:策略UUID外键(新数据用UUID,旧数据回填后也有)
ADD COLUMN strategy_id UUID REFERENCES strategies(strategy_id),
-- 新增:写入时快照策略名称,防止改名后历史断层
ADD COLUMN strategy_name_snapshot TEXT,
-- 保留:旧的 strategy 文本字段改为只读(迁移后不再写入,仅查询兼容用)
-- 注:旧字段 strategy TEXT 继续保留,不删除
;
-- 新数据索引
CREATE INDEX idx_paper_trades_strategy_id ON paper_trades(strategy_id);迁移后写入规则:
strategy_id:必填,写入 UUIDstrategy_name_snapshot:必填,写入当时的display_namestrategy(旧字段):不再写入,仅保留历史数据,只读
2.3 signal_indicators 表(信号记录,修改项)
ALTER TABLE signal_indicators
ADD COLUMN strategy_id UUID REFERENCES strategies(strategy_id),
ADD COLUMN strategy_name_snapshot TEXT;同 paper_trades,旧 strategy 字段保留只读。
2.4 paper_positions 表(持仓记录,修改项)
ALTER TABLE paper_positions
ADD COLUMN strategy_id UUID REFERENCES strategies(strategy_id),
ADD COLUMN strategy_name_snapshot TEXT;3. 迁移方案
3.1 旧策略固定 UUID 映射
迁移时为现有三条策略分配固定 UUID(预先确定,写入迁移脚本):
| 旧策略名 | 固定 UUID | 备注 |
|---|---|---|
| v53 | 00000000-0000-0000-0000-000000000053 | 便于识别 |
| v53_middle | 00000000-0000-0000-0000-000000000054 | 便于识别 |
| v53_fast | 00000000-0000-0000-0000-000000000055 | 已废弃但数据保留 |
3.2 迁移脚本逻辑(伪代码)
-- Step 1: 在 strategies 表插入三条旧策略记录
INSERT INTO strategies (strategy_id, display_name, symbol, status, schema_version, ...)
VALUES
('00000000-...0053', 'V5.3 Standard (BTC)', 'BTCUSDT', 'running', 1, ...),
-- 注:v53 是多币种策略,每个币种各插一条
...;
-- Step 2: 回填 paper_trades
UPDATE paper_trades
SET strategy_id = '00000000-...0053',
strategy_name_snapshot = 'V5.3 Standard'
WHERE strategy = 'v53';
-- Step 3: 回填 signal_indicators、paper_positions(同上)
-- Step 4: 验证回填完整性
SELECT strategy, COUNT(*) FROM paper_trades WHERE strategy_id IS NULL GROUP BY strategy;
-- 预期:0行(全部回填完成)3.3 回滚路径
- 迁移前:
git tag v5.3-before-migration打标签 - 迁移前:
pg_dump arb_engine > backup_before_v54.sql备份数据库 - 回滚时:停 V5.4 Strategy Factory → 恢复旧
signal_engine.py(按 git tag 回退) - 无需恢复 DB(新字段不影响旧代码读取,兼容)
4. API 接口定义
所有接口需 JWT 认证(Authorization: Bearer <token>)。
4.1 策略管理
POST /api/strategies — 创建策略
Request Body:
{
"display_name": "我的BTC激进策略",
"symbol": "BTCUSDT",
"direction": "both",
"initial_balance": 10000,
"cvd_fast_window": "30m",
"cvd_slow_window": "4h",
"weight_direction": 55,
"weight_env": 25,
"weight_aux": 15,
"weight_momentum": 5,
"entry_score": 75,
"gate_obi_enabled": true,
"obi_threshold": 0.3,
"gate_whale_enabled": true,
"whale_cvd_threshold": 0.0,
"gate_vol_enabled": true,
"atr_percentile_min": 20,
"gate_spot_perp_enabled": false,
"spot_perp_threshold": 0.002,
"sl_atr_multiplier": 1.5,
"tp1_ratio": 0.75,
"tp2_ratio": 1.5,
"timeout_minutes": 240,
"flip_threshold": 80,
"description": "可选描述"
}校验规则:
weight_direction + weight_env + weight_aux + weight_momentum == 100,否则返回 400- 所有数值字段在允许范围内,否则返回 400 并说明超限字段
Response 200:
{
"strategy_id": "uuid-...",
"display_name": "我的BTC激进策略",
"status": "running",
"created_at": 1741697000000
}GET /api/strategies — 获取策略列表
Query Params:
include_deprecated=true|false(默认 false,只返回 running/paused)
Response 200:
{
"strategies": [
{
"strategy_id": "uuid-...",
"display_name": "V5.3 Standard",
"symbol": "BTCUSDT",
"status": "running",
"current_balance": 8500.0,
"initial_balance": 10000.0,
"net_usdt": -1500.0,
"net_r": -7.5,
"trade_count": 191,
"win_rate": 46.6,
"avg_win_r": 0.50,
"avg_loss_r": -0.78,
"open_positions": 0,
"pnl_usdt_24h": -200.0,
"pnl_r_24h": -1.0,
"last_trade_at": 1741697000000,
"last_run_at": 1741697100000
}
]
}GET /api/strategies/{id} — 获取策略详情(含完整参数)
Response 200:在列表字段基础上额外返回所有配置参数字段(权重、Gate、风控等)。
PATCH /api/strategies/{id} — 更新策略参数
Request Body:只传需要修改的字段(Partial Update)。
约束:
status = deprecated的策略不允许修改参数(返回 403)- 权重合计校验同创建接口
POST /api/strategies/{id}/pause — 暂停策略
Worker 停止开新仓,不影响现有持仓(继续管理直到平仓)。
POST /api/strategies/{id}/resume — 恢复策略
POST /api/strategies/{id}/deprecate — 废弃策略
Request Body:{ "confirm": true }(防止误操作)
废弃后:
status→deprecateddeprecated_at→ NOW()- Worker 停止运行
- 数据永久保留
POST /api/strategies/{id}/restore — 重新启用废弃策略
恢复至 running 状态,继续原有余额和历史数据。
POST /api/strategies/{id}/add-balance — 追加余额
Request Body:{ "amount": 5000.0 }
执行逻辑:
initial_balance += amount
current_balance += amount4.2 策略广场汇总(已有端点,保留)
GET /api/strategy-plaza— 所有活跃策略卡片数据(同GET /api/strategies)GET /api/strategy-plaza/{id}/summary— 单策略汇总
5. Feature Event 结构(Signal Engine → Workers)
Signal Engine 每15秒广播一次,Workers 订阅后消费。
@dataclass
class FeatureEvent:
# 时间
ts: int # Unix ms
# 基础行情
symbol: str # 'BTCUSDT' | 'ETHUSDT' | ...
price: float # 实时最新成交价(last_trade_price,非均价)
atr_value: float # ATR(14)
# CVD(全部5个窗口,Worker 按需取用)
cvd_5m: float
cvd_15m: float
cvd_30m: float
cvd_1h: float
cvd_4h: float
# OBI
obi: float # 订单簿失衡 [-1, 1]
# Whale flow
whale_cvd: float # 大单净买入 CVD
whale_buy_ratio: float # 大单买入比例 [0, 1]
# 现货/永续溢价
spot_perp_div: float # 现货-永续溢价率
# 市场环境
funding_rate: float # 资金费率
open_interest_change: float # OI变化率
# ATR 百分位(用于 gate_vol 判断)
atr_percentile: int # 0-100约束:
price必须使用实时点价(last_trade_price),不得使用均价或历史价格- Signal Engine 只计算并广播 feature,不做任何评分或开仓决策
6. Worker 配置读取规则
Worker 在每次收到 FeatureEvent 时:
- 从 DB 读取最新配置(
SELECT * FROM strategies WHERE strategy_id = ? AND status = 'running') - 若
status != 'running',跳过本次评估 - 更新
last_run_at = NOW() - 按配置中的 CVD 窗口、权重、Gate 阈值进行评分
- 满足入场条件则开仓,开仓记录写入
paper_trades(含strategy_id+strategy_name_snapshot)
7. 参数默认值与边界一览
| 参数 | 默认值 | 最小值 | 最大值 | 单位 |
|---|---|---|---|---|
| weight_direction | 55 | 10 | 80 | 整数,% |
| weight_env | 25 | 5 | 60 | 整数,% |
| weight_aux | 15 | 0 | 40 | 整数,% |
| weight_momentum | 5 | 0 | 20 | 整数,% |
| entry_score | 75 | 60 | 95 | 整数,分 |
| obi_threshold | 0.3 | 0.1 | 0.9 | float |
| whale_cvd_threshold | 0.0 | -1.0 | 1.0 | float |
| atr_percentile_min | 20 | 5 | 80 | 整数,% |
| spot_perp_threshold | 0.002 | 0.0005 | 0.01 | float |
| sl_atr_multiplier | 1.5 | 0.5 | 3.0 | float,倍 |
| tp1_ratio | 0.75 | 0.3 | 2.0 | float,×RD |
| tp2_ratio | 1.5 | 0.5 | 4.0 | float,×RD |
| timeout_minutes | 240 | 30 | 1440 | 整数,分钟 |
| flip_threshold | 80 | 60 | 95 | 整数,分 |
| initial_balance | 10000 | 1000 | 1000000 | USDT |
8. 上线步骤(概要)
详细操作 SOP 由小周编写,此处只列关键节点:
- 迁移前备份:
pg_dump arb_engine > backup_before_v54.sql - 打 Git Tag:
git tag v5.3-before-migration - 执行 Schema 迁移:新增字段、创建
strategies表 - 执行数据迁移:插入三条旧策略记录,回填
strategy_id+strategy_name_snapshot - 验证回填完整性:确认无 NULL 的
strategy_id - 停旧引擎,启新 Strategy Factory
- 验证三策略心跳正常(
last_run_at在15秒内更新) - 上线当天限制:不开放"新增策略"功能,只迁移现有三条,观察1-2个交易日
9. Review 检查清单
- 范总确认数据合约整体方向
- 小范审阅表结构和 API 逻辑
- 小周确认迁移步骤可操作性,并编写上线/回滚 SOP
- 所有人确认后,露露开始编码