feat: add leader research agent
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-04
|
||||
@@ -0,0 +1,282 @@
|
||||
## Context
|
||||
|
||||
PolyHermes 当前已有三层跟单工作流:
|
||||
|
||||
- `Leader 管理` 保存可被跟单的钱包地址,对应 `copy_trading_leaders`。
|
||||
- `Leader 池` 管理人工候选、观察、小额试跟、冷却、淘汰,对应 `copy_trading_leader_pool`。
|
||||
- `跟单配置` 管理真实账户、leader 和风控参数,对应 `copy_trading`。
|
||||
|
||||
这个结构已经把“地址库”和“真钱跟单”拆开,但仍需要用户自己去找 leader、判断是否值得观察、跟踪表现、决定是否小额试跟。用户的目标不是手动维护池子,而是让系统自动发现优秀且可复制的 leader,先纸跟验证,再由用户授权真钱动作。
|
||||
|
||||
本设计把新增能力定位为 Leader Research Agent。它是研究代理,不是自动交易代理。它可以自动发现、自动纸跟、自动建议、自动冷却;它不能自动启用真钱跟单。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 提供多源候选发现,第一阶段支持 watchlist、已有 Leader 管理记录和 activity-derived candidates。
|
||||
- 为研究运行、候选、分数、事件、纸跟 session、纸跟交易、纸跟持仓建立独立数据模型。
|
||||
- 持久化原始或规范化 activity event,使纸跟可以基于可重放事件运行,而不是复用真实订单表。
|
||||
- 用透明规则计算 copyability score,并保存分项分数和 score version。
|
||||
- 自动推进研究状态,但研究状态必须与 Leader 池状态分离。
|
||||
- 在不锁定的情况下,自动化只能保守地增强 Leader 池记录,不能自动改成真实 `TRIAL` 或 `ACTIVE`。
|
||||
- 提供操作台展示运行状态、候选详情、纸跟表现、待处理决策和源健康。
|
||||
- 提供手动审批动作,创建保守的 `enabled=false` 真实跟单配置。
|
||||
- 为源失败、quote 不可用、valuation unknown、重复事件、锁定候选、非法真钱启用等关键路径提供可见错误和测试。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- 不自动启用真钱跟单。
|
||||
- 不自动加仓、不自动增加 fixed amount、不自动放宽风控参数。
|
||||
- 不做黑盒 AI/ML 评分。
|
||||
- 不在第一阶段依赖公开 leaderboard 端点。
|
||||
- 不复用 `copy_order_tracking` 作为纸跟账本。
|
||||
- 不把 unknown valuation 当成 confirmed zero。
|
||||
- 不替换现有 Leader 池、Leader 管理、跟单配置和真实 PnL 统计。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 研究状态独立于 Leader 池状态
|
||||
|
||||
研究状态回答“系统证明了什么”,Leader 池状态回答“用户当前怎么处理这个 leader”。两者不能合并。
|
||||
|
||||
研究状态:
|
||||
|
||||
```text
|
||||
DISCOVERED -> CANDIDATE -> PAPER -> TRIAL_READY
|
||||
\-> COOLDOWN -> RETIRED
|
||||
```
|
||||
|
||||
Leader 池状态:
|
||||
|
||||
```text
|
||||
CANDIDATE -> WATCH -> TRIAL -> ACTIVE
|
||||
\-> COOLDOWN -> RETIRED
|
||||
```
|
||||
|
||||
映射规则:
|
||||
|
||||
```text
|
||||
research DISCOVERED
|
||||
-> 可以只存在于 leader_research_candidate,不强制创建 Leader 池项
|
||||
|
||||
research CANDIDATE
|
||||
-> 展示给用户时可创建或更新 Leader 池 CANDIDATE
|
||||
|
||||
research PAPER
|
||||
-> Leader 池保持 WATCH,或后续 UI 暴露 PAPER
|
||||
|
||||
research TRIAL_READY
|
||||
-> Leader 池保持 WATCH,并展示“建议小额试跟” badge
|
||||
-> 不能自动变成 Leader 池 TRIAL
|
||||
|
||||
research COOLDOWN
|
||||
-> 未锁定时可以同步 Leader 池 COOLDOWN
|
||||
|
||||
research RETIRED
|
||||
-> 只有 agent 拥有且未锁定的候选,才可同步 Leader 池 RETIRED
|
||||
```
|
||||
|
||||
`TRIAL_READY` 只是建议。只有用户创建了真实禁用试跟配置后,Leader 池才可以进入 `TRIAL`。
|
||||
|
||||
### 2. 纸跟必须独立建账
|
||||
|
||||
`enabled=false` 的真实跟单配置不会产生模拟成交、模拟持仓、过滤原因、quote confidence 和纸跟 PnL。把它伪装成纸跟会让后续晋升建议没有证据链。
|
||||
|
||||
新增建议表:
|
||||
|
||||
```text
|
||||
leader_paper_session
|
||||
leader_paper_trade
|
||||
leader_paper_position
|
||||
```
|
||||
|
||||
每笔纸跟交易至少记录:
|
||||
|
||||
```text
|
||||
leader_trade_id
|
||||
leader_price
|
||||
leader_size
|
||||
simulated_price
|
||||
simulated_size
|
||||
simulated_amount
|
||||
fill_assumption: LEADER_PRICE | BEST_ASK_AT_EVENT | MID_PRICE | UNKNOWN
|
||||
quote_confidence: HIGH | MEDIUM | LOW | UNKNOWN
|
||||
quote_source
|
||||
quote_timestamp
|
||||
filter_result: PASSED | FILTERED
|
||||
filter_reason
|
||||
valuation_status: AVAILABLE | NO_MATCH | UNAVAILABLE | CONFIRMED_ZERO
|
||||
```
|
||||
|
||||
`UNAVAILABLE` 和 `UNKNOWN` 不得计为真实归零。这个约束必须沿用到纸跟 PnL 和前端展示。
|
||||
|
||||
### 3. 第一阶段先做可重放事件和内部来源
|
||||
|
||||
第一阶段候选来源:
|
||||
|
||||
```text
|
||||
watchlist
|
||||
已有 Leader 管理记录
|
||||
已持久化 activity event 中可归因的钱包
|
||||
```
|
||||
|
||||
公开 leaderboard 保留为后续来源,不作为第一阶段 apply-ready 的依赖。原因是 leaderboard 端点可能不稳定或未文档化,不能让第一版核心闭环被外部端点卡住。
|
||||
|
||||
如果当前 app 没有持久化 raw activity event,需要新增 append-only 表:
|
||||
|
||||
```text
|
||||
leader_activity_event
|
||||
```
|
||||
|
||||
推荐唯一键:
|
||||
|
||||
```text
|
||||
source + event_id
|
||||
```
|
||||
|
||||
如果 event_id 缺失,必须生成稳定 fallback key,避免重启或重放时重复纸跟。
|
||||
|
||||
### 4. 评分必须可解释且可版本化
|
||||
|
||||
不要只保存一个总分。保存分项分数、总分、score version 和 reason。
|
||||
|
||||
分项:
|
||||
|
||||
```text
|
||||
profit_signal
|
||||
repeatability
|
||||
liquidity_fit
|
||||
entry_price_fit
|
||||
slippage_risk
|
||||
holding_period_fit
|
||||
market_type_risk
|
||||
drawdown_risk
|
||||
exit_liquidity_risk
|
||||
data_freshness
|
||||
filter_pass_rate
|
||||
```
|
||||
|
||||
研究状态迁移必须记录 rule version,避免以后调整阈值后无法解释旧决策。
|
||||
|
||||
默认阈值:
|
||||
|
||||
```text
|
||||
DISCOVERED -> CANDIDATE
|
||||
条件:候选来自可信来源,地址格式有效
|
||||
|
||||
CANDIDATE -> PAPER
|
||||
条件:score >= 60,未锁定,未退休,source 48 小时内新鲜
|
||||
|
||||
PAPER -> TRIAL_READY
|
||||
条件:
|
||||
纸跟时间 >= 7 天
|
||||
模拟交易数 >= 10
|
||||
copyable PnL > 0
|
||||
最大回撤 >= -15%
|
||||
UNKNOWN quote 暴露占比 <= 20%
|
||||
filtered-trade ratio < 50%
|
||||
无 critical risk flag
|
||||
|
||||
PAPER -> COOLDOWN
|
||||
条件:
|
||||
最大回撤 < -20%
|
||||
或 10 笔后 copyable PnL < -5
|
||||
或 quote/source stale > 72 小时
|
||||
或存在 thin_liquidity_exit_risk
|
||||
|
||||
COOLDOWN -> CANDIDATE
|
||||
条件:cooldown_until 已过,source 重新新鲜,未锁定
|
||||
|
||||
COOLDOWN -> RETIRED
|
||||
条件:3 次冷却周期,或 30 天无新鲜来源
|
||||
```
|
||||
|
||||
这些阈值是第一版保守默认值,不是金融真理;后续可配置。
|
||||
|
||||
### 5. 后端强制真钱边界
|
||||
|
||||
研究代理可以推荐小额试跟,但不能启用真钱。
|
||||
|
||||
手动审批流:
|
||||
|
||||
```text
|
||||
用户打开候选详情
|
||||
-> 点击“创建禁用试跟配置”
|
||||
-> 前端展示 fixed amount、max daily loss、max daily orders、price range、max position value
|
||||
-> 用户确认
|
||||
-> 后端组装 CopyTradingCreateRequest
|
||||
-> 后端强制 enabled=false
|
||||
-> 返回 created copyTrading
|
||||
-> 用户必须去 跟单配置 页面手动启用
|
||||
```
|
||||
|
||||
后端必须忽略或拒绝任何客户端传入的 `enabled=true`、更大 fixed amount 或更松风控参数。安全边界在后端,不在弹窗。
|
||||
|
||||
### 6. 操作台先做“晨报式”决策界面
|
||||
|
||||
第一版页面不做复杂量化终端。优先回答:
|
||||
|
||||
```text
|
||||
今天有什么变化?
|
||||
哪些候选需要我决策?
|
||||
为什么推荐?
|
||||
证据是什么?
|
||||
风险是什么?
|
||||
我能安全点击什么?
|
||||
```
|
||||
|
||||
页面模块:
|
||||
|
||||
```text
|
||||
Run Status
|
||||
Candidate Detail
|
||||
Paper Sessions
|
||||
Pending Decisions
|
||||
Source Health
|
||||
```
|
||||
|
||||
### 7. 调度必须有 overlap guard 和 run record
|
||||
|
||||
新增 `LeaderResearchJobService` 使用现有 Spring `@Scheduled` 模式,但默认关闭或可配置开启。
|
||||
|
||||
每次运行必须创建 `leader_research_run`,记录:
|
||||
|
||||
```text
|
||||
status
|
||||
started_at
|
||||
finished_at
|
||||
duration
|
||||
source counts
|
||||
candidate counts
|
||||
error class
|
||||
error message
|
||||
partial failure flag
|
||||
```
|
||||
|
||||
如果上一次运行还未结束,新运行 MUST 跳过并记录 overlap 事件,不能并发推进状态。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [纸跟精度看起来比实际更高] -> 每笔纸跟交易必须保存 fill assumption、quote confidence 和 valuation status;UI 必须展示 unknown/partial 状态。
|
||||
- [source 失败导致错误降级候选] -> source failure 只更新 source health,不得静默删除候选或降低 score。
|
||||
- [自动状态机误伤人工决策] -> `locked=true` 的候选和池子项不得被自动化改变状态、建议配置或 trial recommendation。
|
||||
- [通知系统 Telegram-first] -> 第一阶段先落 `leader_research_event` 和控制台提示,外部通知渠道在事件流稳定后再复用/扩展通知配置。
|
||||
- [表数量增加导致复杂度上升] -> 用里程碑拆分:先数据 spine,再纸跟,再评分状态机,再 UI/通知,再手动审批。
|
||||
- [数据量增长影响性能] -> 为 event、candidate、paper trade、paper position、run、event 表添加唯一键和查询索引,并对详情列表分页。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 新增研究与纸跟相关 Flyway 迁移,所有表为空表创建,不修改现有真实订单热表。
|
||||
2. 部署后端,但 research job 默认关闭。
|
||||
3. 部署前端操作台,若 job 未启用则展示禁用/空态。
|
||||
4. 在本地或测试环境手动运行 research job,验证 run record、source health、candidate、paper session 和 paper trade。
|
||||
5. 开启 watchlist + existing leaders 来源,不启用 public leaderboard。
|
||||
6. 确认内部 research events 稳定后再接外部通知渠道。
|
||||
7. 最后启用手动“创建禁用试跟配置”入口。
|
||||
|
||||
Rollback:
|
||||
|
||||
- 如果 job 出错,关闭 research job 配置并保留数据表。
|
||||
- 如果 UI 出错,隐藏菜单或回滚前端路由。
|
||||
- 如果迁移失败,在启用 job 前停止部署;不要在热回滚中删除已有研究数据。
|
||||
@@ -0,0 +1,37 @@
|
||||
## Why
|
||||
|
||||
当前 `Leader 池` 已经解决了“候选、观察、小额试跟、冷却、淘汰”的人工决策层,但用户的真实目标更靠前:系统自动发现优秀且可复制的 leader,先用纸跟证据验证,再让用户决定是否创建真实小额跟单配置。
|
||||
|
||||
如果只搬运排行榜,系统会把“leader 自己赚钱”误当成“用户也能跟着赚钱”。本变更要把 PolyHermes 从手动候选池升级为 paper-first 的 Leader Research Agent:自动发现、自动纸跟、自动解释、自动建议,但真钱启用必须手动确认。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增 Leader Research Agent 能力,提供多源候选发现、研究运行记录、源健康状态和候选评分。
|
||||
- 新增独立纸跟账本,记录模拟买卖、模拟持仓、过滤原因、估值状态、quote confidence 和纸跟 PnL。
|
||||
- 新增研究状态机,支持 `DISCOVERED`、`CANDIDATE`、`PAPER`、`TRIAL_READY`、`COOLDOWN`、`RETIRED` 等研究状态,并与现有 Leader 池状态分离。
|
||||
- 新增可解释 copyability score,按收益信号、可重复性、流动性适配、入场价格适配、滑点风险、持仓周期、市场类型风险、回撤风险、退出流动性风险、数据新鲜度和过滤通过率拆分。
|
||||
- 新增 Leader Research 操作台,展示运行状态、候选详情、纸跟证据、待处理决策和数据源健康。
|
||||
- 新增研究事件与通知摘要,让系统主动提示新增候选、纸跟达标、建议小额试跟、冷却、数据失败和数据过期。
|
||||
- 新增手动审批路径:用户从研究候选详情确认后,系统只能创建 `enabled=false` 的保守真实跟单配置;研究代理不得自动启用真钱跟单。
|
||||
- 第一阶段候选来源仅包含 watchlist、已有 `Leader 管理` 记录和已持久化 activity 事件;公开 leaderboard 接入保留为后续能力,等端点契约和失败行为确认后再启用。
|
||||
- 不做自动真钱启用、不做自动加仓、不做自动放大固定金额、不做黑盒 AI 评分、不删除用户已有 leader 或跟单配置。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `leader-research-agent`: 自动研究 leader 的完整能力,包括候选发现、纸跟账本、copyability 评分、研究状态机、操作台、通知事件和手动创建禁用试跟配置。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
无。
|
||||
|
||||
## Impact
|
||||
|
||||
- 后端新增 research 相关实体、Flyway 迁移、Repository、DTO、Service、Controller、定时任务和错误码。
|
||||
- 后端需要复用现有 `copy_trading_leaders`、`copy_trading_leader_pool`、`copy_trading`、`CopyTradingService`、`LeaderPoolService` 和 activity 监听链路。
|
||||
- 后端需要新增 append-only activity event 持久化能力,如果当前实时 activity 事件没有落库,则纸跟必须先基于该事件表运行。
|
||||
- 前端新增 Leader Research 操作台页面、路由、菜单入口、API service、类型定义和中文/英文/繁中文文案。
|
||||
- 前端 Leader 池需要能展示研究推荐 badge 或跳转研究候选详情,但不得把 `TRIAL_READY` 直接表现成真实 `TRIAL`。
|
||||
- 通知系统先复用内部 `leader_research_event` 和控制台提示;外部通知渠道在事件流稳定后再接入现有通知配置抽象。
|
||||
- 交易安全影响:本变更会靠近真钱配置创建路径,因此所有真实配置创建必须后端强制 `enabled=false`,并通过测试证明研究代理没有任何自动启用真钱的路径。
|
||||
@@ -0,0 +1,228 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 提供 Leader Research 操作台
|
||||
系统 SHALL 在受保护的 Web 应用中提供 Leader Research 操作台,用于查看自动研究运行状态、候选、纸跟证据、待处理决策和数据源健康。
|
||||
|
||||
#### Scenario: 打开操作台
|
||||
- **WHEN** 已登录用户打开 Leader Research 页面
|
||||
- **THEN** 系统 MUST 展示最近研究运行状态、候选概览、待处理决策、纸跟概览和数据源健康
|
||||
|
||||
#### Scenario: 研究功能未启用
|
||||
- **WHEN** 研究 job 未启用或尚未运行
|
||||
- **THEN** 页面 MUST 展示明确空态,并 MUST NOT 暗示系统已经完成 leader 研究
|
||||
|
||||
#### Scenario: 数据源部分失败
|
||||
- **WHEN** 部分候选来源失败但其他来源可用
|
||||
- **THEN** 页面 MUST 展示 degraded 状态,并 MUST 继续展示可用来源产生的候选和证据
|
||||
|
||||
### Requirement: 记录研究运行
|
||||
系统 SHALL 为每次自动或手动研究运行记录 run record,确保研究结果可追溯、可排查且不会静默失败。
|
||||
|
||||
#### Scenario: 成功运行研究任务
|
||||
- **WHEN** 研究任务完成一次正常运行
|
||||
- **THEN** 系统 MUST 保存运行状态、开始时间、结束时间、耗时、来源统计、候选统计和成功状态
|
||||
|
||||
#### Scenario: 研究任务部分失败
|
||||
- **WHEN** 研究任务中某个来源或阶段失败但整体任务仍可继续
|
||||
- **THEN** 系统 MUST 将 run 标记为 partial failure,并 MUST 保存失败来源、错误类型和错误信息
|
||||
|
||||
#### Scenario: 防止并发运行
|
||||
- **WHEN** 上一次研究任务仍在运行时触发新的研究任务
|
||||
- **THEN** 系统 MUST 跳过新的任务或拒绝新的任务,并 MUST 记录 overlap 事件
|
||||
|
||||
### Requirement: 多源发现候选
|
||||
系统 SHALL 支持从多个来源发现 leader 候选,并将候选标准化为统一研究候选记录。
|
||||
|
||||
#### Scenario: 从 watchlist 发现候选
|
||||
- **WHEN** 系统运行 watchlist 来源
|
||||
- **THEN** 系统 MUST 为 watchlist 中的有效钱包创建或更新研究候选
|
||||
|
||||
#### Scenario: 从已有 Leader 管理记录发现候选
|
||||
- **WHEN** 系统运行已有 leader 来源
|
||||
- **THEN** 系统 MUST 为 `copy_trading_leaders` 中的有效 leader 创建或更新研究候选
|
||||
|
||||
#### Scenario: 从 activity 事件发现候选
|
||||
- **WHEN** 系统从已持久化 activity event 中识别可归因的钱包
|
||||
- **THEN** 系统 MUST 创建或更新研究候选,并 MUST 记录来源为 activity-derived
|
||||
|
||||
#### Scenario: 来源返回空结果
|
||||
- **WHEN** 某个来源成功运行但没有发现候选
|
||||
- **THEN** 系统 MUST 记录该来源成功且候选数为 0,不得把它当作失败
|
||||
|
||||
#### Scenario: 来源失败
|
||||
- **WHEN** 某个来源超时、限流、解析失败或返回异常
|
||||
- **THEN** 系统 MUST 更新来源健康状态,并 MUST NOT 因本次失败删除候选或自动降级候选
|
||||
|
||||
### Requirement: 持久化 activity event
|
||||
系统 SHALL 持久化用于纸跟的 activity event,确保纸跟可以重放、去重和排查。
|
||||
|
||||
#### Scenario: 保存新的 activity event
|
||||
- **WHEN** 系统接收到包含交易者、市场、方向、价格、数量和时间的 activity event
|
||||
- **THEN** 系统 MUST 保存该事件,并 MUST 记录 source、event id、钱包地址、市场、方向、价格、数量、时间戳和原始 payload 摘要
|
||||
|
||||
#### Scenario: 重复 activity event
|
||||
- **WHEN** 系统再次接收到相同 source 和 event id 的 activity event
|
||||
- **THEN** 系统 MUST 不创建重复事件,并 MUST 保持纸跟处理幂等
|
||||
|
||||
#### Scenario: activity event 缺少必需字段
|
||||
- **WHEN** activity event 缺少钱包地址、市场、方向、价格或数量
|
||||
- **THEN** 系统 MUST 标记该事件不可用于纸跟,并 MUST 记录原因
|
||||
|
||||
### Requirement: 建立独立纸跟账本
|
||||
系统 SHALL 使用独立纸跟账本记录模拟买卖、模拟持仓、过滤结果和纸跟 PnL,不得使用真实订单跟踪表伪装纸跟。
|
||||
|
||||
#### Scenario: 启动纸跟 session
|
||||
- **WHEN** 研究候选达到进入纸跟的条件
|
||||
- **THEN** 系统 MUST 创建 paper session,并 MUST 将候选研究状态更新为 `PAPER`
|
||||
|
||||
#### Scenario: 记录纸跟买入
|
||||
- **WHEN** 已进入纸跟的候选出现符合过滤条件的 BUY activity event
|
||||
- **THEN** 系统 MUST 记录 paper trade 和 paper position,并 MUST 保存模拟价格、模拟数量、fill assumption 和 quote confidence
|
||||
|
||||
#### Scenario: 记录纸跟卖出
|
||||
- **WHEN** 已进入纸跟的候选出现可匹配的 SELL activity event
|
||||
- **THEN** 系统 MUST 更新对应 paper position,并 MUST 记录 realized paper PnL
|
||||
|
||||
#### Scenario: 记录被过滤交易
|
||||
- **WHEN** 候选交易因价格区间、流动性、风控或数据缺失被过滤
|
||||
- **THEN** 系统 MUST 记录 filtered paper trade 或 research event,并 MUST 保存 filter reason
|
||||
|
||||
#### Scenario: 估值不可用
|
||||
- **WHEN** 纸跟持仓无法获得可靠 quote 或 position valuation
|
||||
- **THEN** 系统 MUST 将 valuation status 标记为 `UNAVAILABLE` 或 `UNKNOWN`,并 MUST NOT 将其计为 confirmed zero
|
||||
|
||||
### Requirement: 计算可解释 copyability score
|
||||
系统 SHALL 为研究候选计算可解释的 copyability score,并保存分项分数、总分、版本和原因。
|
||||
|
||||
#### Scenario: 保存分项分数
|
||||
- **WHEN** 系统计算候选评分
|
||||
- **THEN** 系统 MUST 保存收益信号、可重复性、流动性适配、入场价格适配、滑点风险、持仓周期、市场类型风险、回撤风险、退出流动性风险、数据新鲜度和过滤通过率
|
||||
|
||||
#### Scenario: 保存评分版本
|
||||
- **WHEN** 系统保存候选评分
|
||||
- **THEN** 系统 MUST 保存 score version,以便后续解释历史评分
|
||||
|
||||
#### Scenario: 单次大赢不能主导评分
|
||||
- **WHEN** 候选只有单次异常盈利但样本量不足
|
||||
- **THEN** 系统 MUST 限制收益信号对总分的影响,并 MUST 通过样本量或可重复性降低晋升概率
|
||||
|
||||
### Requirement: 自动推进研究状态
|
||||
系统 SHALL 基于透明规则自动推进研究状态,并记录每次状态变化的原因。
|
||||
|
||||
#### Scenario: 候选进入纸跟
|
||||
- **WHEN** 候选分数达到阈值、来源新鲜、未退休且未锁定
|
||||
- **THEN** 系统 MUST 将研究状态从 `CANDIDATE` 推进为 `PAPER`,并 MUST 记录规则版本和原因
|
||||
|
||||
#### Scenario: 纸跟达标进入试跟建议
|
||||
- **WHEN** 候选纸跟至少 7 天、模拟交易至少 10 笔、copyable PnL 为正、最大回撤不低于 -15%、UNKNOWN quote 暴露不超过 20%、过滤比例低于 50% 且无 critical risk flag
|
||||
- **THEN** 系统 MUST 将研究状态推进为 `TRIAL_READY`,并 MUST 生成试跟建议事件
|
||||
|
||||
#### Scenario: 纸跟风险进入冷却
|
||||
- **WHEN** 候选最大回撤低于 -20%、10 笔后 copyable PnL 小于 -5、quote 或 source stale 超过 72 小时,或出现 thin liquidity exit risk
|
||||
- **THEN** 系统 MUST 将研究状态推进为 `COOLDOWN`,并 MUST 记录风险原因
|
||||
|
||||
#### Scenario: 冷却后恢复候选
|
||||
- **WHEN** 候选冷却截止时间已过、来源重新新鲜且未锁定
|
||||
- **THEN** 系统 MAY 将研究状态恢复为 `CANDIDATE`,并 MUST 记录恢复原因
|
||||
|
||||
#### Scenario: 多次冷却后退休
|
||||
- **WHEN** 候选经历 3 次冷却周期或 30 天没有新鲜来源
|
||||
- **THEN** 系统 MAY 将研究状态推进为 `RETIRED`,并 MUST 记录退休原因
|
||||
|
||||
### Requirement: 尊重锁定候选
|
||||
系统 SHALL 支持锁定研究候选或 Leader 池项,避免自动任务覆盖人工判断。
|
||||
|
||||
#### Scenario: 锁定候选
|
||||
- **WHEN** 用户锁定某个研究候选
|
||||
- **THEN** 自动任务 MUST NOT 改变该候选的研究状态、试跟建议、建议配置或冷却/退休状态
|
||||
|
||||
#### Scenario: 锁定候选仍可更新证据
|
||||
- **WHEN** 锁定候选出现新的来源证据或纸跟证据
|
||||
- **THEN** 系统 MAY 追加只读证据,但 MUST NOT 改变人工锁定的决策字段
|
||||
|
||||
### Requirement: 保守增强 Leader 池
|
||||
系统 SHALL 允许研究代理保守地增强现有 Leader 池记录,但不得替代 Leader 池的人工作业语义。
|
||||
|
||||
#### Scenario: 研究候选同步到 Leader 池
|
||||
- **WHEN** 候选进入 `CANDIDATE` 或更高研究状态且需要展示给用户
|
||||
- **THEN** 系统 MAY 创建或更新对应 Leader 池项,并 MUST 保留 Leader 池作为候选决策层
|
||||
|
||||
#### Scenario: 试跟建议不等于真实试跟状态
|
||||
- **WHEN** 候选研究状态为 `TRIAL_READY`
|
||||
- **THEN** 系统 MUST NOT 自动把 Leader 池状态改为 `TRIAL` 或 `ACTIVE`
|
||||
|
||||
#### Scenario: 不自动放大建议配置
|
||||
- **WHEN** 自动任务更新已有 Leader 池记录
|
||||
- **THEN** 系统 MUST NOT 自动增加 suggested fixed amount、suggested max daily loss 或 suggested max daily orders
|
||||
|
||||
#### Scenario: 不覆盖手工备注
|
||||
- **WHEN** 自动任务写入研究摘要
|
||||
- **THEN** 系统 MUST NOT 覆盖用户手工 notes,只能追加或写入独立研究摘要字段
|
||||
|
||||
### Requirement: 手动创建禁用试跟配置
|
||||
系统 SHALL 支持用户从试跟建议手动创建禁用的保守真实跟单配置,并禁止研究代理自动启用真钱。
|
||||
|
||||
#### Scenario: 创建禁用试跟配置
|
||||
- **WHEN** 用户从 `TRIAL_READY` 候选详情点击创建禁用试跟配置并确认
|
||||
- **THEN** 后端 MUST 通过现有跟单配置服务创建 `enabled=false` 的保守 `FIXED` 配置
|
||||
|
||||
#### Scenario: 后端强制禁用状态
|
||||
- **WHEN** 创建禁用试跟配置请求包含 `enabled=true` 或其他试图立即启用的字段
|
||||
- **THEN** 后端 MUST 忽略或拒绝这些字段,并 MUST NOT 创建启用中的真实跟单配置
|
||||
|
||||
#### Scenario: 创建前展示风险参数
|
||||
- **WHEN** 用户确认创建禁用试跟配置
|
||||
- **THEN** UI MUST 展示 fixed amount、max daily loss、max daily orders、price range 和 max position value
|
||||
|
||||
#### Scenario: 已存在同账户同 leader 配置
|
||||
- **WHEN** 用户尝试为同一账户和 leader 创建禁用试跟配置且配置已存在
|
||||
- **THEN** 系统 MUST 拒绝默认创建,并 MUST 展示已有配置提示
|
||||
|
||||
### Requirement: 记录研究事件和通知摘要
|
||||
系统 SHALL 为关键研究动作记录事件,并在事件流稳定后提供通知摘要。
|
||||
|
||||
#### Scenario: 记录关键研究事件
|
||||
- **WHEN** 系统发现新候选、启动纸跟、晋升试跟建议、进入冷却、退休、来源失败或 valuation stale
|
||||
- **THEN** 系统 MUST 写入 leader research event,并 MUST 包含候选、事件类型、原因和时间
|
||||
|
||||
#### Scenario: 操作台展示待处理事件
|
||||
- **WHEN** 存在试跟建议或数据源失败事件
|
||||
- **THEN** 操作台 MUST 展示这些事件,并 MUST 提供跳转到候选详情或源健康详情的入口
|
||||
|
||||
#### Scenario: 外部通知失败
|
||||
- **WHEN** 外部通知渠道发送失败
|
||||
- **THEN** 系统 MUST 保留 research event,并 MUST 标记通知失败,不得丢失研究事件
|
||||
|
||||
### Requirement: 提供研究 API
|
||||
系统 SHALL 提供受保护的 Leader Research API,用于运行研究、查看运行状态、查看候选、查看纸跟详情、查看事件和创建禁用试跟配置。
|
||||
|
||||
#### Scenario: 手动触发研究运行
|
||||
- **WHEN** 用户请求手动运行研究任务
|
||||
- **THEN** 后端 MUST 校验权限和 overlap guard,并 MUST 返回 run record 或明确跳过原因
|
||||
|
||||
#### Scenario: 查询候选列表
|
||||
- **WHEN** 前端请求候选列表
|
||||
- **THEN** 后端 MUST 返回候选研究状态、来源、总分、关键风险、纸跟摘要和待处理决策状态
|
||||
|
||||
#### Scenario: 查询候选详情
|
||||
- **WHEN** 前端请求候选详情
|
||||
- **THEN** 后端 MUST 返回来源历史、score components、paper session、paper trades、paper positions、research events 和 Leader 池映射信息
|
||||
|
||||
#### Scenario: 查询源健康
|
||||
- **WHEN** 前端请求数据源健康
|
||||
- **THEN** 后端 MUST 返回每个来源的最近成功时间、最近失败时间、错误类型、错误信息和 stale 状态
|
||||
|
||||
### Requirement: 保证研究任务可观测和可回滚
|
||||
系统 SHALL 提供研究任务的日志、指标、运行记录和开关,确保上线后可以诊断、暂停和回滚。
|
||||
|
||||
#### Scenario: 研究 job 默认关闭
|
||||
- **WHEN** 新版本首次部署
|
||||
- **THEN** 研究 job SHOULD 默认为关闭或可配置关闭,直到人工验证通过
|
||||
|
||||
#### Scenario: 记录结构化日志
|
||||
- **WHEN** 研究任务运行、候选状态变化、纸跟交易记录、源失败或手动审批发生
|
||||
- **THEN** 后端 MUST 记录包含 runId、candidateId、source、eventId、oldState、newState 或 copyTradingId 的结构化日志
|
||||
|
||||
#### Scenario: 关闭研究 job
|
||||
- **WHEN** 运维关闭研究 job 配置
|
||||
- **THEN** 系统 MUST 停止自动研究运行,但 MUST 保留已有研究数据和页面查询能力
|
||||
@@ -0,0 +1,208 @@
|
||||
## 1. 后端数据模型与迁移
|
||||
|
||||
- [x] 1.1 新增 Flyway 迁移,创建 `leader_research_run` 表,记录运行状态、时间、耗时、来源统计、候选统计、错误类型、错误信息和 partial failure 标记。
|
||||
- [x] 1.2 新增 Flyway 迁移,创建 `leader_research_candidate` 表,记录钱包地址、关联 leaderId、研究状态、来源、score、reason、risk flags、锁定字段和时间戳。
|
||||
- [x] 1.3 新增 Flyway 迁移,创建 `leader_research_score` 表,记录 score version、总分和所有 copyability 分项。
|
||||
- [x] 1.4 新增 Flyway 迁移,创建 `leader_research_event` 表,记录研究事件类型、candidateId、runId、原因、payload 摘要、通知状态和时间戳。
|
||||
- [x] 1.5 新增 Flyway 迁移,创建 `leader_research_source_state` 表或等价字段,记录每个来源的最近成功、最近失败、错误类型、错误信息和 stale 状态。
|
||||
- [x] 1.6 新增 Flyway 迁移,创建 `leader_activity_event` append-only 表,若当前 app 未持久化 raw activity event,则用于纸跟重放和去重。
|
||||
- [x] 1.7 新增 Flyway 迁移,创建 `leader_paper_session` 表,记录 candidateId、状态、开始/结束时间、统计摘要和 PnL 摘要。
|
||||
- [x] 1.8 新增 Flyway 迁移,创建 `leader_paper_trade` 表,记录 leader trade、模拟成交、filter reason、fill assumption、quote confidence 和 valuation status。
|
||||
- [x] 1.9 新增 Flyway 迁移,创建 `leader_paper_position` 表,记录 session、market、outcome、数量、成本、当前估值、realized/unrealized PnL 和 valuation status。
|
||||
- [x] 1.10 为 activity event、candidate、paper trade、paper position、run、event 和 source state 添加唯一键与查询索引,覆盖去重、分页、状态筛选和候选详情查询。
|
||||
- [x] 1.11 新增 JPA entity 与 repository,覆盖所有 research、activity、paper 相关表。
|
||||
- [x] 1.12 新增 research 状态、paper session 状态、valuation status、quote confidence、fill assumption、event type 和 source type 枚举。
|
||||
- [x] 1.13 `leader_activity_event` 必须包含 `normalized_wallet`、`source_event_id`、`stable_event_key`、`event_time`、`raw_payload_hash`、`payload_summary`、`usable_for_discovery`、`unusable_reason`、`paper_processing_status`、`processing_attempts`、`paper_processing_started_at`、`paper_processed_at` 和 `last_processing_error`。
|
||||
- [x] 1.14 `leader_research_candidate` 必须记录 agent ownership/provenance,区分 agent 创建候选、用户已有 leader、用户锁定候选和人工池子项,避免自动退休或覆盖用户资产。
|
||||
- [x] 1.15 `leader_research_run` 必须支持单实例运行锁或等价约束,保证同一时间最多一个 research run 推进候选状态。
|
||||
- [x] 1.16 为 `leader_activity_event(paper_processing_status, event_time)`、`leader_activity_event(normalized_wallet, event_time)`、`leader_paper_trade(session_id, leader_trade_id)`、`leader_research_candidate(research_state, last_source_seen_at)` 添加组合索引。
|
||||
- [x] 1.17 为 paper trade 增加数据库唯一约束,至少覆盖 `session_id + leader_trade_id + side`,用数据库兜底防止重复模拟成交。
|
||||
- [x] 1.18 所有新增表必须有可回滚的空表迁移策略;迁移不得修改现有真实订单热表语义。
|
||||
|
||||
## 2. Activity 事件持久化
|
||||
|
||||
- [x] 2.1 新增 `LeaderActivityIngestionService`,负责 research 专用 activity event 标准化、去重、持久化和不可用原因记录。
|
||||
- [x] 2.2 保持现有 `PolymarketActivityWsService` 的真实跟单快路径不被 research 拖慢;不得依赖它当前的“已监听 leader 地址预过滤”来发现未知 leader。
|
||||
- [x] 2.3 新增 bounded Data API backfill 来源,按 watchlist、已有 Leader 管理记录和 active research candidates 拉取 `/activity`,用于补齐历史 paper event。
|
||||
- [x] 2.4 新增 research global activity capture 扩展点,解析全局 WS activity 时必须在地址过滤前标准化事件;该能力默认关闭,并受配置开关、每分钟写入上限、payload 截断和保留策略保护。
|
||||
- [x] 2.5 如果 global capture 未启用,activity-derived source 必须在 source health 中明确显示 disabled/degraded,不得假装已经自动发现未知 leader。
|
||||
- [x] 2.6 为 activity event 实现 source + eventId 幂等保存;缺失 eventId 时用 wallet、conditionId、asset、side、price、size、timestamp、transactionHash 的稳定 hash 生成 fallback key。
|
||||
- [x] 2.7 对缺少钱包地址、市场、方向、价格或数量的 event 仍写入摘要,并标记不可用于 discovery/paper trading 的原因。
|
||||
- [x] 2.8 确保 activity event 持久化失败不会阻断现有真实跟单处理链路;失败只写 research run/source error。
|
||||
- [x] 2.9 新增 activity source health 更新,区分 Data API success empty、Data API failure、WS capture disabled、WS parse failure、write capped 和 stale。
|
||||
- [x] 2.10 新增 activity event repository 查询方法,支持按钱包、时间窗口、未处理状态、来源、可发现状态和 stable key 查询。
|
||||
- [x] 2.11 新增 activity ingestion 测试,覆盖正常保存、重复事件、缺失字段、fallback key、持久化失败隔离、write cap、WS capture disabled 和 Data API success empty。
|
||||
- [x] 2.12 新增回归测试,证明 current copy-trading WS 的已知 leader 过滤不会阻断 research ingestion 对未知钱包的发现路径。
|
||||
|
||||
## 3. 候选来源与研究运行
|
||||
|
||||
- [x] 3.1 新增 `LeaderResearchJobService`,支持手动 runOnce 和定时运行,默认通过配置关闭自动调度。
|
||||
- [x] 3.2 为研究任务实现 overlap guard,当前一 run 未结束时跳过或拒绝新 run,并写入 research event。
|
||||
- [x] 3.3 新增 `LeaderResearchSourceService`,统一 watchlist、已有 Leader 管理记录和 activity-derived candidates;每个 source 返回 typed result,包含 candidates、source status、error class、error message 和 freshness。
|
||||
- [x] 3.4 新增 watchlist 配置读取路径,支持配置钱包地址、备注和来源标签。
|
||||
- [x] 3.5 实现 existing leaders 来源,从 `copy_trading_leaders` 创建或更新研究候选。
|
||||
- [x] 3.6 实现 activity-derived 来源,从 `leader_activity_event` 中发现 fresh、usable、可归因钱包;如果 global capture 未启用,只能基于已持久化事件工作,并必须展示 source limitation。
|
||||
- [x] 3.7 候选创建必须复用 `LeaderRepository` 的唯一地址语义;新 leader address 必须标准化小写并验证 42 位 EVM 地址格式。
|
||||
- [x] 3.8 每个来源运行后更新 source state,区分 success with zero candidates、failure、stale、disabled、degraded 和 partial failure。
|
||||
- [x] 3.9 公开 leaderboard 来源只保留接口/扩展点,不作为第一阶段启用来源;不得在实现中偷偷依赖未确认 endpoint。
|
||||
- [x] 3.10 候选合并必须保留所有来源 evidence,不得因为同一钱包重复出现而覆盖更早来源、用户备注或锁定状态。
|
||||
- [x] 3.11 新增 run-level dry-run 或 preview 能力,允许查看本次将新增/更新/冷却多少候选而不推进状态。
|
||||
- [x] 3.12 新增候选来源测试,覆盖空结果、失败结果、disabled source、重复候选、无效地址、已有 leader 复用和用户锁定保护。
|
||||
- [x] 3.13 新增研究运行测试,覆盖成功、partial failure、overlap guard、run record 完整性、source limitation 和 preview 不产生状态副作用。
|
||||
- [x] 3.14 新增生产失败场景测试:某个 source 超时或抛异常时,其他 source 仍能产出候选,且不会删除或降级已有候选。
|
||||
|
||||
## 4. 纸跟账本与模拟成交
|
||||
|
||||
- [x] 4.1 新增 `LeaderPaperTradingService`,根据候选和 activity event 启动或更新 paper session。
|
||||
- [x] 4.2 `LeaderPaperTradingService` 必须按 batch claim `leader_activity_event`,通过状态从 `NEW`/`RETRYABLE` 原子更新到 `PROCESSING` 后再处理,避免并发 run 重复模拟成交。
|
||||
- [x] 4.3 对进入 `PAPER` 状态的候选,处理 BUY event 并记录 paper trade 与 paper position。
|
||||
- [x] 4.4 对进入 `PAPER` 状态的候选,处理 SELL event 并按持仓匹配规则更新 paper position 和 realized PnL。
|
||||
- [x] 4.5 将现有 `CopyTradingFilterService` 抽出或复用为 paper-safe evaluator;paper 场景不得调用真实账户持仓检查来决定模拟持仓,必须使用 paper position provider。
|
||||
- [x] 4.6 为 research 定义保守 paper config,包含 fixed amount、max daily loss、max daily orders、min/max price、max position value、support sell 和 market end guard。
|
||||
- [x] 4.7 每笔 paper trade 保存 leader price、leader size、simulated price、simulated size、simulated amount、fill assumption、quote confidence、quote source、quote timestamp、filter result 和 filter reason。
|
||||
- [x] 4.8 对 quote/valuation 不可用的持仓标记 `UNAVAILABLE` 或 `UNKNOWN`,并确保不计为 confirmed zero。
|
||||
- [x] 4.9 `copyable PnL` 必须区分 realized PnL、available unrealized PnL、unknown valuation exposure 和 confirmed zero exposure;unknown/unavailable 不得伪装成亏到 0。
|
||||
- [x] 4.10 为 paper trade 实现 leaderTradeId 幂等去重,重复 activity event 不得重复产生纸跟。
|
||||
- [x] 4.11 处理失败必须增加 `processing_attempts`、记录 `last_processing_error`,超过阈值进入 `FAILED` 并写 research event,不得无限重试卡住整轮 run。
|
||||
- [x] 4.12 新增 paper session 汇总计算,包含交易数、过滤数、open exposure、realized/unrealized/copyable PnL、max drawdown、unknown valuation exposure、confirmed zero exposure 和 filtered ratio。
|
||||
- [x] 4.13 新增纸跟服务测试,覆盖 BUY、SELL、过滤、重复 event、unknown valuation、confirmed zero、PnL 计算、max drawdown、event claim 并发、失败重试和 FAILED 隔离。
|
||||
|
||||
## 5. Copyability 评分与研究状态机
|
||||
|
||||
- [x] 5.1 新增 `LeaderResearchScoringService`,计算并保存所有 copyability 分项和总分。
|
||||
- [x] 5.2 定义 `score_version = research-copyability-v1`,写明每个分项的 0-100 取值范围、权重、缺数据策略和总分计算公式。
|
||||
- [x] 5.3 v1 默认权重建议:profit signal 20、repeatability 15、liquidity fit 10、entry price fit 10、slippage risk 10、drawdown risk 10、holding period fit 5、market type risk 5、exit liquidity risk 5、data freshness 5、filter pass rate 5。
|
||||
- [x] 5.4 实现收益信号封顶逻辑,避免单次大赢主导评分;样本量不足时总分必须被 cap,且不能进入 `TRIAL_READY`。
|
||||
- [x] 5.5 实现 repeatability、liquidity fit、entry price fit、slippage risk、holding period fit、market type risk、drawdown risk、exit liquidity risk、data freshness 和 filter pass rate 分项。
|
||||
- [x] 5.6 对 quote unknown、valuation unavailable、source stale、filtered ratio 过高和 critical risk flag 定义明确扣分或晋升阻断规则。
|
||||
- [x] 5.7 新增 `LeaderResearchStateMachine`,实现 `DISCOVERED -> CANDIDATE -> PAPER -> TRIAL_READY -> COOLDOWN/RETIRED` 迁移。
|
||||
- [x] 5.8 状态迁移必须在事务中保存 rule version、oldState、newState、trigger reason、runId 和 research event。
|
||||
- [x] 5.9 实现 `CANDIDATE -> PAPER` 默认阈值:score >= 60、未锁定、未退休、source 48 小时内新鲜。
|
||||
- [x] 5.10 实现 `PAPER -> TRIAL_READY` 默认阈值:纸跟 >= 7 天、交易 >= 10、copyable PnL > 0、最大回撤不低于 -15%、UNKNOWN quote 暴露 <= 20%、过滤比例 < 50%、无 critical risk flag。
|
||||
- [x] 5.11 实现 `PAPER -> COOLDOWN` 默认阈值:最大回撤 < -20%、10 笔后 copyable PnL < -5、quote/source stale > 72 小时或 thin liquidity exit risk。
|
||||
- [x] 5.12 实现 cooldown 恢复和退休规则。
|
||||
- [x] 5.13 实现 locked 候选保护,自动任务不得改变锁定候选的状态、试跟建议、建议配置或冷却/退休状态。
|
||||
- [x] 5.14 新增评分和状态机测试,覆盖全部迁移、边界阈值、锁定保护、source stale、rule version、缺数据 cap、单次大赢 cap 和 critical risk 晋升阻断。
|
||||
|
||||
## 6. Leader 池联动与真钱安全边界
|
||||
|
||||
- [x] 6.1 新增 research 与 `copy_trading_leader_pool` 的映射服务,确保研究状态与 Leader 池状态分离。
|
||||
- [x] 6.2 当研究候选进入 `CANDIDATE` 或更高状态且需要展示时,保守创建或更新 Leader 池项。
|
||||
- [x] 6.3 `TRIAL_READY` 只能在 Leader 池展示“建议小额试跟” badge,不得自动把 Leader 池状态改为 `TRIAL` 或 `ACTIVE`。
|
||||
- [x] 6.4 自动任务不得增加 existing pool 的 suggested fixed amount、suggested max daily loss 或 suggested max daily orders。
|
||||
- [x] 6.5 自动任务不得覆盖用户手工 notes;研究摘要必须写入独立字段或 append-only event。
|
||||
- [x] 6.6 新增 research 专用手动审批服务,从 `TRIAL_READY` 候选创建禁用试跟配置;不得原样复用当前 `LeaderPoolService.createTrialConfig`,除非先重构出 disabled-only 安全 helper。
|
||||
- [x] 6.7 research approval request DTO 不允许暴露 `enabled`、`enableImmediately` 或放宽风控字段;后端组装 `CopyTradingCreateRequest` 时必须强制 `enabled=false`。
|
||||
- [x] 6.8 如果客户端篡改提交 `enabled=true`、更大 fixed amount、更高 max daily loss、更多 max daily orders 或更宽 price range,后端必须拒绝或忽略,并写入 safety research event。
|
||||
- [x] 6.9 创建禁用试跟配置前检查同账户同 leader 是否已有跟单配置,默认拒绝重复创建;双击提交必须只创建一条配置。
|
||||
- [x] 6.10 用户明确创建 disabled trial config 成功后,Leader 池才可以从 WATCH/建议状态进入 `TRIAL`;仅 `TRIAL_READY` recommendation 不得进入 `TRIAL`。
|
||||
- [x] 6.11 创建禁用试跟配置成功后写入 research event,并提供跳转 `跟单配置` 的信息。
|
||||
- [x] 6.12 新增安全测试,覆盖客户端篡改 `enabled=true`、高 fixed amount、放宽风控、locked 候选、重复配置、双击创建、TRIAL_READY 不自动 TRIAL 和 disabled config 创建后 copy_trading.enabled 仍为 false。
|
||||
|
||||
## 7. 后端 API 与错误处理
|
||||
|
||||
- [x] 7.1 新增 `LeaderResearchController`,提供研究运行、候选列表、候选详情、paper session、source health、research events 和手动创建禁用试跟配置 API。
|
||||
- [x] 7.2 所有 research API 必须走现有受保护路由与鉴权边界。
|
||||
- [x] 7.3 新增 research DTO,覆盖 run summary、candidate summary/detail、score components、paper session、paper trade、paper position、source health、event 和 approval response。
|
||||
- [x] 7.4 新增 research 错误码和中英繁 i18n 文案,覆盖 run overlap、candidate not found、candidate locked、not trial ready、source unavailable、paper valuation unavailable、real money activation forbidden。
|
||||
- [x] 7.5 服务内部使用命名错误或明确 result 类型,不得只用 catch-all Exception 表达业务失败。
|
||||
- [x] 7.6 所有源失败、解析失败、状态迁移失败、纸跟失败和审批失败必须写入 research event 或 run error。
|
||||
- [x] 7.7 新增 controller 测试,覆盖所有 API 的成功路径、参数错误、权限/保护边界、业务错误和真钱启用拒绝。
|
||||
- [x] 7.8 手动 run 和创建禁用试跟配置 API 必须有重复提交保护;重复请求返回已有 run/config 或明确拒绝,不得产生重复副作用。
|
||||
- [x] 7.9 候选详情 API 必须分页返回 paper trades 和 research events,不得一次性返回完整历史。
|
||||
- [x] 7.10 API 错误响应必须让前端能区分 `disabled source`、`degraded source`、`valuation unknown`、`candidate locked` 和 `real money activation forbidden`。
|
||||
|
||||
## 8. 前端类型、API 与操作台
|
||||
|
||||
- [x] 8.1 在 `frontend/src/types` 中新增 Leader Research 类型,覆盖状态、source health、score components、paper session/trade/position、events 和 approval request/response。
|
||||
- [x] 8.2 在 `frontend/src/services/api.ts` 新增 `leaderResearch` API 分组。
|
||||
- [x] 8.3 新增 `LeaderResearch` 页面和受保护路由。
|
||||
- [x] 8.4 在左侧菜单合适位置新增 `Leader Research` 或 `Leader 雷达` 入口,避免和现有 `Leader 池` 混淆。
|
||||
- [x] 8.5 操作台顶部展示 Today summary:trial-ready 数、新候选数、新纸跟数、冷却数、source stale 数。
|
||||
- [x] 8.6 实现 Run Status 模块,展示最近运行、耗时、状态、来源统计和失败信息。
|
||||
- [x] 8.7 实现 Pending Decisions 模块,展示 `TRIAL_READY` 候选和手动创建禁用试跟配置入口。
|
||||
- [x] 8.8 实现 Candidate Detail,展示来源历史、score components、paper session summary、risk flags、research events 和 Leader 池映射状态。
|
||||
- [x] 8.9 实现 Paper Sessions/Trades 展示,明确展示 valuation status、quote confidence 和 filtered reason。
|
||||
- [x] 8.10 实现 Source Health 模块,区分 success empty、failure、stale 和 degraded。
|
||||
- [x] 8.11 创建禁用试跟配置前,UI 必须展示 fixed amount、max daily loss、max daily orders、price range 和 max position value,并要求确认。
|
||||
- [x] 8.12 UI 不得把 `TRIAL_READY` 文案表现成已经真实试跟;必须明确“建议小额试跟,待你确认”。
|
||||
- [x] 8.13 新增 zh-CN、zh-TW、en 文案。
|
||||
- [x] 8.14 确保移动端操作台至少可查看 summary、pending decisions 和 candidate detail,不出现不可操作表格。
|
||||
- [x] 8.15 UI 必须展示 activity source limitation:global capture disabled、Data API backfill stale、source degraded 等状态,避免用户误以为系统已经全网自动发现。
|
||||
- [x] 8.16 创建禁用试跟配置按钮必须防双击,提交中禁用,并在重复配置错误时跳转或提示已有配置。
|
||||
- [x] 8.17 Candidate Detail 必须把 `UNKNOWN`、`UNAVAILABLE`、`NO_MATCH`、`CONFIRMED_ZERO` 用不同文案和颜色展示,不能都显示成 0。
|
||||
- [x] 8.18 Leader 池或 Leader Research 的 `TRIAL_READY` badge 必须和真实 `TRIAL` 状态视觉区分,避免用户误以为真钱已开始。
|
||||
|
||||
## 9. 通知与内部事件
|
||||
|
||||
- [x] 9.1 新增 research event 查询与标记通知状态能力。
|
||||
- [x] 9.2 第一阶段在操作台展示内部事件,不强依赖外部通知渠道。
|
||||
- [x] 9.3 新增通知摘要生成服务,基于 research event 聚合新增候选、纸跟达标、建议试跟、冷却、source failure 和 stale data。
|
||||
- [x] 9.4 外部通知发送失败时必须保留 research event,并记录通知失败原因。
|
||||
- [x] 9.5 如果接入现有 Telegram 通知,必须避免硬编码新渠道 secret,并复用现有通知配置读取路径。
|
||||
- [x] 9.6 新增通知测试,覆盖事件生成、摘要生成、发送失败和事件保留。
|
||||
- [x] 9.7 通知摘要必须包含 safety-relevant 事件:source disabled/degraded、valuation unknown、approval rejected、duplicate approval 和 real money activation forbidden。
|
||||
- [x] 9.8 通知事件必须可去重,避免同一候选每轮 research run 重复推送相同 `TRIAL_READY` 或 source failure。
|
||||
|
||||
## 10. 性能、索引与数据保留
|
||||
|
||||
- [x] 10.1 候选列表、paper trade 列表、research event 列表必须分页。
|
||||
- [x] 10.2 研究任务每次运行只处理 active candidates 和新 activity events,不得全量重算全部历史。
|
||||
- [x] 10.3 为所有详情查询路径增加 repository 查询或聚合,避免 N+1 查询。
|
||||
- [x] 10.4 增加 paper/activity 数据保留策略配置,默认保留足够研究窗口但避免无限增长。
|
||||
- [x] 10.5 新增性能相关测试或验证脚本,至少覆盖 100 个候选、1 万条 activity event、1 万条 paper trade 的列表和一次研究运行。
|
||||
- [x] 10.6 research run 必须使用 cursor/checkpoint 记录上次处理到的 event time 或 stable key;失败重跑时只回看有限窗口。
|
||||
- [x] 10.7 paper processing 每批必须有 batch size 上限、运行时间上限和写入上限,避免一次 run 长时间占用数据库。
|
||||
- [x] 10.8 global activity capture 如果启用,必须有每分钟写入上限、payload 最大长度、失败熔断和可观测计数。
|
||||
- [x] 10.9 候选详情必须用聚合 DTO 或批量查询组装 score、paper summary、source health、pool mapping,禁止对列表中每个 candidate 单独查多张表。
|
||||
|
||||
## 11. 文档与运维
|
||||
|
||||
- [x] 11.1 新增中文文档,说明 Leader Research Agent、Leader 池、Leader 管理和跟单配置的区别。
|
||||
- [x] 11.2 文档明确:研究代理可以自动纸跟和推荐,但绝不会自动启用真钱跟单。
|
||||
- [x] 11.3 文档说明研究状态和 Leader 池状态映射,特别是 `TRIAL_READY` 不等于 `TRIAL`。
|
||||
- [x] 11.4 新增运维说明,覆盖开启/关闭 research job、查看 source health、排查 unknown valuation、排查重复 event 和回滚。
|
||||
- [x] 11.5 更新相关 README 或 docs 索引,指向 Leader Research 文档。
|
||||
- [x] 11.6 文档明确 activity-derived discovery 的真实覆盖范围:watchlist/existing leader Data API backfill、global capture 是否启用、public leaderboard 尚未接入。
|
||||
- [x] 11.7 运维说明必须包含 kill switch:关闭 scheduled research、关闭 global activity capture、隐藏 approval endpoint 或前端入口。
|
||||
|
||||
## 12. 验证
|
||||
|
||||
- [x] 12.1 运行后端 research 相关单元测试和 controller 测试。
|
||||
- [x] 12.2 运行已有 Leader 池、跟单配置、PnL 统计相关测试,确保未破坏现有安全边界。
|
||||
- [x] 12.3 运行前端 TypeScript 构建。
|
||||
- [x] 12.4 运行前端 lint。
|
||||
- [x] 12.5 手动验证 research job 默认关闭、手动 run、source health、候选列表、候选详情、纸跟详情和 pending decisions。
|
||||
- [x] 12.6 手动验证创建禁用试跟配置后 `copy_trading.enabled=false`,且不会自动启用。
|
||||
- [x] 12.7 手动验证 source failure 不会删除候选、不会降级 locked 候选、不会把 unknown valuation 展示成 confirmed zero。
|
||||
- [x] 12.8 在本地或测试环境验证重复 activity event 不会产生重复 paper trade。
|
||||
- [x] 12.9 运行 `./gradlew test --tests "*LeaderResearch*"`,覆盖 research service、state machine、paper trading、approval safety 和 controller。
|
||||
- [x] 12.10 运行 `./gradlew test --tests "*LeaderPool*" --tests "*CopyTrading*" --tests "*Pnl*"`,确保现有 Leader 池、跟单配置和 PnL 语义未回退。
|
||||
- [x] 12.11 使用 gstack/browser 或 Playwright 进行前端安全 QA,覆盖 `TRIAL_READY` 文案、disabled approval modal、双击提交、source degraded、valuation unknown 和移动端关键路径。
|
||||
- [x] 12.12 使用 `/qa` 时优先加载 `/Users/codyhhchen/.gstack/projects/WrBug-PolyHermes/codyhhchen-feat-real-pnl-statistics-eng-review-test-plan-20260504-210925.md` 作为主测试输入。
|
||||
- [x] 12.13 验证当前 `PolymarketActivityWsService` 的已知 leader 过滤不会阻断 research ingestion 的未知钱包发现路径。
|
||||
- [x] 12.14 验证 research job kill switch 生效:关闭后不再推进状态、不再处理 paper events,但页面仍可读历史数据。
|
||||
|
||||
## 13. 一次性实施顺序与合并策略
|
||||
|
||||
- [x] 13.1 第一批实现数据 spine:迁移、entity、repository、enum、source state、run record、activity event 和 processing status。
|
||||
- [x] 13.2 第二批实现 ingestion 与 source:Data API backfill、optional global capture、watchlist、existing leaders、activity-derived candidates 和 source health。
|
||||
- [x] 13.3 第三批实现 paper trading:event claim、paper config、BUY/SELL、filter evaluator、valuation、PnL、drawdown 和重试隔离。
|
||||
- [x] 13.4 第四批实现 scoring/state machine:score v1 公式、状态迁移、locked protection、cooldown/retire 和 research events。
|
||||
- [x] 13.5 第五批实现 Leader 池联动和 disabled approval safety:pool mapping、recommendation badge、disabled-only config creation、duplicate protection 和 safety tests。
|
||||
- [x] 13.6 第六批实现 API 和前端操作台:run status、candidate list/detail、paper sessions、source health、pending decisions、approval modal 和 i18n。
|
||||
- [x] 13.7 第七批实现通知、运维文档、kill switch、性能脚本和全量 QA。
|
||||
- [x] 13.8 每一批都必须先补对应测试再合并到下一批;不得把 safety tests 延后到最后。
|
||||
- [x] 13.9 如果并行工作,数据 spine 是共享依赖;paper trading、frontend shell、notification summary 可以并行,但 approval safety 必须等 DTO/服务边界稳定后再接。
|
||||
|
||||
## 14. Review 整改任务
|
||||
|
||||
- [x] 14.1 修复 locked candidate 安全边界:`LeaderResearchStateMachine.advance()` 对锁定候选必须完全跳过状态、score、badge、summary、Leader 池映射和建议配置写入,不得调用会产生副作用的 `syncCandidate`;补充 locked candidate 不变更 pool/candidate/poolId 的回归测试。
|
||||
- [x] 14.2 修复 `DISCOVERED` 候选污染 Leader 池:状态机或 pool mapping 只能在候选达到 `CANDIDATE` 或更高状态时创建/更新 `copy_trading_leader_pool`,原始 `DISCOVERED` 钱包不得出现在 Leader 池;补充 `DISCOVERED` 不建池、`CANDIDATE+` 才建池的测试。
|
||||
- [x] 14.3 修复创建禁用试跟配置的并发重复问题:为同账户同 leader 恢复数据库级唯一保护或引入等价事务锁/幂等键,确保双击、并发请求和重试最多创建一条 copy-trading config;补充并发审批测试和迁移回归测试。
|
||||
- [x] 14.4 修复 Data API backfill 失败被误报为 source success:`backfillWalletActivities` 失败必须向 `captureSource` 返回 typed failure/partial failure,source health 和 research run 必须显示 failure/degraded,而不是 SUCCESS;补充 Data API failure、success empty、partial failure 的 source health 测试。
|
||||
- [x] 14.5 修复前端 approval preview 硬编码风险参数:确认弹窗必须展示后端返回或候选池建议的 `fixedAmount`、`maxDailyLoss`、`maxDailyOrders`、`minPrice`、`maxPrice`、`maxPositionValue`,不得写死 1 USDC/5 USDC/10 orders/0.10-0.80;补充 UI 数据映射测试或浏览器 QA。
|
||||
- [x] 14.6 修复 candidate 搜索只搜当前页:后端搜索必须在数据库查询层按 wallet/address/source/status 等条件过滤并返回正确 total,不得先分页再内存过滤;补充分页外命中、空结果和 total 计数测试。
|
||||
- [x] 14.7 修复 candidate list N+1 查询:列表 DTO 组装必须批量加载 leader、pool mapping、score/paper summary 等依赖,禁止每个 candidate 单独查多张表;补充 50+ 候选列表查询数量或性能回归测试。
|
||||
- [x] 14.8 补齐 Review 发现对应的验证任务:完成后必须运行前端 build/lint、后端 `LeaderResearch` 相关测试、Leader 池/跟单配置/PnL 回归测试,并在本机没有 Java Runtime 时先安装或切换到可运行 Java 的环境再执行后端测试。
|
||||
- [x] 14.9 完成未勾选的安全和 QA 任务后再关闭 change:至少覆盖 activity source health、候选来源、研究运行、纸跟、评分状态机、approval safety、controller、通知、数据保留、手动 QA 和浏览器 QA;不得只修 review 代码而保留关键验证项未完成。
|
||||
Reference in New Issue
Block a user