AlphaQuant-Bot · 通用自动化合约交易框架 v1 · 15 个模块

模块技术选型 · 字段与设计要点

⬡ claude-opus-4-7 · 2026-05-20

基础层

宿主 · 协调层
L0 MultiSystemRunner
技术选型
  • asyncio + asyncio.TaskGroup(Python 3.11+):每个 SystemInstance 作为独立 Task,TaskGroup 提供结构化并发,子任务异常不会静默吞掉
  • signal.signal(SIGTERM/SIGINT) + asyncio.Event 实现优雅退出:收到信号后置位 shutdown_event,各模块在循环中检查
  • contextvars.ContextVar 注入 system_id / symbol,配合 structlog 自动给每条日志打标签,多系统日志不混淆
  • 不用多进程/多线程:CCXT 异步版本(ccxt.async_support)+ websockets 已足够,单进程调试链路最短
输入契约
字段类型说明
system_configs
系统配置列表
list[SystemConfig]各系统实例配置列表
shared_hubs
共享上下文
SharedContext包含 MarketDataHub、TrendResultCache、KeyLevelCache、SymbolStrategyRegistry、RiskController、RevengeController 的共享上下文
输出契约
字段类型说明
runtime_status
运行状态
dict[system_id, SystemRuntimeStatus]每个系统的运行状态:RUNNING/STOPPED/ERROR、last_heartbeat、last_error
shutdown_report
关机报告
ShutdownReport优雅退出时各系统的持仓快照、未完成订单清单
关键设计点
故障隔离

单个 system 抛异常不能拖垮全局。每个 SystemInstance 外层包 while not shutdown: try: await run() except: log + sleep(backoff) + continue,崩溃次数超阈值才真正下线

心跳与僵尸检测

每个 system 必须周期性更新 last_heartbeat,Runner 主循环检测 >N 分钟没心跳的 system 强制重启。asyncio 死锁/await 卡死时只靠异常捕获救不回来

启动顺序

MarketDataHub → Cache → Registry → 各 SystemInstance。SystemInstance 启动时必须等 Hub 至少有一份完整 K 线快照,否则首轮分析会拿到空数据

架构已定 · 当前版本暂缓
L0 RiskController
技术选型
  • 状态用 dataclass + aiofiles 持久化到 JSON(risk_state_YYYYMMDD.json),进程重启不丢失当日累计亏损
  • 日界切换用 pytz + 用户配置的 risk_timezone,跨日时归零并归档旧日文件
  • asyncio.Lock 保护亏损累加,避免多个 system 同时平仓时竞态写入
输入契约
字段类型说明
symbol
交易对
str交易对
system_id
系统ID
str发起方系统 ID
intended_position
预期持仓
PositionIntent含 entry/stop/qty,用于计算最大潜在亏损
current_account_state
账户状态
AccountState当前余额、已用保证金
输出契约
字段类型说明
decision
风控决策
Literal["ALLOW","REJECT_SYMBOL_DAILY","REJECT_ACCOUNT_DAILY","REJECT_DRAWDOWN_LEVEL_N"]是否允许开仓
remaining_budget
剩余可亏额度
dict[str, Decimal]该 symbol 剩余可亏额度、账户剩余可亏额度
cooldown_until
熔断解除时间
datetime | None触发熔断后的解除时间
关键设计点
以"已实现亏损 + 未实现最大潜在亏损"为准

只看已实现亏损会让仓位叠加突破上限,必须把当前持仓的 stop 距离也算进"理论最大亏损"

多级熔断要可逆但有滞回

例如 -3% 暂停 1 小时、-5% 暂停当日;恢复时检查是否仍处亏损区间,避免 ping-pong 反复解禁

持久化时机

每次累加完立即 flush,不能依赖进程退出钩子(kill -9 拿不到)

架构已定 · 当前版本暂缓
L0 RevengeController
技术选型
  • 内存中维护 revenge_events: dict[event_id, RevengeEvent],event_id = hash(symbol + direction + price_bucket + time_bucket)
  • 价格重叠判定:abs(level_a - level_b) / mid < 0.004(±0.4%)
  • sortedcontainers.SortedList 按时间戳索引,超 4 小时的事件自动剔除(懒删除)
输入契约
字段类型说明
symbol
交易对
str交易对
direction
做单方向
Literal["LONG","SHORT"]做单方向
key_level
关键位
KeyLevel含 zone_low/zone_high 的价格区间
system_id
系统ID
str发起方系统 ID
proposed_qty
请求仓位
Decimal请求的仓位大小
输出契约
字段类型说明
event_id
复仇事件ID
str归属的复仇事件 ID
allowed_qty
允许仓位
Decimal分配给本次请求的配额(可能被压缩)
event_state
事件状态
RevengeEventState已用配额、参与系统列表、首次触发时间
关键设计点
关键位重叠用区间相交,非中心点距离

用户关键位本身是矩形区间,必须用区间 IoU 或边界距离判定,否则"宽区间"会被误判为不重叠

配额先到先得 + 留 buffer

首个系统拿主配额(如 60%),后续系统按剩余均分,避免单系统垄断复仇配额

事件合并而非创建

新请求来时先查是否落入已有 event 的重叠区间,落入则合并而非新建,防止同一关键位被切成多个独立事件

共享数据层

K 线统一拉取 · 去重共享
L1 MarketDataHub
技术选型
  • ccxt.async_support:REST 拉历史 K 线做冷启动,WS 增量更新 last bar
  • 内存结构:dict[(symbol, timeframe), pandas.DataFrame],index=close_time(UTC ms),列=[open, high, low, close, volume]
  • asyncio.Lock per (symbol, tf) 防止读写冲突;订阅者用 asyncio.Event 通知新 bar 闭合
  • 持久化:每个 (symbol, tf) 落一个 parquet 文件(pyarrow),重启时增量补齐到当前时间
输入契约
字段类型说明
subscriptions
订阅列表
list[tuple[symbol, timeframe]]全局去重后的订阅列表
kline_window
K线窗口大小
int每个 (symbol, tf) 维持的最大 bar 数(滑动窗口)
输出契约
字段/方法类型说明
get_klines(symbol, tf, n)
获取K线
DataFrame最近 n 根已闭合 K 线
on_bar_close(symbol, tf)
K线闭合监听
AsyncIterator[Bar]异步迭代器,每根新闭合 K 线推送一次
Bar
K线数据体
dataclassopen_time, close_time, o, h, l, c, v, is_closed
关键设计点
只在 K 线"闭合"时触发下游

WS 推的是 tick 级更新,必须等 close_time 抵达才视为新 bar,否则下游拿到反复变动的"未完成 bar"导致信号抖动

时间对齐用交易所 close_time

所有 timeframe 用交易所返回的 close_time(UTC ms),不要本地时间戳。多 timeframe 联动时,下游必须用 close_time 而非序号对齐

断线重连补洞

WS 断开重连后必须用 REST 比对最后一根 bar 的 close_time,缺失的中间 bar 用 fetch_ohlcv 回补,否则 EMA/趋势线类指标会错位

趋势计算结果缓存
L1 TrendResultCache
技术选型
  • 内存 dict[cache_key, TrendResult] + cachetools.TTLCache 或自实现按 source_close_time 淘汰
  • cache_key = (symbol, timeframe, method, params_hash),params_hash = hashlib.md5(json.dumps(params, sort_keys=True)).hexdigest()[:8]
  • 持久化:msgpack 落盘到 cache/trend/{symbol}_{tf}_{method}.msgpack,重启复用,支持回测
输出契约(TrendResult 字段)
字段类型说明
direction
做单方向
Literal["UP","DOWN","RANGE"]趋势方向
stageLiteral["initiation","extension","pullback","reversal"]趋势阶段
extreme_price
极值价格
Decimal当前趋势的极值
extreme_time
极值时间
int极值出现的 close_time(UTC ms)
pullback_depth
回调深度
Decimal | None回调深度(占趋势幅度比例),仅 pullback 阶段有值
source_close_time
源K线收盘时间
int产生该结果的最新 K 线 close_time
computed_at
计算时间戳
int计算时间戳
algo_version
算法版本
str算法版本号,用于 cache 失效判定
关键设计点
失效判定用 source_close_time

同一 timeframe 在 close_time 不变时结果必然一致,用 wall time TTL 会浪费算力或拿到过期值

params_hash 必须稳定

浮点参数要 round 到固定精度(如 6 位)后再 hash,否则 1.0 vs 1.0000001 会击穿缓存

回测可复用性

cache 文件要带版本号字段 algo_version,算法升级时旧 cache 自动失效但保留供 A/B 对比

关键位识别结果缓存
L1 KeyLevelCache
技术选型
  • 与 TrendResultCache 同构,但 entry 含 source_close_times 列表(关键位由多根 K 线推导)
  • 示例 key:BTCUSDT_H4_swing_high_low_a3f2c1(symbol_tf_method_paramshash)
  • 失效策略:参与计算的任一源 K 线 close_time 变化即整条失效(关键位对源数据高度敏感)
输出契约(KeyLevel 字段)
字段类型说明
zone_low
区间下边界
Decimal区间下边界(不是单点,强制规范)
zone_high
区间上边界
Decimal区间上边界
zone_type
支撑/阻力类型
Literal["support","resistance"]支撑或阻力
touch_count
触碰次数
int历史触碰次数
last_touch_time
最近触碰时间
int最近一次触碰的 close_time
strength
综合强度评分
Decimal综合强度评分(触碰次数 × 时间衰减)
origin_method
来源算法
str产生该关键位的算法名
is_historical
是否历史强位
bool是否为历史强位(超出当前价格一定距离)
关键设计点
关键位必须是区间(zone_low / zone_high)

所有上下游必须用双值区间,禁止单点。PlanModule 计算止损时用 zone 边界 + buffer,不用 zone 中心

历史关键位强制保留

超过当前价格相当距离的历史强位(touch_count ≥ 3)仍要输出,标记 is_historical=True,用于图表显示和止盈目标

去重合并近邻关键位

不同 method 产生的近邻关键位(区间重叠 >50%)要合并,避免 PlanModule 看到密集"假关键位"

交易对路由
L1 SymbolStrategyRegistry
技术选型
  • YAML 配置文件 registry.yaml,pydantic v2 解析校验
  • 运行时数据结构:dict[symbol, list[SystemBinding]],反查 dict[system_id, list[symbol]]
  • 热更新:watchfiles 监听文件变化,diff 出新增/移除后通知 MultiSystemRunner
输出契约(方法)
方法返回说明
get_systems_for_symbol(symbol)
查交易对关联系统
list[system_id]查询该交易对激活了哪些系统
get_symbols_for_system(system_id)
查系统关联交易对
list[str]查询该系统跟踪哪些交易对
get_all_subscriptions()
获取全部去重订阅
set[tuple[symbol, timeframe]]供 MarketDataHub 去重订阅
关键设计点
双向索引

一个 symbol 可能同时被多个 system 跟踪(这正是 RevengeController 存在的前提),数据结构要同时支持 symbol→systems 和 system→symbols 查询

热更新的事务性

变更必须原子生效,建议 swap 引用而非原地修改,否则可能出现"某 symbol 暂时无系统跟踪导致持仓失监控"

系统接口层

系统实例配置 Schema
L2 SystemConfig
技术选型
  • pydantic.BaseModel v2:类型校验 + 字段约束 + JSON Schema 导出
  • pydantic-settings 支持 yaml/env 双源加载
  • @field_validator 校验 timeframe 合法性、symbols 格式(BTC/USDT:USDT 永续合约写法)
  • method 配置用 discriminated union:{type: "ema_combo", params: {...}},pydantic 按 type 路由到对应子 Schema
Schema 字段
字段类型说明
exchange
交易所
Literal["binance","bybit",...]交易所
symbol
交易对(实例参数)
str启动实例时传入,不在配置文件中定义。同一份配置可复用于不同交易对
trend_timeframe
趋势分析周期
str趋势级别,如 "4h"
main_timeframe
主交易周期
str主级别,如 "15m"
kline_window
K线窗口大小
intK 线窗口长度
trend_method
趋势分析方法
TrendMethodConfigdiscriminated union:含 type + params
keylevel_method
关键位识别方法
KeyLevelMethodConfigdiscriminated union:含 type + params
signal_method
入场信号方法
SignalMethodConfigdiscriminated union:含 type + params
tp_method
止盈算法
TpMethodConfigdiscriminated union;可选:fixed_rr(固定盈亏比倍数)/ keylevel_tp(下一关键位近端,不存在时降级为 fixed_rr)
sl_method
止损算法
SlMethodConfig可选:zone_atr(关键区反向边界外 stop_atr_buffer 倍 ATR)
sizing_method
仓位计算
SizingMethodConfig可选:fixed_risk_pct(qty = balance × risk_pct / |entry − stop|)
trade_direction
做单方向
Literal["TREND_FOLLOW","LONG_ONLY","SHORT_ONLY","COUNTER_TREND"]TREND_FOLLOW:趋势方向一致时才开仓;LONG_ONLY / SHORT_ONLY:单方向;COUNTER_TREND:逆势
risk_pct
风险敞口
Decimal每笔最大亏损占账户余额的比例,如 0.01 = 1%;供 sizing_method 计算仓位用
stop_atr_buffer
ATR 缓冲倍数
Decimal止损在关键区边界外额外留出的 ATR 倍数,默认 0.5
min_rr_ratio
最小盈亏比
Decimal用第一档 TP 计算;低于此值时 PlanModule 短路
auto_trade
是否真实下单
boolFalse(默认):只推通知、记录计划;True:向交易所发送真实订单
session_end_time
会话结束时间
str | NoneUTC 时间字符串,如 "23:00";到达后不再新开仓
discord_webhook
Discord 通知地址
str | NoneNotifier 推送信号、成交、平仓三类通知
关键设计点
timeframe 校验要去交易所拉

不是所有交易所支持所有周期(Bybit 没有 2h),启动时调用 exchange.timeframes 校验,避免运行期才报错

参数 hash 化

SystemConfig 要能产生稳定的 config_hash,供 TrendResultCache/KeyLevelCache 作为 params_hash 来源,保证缓存 key 唯一

流水线模块(可插拔)

趋势判断 · 整体替换实现
M1 TrendModule
技术选型
  • pandas + numpy 做 K 线计算;EMA 用 pandas.Series.ewm
  • 形态识别(Vegas 隧道、趋势线)用纯 numpy 向量化,不引入 ta-lib(C 依赖部署麻烦)
  • 算法注册表:TREND_METHODS: dict[str, Callable[[DataFrame, params], TrendResult]],可插拔
  • 可选算法:裸K结构、EMA组(三均线/Vegas隧道)、趋势线、形态识别(高低点序列)
输入契约
字段类型说明
klines
K线数据
DataFrame来自 MarketDataHub 的趋势级别 K 线
params
算法参数
dict算法参数
cached_result
缓存结果
TrendResult | None来自 TrendResultCache,source_close_time 未变时直接复用
输出契约(TrendResult 见缓存章节,额外字段)
字段类型说明
should_short_circuit
是否触发短路
booldirection=RANGE 时为 True,下游流水线停止执行
strength
综合强度评分
Decimal | None趋势强度(预留字段,当前版本不输出)
关键设计点
震荡时短路要明确

返回 direction=RANGE 时 should_short_circuit=True,PlanModule 不应被迫处理"无方向"输入

stage 字段语义清晰

pullback_depth 仅在 stage=pullback 时有意义,其他阶段为 None,避免下游误用非法值

strength 预留但隐藏

当前版本 strength 不参与下游逻辑,但 dataclass 保留字段,避免后续加字段触发上下游重构

关键位识别 · 整体替换实现
M2 KeyLevelModule
技术选型
  • 摆动高低点:scipy.signal.argrelextrema 或自实现 N 根左/右 fractal 判定
  • 整数关口/均线:直接计算 EMA200 等并构造 zone,zone 宽度 = k * ATR(N) 自适应波动率
  • 区间合并用排序 + 扫描线(关键位数量通常 <100,简单实现足够,无需区间树)
  • 算法注册表:KEYLEVEL_METHODS: dict[str, Callable[[DataFrame, TrendResult, params], KeyLevelResult]]
输入契约
字段类型说明
klines
K线数据
DataFrame主级别 K 线
trend_result
趋势结果
TrendResult用于过滤无效方向的关键位(上行趋势只保留 support)
params
算法参数
dict算法参数
cached_result
缓存结果
KeyLevelResult | None来自 KeyLevelCache,source_close_times 未变时复用
输出契约(额外字段)
字段类型说明
levels
关键位列表
list[KeyLevel]KeyLevel 见缓存章节
age_bars
新鲜度(距当前K线数)
int关键位距当前 K 线的 bar 数,衡量"新鲜度"
should_short_circuit
是否触发短路
boollevels 为空时为 True
关键设计点
zone 宽度用 ATR 自适应

固定 % 或固定点数在不同币种上失真,用 zone_width = k * ATR(N) 让区间随波动率缩放,同样参数在 BTC 和 山寨币上都能合理运作

trend-aware 过滤

上行趋势中只保留 support zones(阻力位保留供止盈参考),避免给 SignalModule 喂大量逆势位导致信号噪声

入场信号识别 · 整体替换实现
M3 SignalModule
技术选型
  • 形态识别(吞没、锤子、孕线)用纯 numpy 实现,每个 pattern 一个独立函数 detect_engulfing(df) -> bool[]
  • 算法注册表:SIGNAL_METHODS: dict[str, Callable]
  • 信号评分用加权求和(不引入 ML,保持可解释性)
  • 可选算法:金K/银K(蜡烛形态)、K 线结构形态、均线交叉信号
输入契约
字段类型说明
klines
K线数据
DataFrame主级别最近 N 根已闭合 K 线
trend_result
趋势结果
TrendResult用于方向过滤
key_levels
关键位列表
list[KeyLevel]候选关键位
params
算法参数
dict算法参数
输出契约
字段类型说明
signal_type
信号类型
str信号类型,如 "engulfing_bullish"
signal_bar_close_time
信号K线收盘时间
int信号 K 线的 close_time,用于去重
signal_bar_ohlc
信号K线OHLC快照
dict信号 K 线的 OHLC 快照
related_key_level
关联关键位
KeyLevel信号关联的关键位(必须绑定)
direction
做单方向
Literal["LONG","SHORT"]做单方向
confidence
信号置信度
Decimal信号置信度评分(0–1)
raw_features
原始特征值
dict原始特征值,供 ReviewLogger 存档
should_short_circuit
是否触发短路
bool无合格信号时为 True
关键设计点
信号必须绑定 key_level

单纯"K 线形态"不构成信号,必须发生在某个 key_level 的 zone 内或边界,绑定后才进入 PlanModule

只在新闭合 K 线触发

禁止"未闭合 K 线产生信号"导致重复触发,bar_close_time 必须等于本轮 close_time

去重防重单

同一 signal_bar_close_time + 同一 key_level 只能产生一次 signal,防止流水线被重复触发时重复下单

交易计划生成 · 止盈算法可选
M4 PlanModule
技术选型
  • decimal.Decimal 全程,避免浮点精度坑(交易所 price/qty 步长校验严格)
  • 用 ccxt.market(symbol) 拿 precision / limits,对 entry/stop/qty round 到合规精度
  • 仓位 sizing:fixed-fractional,risk_amount = balance * risk_pct,qty = risk_amount / abs(entry - stop)
  • 止盈算法可选:固定比例 TP(min_rr_ratio × stop_distance)或关键位 TP(下一个阻力 zone 边界)
输入契约
字段类型说明
signal
入场信号
Signal来自 SignalModule
trend_result
趋势结果
TrendResult用于止盈目标参考
key_levels
关键位列表
list[KeyLevel]用于关键位 TP 算法
account_state
账户状态
AccountState当前余额,用于仓位计算
params
算法参数
dictmin_rr_ratio, risk_pct, stop_buffer_atr_mult, tp_method
输出契约(TradePlan 字段)
字段类型说明
entry_price
入场价
Decimal入场价(已对齐精度)
entry_type
下单类型
Literal["LIMIT","MARKET"]下单类型
stop_price
止损价
Decimal止损价(zone 外侧 + ATR buffer)
take_profits
止盈档位
list[TakeProfit]止盈档位列表(含 price、qty_ratio)
qty
下单数量
Decimal下单数量(已对齐步长)
rr_ratio
实际盈亏比
Decimal盈亏比(以第一档 TP 计算)
expected_loss
预期最大亏损
Decimal预期最大亏损金额
plan_id
计划唯一ID
str唯一 ID,作为 OrderManager 幂等键
expires_at
计划有效期
int计划有效期(UTC ms),超时未成交则取消
should_short_circuit
是否触发短路
boolrr_ratio < min_rr_ratio 时为 True
关键设计点
止损放在 zone 外侧 + ATR buffer

信号关联关键位是区间,止损必须落在 zone 反向边界外 k * ATR,不能用 zone 中心,否则正常波动会被洗出

盈亏比用第一档 TP 计算

用最远 TP 会虚高 RR,导致大量低质量信号通过 min_rr_ratio 门槛,必须用第一档 TP 保守计算

精度对齐与最小名义价值

qty 必须先按 amount_step round down,再校验 qty * price >= min_notional,否则下单会被交易所拒绝

下单管理 · 状态机
M5A OrderManager
技术选型
  • ccxt.async_support 的 create_order / cancel_order / fetch_order
  • 订单状态机:PENDING → SUBMITTED → FILLED / EXPIRED / CANCELED / REJECTED,用枚举 + 跳转表
  • 本地订单簿用 aiosqlite(SQLite 是文件级,零运维,最适合订单状态机)或 JSON 行式追加
  • WebSocket user data stream 接收 ORDER_TRADE_UPDATE,REST 轮询作为兜底
输入契约
字段类型说明
plan
交易计划
TradePlan来自 PlanModule 的完整交易计划
idempotency_key
幂等键
str防止重复提单,通常用 plan_id
输出契约(OrderRecord 字段)
字段类型说明
order_id
本地订单ID
str本地唯一 ID
exchange_order_id
交易所订单ID
str交易所返回的订单 ID
plan_id
计划唯一ID
str关联的交易计划
status
订单状态
Literal["PENDING","SUBMITTED","FILLED","EXPIRED","CANCELED","REJECTED"]当前状态
filled_qty
实际成交量
Decimal实际成交量
avg_fill_price
成交均价
Decimal成交均价
event
状态变更事件
Literal["FILLED","EXPIRED","REJECTED","CANCELED"]推送给 PositionMonitor / ReviewLogger
关键设计点
幂等键防重单

网络重试/进程崩溃重启时必须用 idempotency_key 查本地状态,已 SUBMITTED 的不再重发,否则极易双倒

WS + REST 双通道兜底

只信 WS 会丢事件(断线期),只用 REST 延迟高,必须两者合一,事件去重用 exchange_order_id + update_time

EXPIRED 处理明确

LIMIT 单到达过期时间未成交要主动 cancel 并标记 EXPIRED,留着会在突变行情中突然成交导致计划失效

持仓监控 · WebSocket 驱动
M5B PositionMonitor
技术选型
  • WebSocket 持仓推送 + 价格推送双订阅(mark price stream)
  • 移动止损用本地计算 + REST 修改止损单,不依赖交易所 trailing stop(各交易所参数不一致)
  • 状态机:OPEN → PARTIAL_TP → MOVED_STOP → CLOSED
  • 单独 asyncio Task,priority 高于分析流水线,确保毫秒级响应
输入契约
字段类型说明
position
持仓信息
Position来自 OrderManager FILLED 事件
plan
交易计划
TradePlan原始计划(含 TP 列表、移损规则)
live_price_stream
实时价格流
AsyncIterator[Price]实时价格流(mark price)
输出契约(PositionEvent 字段)
字段类型说明
type
事件类型
Literal["TP_HIT","SL_HIT","STOP_MOVED","CLOSED"]事件类型
price
触发价格
Decimal触发价格
qty_closed
本次平仓量
Decimal本次平仓量
realized_pnl
本次实现盈亏
Decimal本次实现盈亏
closed_position
完整平仓记录
ClosedPosition平仓后完整记录,传给 ReviewLogger
关键设计点
本地止损 + 交易所止损双保险

仅靠交易所 SL 在闪崩/API 故障时可能滑点严重;本地监控达到 SL 价格立即用市价平仓兜底

移损要原子

先创建新止损单成功,再撤旧单;反过来操作可能瞬间裸奔(无止损单保护)

价格源一致性

判定 TP/SL 必须用与下单同源的价格(mark price vs last price 在合约里差异巨大),必须与 PlanModule 约定一致

复盘归档 · 通知推送
M5C ReviewLogger
技术选型
  • 每笔交易写一个 JSON 文件 reviews/{symbol}/{plan_id}.json,含完整生命周期
  • 同时追加到 reviews/index.ndjson 供后续批量分析(每行一条 summary)
  • 关联快照:触发信号时把 trend_result / key_levels / signal / klines_snapshot 一并存档,回测可复现
  • Discord 通知:aiohttp POST webhook,含交易摘要 + matplotlib K 线图附件
输入契约
字段类型说明
lifecycle
交易生命周期
TradeLifecycle汇总 plan + orders + position_events + close_result
context_snapshot
市场上下文快照
ContextSnapshot触发时的市场上下文(趋势/关键位/信号/K线快照)
输出契约(summary 字段)
字段类型说明
plan_id
计划唯一ID
str
symbol
交易对
str
direction
做单方向
Literal["LONG","SHORT"]
entry / exit
入场/出场价
Decimal实际成交的入场/出场价
pnl / pnl_pct
盈亏金额/百分比
Decimal盈亏金额和百分比
duration
持仓时长(秒)
int持仓时长(秒)
max_favorable_excursion
最大有利幅度 MFE
Decimal最大有利幅度(MFE)
max_adverse_excursion
最大不利幅度 MAE
Decimal最大不利幅度(MAE)
exit_reason
平仓原因
Literal["TP","SL","MANUAL","EXPIRED"]平仓原因
review_file_path
归档文件路径
str完整 JSON 归档路径
关键设计点
MFE / MAE 必须在持仓期间持续更新

最大有利/不利幅度是后续优化止损止盈的关键指标,必须在 PositionMonitor 阶段就持续记录,不能事后从 K 线还原(粒度已丢失)

快照不可变 + 版本化

context_snapshot 一旦写入不再改动,文件名带 schema_version,算法迭代后老 review 仍可读,不会因 Schema 变化报错

失败不阻塞主流程

Discord 推送/文件写入失败要 try/except + 重试队列,归档失败不能影响下一笔交易的执行

跨模块统一约定

与 trading_framework_v1 的差异

对比来源:trading_framework_v1.html(框架接口协议层)vs 本文档(Opus 4.7 技术选型层)。差异分为三类:框架文档有而本文缺失、本文有而框架文档未涉及、字段命名/语义不同。

SystemConfig 框架文档有 · 本文缺失的字段
字段中文名说明补充建议
system_id
系统唯一标识
系统唯一标识 框架文档要求每个系统实例有唯一 ID(如 "sanbuqu_v1"),用于日志标签和状态追踪 需补充
datafeed_lib / datafeed_symbol
数据源配置
数据源配置 框架文档有 datafeed_lib、datafeed_exchange_id、datafeed_symbol、refresh_mode、refresh_delay_seconds 五个数据采集参数 需补充
trend_methods_aux / signal_methods_aux
辅助方法列表
辅助方法列表 框架文档支持主方法 + 辅助方法列表,辅助方法用于信号置信度加权;本文只有单一 method 字段 需补充
trade_direction_policy
顺势/逆势
做单方向策略 框架文档明确区分顺势/逆势交易,逆势需要更高信号质量阈值;本文未体现 需补充
entry_style
左侧/右侧入场
入场时机风格 框架文档区分左侧(首次触碰)和右侧(二次确认)入场,SignalModule 输出 entry_timing.side 与之匹配 需补充
take_profit_strategy_default
默认止盈策略
默认止盈策略 框架文档将止盈策略(KeyLevel / TrailingMA / Equidistant)提升到系统配置层,本文仅在 PlanModule params 中提及 可合并
risk_mode / risk_value / margin_mode / leverage
仓位与杠杆配置
仓位与杠杆 框架文档将 risk_mode(fixed_amount / equity_percent)、leverage、margin_mode 纳入系统配置;本文 PlanModule 仅有 risk_pct 参数 需补充
protection_check_delay_seconds
止损确认延迟
保护参数 框架文档有四个保护参数:止损确认延迟、WebSocket 故障超时、订单取消超时、取消价格缓冲;本文未覆盖 需补充
KeyLevel 字段语义差异
维度框架文档本文档(Opus)
生命周期状态 有 status 字段:ACTIVE / HIDDEN(价格远离超 3×ATR) / EXPIRED(超出 kline_window),支持复活机制 无 status,用 is_historical 布尔值区分当前/历史位,语义更简化
形成原因 有 reasons 字段(列表),记录该关键位形成的多个理由,PlanModule 按 reasons 数量筛选置信度 无 reasons,用 touch_count + strength 替代,但缺少"理由去重计数"逻辑
多周期融合 有 timeframes 字段,记录哪些周期共同确认了该关键位(±0.4% 合并),多周期=更高置信 无 timeframes,仅有 origin_method,跨周期融合逻辑未体现
M3 Signal 框架文档有 · 本文缺失的字段
字段框架文档语义本文差异
signal_subtype
信号子类型
细化信号类型(如 bullish_engulfing 的子类型),用于统计分析 本文无 subtype,仅有 signal_type
pattern_prices
形态K线OHLC
结构化记录形态的 open/high/low/close,止损价直接从 pattern_prices.low/high 取,有明确的固定止损规则 本文用 signal_bar_ohlc(dict),止损规则由 PlanModule 自行计算,不强制绑定形态价格
entry_timing.side
左侧/右侧标记
标记本次信号是首次触碰(左侧)还是二次确认(右侧),与 SystemConfig.entry_style 匹配才通过 本文无此字段,左侧/右侧概念未引入
M4 Plan 逻辑差异
两步入场试价(框架文档有,本文缺失)

框架文档:先按市价(pattern_prices.close)计算 RR,不足则降级为限价单(多头取 low + 50% 回撤,空头对称),两步都不足才短路。本文只提到 entry_type 字段,未定义降级逻辑。

止损固定为形态极值(框架文档有,本文缺失)

框架文档:多头止损 = pattern_prices.low,空头止损 = pattern_prices.high,两步试价期间止损不变。本文使用 zone 外侧 + ATR buffer,是另一种止损方案,与框架文档不同。

reasons 数量阈值(框架文档有,本文缺失)

框架文档:len(unique(reasons)) < threshold 则不生成计划(要求多个理由支撑)。本文依赖 confidence 评分,但无明确的 reasons 计数机制。

字段命名差异

框架文档 → 本文档:
min_risk_reward → min_rr_ratio | stop_loss_price → stop_price | t1_price → take_profits[0].price | position_size → qty

M5A/M5B 框架文档有 · 本文未覆盖的运营保护机制
杠杆确认(OrderManager 下单前)

下单前 REST 查询当前交易所杠杆,与 SystemConfig.leverage 不符时先调用 SET LEVERAGE API,再下单,防止因账户状态遗留导致仓位暴露不符预期。

止损保护确认(OrderManager 成交后)

成交后 15 秒内 REST 确认止损单已存在,若缺失则重新挂单;重试失败触发 emergency_flatten(市价减仓平仓)。

WebSocket 故障安全(PositionMonitor)

WS 断开超过 websocket_failsafe_seconds 且 REST 也失败时,以 stop_loss_price 触发本地市价平仓,记录 close_reason = "connection failsafe"。

跳空价格处理(PositionMonitor)

收到成交通知时,若 filled_price 已穿越 stop_loss_price,立即以实际成交价平仓,不等止损单回调,防止跳空滑点扩大。

每日强制平仓

框架文档要求在配置的每日结束时间按比例强平持仓,本文未提及该机制(PositionMonitor 仅处理 TP/SL/移损)。

本文新增 本文档有 · 框架文档未明确定义的内容
内容说明
MFE / MAE 追踪最大有利/不利幅度在持仓期间持续更新并归档,框架文档 ReviewLogger 仅提"复盘记录",无此字段
plan_id / expires_at本文明确将 plan_id 作为幂等键贯穿 M4→M5A→M5C,框架文档未定义 plan 的唯一标识方案
age_bars(KeyLevel)关键位"新鲜度"(距当前 K 线数),框架文档无此字段
auto_trade(SystemConfig)框架文档隐含此概念但未命名字段;本文明确为 bool 开关
discord_webhook(SystemConfig)框架文档通知渠道未纳入 SystemConfig Schema,本文直接放入配置
MarketDataHub 断线补洞逻辑本文明确用 REST 比对 close_time 回补缺失 bar,框架文档未详细描述
cache 持久化方案(msgpack/parquet)本文明确了 TrendResultCache / MarketDataHub 的持久化格式;框架文档只定义接口不涉及实现