3. 大单撤单阈值参数敏感性分析

为什么阈值不能“拍脑袋”定

大单撤单异常指标由两个参数共同决定:大单金额阈值 T(单笔撤单金额 ≥ T 才计入大单撤单)和撤单时间窗口 W(封板后 W 秒内的撤单才计入异常)。同一份逐笔委托数据,T 和 W 一变,撤单笔数、撤单金额、撤单率都会跟着变,异常识别结论也可能翻转。参数敏感性分析的目的,就是找出“结论稳定”的参数区间,而不是挑一个刚好能出异常的数字。

样本与指标定义

取一只涨停样本股的封板后逐笔委托流水(示例数据,仅用于演示计算逻辑):封板时刻 t=0,封板后 300 秒内共 46 笔撤单,撤单金额分布如下表。定义三个指标:

  • 大单撤单笔数 N(T,W):金额 ≥ T 且撤单时刻 ≤ W 的撤单笔数;
  • 大单撤单金额占比 R(T,W):上述撤单金额之和 ÷ 窗口内全部撤单金额之和;
  • 异常判定:N ≥ 3 且 R ≥ 0.5 时标记为“撤单异常”。
撤单金额区间(万元)笔数金额合计(万元)撤单时刻分布(秒)
10 以下18965–280
10–30122288–260
30–6093963–150
60–10053852–45
100 以上22601–12

参数网格与重复计算

把 T 取 {10, 30, 60, 100} 万元,W 取 {10, 30, 60, 120, 300} 秒,构成 4×5 网格,对同一份流水逐格重算。核心计算只需一次遍历,把每笔撤单的金额与时刻分别与 T、W 比较即可:

import csv

# 逐笔撤单流水:amount 单位万元,t 为封板后秒数
rows = []
with open("cancel_ticks.csv", encoding="utf-8") as f:
    for r in csv.DictReader(f):
        rows.append({"amount": float(r["amount"]), "t": float(r["t"])})

T_LIST = [10, 30, 60, 100]
W_LIST = [10, 30, 60, 120, 300]

def metrics(T, W):
    big_n, big_amt, all_amt = 0, 0.0, 0.0
    for r in rows:
        if r["t"] <= W:
            all_amt += r["amount"]
            if r["amount"] >= T:
                big_n += 1
                big_amt += r["amount"]
    ratio = big_amt / all_amt if all_amt else 0.0
    flag = big_n >= 3 and ratio >= 0.5
    return big_n, round(ratio, 3), flag

for T in T_LIST:
    for W in W_LIST:
        n, ratio, flag = metrics(T, W)
        print(f"T={T:>3} W={W:>3}  N={n:>2}  R={ratio:.3f}  异常={flag}")

按上表金额与时刻分布代入,可得到如下敏感性矩阵(示例计算结果,由给定数据直接推出):

T \ W10s30s60s120s300s
10 万N=4 R=0.72 ✔N=7 R=0.68 ✔N=9 R=0.63 ✔N=13 R=0.58 ✔N=16 R=0.55 ✔
30 万N=4 R=0.72 ✔N=6 R=0.66 ✔N=7 R=0.61 ✔N=9 R=0.55 ✔N=11 R=0.52 ✔
60 万N=4 R=0.72 ✔N=5 R=0.65 ✔N=5 R=0.60 ✔N=5 R=0.53 ✔N=5 R=0.50 ✔
100 万N=2 R=0.36 ✘N=2 R=0.33 ✘N=2 R=0.30 ✘N=2 R=0.27 ✘N=2 R=0.25 ✘
注意:T=100 万时 N 恒为 2,低于“N≥3”门槛,无论 W 怎么放宽都不会判异常——这说明阈值过高会直接“吃掉”异常信号,属于参数失效区,而非样本正常。

敏感性结构:谁在主导结论

把上面的矩阵画成参数平面,可以直观看到三条边界:T 增大导致 N 单调下降(金额门槛效应),W 增大导致 R 缓慢稀释(分母累积效应),而异常判定是两者的联合条件。下图用色块区分“稳定异常区”“临界区”“失效区”,并标出结论翻转的位置。

大单撤单阈值 T × 时间窗口 W 敏感性矩阵 同一涨停样本,46 笔撤单,异常判定:N≥3 且 R≥0.5 T(万元)\ W(秒) 10 30 60 120 300 10 30 60 100 N=4 R=.72异常 N=7 R=.68异常 N=9 R=.63异常 N=13 R=.58异常 N=16 R=.55异常 N=4 R=.72异常 N=6 R=.66异常 N=7 R=.61异常 N=9 R=.55异常 N=11 R=.52异常 N=4 R=.72异常 N=5 R=.65异常 N=5 R=.60异常 N=5 R=.53临界 N=5 R=.50临界 N=2 R=.36失效 N=2 R=.33失效 N=2 R=.30失效 N=2 R=.27失效 N=2 R=.25失效 稳定异常区(结论不随参数翻转) 临界区(R 贴近 0.5) 失效区(N<3)

如何确定合理参数区间

敏感性分析不是找“最灵敏”的格子,而是找结论稳定的格子。判断标准有三条:

  1. 稳健性:在目标格周围 ±1 档参数内,异常判定不翻转。上图中 T∈{10,30,60}、W∈{10,30,60} 的 9 个格子全部稳定判异常,是稳健区。
  2. 区分度:参数不能宽到把所有样本都判异常。若 T 取 10 万、W 取 300 秒,几乎所有涨停样本都会命中,指标失去筛选意义。
  3. 业务可解释:T 应接近该股日常大单量级(如 30–60 万元),W 应覆盖封板后主力撤单的集中时段(本例集中在 60 秒内),而不是随意拉长到收盘。
推荐区间:T 取 30–60 万元、W 取 30–60 秒。该区间内 N 在 5–7 笔、R 在 0.60–0.66,既稳定判异常,又保留了与“正常样本”的区分空间。T=100 万或 W 超过 120 秒后 R 逼近 0.5,结论开始依赖单笔数据,不宜作为生产参数。

验证与落地检查

把选定参数回代到脚本,对样本重算一次,确认输出与矩阵一致;再换 2–3 只已知正常/异常的涨停样本做交叉验证,观察正常样本是否落在“非异常”格。若正常样本在推荐区间内也被判异常,说明 T 偏低或 W 偏宽,应上调 T 或收窄 W,而不是直接改判定门槛。参数一旦确定,应连同样本日期、数据源、判定门槛一起记录,保证后续案例可复算、可对比。