edit | blame | history | raw

---
name: 跟单功能重构
overview: 重构跟单功能以对齐普通合约交易口径:按币数量下单、开平仓完整计入手续费与资金费、引入跟单员申请审核流程、补齐实时持仓与跟单关系展示,并将停止跟单设计为异步全平以支持高并发场景。
todos:
- id: align-follow-qty
content: 把跟单配置与执行口径统一为币数量,完成接口校验和旧字段兼容设计
status: pending
- id: refactor-follow-executor
content: 重构跟单开平仓派生执行器,按普通合约流程复用费用与结算,并加入幂等与批量异步编排
status: pending
- id: async-stop-follow
content: 实现停止跟单异步全平、状态流转、失败重试与结果查询
status: pending
- id: trader-audit-square
content: 完善跟单员申请审核与广场可见性过滤,只展示审核通过的跟单员
status: pending
- id: positions-and-views
content: 补齐跟单用户与跟单员两侧的实时持仓和跟单关系查询接口
status: pending
- id: verify-regressions
content: 验证费用结算、钱包扣退、审核过滤、停止跟单和高并发跟单场景
status: pending

isProject: false

跟单功能重构计划

目标

  • 跟单下单与普通合约完全对齐:使用币数量口径,走同一套保证金、手续费、资金费、持仓结算规则。
  • 跟单员必须先申请、后台审核通过后,才能在跟单广场展示并触发带单逻辑。
  • 跟单用户和跟单员都能看到实时持仓与跟单关系;停止跟单采用异步全平,避免大量用户同时平仓阻塞接口。
  • 在高并发跟单场景下,重构执行编排,避免当前串行循环造成堆积或重复问题。

现状结论

  • 普通合约下单接口 OpenAction.amount 已按“币数量”口径接收,ApiContractApplyOrderController.open 直接写入 ContractApplyOrder.volume
  • 当前跟单配置存的是 TraderFollowUser.volume/volumeMax,语义仍偏“张数/比例”,需要改成“币数量最小值/最大值”并在跟单创建、修改、执行时统一校验。
  • 跟单开仓/平仓目前是在 ContractOrderService 成交后触发 TraderFollowUserOrderServiceImpl.traderOpen/traderClose,但实现偏逐个用户串行生成委托。
  • 跟单员申请/审核基础已存在:ApiTraderController.applyTrader.checked=0AdminTraderController.check 审核;但广场查询侧仍需强制只展示 checked=1

改造范围

方案设计

1. 统一跟单数量口径为币数量

  • TraderFollowUser.volumevolumeMax 的业务语义从“张数/比例”调整为“最小跟单币数量/最大跟单币数量”。
  • API save.actionchangeFollow.action 增加区间校验:最小值 > 0,最大值 >= 最小值。
  • 跟单执行时不再基于“固定张数/比例”推导,而是读取该跟随者配置的币数量直接生成 ContractApplyOrder.volume / volumeOpen,和普通合约 open.action 保持一致。
  • 对已有 followType 做兼容处理:如果前端和数据库已大量依赖,可先保留字段但废弃“比例跟单”逻辑,仅支持固定币数量模式;旧数据迁移为固定数量。

2. 跟单开平仓对齐普通合约费用与结算

  • 跟单开仓继续复用 ContractApplyOrderService.saveCreate/open,保证金、手续费、资金费、平仓结算统一走普通合约规则。
  • 重点核对并修正跟单相关分支,确保:
  • 开仓从跟单钱包扣保证金和手续费。
  • 平仓时释放保证金、计入平仓手续费和资金费,并回写跟单钱包。
  • 跟单撤单或停止跟单引发的待成交单取消,也走跟单钱包退款,不混用普通钱包。
  • TraderFollowUserOrder 增加足够字段,确保能追踪“跟单关系 + 跟随委托单/持仓单 + 状态 + 停止来源”,支持后续异步全平和重试。

3. 跟单员申请审核与广场展示

  • 复用现有 Trader.checked 状态,不另起新审核框架。
  • 用户申请成为跟单员时写入申请资料并置 checked=0;后台审核后更新 checked
  • 跟单广场和所有可跟随交易员查询统一只返回 checked=1state=1 的交易员。
  • 带单触发处继续使用 findByPartyIdAndChecked(...,1) 兜底,避免未审核用户即使手工构造数据也能触发跟单。

4. 实时持仓与关系展示

  • 跟单用户侧:提供“我当前跟随的交易员 + 当前跟单持仓 + 跟单状态(跟随中/停止中/已停止)”查询。
  • 跟单员侧:提供“我下面有多少跟单用户、每个用户当前持仓、汇总跟单人数/持仓币数量”查询。
  • 查询尽量基于现有 ContractOrder.followTraderFollowUserTraderFollowUserOrder 组合装配,避免新建重复持仓表;确有缺口时只补必要索引或状态字段。

5. 停止跟单改为异步全平

  • cancelFollow.action 改为:
  • 先把 TraderFollowUser.state 置为“停止中”。
  • 收集该用户在该交易员下的未平跟单持仓,异步投递平仓任务。
  • 任务逐笔创建平仓委托,复用现有合约平仓链路。
  • 全部完成后置为“已停止”;失败记录明细并支持重试。
  • 接口返回立即成功,并让前端通过状态查询看到“处理中”。

6. 高并发保护与执行编排

  • 当前 TraderFollowUserOrderServiceImpl.traderOpen/traderClose 为逐用户串行处理,需要重构为“批量拉取跟单关系 + 分片生成任务 + 统一入异步队列”。
  • 保持真正的订单撮合与持仓结算仍走现有合约链路,但将“跟单派生任务”从同步循环改为异步批量编排,降低交易员成交线程阻塞。
  • 增加以下保护:
  • 跟单开平仓任务幂等键:traderOrderNo + followerPartyId + actionType
  • 跟单停止任务幂等键:followRelationId + stopBatchNo
  • 必要的状态流转:跟随中 -> 停止中 -> 已停止
  • 对高频同用户任务增加更细粒度锁,避免重复创建委托

建议数据流

flowchart TD
    traderFilled[TraderFilled] --> dispatchFollow[DispatchFollowTasks]
    dispatchFollow --> followTaskQueue[FollowTaskQueue]
    followTaskQueue --> buildApplyOrder[BuildFollowerApplyOrder]
    buildApplyOrder --> contractCreate[ContractApplyOrderService.saveCreate]
    contractCreate --> contractQueue[NEW_CONTRACT_APPLY_ORDERS]
    contractQueue --> contractHandle[ContractApplyOrderHandleJob]
    contractHandle --> saveOpenClose[ContractOrderService.saveOpenOrSaveClose]

    userStopFollow[UserStopFollow] --> markStopping[MarkFollowStopping]
    markStopping --> stopTaskQueue[StopFollowTaskQueue]
    stopTaskQueue --> closeFollowerOrders[CreateFollowerCloseOrders]
    closeFollowerOrders --> contractQueue
    closeFollowerOrders --> markStopped[MarkFollowStopped]

实施顺序

  1. 先重构跟单配置模型和接口校验,把“币数量最小/最大值”口径固定下来。
  2. 再重构跟单开仓/平仓执行器,使其按币数量直接生成跟单委托,并补齐幂等与异步编排。
  3. 然后补停止跟单异步全平链路和状态流转。
  4. 最后收口跟单员申请审核、广场展示过滤和持仓/跟单关系查询接口。
  5. 补充针对关键交易链路的回归测试或最小可验证用例,重点覆盖费用结算、停止跟单、审核过滤和批量跟单任务幂等。

风险与验证重点

  • 跟单数量口径切换后,历史 TraderFollowUser 数据需兼容;需要明确旧“比例跟单”是否全部废弃并做一次迁移。
  • 跟单撤单、停止跟单、任务失败重试时,必须确认退款/回滚全部走跟单钱包。
  • 当前普通合约处理队列吞吐较低,若跟单用户量大,仅重构跟单编排仍可能受下游单线程消费限制;必要时需要同步评估 ContractApplyOrderHandleJob 的消费能力。
  • 广场查询要同时修复 TraderServiceImpl.getPaged 过滤条件未生效的问题,避免审核状态和展示结果不一致。