Edgekit 需求文档 (PRD)

纯函数式交易执行与监控引擎

Author

Edgekit Team

Published

June 13, 2026

1 概览

1.1 项目背景

Edgekit 用数学手段管理交易资金的乘法过程,避免执行不当导致的结构性破产。项目动机见为什么做 Edgekit

Important规格写在这里

具体的公式、参数和算法都定义在本文档。其余文档各有分工,引用这里的规格而不另立定义:why 说明为什么这么设计,how 讲设计思路,plan 讲怎么落地成代码,README 是概览。

1.2 核心目标

Edgekit 由两个纯函数组成:

  • solver:交易开始前回答”该不该做、单笔该冒多大险”。
  • monitor:交易过程中回答”优势还在不在、要不要停”。

两者之上有一条共同原则:先保住本金。停错了,损失的是机会,可以重来;亏光了,游戏直接结束。所以宁可多停一次,也不能该停的时候没停。

1.3 分层架构

随机性是这个库最需要管住的东西。系统分成三层,边界一句话说清:core 不允许任何随机;tooling 允许随机,但必须显式给种子;policy 是连接两层的配置文件。

内容 随机性
core solver、monitor、engine 换算 禁止,纯确定性函数
tooling 模拟工具(选 xd、标定报警线、校核熔断线) 允许,种子必须显式传入并记录
policy JSON 配置文件,载入后冻结 不适用,记录 tooling 的产物和种子

core 在任何调用链上都不会触发模拟。tooling 算出来的东西只能写进 policy,再由 policy 进入 core。


2 核心定义

2.1 Edge(优势)

优势由两个参数描述:

  • p:胜率
  • RR:盈亏比(平均盈利 / 平均亏损)

优势为正的条件:p \times RR > 1 - p

统计口径:全库的胜率、盈亏比、每笔盈亏,一律指扣除滑点和手续费之后的净结果。交易成本在数据进入系统之前就扣掉,运行过程中不再处理,监控信号也就不会被成本波动干扰。

2.2 风险 (Risk)

风险 = 止损被触发时,账户损失的金额,以 base 的百分比表示。

  • 它不是仓位大小,不是保证金,也不是杠杆。
  • 这个定义默认止损能在止损价附近成交。跳空、闪崩时会失真,见 Section 8

2.3 资本基准 (base)

计算单笔风险时的分母。它不跟着净值实时变动,只按下面的再基准化规则调整。

2.4 再基准化 (x-rebase)

base 什么时候动?两条规则,方向不同:上调慢,下调快。

\text{Equity} \ge x \times \text{base} \implies \text{base} = \text{Equity} \qquad \text{(上调)}

\text{Equity} \le d \times \text{base} \implies \text{base} = \text{Equity} \qquad \text{(下调)}

上调慢,是为了避免完全复利:净值一涨就加码,对参数错误极其敏感。下调快,是为了堵住一个漏洞:如果 base 只升不降,净值下跌后,固定的风险金额占剩余资金的比例会越来越高,相当于越亏越加码。

d 的含义可以精确说出来:base 固定期间,单笔风险金额不变,这笔钱占当前资金的比例最高出现在”即将触发下调”的位置,恰好是 f/df 为风险比例)。所以 d 直接控制最坏时刻的相对风险膨胀倍数d = 0.8 意味着最多膨胀到 1.25 倍。xd 都由模拟联合选定,见 Section 5

只允许这种到达阈值后的一次性调整,不允许部分调整、平滑过渡或取平均。

2.5 每笔结果的计量单位 (X_t)

把第 t 笔交易的盈亏除以这笔交易的风险额,得到的就是交易者常说的”R 倍数”:

  • 止损出场:X_t \approx -1(亏掉一份风险)。有滑点或跳空时会低于 -1,按实际值记录,不截断——比预期更深的亏损正是该停手的证据。
  • 盈利出场:X_t 等于这笔实际实现的盈亏比。

X_t 的长期平均值就是优势本身:\mathbb{E}[X] = p \cdot RR - (1-p)。monitor 盯的就是这个量。

进入监控统计时,盈利一侧截断到 3 \times RR_0 为止,避免一笔超大盈利把已经退化的策略拉回”看起来正常”。截断只影响检验用的统计量,不影响记账。

2.6 当前回撤 (DD)

DD_{current} = 1 - \frac{\text{当前净值}}{\text{净值历史高点}}

注意这是当前离高点有多深,净值涨回去它就变小。不要用”迄今最大回撤”——那个数字只会变大不会变小,时间足够长必然越过任何固定阈值,它反映的是时间长短,不是策略好坏。

2.7 停止与继续的双重标准

Important两个方向的证据标准不一样
  • :一条充分证据就停。回撤碰到熔断线停,统计检验报警也停,互相不需要确认。
  • 继续:宣告”一切正常”需要足够样本(n \ge n_{min});停过之后要恢复,需要人工复核并启用新的 policy。

“多收集几个信号互相印证,免得误判”——这种谨慎只允许用在继续方向,不允许用在停止方向。


3 功能需求:solver

3.1 输入参数

solver 不接受”胜率 0.6”这样的单个数字,要的是”100 笔里赢了 60 笔”。没有样本量,就没有凯利。

参数 类型 说明 范围
wins int 样本中的盈利笔数 ≥ 0
losses int 样本中的亏损笔数 ≥ 0
RR float 盈亏比估计值(净结果口径) > 0
cv_win float 盈利金额的变异系数,可选 > 0,默认 1.0
cv_loss float 亏损金额的变异系数,可选 > 0,默认 1.0
kelly_fraction float 凯利分数 (0, 1],默认 0.5
risk_cap float 风险比例硬上限 (0, 1),默认 0.02
confidence float 置信下限的单侧置信水平 (0.5, 1),默认 0.90

胜率 \hat{p} = \text{wins} / (\text{wins} + \text{losses}) 由 solver 内部计算。

3.2 计算逻辑

思路一句话:不用”你报的胜率”算,用”按你的样本量,胜率保守地说至少有多少”算。样本越少,这个保守值离你报的数字越远,结果越保守;样本足够多,两者趋同。

n = \text{wins} + \text{losses}z 为置信水平对应的单侧正态分位数(90% 对应 z \approx 1.28)。

  1. 胜率的置信下限(Wilson 公式): p_{LB} = \frac{\hat{p} + \frac{z^2}{2n} - z\sqrt{\frac{\hat{p}(1-\hat{p})}{n} + \frac{z^2}{4n^2}}}{1 + \frac{z^2}{n}}
  2. 盈亏比的置信下限(对数正态近似): RR_{LB} = RR \times e^{-z \sigma}, \qquad \sigma = \sqrt{\frac{cv_{win}^2}{\text{wins}} + \frac{cv_{loss}^2}{\text{losses}}}
  3. 把两个下限代入凯利公式: f_{LB} = \frac{p_{LB} \times RR_{LB} - (1 - p_{LB})}{RR_{LB}}
  4. 交易许可:\text{edge\_gate} = (f_{LB} > 0)。按保守值算仍有正优势,才放行。
  5. 风险比例: \text{risk\_fraction} = \min\big(\max(0,\ f_{LB} \times \text{kelly\_fraction}),\ \text{risk\_cap}\big)

保守只靠这一个机制。我们刻意不再叠第二层(比如让凯利分数也随样本量缩小):两个保守机制叠在一起,审计时说不清各自贡献了多少。

Tip数值示例

样本 100 笔,赢 60 笔,盈亏比 1.5:

  • 直接用估计值算:半凯利 = 0.167
  • 用置信下限算:p_{LB} \approx 0.536RR_{LB} \approx 1.155,半凯利 = 0.067
  • 再过硬上限:最终 risk_fraction = 0.02risk_cap 生效)

从 0.167 到 0.02 这条递减链就是审计信息,报告必须把三个数都给出来。

3.3 输出结果

字段 类型 说明
edge_gate bool 是否允许交易
risk_fraction float 推荐的单笔风险比例
report object 见下节
Note

xd 不是 solver 的输出,而是 policy 的输入,由 tooling 离线算好写进去(见 Section 5)。这样 core 不必碰随机数,也就不和”用蒙特卡洛选 x“冲突。

3.4 报告的要求

report 必须包含:

  • 计算依据\hat{p}p_{LB}RR_{LB}、估计值算出的凯利、下限算出的凯利、最终值,以及最后是哪一层约束生效(凯利分数还是 risk_cap)。
  • 敏感度pRR 各变动 ±5%(相对)时,risk_fraction 会变成多少。
  • 上限的代价g(\text{risk\_fraction}) / g(f_{LB}),告诉使用者保守换走了多少理论增长。其中 g(f) = p_{LB}\ln(1 + f \cdot RR_{LB}) + (1-p_{LB})\ln(1-f)

禁止输出”生存概率 97%“这类用估计值直接算出来的数字。所有概率性结论必须注明前提:”假设置信下限对应的参数为真”。


4 功能需求:monitor

monitor 有两道防线。第一道看钱:回撤碰到熔断线,直接停。第二道看统计:每笔结果持续累积证据,证据够了也停。两道防线彼此独立,互相不需要确认。

4.1 输入参数

基线(来自 policy,校验后冻结):

  • p_0RR_0n_0:初始参数(净结果口径)
  • \text{edge}_0 = p_0 \cdot RR_0 - (1-p_0)
  • CUSUM 的参考值 k 和报警线 h(含义见下节;h 没有默认值,必须由 tooling 标定后写入 policy)
  • DD_hard:回撤熔断线,默认 0.30
  • n_{min}:宣告”正常”所需的最少样本,默认 20

运行时输入(每笔显式传入,monitor 自己不保存任何东西):

  • S_{prev}:上一笔之后的累计值,第一笔传 0
  • X_t:本笔的 R 倍数(Section 2.5
  • DD_{current}:当前回撤
  • n:当前样本量
  • \hat{p}\hat{RR}:只用于诊断,不参与判定

函数形如 (\text{baseline}, \text{snapshot}, S_{prev}) \to (\text{state}, \text{risk\_multiplier}, S_t, \text{diagnostics})。累计值从参数进、从返回值出,monitor 本身仍是纯函数。

4.2 累积和检验(CUSUM)

CUSUM 是统计学里检测”分布是否发生了变化”的经典方法。做法:把每笔结果与一个固定参考值的差距逐笔累加。策略正常时,多数交易好于参考值,累计值贴着零;优势消失后,差距持续累积,累计值一路上升,越过报警线就报警。全程是确定的四则运算,每一步都能手工复算。

S_t = \max\big(0,\ S_{t-1} + (k - X_t^{w})\big), \qquad X_t^{w} = \min(X_t,\ 3 \times RR_0)

  • 参考值 k = \text{edge}_0 / 2:取”基线优势”和”零优势”的中点。
  • 报警线 h:由 tooling 模拟标定,标准是健康策略平均至少 ARL_0 笔(默认 500)才误报一次。
  • 它监控的是胜率和盈亏比合在一起的总体表现(X_t 的均值就是优势本身),所以无论胜率下降、盈亏比恶化,还是两边各差一点,都反映在同一个数字里。哪怕只有单一维度恶化也能被发现,不会因为”另外两项还正常”而漏掉。

CUSUM 不是机器学习,也不是在线学习:它不修改任何参数,只是把偏差累加起来和固定的报警线比较。S_t 的完整轨迹本身就是审计记录。

4.3 决策规则

按优先级从上往下,第一条命中即返回:

优先级 条件 状态 risk_multiplier 动作
0 输入违反校验规则 抛错(见 Section 10
1 DD_{current} \ge DD_{hard} INVALID 0.0 PAUSE(回撤熔断)
2 S_t \ge h INVALID 0.0 PAUSE(统计报警)
3 h/2 \le S_t < h DEGRADED 0.5 REDUCE_RISK
4 n < n_{min} INSUFFICIENT_DATA 1.0 HOLD,明示样本不足
5 其余 OK 1.0 HOLD

三个要点:

  • 回撤熔断优先级最高,第 1 笔交易就生效。保护本金不需要样本量,也不接受统计信号否决。
  • 统计报警不受 n_{min} 限制(表里第 2 行在第 4 行之前)。开局连亏十几笔本身就是足够的证据;n_{min} 只拦”宣告正常”,不拦”宣告失效”。
  • “风险减半”是正式输出字段 risk_multiplier,引擎按 risk_fraction × risk_multiplier 执行,不是藏在状态表里的隐含约束。

DD_hard 默认 0.30 的依据:分数凯利下有个近似公式——净值从高点跌掉超过 1-\lambda 的终身概率约为 \lambda^{2/c-1}c 是凯利分数)。按半凯利算,终身碰一次 30% 回撤线的概率约 34%,也就是说健康策略约有三分之一的机会经历一次”白停一次 + 人工复核”。我们接受这个代价:停错了可以恢复,该停没停就回不了头。何况实际执行被 risk_cap 压得远低于半凯利,真实的误触发率比 34% 低得多。tooling 提供按 policy 实际参数的模拟校核(?@sec-sim)。

4.4 诊断(不参与判定)

报警或降档之后,diagnostics 回答”问题出在哪个环节”,供人工复核:

  • 胜率:单侧检验 \hat{p} 是否显著低于 p_0\alpha = 0.05;样本小于 30 用精确二项检验)。
  • 盈亏比:\ln \hat{RR} 的单侧置信上限是否低于 \ln RR_0

胜率检验只看下行:胜率往上偏不是失效,不该报。

4.5 恢复规则

PAUSE 之后,monitor 不提供自动恢复。想恢复,需要人工看过诊断结果,用新的基线参数生成新版 policy:新的 p_0RR_0n_0,重新标定 h,累计值归零。每次恢复都留下版本记录。


5 x 和 d 怎么选(tooling)

x(上调门槛)和 d(下调门槛)由 tooling 的 x_sweep 离线联合选定,写入 policy。

先看两个参数各自控制什么:

  • x 控制复利的节奏。越大,上调越少,越接近”永不加码”:安全但增长慢。越小越接近完全复利:增长快但对参数错误敏感。
  • d 控制最坏时刻的相对风险。base 固定期间风险金额不变,占当前资金的比例最高为 f/dd 越接近 1,下调越及时,相对风险越稳,但跌一点就减码,回本变慢;d 越小,风险金额在回撤里撑得越久,增长快,但最坏时刻下注越重。

两个参数都在”增长”和”安全”之间做交换,而且互相影响(下调过的 base 会改变下一次上调的位置),所以放进同一个模拟里联合选择。算法要素全部固定,照着实现,谁做结果都一样:

  1. 候选网格x \in \{1.1, 1.2, \ldots, 3.0\}(步长 0.1),d \in \{0.70, 0.75, 0.80, 0.85, 0.90\},共 20 \times 5 = 100 个组合。
  2. 路径模拟:每个组合模拟 10,000 条路径 × 500 笔交易,按 policy 的参数和上面的双向调整规则生成净值。
  3. 可行条件:存活率 ≥ 95%。存活 = 整条路径的当前回撤从未碰到 DD_hard
  4. 选择与并列:可行的组合里,取”终值对数的中位数”最大者。与最优值差距 1% 以内算并列;并列时先取更大的 d(最坏相对风险更稳),再取更大的 x(加码更晚)。
  5. 种子:随机数种子显式传入,连同数据生成方式、工具版本一起写进 policy 的 provenance(来源记录)。同一个种子,结果完全一样。

没有任何组合可行时,返回 x = \infty(永不上调)、d = 0.90(最快下调)并告警。

不跑模拟时的缺省值:d = 0.8,含义是”允许最坏相对风险膨胀到 1.25 倍”;想更紧就提高 d(一般地,允许膨胀 m 倍对应 d = 1/m)。x 没有缺省值,必须模拟产出。

模拟用什么方式生成数据(DGP)必须声明。默认:每笔独立,按 p_0 定胜负;盈利幅度服从均值 RR_0、变异系数 cv_win 的对数正态分布;亏损固定 -1。盈亏成串出现的策略(比如趋势策略),独立性假设会低估风险,应改用对真实交易记录的分块重抽样(block bootstrap)。无论用哪种,假设本身要随结果一起输出。


6 系统产出物

6.1 策略配置 (Policy)

用 JSON Schema 定义。Schema 只管字段形状;“载入后不可变”要靠实现保证(比如 frozen dataclass)。必含字段:

字段
基线 p0, RR0, n0
solver 参数 kelly_fraction, risk_cap, confidence, risk_fraction(求解结果)
monitor 参数 k, h, DD_hard, n_min
再基准化 x, d
engine portfolio_cap, gap_multiplier
来源记录 sim_seed, dgp, tool_version, policy_version

6.2 执行引擎 (Engine)

risk_fraction × risk_multiplier 换算成具体品种的仓位,支持现货、杠杆、期货。另有两条账户级约束:

  • 持仓总量约束:所有未平仓位的风险加起来不超过 portfolio_cap(默认 0.06)。几个相关性高的头寸同时止损,是单笔风险定义覆盖不到的最大敞口。
  • 跳空缓冲:容易跳空或带杠杆的品种,设置 gap_multiplier m \ge 1,单笔预算按 risk_fraction / m 执行,相当于预留 m 倍滑点的余地。

6.3 模拟工具 (Sim)

tooling 层,离线运行,种子显式传入:

  • x_sweep:按 Section 5 联合选定 xd
  • calibrate_h:模拟健康策略,找出满足 ARL_0 的报警线 h
  • dd_check:校核 DD_hard 在当前 policy 参数下的误触发概率。

7 默认参数总表

参数 默认值 所属 依据
kelly_fraction 0.5 solver 用约 1/4 的增长换一半波动(见 why
confidence 0.90(单侧) solver 保守性与可用性的平衡
risk_cap 0.02 solver 机构常规单笔风险是 0.25%–2%;0.02 落在上沿,连亏约 35 笔才腰斩
cv_win, cv_loss 1.0 solver 没有更好证据时的保守缺省
k \text{edge}_0/2 monitor 基线优势与零优势的中点
h 无默认,必须标定 monitor calibrate_hARL_0 产出
ARL_0 500 笔 tooling 健康策略的平均误报间隔
DD_hard 0.30 monitor Section 4.3
n_{min} 20 monitor 宣告”正常”的最少样本
盈利截断 3 \times RR_0 monitor 防单笔大赚掩盖退化
x 无默认,模拟产出 policy Section 5
d 0.8(不跑模拟时的缺省) policy 最坏相对风险最多膨胀 1.25 倍;模拟时与 x 联合选定
portfolio_cap 0.06 engine 持仓风险总量上限
gap_multiplier 1.0 engine 流动性好的现货;易跳空或带杠杆的品种应大于 1

8 适用前提

以下四个前提是全库结论成立的条件。前提不成立,结论也不成立,所以必须写明:

  1. 止损能够成交。 跳空、闪崩、流动性枯竭时,实际亏损会超过 risk_fraction,杠杆进一步放大。这类风险无法消除,只能缓解:gap_multiplier 预留缓冲、portfolio_cap 限制总敞口、超出预期的亏损原样计入监控统计。
  2. 输入已扣除交易成本。 胜率、盈亏比都指扣除滑点和手续费之后的净结果。用未扣成本的数字,所有结论都会偏乐观。
  3. 置信下限只能应对样本不足。 回测过拟合、幸存者偏差、市场环境变化,它都应对不了。库的输出质量,上限由用户输入的质量决定——这句话要写在用户文档最显眼的位置。
  4. 模拟默认每笔交易相互独立。 盈亏成串出现的策略风险会被低估,应改用分块重抽样。

9 技术约束

9.1 纯函数要求

  • core:同样的输入(包括显式传入的 S_{prev} 和 policy)必须得到同样的输出。不允许随机、时间依赖、外部 IO;所有状态走参数和返回值。
  • tooling:同样的种子必须得到同样的输出。

9.2 禁止清单

  • 在线学习:不允许在运行中自动调整 pRR
  • 赌徒谬误:不允许按最近的胜负序列调整仓位。
  • 逻辑蔓延:不允许加入未经数学审计的”聪明”规则。
  • core 触发模拟xdh 这类模拟产物只能经 policy 进入 core。

两点澄清,避免误判:CUSUM 是确定性的经典统计检验,每一步都能手工复算,不属于”在线学习”;risk_multiplier 由统计检验触发,依据的是检验结果而不是最近几笔的输赢,不属于”按胜负序列调仓”。


10 校验规则与质量标准

哪些输入直接报错、哪些输入正常返回”别交易”,分两张清单,不再含糊。

第一张:结构非法,校验期抛错。 这些值在任何语义下都不可能合法:

输入 非法条件
wins, losses, n, n0 负数或非整数
RR, RR0 \le 0
p0 不在 (0, 1) 开区间内(基线退化成必胜或必输,没有监控意义)
kelly_fraction 不在 (0, 1]
risk_cap, confidence, DD_hard, d 超出各自声明的区间
DD_{current} 不在 [0, 1)

第二张:证据不足或优势不存在,运行期降级。 输入本身合法,结论是”别交易”或”没法判断”:

情形 行为
wins = 0 edge_gate = False,报告注明
losses = 0(盈亏比的不确定性估不出来) edge_gate = False,报告注明证据不足
f_{LB} \le 0 edge_gate = False
monitor 收到 n < n_{min} 且无报警 INSUFFICIENT_DATA,既不宣告正常也不宣告失效

划分原则:构造上就非法的(类型错、范围越界)一律抛错;输入合法但证据不支持交易的,正常返回并降级。p_0 = 0 这种属于构造非法(抛错),wins = 0 这种属于证据不足(降级),两者不要混为一谈。

10.1 质量标准

  • 可审计:每个输出附带完整的计算过程;CUSUM 轨迹、置信下限的推导链、哪层约束生效,都能追溯。
  • 报告要求:见 Section 3.4
  • 一致性:其他文档只引用、不重复定义本文的规格;一旦出现漂移,按缺陷修复,对齐回本文。