本文档面向首次使用 DeltaLab 的期权投资者,用户需要对期权 Delta 动态对冲有基本的了解,通过本文档可以快速上手进行各种类型期权的动态对冲回测。
pricing/Option_AS.py 使用了 match/case 语法,需要 Python 3.10+。建议 3.11 或更高版本。
| 库 | 用途 |
|---|---|
numpy |
全部数值计算 |
scipy |
Option_Vanilla 用 scipy.stats.norm;GUI 波动率分布图用 scipy.stats.norm |
pandas |
结果表格、Wind/CSV 数据读取 |
matplotlib |
图表展示(GUI 在 gui_app.py 中强制使用 TkAgg 后端) |
Pillow (PIL) |
仅用于 tools/make_icon.py / make_banner.py / make_workflow.py 生成图标与 README 资源;运行 GUI 本身不需要 |
tkinter |
GUI 框架,标准库自带;个别 Linux 发行版需额外安装 python3-tk |
| 库 | 触发条件 | 不装时的影响 |
|---|---|---|
WindPy |
在「数据来源」选 Wind |
选 Wind 模式运行时会抛 ImportError(提示见 pricing/wind_data.py 的 _ensure_wind),需安装 Wind 终端 + Python 插件,并已登录 |
CSV 与模拟模式无 Wind 依赖,可在普通环境下完整使用。
默认 CI 产出的 zip 不带 WindPy(GitHub runners 上没有 Wind 终端)。若要让发布包支持 Wind 数据源,需要在装有 Wind 终端且能 python -c "import WindPy" 的机器上本地打包:
# 确认 WindPy 可用
python -c "import WindPy; print(WindPy.__file__)"
# 本地打包
pyinstaller --noconfirm deltalab.specdeltalab.spec 的 WindPy 段会自动探测:
- import 成功 → 打印
[deltalab.spec] WindPy 已安装, 打入发布包,并通过collect_submodules / collect_dynamic_libs / collect_data_files把 WindPy 一并收入dist/DeltaLab/ - import 失败 → 打印跳过原因,发布包仍可产出,只是 Wind 模式运行时会在
_ensure_wind()里报错
冻结构建运行时,_ensure_wind() 会把原始 ImportError / DLL 加载错误拼进异常文本,并在 sys.frozen=True 时追加一句"请在装有 Wind 终端的机器上重新打包"的提示,方便定位到底是 DLL 丢了还是终端没登录。
GUI 在启动时会按平台自动挑选可用 CJK 字体(见 gui_app.py 顶部字体配置):
- Windows:
Microsoft YaHei/SimHei/SimSun - macOS:
PingFang SC等 - Linux:
Noto Sans CJK SC等
若系统找不到任何 CJK 字体,matplotlib 会回退到 DejaVu Sans,中文会显示为方块;属于显示问题,不影响数值结果。
GUI 启动时会通过 BacktestApp._apply_window_icon() 自动加载 assets/ 下的图标:
- Windows 优先走
assets/deltalab.ico(16/32/48/64/128/256 多尺寸),在任务栏/标题栏表现最佳。 - macOS / Linux 或 Windows 上
.ico加载失败时,回退到assets/deltalab.png+iconphoto()。 - 两个文件都缺失时静默跳过,不影响主流程。
图标、banner、工作流示意图都是用 tools/ 下的脚本生成的(依赖 Pillow),可随时重跑调整外观:
python tools/make_icon.py # 生成 assets/deltalab.png / .ico
python tools/make_banner.py # 生成 assets/banner.png (README 顶部)
python tools/make_workflow.py # 生成 assets/workflow.png (工作流示意图)在仓库根目录执行:
python gui_app.py入口为 gui_app.py 的 main()。窗口默认大小 1600x1000,最小尺寸 1200x720。
- 路径中含中文一般没问题,但若遇到 Wind/CSV 加载失败,可优先排查路径。
- 高 DPI 屏幕下,左侧参数面板已包了 Canvas + Scrollbar,可滚轮浏览,不会出现底部按钮被裁的情况。
主窗口由 _build_ui() 构建并分为左右两栏(ttk.PanedWindow),可拖动中间分隔条。
由上至下分四块:
- 期权类型 —— 选大类与子类型
- 期权参数 —— 随期权大类动态生成的输入框
- 回测设置 —— 数据来源、对冲策略、滑点、合约乘数等
- 运行按钮区 ——
运行回测/保留当前结果到对比/回测结果对比/绘制结构图/ 进度条
| Tab | 内容 |
|---|---|
回测摘要 |
单路径盈亏分解 + Greeks 统计 + 蒙特卡洛分布统计(若有) |
回测结果对比 |
只管理会话内已保留的普通回测快照,并支持实时勾选对比 |
◷ 历史择优 |
独立配置历史候选策略与参数,展示 CSV / Wind 滚动择优结果,并将推荐衔接到单次回测 |
对冲图表 |
6 宫格:标的路径、Delta 与持仓、Gamma、Vega、Theta、累计盈亏 |
波动率分析 |
4 宫格:滚动 RV vs IV、累计 RV、价差、日收益分布 |
盈亏分布 |
仅模拟模式且 n_paths>1 时显示蒙特卡洛分布 |
结构分析 |
点 绘制结构图 后展示当前期权结构和价格 / Greeks 对 S 的扫描曲线 |
每日明细 |
只显示建仓、策略、收盘兜底与终止对冲触发记录的表格 + 导出 CSV |
底部状态栏实时显示「就绪 / 正在运行 / 完成」。
下文中所有参数名、控件值、字符串均直接对应
gui_app.py当前代码,引用时用行内 code 格式。
| 控件 | 选项 | 默认 | 说明 |
|---|---|---|---|
大类 |
香草期权 (Vanilla) / 累计期权 (Decumulator) / 亚式期权 (Asian) / 气囊期权 (Airbag) / 雪球期权 (Snowball) |
香草期权 (Vanilla) |
见 OPTION_CLASSES |
子类型 |
跟随大类切换 | 各大类的第一个 | 子类型驱动 optiontype 字段,决定走哪一种 payoff |
各大类的子类型集(见 gui_app.py:OPTION_CLASSES):
- Vanilla:
Eu - Decumulator:
Opt_Decumulator_Back/Opt_Decumulator_Fix/Opt_EnDecumulator/Opt_EnDecumulator_Fix/Opt_ASGQ_call_put/Opt_ASGQ_EP/Opt_ASGQ_EF/Opt_ASGQ_DP/Opt_ASGQ_DF - Asian:
Asian/EnhanceAsian - Airbag:
Opt_Airbag - Snowball:
Opt_Snowball
每个子类型的 payoff 公式见 gui_app.py:STRUCTURE_DOCS,也会在「结构分析」Tab 顶部展示。
每个字段默认渲染为一个 Entry,初始值取自 OPTION_CLASSES[...]["params"] 的 default;空字符串会被解释为 0(见 _collect_gui_state)。若参数元组带有第 5 项 choices 映射(例如 cp),则改渲染为只读 Combobox,_collect_gui_state 会按映射将显示文本还原为内部数值。
| 参数 | 含义 | 类型 | 默认 |
|---|---|---|---|
s0 |
初始价格 S0 | float | 100.0 |
K |
行权价 | float | 100.0 |
T_days |
期限(交易日) | int | 22 |
sigma |
波动率(年化,小数) | float | 0.18 |
cp |
方向,下拉选择 看涨 (Call) / 看跌 (Put),内部映射为 1 / -1 |
int | 1(看涨) |
r |
无风险利率 | float | 0.03 |
q |
分红率 | float | 0.03 |
定价走 BS 封闭解(Option_Vanilla.blsprice)。
| 参数 | 含义 | 类型 | 默认 |
|---|---|---|---|
s0 |
初始价格 | float | 100.0 |
K |
行权价 | float | 90.0 |
T_days |
剩余期限(交易日) | int | 20 |
T_over |
已过天数 | int | 0 |
sigma |
波动率 | float | 0.18 |
H |
障碍价格(敲出/熔断) | float | 110.0 |
N |
杠杆倍数(跌破 K 后) | int | 2 |
cp |
方向,下拉选择 看涨 (Call) / 看跌 (Put),内部映射为 1 / -1 |
int | 1(看涨) |
fix |
固定赔付(*_Fix 子类型用) |
float | 0.0,传 0 → 视为未设置(None) |
P |
保障价格(ASGQ_*P 用) |
float | 0.0,传 0 → None |
amount |
固定金额(ASGQ_*F 用) |
float | 0.0,传 0 → None |
r / q |
利率 / 分红 | float | 0.03 / 0.03 |
nPath |
MC 路径数 | int | 100000 |
注意 fix / P / amount 的「0 当 None」是在 OPTION_CLASSES["累计期权"]["build"] 里做的,对应不需要这些字段的子类型可以保留 0。
| 参数 | 含义 | 类型 | 默认 |
|---|---|---|---|
s0 |
初始价格 | float | 100.0 |
K |
行权价 | float | 100.0 |
E |
增强价(仅 EnhanceAsian 用) |
float | 100.0 |
T |
期限(交易日) | int | 22 |
N |
观察日数(取末 N 日均价) | int | 22 |
sigma |
波动率 | float | 0.15 |
cp |
方向,下拉选择 看涨 (Call) / 看跌 (Put),内部映射为 1 / -1 |
int | 1(看涨) |
minPay |
最低赔付 | float | 0.0 |
maxPay |
最高赔付 | float | 999999.0(实际充当 +∞) |
r / q |
利率 / 分红 | float | 0.03 / 0.03 |
nPath |
MC 路径数 | int | 100000 |
| 参数 | 含义 | 类型 | 默认 |
|---|---|---|---|
s0 |
初始价格 | float | 100.0 |
K |
行权价 | float | 100.0 |
KI |
敲入价 | float | 90.0 |
T_days |
期限(交易日) | int | 20 |
sigma |
波动率 | float | 0.18 |
pr |
未敲入参与率 | float | 0.8 |
pr_ki |
已敲入参与率 | float | 1.0 |
cp |
方向,下拉选择 看涨 (Call) / 看跌 (Put),内部映射为 1 / -1 |
int | 1(看涨) |
r / q |
利率 / 分红 | float | 0.03 / 0.03 |
nPath |
MC 路径数 | int | 100000 |
观察日默认取 range(1, T_days+1)(每日观察),见 OPTION_CLASSES["气囊期权"]["build"]。
| 参数 | 含义 | 类型 | 默认 |
|---|---|---|---|
s00 |
入场价 / 期初名义价格,票息与亏损封顶基准 | float | 100.0 |
s0 |
当前价格 / 回测参考价 | float | 100.0 |
K |
敲入后到期亏损参考价,通常等于 s00 |
float | 100.0 |
KI |
敲入价,雪球向下敲入,反雪球向上敲入 | float | 80.0 |
KO |
期初敲出价,配合 ko_step 可形成降敲序列 |
float | 103.0 |
T |
剩余期限(交易日) | int | 243 |
first_obs_d |
首次敲出观察日,支持预设或手填交易日数 | int | 63 |
obs_period_d |
敲出观察间隔,支持预设或手填交易日数 | int | 21 |
ko_step |
每个观察期 KO 递减点数,0 表示平敲 |
float | 0.0 |
sigma |
波动率 | float | 0.15 |
coupon |
未敲入未敲出到期票息率(年化) | float | 0.15 |
coupon_ko |
敲出票息率(年化) | float | 0.15 |
margin_call |
保证金模式,下拉选择 追保(亏损不封顶) / 不追保(有限亏损) |
int | 1(追保) |
margin |
不追保模式下最大亏损封顶比例,亏损封顶为 margin × s00 |
float | 0.2 |
cp |
方向,下拉选择 雪球 (卖看跌) / 反雪球 (卖看涨),内部映射为 -1 / 1 |
int | -1 |
r / q |
利率 / 分红 | float | 0.03 / 0.03 |
nPath |
MC 路径数,需为正偶数 | int | 20000 |
GUI 当前使用交易日计息 (act=1);敲入逐日观察,敲出按 first_obs_d + obs_period_d 生成观察日,并强制最后一次观察落在到期日。回测路径已知时,若观察日触发 KO,HedgeBacktest 会在敲出日提前截断并以敲出票息结算。
数据来源 是单选 Radiobutton,三选一:
| 值 | 标签 | 默认 |
|---|---|---|
simulate |
模拟 | ✓ |
csv |
CSV | |
wind |
Wind |
切换数据来源时,_toggle_source 会动态显示对应参数子区。bar 粒度按数据源管理:
模拟来源显示可选的「模拟采样 bar/日」;Wind 显示「行情采样粒度」,用于决定向
Wind 请求何种行情;CSV / Wind 都不提供每日 bar 数输入框,真实行情由底层按
返回时间索引和交易 session 自动推导(最终实际为日频时固定为 1)。
| 字段 | 含义 | 默认 |
|---|---|---|
种子 |
numpy default_rng 的基础种子 |
42 |
已实现波动率 |
用于生成路径的真实 σ;空 = 用期权 sigma(隐含) |
""(空) |
模拟路径数 |
MC 路径数。>1 时启用蒙特卡洛多路径分析;其中第一条用作主单路径展示 |
10 |
模拟采样 bar/日 |
每个模拟交易日生成的价格采样点数;控制路径离散化和固定间隔策略的触发检查粒度 | 1 |
调高
模拟路径数会显著放慢运行(路径数 × 单路径回测耗时),但能稳定盈亏分布、对冲误差等统计量。Per-path MC 种子:多路径模式下每条路径都有独立的
option.mc_seed = base_seed + path_idx(hedge_backtest.py:277-282),避免所有路径共用同一批 MC 采样而人为压窄分布。整体仍可复现(固定base_seed即可),但子样本之间相互独立。
| 字段 | 含义 | 默认 |
|---|---|---|
文件 |
CSV 路径,旁边有 浏览… 按钮 |
空 |
价格列 |
CSV 中收盘价列名 | close |
底层走 HedgeBacktest.from_csv。日期列默认取第一列
(pd.read_csv(parse_dates=[0]))。仅日期索引按日频处理;带完整时间戳的日内
CSV 会按真实交易日组自动推导每日 bar 数,GUI 不提供手工覆盖。
| 字段 | 含义 | 默认 |
|---|---|---|
代码 |
Wind 标的代码 | 510050.SH |
建仓日 |
期权建仓日(含)。勾选倒推时置灰只读,直接显示倒推结果 | 由截止日倒推 |
按数据截止日倒推 |
按期权剩余期限沿交易日历从截止日往前定位建仓日 | 开启 |
数据截止日 |
日期主控,也是自动倒推口径下的到期日(含) | 最近一个已收盘交易日 |
行情采样粒度 |
只读:披露本次按策略推导出的 Wind 日频 / 分钟 bar | 按策略自动 |
底层走 HedgeBacktest.from_wind。股票 / ETF 等普通单序列使用 "F"(前复权);
明确的具体期货合约使用不复权行情,避免对单一交割合约施加连续合约复权。Wind
日频的每日 bar 数为 1;分钟行情会结合实际返回的时间索引和品种交易 session
自动推导。
日期口径与历史择优同向:截止日往前推,而不是建仓日往后补。倒推走
pricing.trade_calendar(本地 data/tradingday.csv 离线优先),因此两端都落在
真实交易日上;日历没覆盖到截止日时直接报错,而不是拿旧日历末尾当锚点。默认截止
日不含当天:盘中拉行情会让最后一个交易日组只有半天 bar,分钟粒度的策略会被判成
盘中残段而拒绝运行。
两个日期框就是本次真实取数区间,界面不另设「实际区间」说明,因此两格都必须是 实际口径:倒推结果实时回填建仓日框(改截止日或期权期限都会跟着变),截止日填成 周末 / 节假日时在编辑完成(失焦或回车)后落到倒推真正使用的交易日锚点,即不晚于 它的最近交易日。逐次击键不落值,避免打断输入。
取消勾选后建仓日恢复可编辑(初值就是上次倒推出来的那天),截止日退化成请求上限
且不再被落到锚点;期限仍由回测引擎按 T 严格裁剪,若区间不足以覆盖期权剩余
期限,运行前或引擎仍会明确报错,不会压缩期限迁就数据。
「自动(推荐)」会根据当前单次回测策略选择请求口径:
| 当前策略 | 自动粒度原则 |
|---|---|
| 每日收盘 | 日频即可表达策略触发,优先请求日频 |
| 每日固定时刻 | 先按 Wind 代码交易时段跳过休市目标,再请求能覆盖全部生效 HH:MM 的兼容分钟行情 |
| 固定间隔 | 使用推荐的日内粒度,使盘中越带有机会被观察到 |
界面会披露 Wind 最终实际采用的采样粒度,便于解释固定间隔的触发次数与成本。 粒度不再提供手工覆盖:手动调粗只会静默漏掉 bar 内触发、让结论偏乐观。旧默认值中 “Wind 日频 + 固定时刻策略”需要运行后才报错的冲突,已由策略感知的自动粒度 消除。这里的「行情采样粒度」是请求和触发检查口径,并不是可编辑的每日 bar 数。
真实行情模式下,期权参数中的
s0视为「参考价 S_ref」;GUI/底层会按ratio = 真实首日价 / S_ref自动缩放K / KI / H / P / fix / amount等价格量纲字段;雪球还会缩放s00 / K / KI / KO,保证结构相对位置不被破坏。详细缩放表会展示在「回测摘要」Tab 中(由_show_summary渲染),逻辑在hedge_backtest.py:_rescale_option_to_real_s0。
| 字段 | 含义 | 单位 / 取值 | 默认 |
|---|---|---|---|
交易成本率(%) |
单边费率,按成交额收取;GUI 输入百分比,内部除以 100 | float,单位 % | 0.01(即 0.0001) |
头寸方向 |
所有 GUI 回测唯一的方向来源;卖出 (Sell) / 买入 (Buy) 内部分别映射为 1 / -1 |
Radiobutton | 卖出 (Sell) → 1 |
交易数量 |
quantity,将 Δ 转换为标的份数;必须为有限正数,不能用于翻转方向 |
float > 0 | 100 |
合约乘数 |
multiplier,每手对应的标的数量;0 = 不取整 |
float ≥ 0 | 5 |
GUI 默认值
5与底层HedgeBacktest.__init__(multiplier=5)一致,语义是「每 5 个标的为一手,按手数取整」。如果你想完全连续对冲,请填0。
单次回测、多路径回测与历史择优都会在任务启动时读取并冻结左侧头寸方向。 历史择优中的固定 C2C 和全部候选共用该值,不允许同窗跨方向配对。
| 字段 | 含义 | 选项 | 默认 |
|---|---|---|---|
对冲策略 |
调仓触发方式 | 每日收盘 / 每日固定时刻 / 价格或 σ 带宽 | 每日收盘 |
每日收盘保底对冲(重复则跳过) |
紧跟策略下拉的公共开关:每个非结算日收盘至少调仓一次,原策略已在同一根 bar 触发时合并为一次,不重复计成本;同时控制单次回测与历史择优 | 开启 / 关闭 | 开启 |
close_to_close:有真实时间戳时按每个交易 session 的最后一根 bar 调仓;含夜盘时夜盘、跨午夜和次日日盘属于同一交易日。无时间戳模拟路径回退到steps_per_day取模。fixed_times:每天在用户输入的HH:MM时刻调仓。Wind 会按当前代码的交易时段自动跳过明确处于休市区间的目标(例如无夜盘品种的23:00);其余生效时刻仍须由每个纳入回测的交易日组完整覆盖,任一交易日缺 bar 都会明确报错。模拟、Wind 日频和仅日期 CSV 不受支持;CSV 因没有品种交易时段元数据而保持全部目标严格校验。hedge_band:相对上次实际对冲价达到统一带宽后调仓。三个输入框联动,最后编辑的字段是权威输入:
每日收盘保底对冲(重复则跳过) 不是第四种策略,而是适用于以上所有 GUI 策略的
公共规则——所以它排在策略下拉右侧,而不是混在某个策略的专属参数里;历史择优页
不重复提供该开关,任务启动时直接冻结左侧控制的当前值。
开启后,每个非到期、非敲出交易日组都会在最后一根 bar 保证一次 Delta 对齐:
- 原策略若已在同一根 bar 触发,两个条件会合并为一次调仓。例如
close_to_close、包含实际收盘时刻的fixed_times,以及恰好在日末越过带宽的hedge_band都不会产生第二笔重复交易、成本或触发计数。 - 到期或敲出所在的末 bar 优先执行终止处理,直接把标的头寸平至
0,不会先做 一次收盘 Delta 对齐后再平仓。 - 对 CSV / Wind 日内行情,“收盘”是交易 session 分组后的最后一根真实 bar,
不是写死的
15:00;因此可适配夜盘、跨午夜或数据源实际尾 bar 时间。 - 对没有真实时间戳的模拟路径,引擎按最终采用的
steps_per_day划分交易日,并把 每组最后一个步长视为日末。
关闭该开关时,各策略只使用自身的触发条件,行为与原有回测口径一致。
GUI 只保留以上三种策略,默认使用 close_to_close。旧的
FixedFreqStrategy 与 hedge_freq 参数仅为后端 API 兼容入口,不出现在 GUI,
也不参与 GUI 的多策略比较或历史择优;调用方仍可在 Python API 中显式使用。
| 带宽字段 | 同一参考点上的换算关系 |
|---|---|
| 绝对间隔 | absolute |
| 相对间隔 | relative = absolute / S_ref,界面中 0.01 = 1% |
| 日波动 σ 倍数 | k = relative / (sigma_annual / sqrt(ANNUAL_DAYS)) |
编辑任意一项并按回车或移出输入框,会根据当前 s0、年化 sigma 和
ANNUAL_DAYS=243 反推另外两项;修改 s0 或 sigma 也会自动刷新。运行前
会再次严格校验当前可见输入,避免沿用隐藏的旧值。σ 表达模式还可选择
implied / realized 及历史波动率回看期(至少 2 日)。
单次回测的 σ 来源与回看期只服务当前固定间隔策略,不会渗进历史择优——择优页的
候选带宽固定使用输入波动率。候选梯度在独立的“历史择优”页配置,两套页面状态不会
互相遮挡或误触发校验。
三栏联动表示它们在当前参考价格和波动率下对应同一阈值,并不保证整条动态路径 严格等价。普通单次回测会保留用户最后编辑的执行单位:绝对口径保持固定价差, 相对口径相对上次实际对冲价计算,σ 口径则沿用所选 σ 来源和历史波动率回看期动态 计算。改变执行单位可能因此得到不同的后续触发时点。
CSV/Wind 若把期权参考价 S_ref 伸缩到真实首价 S_real,绝对间隔会同步乘以
S_real / S_ref;相对间隔和 σ 倍数保持不变。历史择优会把固定间隔候选统一到
日波动 σ 坐标,并在严格历史区间的各代理段上按 σ 策略执行,因此不依赖某个绝对价格水平。
steps_per_day 仍是回测引擎的重要内部量:它决定日内时间步长、模拟路径长度、
波动率年化口径以及固定间隔策略检查价格越界的频率,但不再作为所有数据来源
共用的顶部输入项。
| 数据来源 | GUI 展示与取值规则 |
|---|---|
| 模拟 | 在模拟参数区显示「模拟采样 bar/日」,可选 1 / 4 / 48 / 240;默认 1 |
| CSV | 不显示可编辑的每日 bar 数;仅日期索引按 1,日内 DatetimeIndex 按真实交易日组自动推导并校验 |
| Wind 日频 | 由「行情采样粒度」自动选择或手工指定;不显示可编辑的每日 bar 数,固定为 1 |
| Wind 分钟 | 由「行情采样粒度」自动选择兼容值或手工指定;实际每日 bar 数按返回的时间索引和品种交易 session 自动推导并校验 |
模拟下拉提示为 1=日频 / 4=60分 / 48=5分 / 240=1分。这里的分钟说明是
标准日盘的直观对应关系;真实行情可能包含午休、夜盘、跨午夜或尾 bar,因此
CSV / Wind 始终以实际交易日组为准,不接受 GUI 手工覆盖。固定间隔策略只会在
已有价格 bar 上检查是否越界,所以模拟采样越密,越能捕捉日内触发。
跨日 bar 上 option.step_forward 被调用;日内 bar 仅用 _bumped_copy(_intraday_elapsed=…) 临时评估 Δ,不污染 option 内部状态(hedge_backtest.py:531-532)。年化口径 dt_bar = 1 / (ANNUAL_DAYS * spd),已实现波动率年化因子 ANNUAL_DAYS * spd。
| 字段 | 含义 | 单位 | 默认 |
|---|---|---|---|
滑点 (bps) |
slippage_bps,单边滑点(万分之一为 1 bps) |
bps | 0 |
实现(hedge_backtest.py:515-596):
- 买入(
trade > 0)成交价上浮bps × 1e-4;卖出下浮。 - TC 同时计入
|trade| × s_exec × tc_rate与|trade| × S × sl_rate两部分(手续费和滑点不重复计)。 - Day 0 建仓也按这个口径收滑点(
hedge_backtest.py:494-507)。
| 按钮 | 行为 |
|---|---|
▶ 运行回测 |
主流程:构建期权 → 生成/读取价格 → 执行 HedgeBacktest.run(),模拟模式 n_paths>1 时还会跑 run_multi 并显示进度条 |
+ 保留当前结果到对比 |
普通回测成功后启用;为当前结果命名并复制一份轻量对比快照。每次成功结果只能保留一次,删除后可重新保留 |
⚖ 回测结果对比 (N) |
打开当前会话的结果池;N 为已保存数量。点击“显示”列会立即用缓存结果刷新曲线、排名与详情,不会重新运行回测。产生方式 列区分手工回测、优选验证与分段重放 |
📊 绘制结构图 |
不依赖回测结果,扫描 S 在 [s0×(1−r), s0×(1+r)] 区间,展示 Price / Δ / Γ / ν / Θ 曲线 |
扫描 ±% |
结构图扫描幅度,默认 30(即 ±30%),合法范围 (0, 100) |
点数 |
扫描点数,默认 31,合法范围 5~201 |
结构图默认会限制
nPath ≤ 20000以加速扫描(见_structure_worker),原值若大于 20000 仅在结构图时生效,回测主流程仍用原值。结构图视角与
头寸方向联动:卖方(position=1)时sign=-1,所有曲线乘以sign(见_show_structure),方便直观判断卖方账户的盈亏方向。
以「卖出 22 日香草 ATM Call、模拟 500 条路径」为例:
- 打开
期权类型→大类选香草期权 (Vanilla),子类型自动Eu。 期权参数区保留默认(s0=100, K=100, T_days=22, sigma=0.18,方向=看涨 (Call),r=0.03, q=0.03)。回测设置:数据来源选模拟种子42已实现波动率留空(=隐含)模拟路径数改为500模拟采样 bar/日1,交易成本率(%)0.01头寸方向选卖出 (Sell)(内部 position=1)交易数量100,合约乘数0(连续对冲)对冲策略close_to_close,滑点 (bps)0
- 点
▶ 运行回测。底部状态栏显示「正在运行回测…」,进度条先显示不定模式,进入 MC 阶段后切换为确定模式(带蒙特卡洛模拟: x/500文字)。 - 完成后状态栏提示当前结果可保留,并自动跳到「回测摘要」Tab。
- 点
+ 保留当前结果到对比,输入名称,例如每日收盘 · 基准。 - 修改
对冲策略或策略专用参数,再次运行并保留,例如固定间隔 · 相对1%。 - 点
⚖ 回测结果对比 (N);在结果池“显示”列勾选两条或更多快照,曲线、排名、摘要卡和相对差异会即时更新。切换勾选不会调用回测引擎,旧结果也不会被最新一次运行覆盖。
预期看到:
- 回测摘要:含期权初始/到期价值、对冲盈亏、MtM 盈亏、对冲误差、Greeks 表格;底部追加蒙特卡洛分布(均值/分位数/盈利概率/RV 统计)。
- 对冲图表:6 宫格曲线。
- 波动率分析:4 宫格,含 RV vs IV、价差填色、日收益直方图叠正态。
- 盈亏分布:直方图 + 散点,含线性拟合斜率(盈亏 vs 波动率价差)。
- 每日明细:只显示触发对冲的记录,并可将同一筛选结果导出 CSV。
- 单路径盈亏分解:
标的对冲盈亏=Σ H[i-1]·(S[i]-S[i-1])—— 标的腿浮动盈亏期权 MtM 盈亏=Σ -position·(V[i]-V[i-1])·quantity—— 期权方价值变动(卖方视角下取负)累计交易成本=Σ TC[i]对冲误差=position·V[0]·quantity + Σ hedge_daily − Σ TC − position·V[-1]·quantity,对应hedge_backtest.py:620
- 波动率分析:
成交隐含波动率直接来自option.sigma;已实现波动率用全样本 bar 级对数收益年化。 - Greeks 统计:表格列出实际期权仓位的 Delta/Gamma/Vega/Theta/Rho,即
portfolio Greek = -position × quantity × raw Greek;底层仍保留每份多头 claim 的raw Greek字段供定价与兼容调用。
6 宫格,从左上到右下:标的价格、Delta 对冲持仓目标 vs 实际持仓、组合 Gamma、组合 Vega、组合 Theta、累计盈亏(绿/红填色表示正负)。
Delta 持仓目标 =
delta × quantity × position,实际持仓shares受multiplier取整影响,会出现明显阶梯。
- (1) 滚动 RV(20d) vs IV,填色表示 RV 与 IV 大小关系(红=RV>IV)。
- (2) 累计 RV 与 IV 的收敛对比。
- (3) 价差时间序列 = IV − 滚动 RV,正值(绿色)表示卖方相对有利。
- (4) 日收益直方图叠 IV 正态、RV 正态;其中日 IV σ =
IV / sqrt(ANNUAL_DAYS)转换为百分比(ANNUAL_DAYS=243,见pricing/constants.py)。
仅 simulate + n_paths>1 时有内容,否则显示提示文字。
- (1) 总盈亏直方图 + 均值线 + 5% VaR 线
- (2) 对冲误差直方图
- (3) 已实现波动率分布
- (4) 总盈亏 vs (IV−RV) 散点 + 线性拟合(斜率正常应为正:RV 比 IV 低越多,卖方赚得越多)
顶部有 STRUCTURE_DOCS 中的中文 payoff 描述 + 当前参数摘要;下方 6 宫格扫描曲线,含 K/H/KI/E/P 等关键价位的虚线标记(颜色区分)。视角受头寸方向控制:卖方(position=1)时 sign=-1,买方(position=-1)时 sign=1,所有曲线均乘以 sign,方便直观判断。
Treeview 只保留 hedge_triggered=True 的生命周期事件:Day 0 初始建仓、
策略触发、公共收盘兜底,以及到期或敲出平仓。策略已触发但目标持仓未变化时仍会
保留,因为这里展示的是“触发”而不是“实际成交”;普通未触发 Bar 不展示。
表格在原 13 个行情、Greeks、持仓与盈亏字段前增加 触发来源。日频保留原交易日
序号;日内行情保留原始 Bar 序号及完整的 YYYY-MM-DD HH:MM 时间,避免同一交易日
的多个触发点混淆。盈亏字段仍是该触发 Bar 的当期值,并非两次触发之间的区间汇总。
导出 CSV 使用表格的同一份筛选结果,以 utf-8-sig 编码保存(Excel 友好)。
普通回测成功后,+ 保留当前结果到对比 会复制一份只包含日级聚合、成交统计
和累计曲线所需字段的轻量快照。它记录的是本次运行时的策略、参数和实际行情,
所以随后修改左侧输入不会反向改变旧结果。快照只存在于当前应用会话,关闭程序
后清空。
结果池支持:
- 显示 / 隐藏:点击“显示”列的
☐ / ☑。每次切换都会同步刷新图表、摘要卡、 排名和详情;只读取已完成快照,不启动线程、不重新读取 Wind/CSV,也不重跑回测。 - 重命名:结果使用稳定 ID 保存,改名只改变展示标签,不会丢失勾选状态或数据。
- 固定基准:买卖方向分组;当前方向最早保留的
close_to_close快照固定为 基准。选择另一方向结果时会切换整组,并自动带入该方向基准;买入与卖出结果 不能进入同一排名。 - 删除:从当前会话移除快照;删除固定基准后,下一条已保留的
close_to_close自动接替。若没有可接替结果,绝对排名与曲线仍保留,但相对指标 显示—并提示先保留每日收盘结果。 - 全选 / 清空:“全选”只选择当前聚焦结果对应的同方向快照,相反方向不会 混入;“清空”可以连同固定基准一起清空显示。之后再选择任一候选会自动带回 同方向基准。选择 0 条时显示操作引导;只有基准 1 条时展示自身指标并提示再选一条。
- 产生方式:
产生方式列显示这条快照是怎么来的 ——手工回测、优选验证·<周期>或分段重放。它读的是快照上的结构化origin字段, 不是名称前缀,因此重命名不会让来源丢失。优选验证的快照还在origin_meta里记录来源周期、当时排名、改善幅度和批次编号;这些只作溯源,不参与本页 任何排名计算,本页指标始终由快照自身的单路径结果算出。
曲线配色与 策略优选 页共用同一份会话级登记表:同一个策略(按策略类型加其
决定性参数识别,固定间隔 按换算后的 σ 归并)在两页拿到相同颜色和标记,
每日收盘 基准固定占用同一色位。因此在优选页看到的某条候选曲线,验证入池后
在本页仍是同一个颜色,可以直接对应起来看。
固定间隔快照会同时记录输入单位,以及期初参考点对应的绝对价格、相对百分比、 日波动 σ 倍数,方便直接识别不同带宽参数。这些换算值是参数注释,不代表三种 执行口径在整条路径上严格等价。不同策略及其专用参数属于对比对象,本身不会触发 “不可比”警告。
系统先强制要求头寸方向一致,再核对三组上下文:实际价格与时间索引、期权结构 参数、数量 / 乘数 / 成本 / 滑点 / 日级聚合口径。除方向外的上下文全部一致时 显示绿色确认;任一组不同时仍允许把曲线并列展示,但会说明排名只适合作为场景 对照,不能把全部差异归因于对冲策略。
顶部四张卡片和排名表口径如下:
| 项目 | 含义 |
|---|---|
| 固定基准 | 当前头寸方向最早保留的 close-to-close 快照;用户改名不会改变其稳定 ID 或基准身份 |
| 基准日净 PnL RMS | close-to-close 每个真实交易日净 PnL 的均方根,金额口径、已扣交易成本 |
| 当前最优 | 所选快照中 RMS 最低的结果;副标题显示它相对固定基准的改善幅度 |
| 基准总成本 / 再触发 | close-to-close 的累计交易成本与除建仓、到期外的触发次数;副标题另列实际成交次数 |
| 较每日收盘改善↑ | `(基准 RMS - 本行 RMS) / |
| 期末净 PnL | 最后一个真实交易日结束时的累计净 PnL |
| 再触发 / 成交 | 前者不含初始建仓和到期处理;后者只统计持仓确实变化的成交,包含建仓与到期平仓 |
| 最大回撤 | 日度累计净 PnL 从历史高点到后续低点的最大金额回撤 |
| 换手额 | `Σ |
累计净 PnL 曲线先把 bar 级损益按真实交易 session 汇总,并已扣除成本。在排名表 中 close-to-close 基准使用虚线,单选一行会突出对应曲线,并在详情区显示它相对 固定基准的 RMS、成本、净 PnL、最大回撤、再触发 / 成交和换手额差异。评分排名 本身仍按 RMS 从低到高排列,固定基准不一定是第一名。
较每日收盘改善↑ 只属于本页(结果对比),策略优选 页已不再展示同名指标——
那一页排名看的是增量收益 / 增量信噪比,两者既非同一统计量也非同一样本:本页
分母是 |基准 RMS|、样本是一条单路径。详情区列出的是原始差值(本行 - 基准),因此对 RMS、
成本、回撤这类越低越好的指标,那里的正值仍代表更差 —— 排名列表头的 ↑ / ↓
标记说明每一列该往哪个方向读。
这个页面只读取和管理已经完成的普通回测快照。历史候选参数、严格区间代理段和历史排名 不会出现在结果池中,也不会与普通快照直接混排;两类结果的统计样本和用途不同, 强行放进同一排名容易造成误读。
◷ 历史择优 与单次回测、回测结果对比平级,拥有独立的参数区、运行状态和结果
容器。它仅接受 CSV / Wind 真实行情;选择模拟来源时页面会阻止启动任务,也不会
生成“历史推荐”。它复用同一回测引擎和评价指标,但不会读取回测结果池作为搜索
输入。
| 参数组 | 用途 |
|---|---|
| 基准环境摘要 | 显示历史行情源、日期区间、期权结构、头寸、数量、成本、滑点与左侧收盘兜底状态,便于核对搜索口径 |
| Wind 历史范围 | 独立指定分析截至日;自动模式取得 max(L_selected) 个评分交易日,并额外请求一个 Day 0 收盘锚点。本页 σ 恒取左侧输入的波动率,因此 realized-HV 预热 V 恒为 0,自动范围不会为预热多留一天(勾选框文案同样只写「+ Day 0 锚点」)。代理期限 T 不扩张证据区间;默认全选时 max(L_selected)=243 |
| 历史行情采样粒度 | 独立选择「自动(推荐)」或高级手工值;一次搜索中的全部候选共享最终实际粒度 |
| 候选策略 | 每日收盘固定作为 C2C 比较基准且不可关闭;必须至少再启用固定时刻或固定间隔中的一种;仅供后端兼容的固定频率策略不参与 |
| 收盘兜底规则来源 | 直接读取左侧唯一的「每日收盘兜底对冲」开关,本页不重复提供控制;启动任务时冻结当前值并应用于全部候选 |
| 固定时刻候选 | 配置一个或多个 HH:MM;默认按同一交易日的业务顺序排列为 23:00,11:30,15:00(前一自然日夜盘 → 次日日盘)。Wind 自动跳过该代码休市时刻,只有完整覆盖其余生效时刻的真实日内样本才参与该案例 |
| 固定间隔候选 (σ) | 逗号分隔的常见带宽梯度,默认 0.5, 0.75, 1, 1.5, 2 |
| 加入当前回测带宽 | 可选地把单次回测区当前绝对 / 相对 / σ 输入换算成 σ 候选后加入搜索 |
| σ 取值 | 候选带宽的 σ 恒取左侧输入的波动率,界面不提供来源选项——择优只比带宽倍数,全部候选共用同一个 σ 才可比。引擎仍支持 realized,但不从这里进入 |
| 分析周期 | 近周、近月、近季、近半年、近年五档复选,默认全选且至少选择一项;每档都从同一分析截止日向前严格连续回放最近 L 日,任务与结果只包含已选周期。短周期更贴近当前,长周期覆盖更多市场阶段、更稳健但反应更慢 |
| 代理期限与结算 | 左侧期权期限 T 只决定每个代理段的最长存续期。L<=T 时区间末按剩余期限 MTM;L>T 时区间内按 T 续接,完整段到期结算,最后不足 T 的尾段 MTM |
| 评价口径 | 候选与固定 C2C 基准只比较双方成功的共同代理段与共同评分日。单一标的序列按增量收益 / 增量信噪比排名(各段日净 PnL 接续后逐日相减);品种历史合约池跨合约无法相加金额,改用各非重叠代理段有界改善按实际评分日数加权。三种状态区分正式历史参考、区间诊断与部分配对 |
核对基准环境、分析周期和候选配置后,点击 开始策略优选 才会读取真实历史并启动严格区间搜索;
若五档周期全部取消,页面会提示“至少选择一个分析周期”,不会读取行情或启动任务。
单纯切换到该页不会自动运行,也不会改动当前单次回测设置。
开始策略优选 固定在页面顶部一行,与「收起 / 展开候选配置」并排:折叠配置或改动
结果区都不会让它移位,出结果后想改参数重跑不必往回找。任务运行期间该行下方显示
本页自己的进度条(左侧参数栏那条共享进度条同时照常工作)。收起候选配置可释放结果区
空间;候选较多时,周期排名表可垂直滚动。
历史择优启动时会冻结左侧「头寸方向」和「每日收盘兜底对冲」的当前值;固定 C2C
及所有候选都采用相同方向和公共规则。因此策略排名比较的是同一仓位方向下,各自
盘中触发方式叠加同一日末约束后的结果,而不是把兜底本身作为独立候选。
期权剩余期限 T 和择优周期 L 是两个独立维度,但不再采用“最近 L 日挑选
多个终点、每个终点再向前回看 T 日”的旧口径:
L是实际进入 PnL 评分的严格连续证据区间。近周、近月、近季、近半年、近年 分别采用5 / 20 / 61 / 122 / 243个交易日,并全部以同一个分析截止日为右端点。T是历史代理合约单段的最大期限,只影响定价、Greeks、代理段切分及结算,不会 把行情扩到严格L区间之前。L <= T时只形成一个代理段;它在区间末仍有T-L日剩余期限,因此按公允价值 MTM,并平掉对冲腿,不错误套用到期 payoff。L > T时在严格区间内按T续接代理合约;完整代理段到期结算,最后不足T的尾段按剩余期限 MTM。结果区会披露代理段总数、到期段数、MTM 段数与实际评分日。- GUI 默认勾选五档且至少保留一项,不再生成或传递
5 / 12 / 24 / 36 / 48的历史终点预算。
这五档是可选的证据 / 稳健性口径,不是统计学置信区间:短周期更能反映近期交易 结构,长周期能覆盖更多行情阶段但对当下变化反应更慢。应优先在同一周期内横向 比较策略,再把本次已选周期的结论并列参考,而不是把不同周期的 RMS 直接混成一个总分。
realized 模式还要在严格区间 Day 0 之前拥有完整 V 日预热,所以正式评分与预热
边界为 N >= L + V;Wind 自动请求还会多留一个 Day 0 收盘锚点。整项自动范围按
max(L_selected) + V + 1个锚点 规划,T 不参与。例如 T=22、V=20
的月度择优需要 20 个评分日、20 个预热日和 1 个锚点,而不是旧口径的
T + L + V = 62 日。implied 模式取 V=0;只有勾选近年时,最长评分区间才使用
243 日。手工范围或实际返回的完整交易日不足时,系统可保留已有共同代理段结果用于诊断,但不把它
标记为完整周期的正式历史参考。
Python API 为旧调用方保留必要兼容字段;GUI 主流程只传入已选 lookbacks,
不传 target_endpoints,结果也不再展示终点预算、终点间隔或相邻窗口重叠率。
历史页的 Wind 设置与单次回测相互独立。常规模式只需指定「分析截至日」,系统
会以 max(L_selected) + V 个评分/预热交易日并加一个 Day 0 锚点为目标自动向前
扩展起始范围:max(L_selected) 取已选周期中最长的严格证据区间,realized σ
再增加区间前 V 日预热。近年档的 243
是项目统一的年度交易日口径,不是简单向前减去 243 个自然日。高级模式允许手工
覆盖起止范围和采样粒度,但手工范围不足时会显示区间不足或区间诊断,不会伪造
已选周期的正式推荐。
历史择优不会把所有期货代码都当成连续品种:
P2609.DCE这类带交割年月的代码是具体合约。系统只使用该合约返回的历史, 不会因季度或年度样本不足而自动扩展到P的其它合约。P.DCE这类“品种 + 交易所”代码是品种历史合约池。系统查询截止日以内的 Windtrade_hiscode逐日历史主力映射,只加载最长已选周期证据范围中真实出现过的 具体合约;不会按交割月份猜测,也不会加载截止日之后才成为主力的合约。- 严格区间只使用最近
L日内的主力映射;区间外最多为首个 Day 0 锚点与 realized σ 的V日预热加载必要行情,不会因代理期限T向更早日期扩张。 - 每个代理段会披露实际具体合约;跨合约图表使用共同代理段,并按安全名义金额 归一化,避免高价合约仅因金额 PnL 更大而支配显示。
若一个历史合约加载失败,涉及该合约的代理段会被标为失败,其它可用代理段继续 运行。周期只有在严格区间及共同代理段覆盖完整时才形成正式参考,否则保留为 “区间不足,仅诊断”。分析日盘中残组只有在行情中确有 尾部残组证据时才自动回退到最近完整交易日;整个当前主力缺行情不会被静默回退成 以前一合约为截止点的正式结论。
历史「自动(推荐)」会综合全部已启用候选决定统一请求粒度:仅有每日收盘候选时
日频即可;包含固定时刻候选时必须选用兼容的分钟行情;固定间隔候选会采用推荐的
日内检查粒度。行情读取完成后,同一具体合约内的全部候选共享完全相同的实际时间
索引和请求粒度;品种池允许不同历史合约按各自真实 session 推导每日 Bar 数。
页面同时披露请求粒度;手工高级覆盖仍
需满足所有启用候选。固定时刻的自动粒度只考虑该代码交易时段内实际生效的
HH:MM;休市目标不会无谓把请求降到更细粒度。
固定时刻候选在启动时只检查数据是否具有真实日内时间轴,不会因为某个代理段 缺少目标 Bar 而被全局移除。每个 Wind 代码先按自身交易时段区分 “休市目标”和“生效目标”:前者自动跳过,后者由每个历史代理段独立校验。 生效时刻缺 Bar 的失败代理段计入跳过诊断,其他代理段和其他候选继续运行;如果固定 时刻候选最终一个有效代理段都没有,界面会显示首个真实缺失时刻原因,而不是笼统 提示历史长度不足。
固定间隔候选统一使用日波动 σ 倍数作为搜索坐标。候选列表留空表示不使用常见
预设;只有在“加入当前回测带宽”开启时,当前带宽换算值才会加入。默认 / 自定义
候选与当前换算值按 10 位有效数字规范去重,包含当前值在内最多 10 档;超过上限
会在启动任务前提示修改,不会静默截断。所有历史固定间隔候选统一按 sigma
策略执行,因此不同价格水平的历史代理段共享同一波动尺度。
绝对、相对和 σ 的换算只表示当前参考点上的阈值对应关系。普通单次回测仍按用户 最后编辑的原始单位执行;历史页的 σ 搜索不会悄悄改变单次回测参数。由于三种口径 在路径推进时更新阈值的方式不同,也不能据此认为它们在所有未来路径上严格等价。
历史页只在本次勾选的周期中回放严格连续历史区间;可选目录为近周、近月、近季、 近半年、近年,未选周期不会运行,也不会在结果区生成空白占位。每日收盘 close-to-close 始终是固定基准;每个周期先形成 C2C 代理段集合,再对每个候选取 双方都成功的共同代理段和共同评分日。
单一标的序列的主排名依据是“增量”,不是 RMS。 对冲的目的是让 gamma scalping 收益最大,其次才是让这份收益更稳,因此排名比较的是“日内额外调仓相对 「日内不动」多赚了多少”。把各段的日净 PnL 首尾接成一条后逐日相减:
增量收益 = Σ(候选日净 PnL - C2C 日净 PnL)(默认口径)增量信噪比 = mean(逐日增量) / std(逐日增量)
单位:增量收益是金额,随 数量 × 乘数 线性放大,与「增量成本」列同
单位可直接相减;增量信噪比是无量纲比值,与仓位大小无关。两者都不是百分比。
它形式上与夏普比率同构,但是逐日原始比值、没有年化,因此不要和年化夏普
放在一起比大小(真要换算需乘 sqrt(243)≈15.6)。不年化是有意的:它在这里只
用于同一批候选之间的横向排序,乘一个常数不改变名次,却会诱导人拿它去和别处
的年化夏普对比。列名用「信噪比」而非「夏普」也是为此——夏普一词自带年化约定,
而信噪比本来就是无量纲的原始比值,不会引出这个误会。
两个口径都在回测时一并算出,结果页点表头即可切换,不必重跑。增量信噪比恰好
等于配对 t 值除以 sqrt(n),因此它在衡量“每单位波动换来多少增量”的同时,也
编码了这份增量有多可靠——样本内偶然赚到的一两天大钱会被自身波动稀释。
为什么可以跨段直接把金额相加。 每段都按该段期初价重定基一份新期权,数量与
合约乘数固定,因此段内 PnL 量级正比于该段 S0——价格高的段权重更大。这不是失真:
若按固定手数、每 T 日滚一次,一年下来的增量金额之和就是字面意义上的实现盈亏,
高价段确实产生了更多绝对损益。同一段内所有候选与 C2C 共用完全相同的期权、数量、
乘数与成本率,因此相减是同口径的。
该结论只在同一标的、同一次运行内成立。跨合约时每手名义金额会变,不再是"固定 手数交易同一个东西",因此品种池模式改用逐段改善率加权而非金额求和。跨运行(不同 截止日或周期)的金额总额同样不可直接比较——段构成变了。
实测参考:510050.SH 近一年 12 段的 S0 区间为 2.846~3.235(1.14 倍),段权重相对
均值偏离最大 ±7%,远小于候选之间的增量差距(约 2 倍量级)。
品种历史合约池只能用改善率排名。 跨合约不能直接把金额 PnL 相加,因为不同
合约的价格与金额尺度可能不同,所以该模式不产出增量指标。系统在每个非重叠代理
段 j 内计算日净 PnL RMS 的有界改善 I_j:
I_j = (C2C RMS_j - 候选 RMS_j) / max(C2C RMS_j, 候选 RMS_j)
再按该段实际评分日数 d_j 加权:I_L(pool) = Σ(d_j × I_j) / Σd_j。
因此品种池结果表里“增量收益 / 增量信噪比 / 增量成本”三列都显示 —,两列表头
也不可点(点了也只是静默回退到同一个值),周期说明会写明本次实际按改善率排名。
若改善与 C2C 持平,固定优先 C2C,避免为无历史改善的候选增加复杂度。
候选必须覆盖该周期全部 C2C 基准代理段和评分日,才可以进入正式历史择优;历史区间 本身不足但候选与现有 C2C 代理段完全配对时,只给“区间诊断”;候选自身缺 Bar 或 失败造成的部分配对只能展示诊断明细,不能成为周期领先者。
排名表展示的四列是增量收益、增量信噪比、增量成本、最大回撤;RMS 得分与代理段
胜率已收敛为选中行的详情串,不再占表宽。周期说明披露
T / L / 实际评分日 / 代理段数 / 到期段 / MTM 段 及终止口径。品种池还披露实际
参与该周期评分的具体合约。只有至少一个非
C2C 候选完成正式共同代理段比较时,才产生“历史最优参考”;
若全部正式候选都不如 C2C,结论会明确显示“每日收盘(基准最优)”,含义是历史
区间支持维持 C2C。代理段胜率表示候选 RMS 严格低于同代理段 C2C RMS 的段数占比;
平局不计胜。所有结论
仅作历史参考,不代表未来表现。
每个已选周期先展示完整策略排名数据表,图表放在数据表下方,两者之间是一条可拖动的 分割线:结果页整体不再滚动,顶部的周期条与结论卡固定,剩余高度由用户在排名表和 图表之间自行分配。初始分割按 45% 摆一次,随后由 tk 按两格的请求高度微调,实际落 在四成上下(约六行排名 + 一块完整图表);拖到任一端都有下限——排名表不少于 150px,图表那一格不少于 280px(扣掉指标条与下钻条后仍留约 160px 绘图高度,坐标轴 和图例不会糊成一团)。窗口缩放时两格按比例同步伸缩,用户拖过之后位置完全由用户 掌握。排名表内部仍有自己的滚动条,图表随格高自适应重绘。
初始分割只摆一次,之后不再跟随:摆放分割线会让图表重绘、改变该格的请求尺寸、
外层 grid 重排后又把分割区高度改掉二十来像素,无条件响应这个回波会形成
摆放 → 重绘 → 重排 → 摆放 的闭环——实测单次渲染里分割线被摆放 300 多次,界面一
帧都画不出来,内存被绘图缓冲区反复分配撑到 GB 级。所以只有幅度超过 15% 的高度变化
(真的拉了窗口)才会重新摆放,另有一个硬性次数上限兜底。排名行保持单选,用于查看详情、应用策略或执行
当前路径验证;勾选与其分离,通过排名表首列 勾选 选择候选。该勾选同时决定图表
叠加哪些曲线,以及“当前路径验证”按批量还是单条执行。切换到某个周期时,默认勾选
排名前三名里存在共同代理段的候选——数的是名次而不是个数:C2C 基准也占一个
名次却不可勾选(它在图上恒在),所以基准排进前三名时默认只会勾上两个候选,不会
为了凑够三个再往下多抓一个名次;名次窗口内若有候选与已选没有共同代理段,跳过它
即可,同样不向下顺延。清空勾选 清除全部,之后可逐项调整(清空后不再自动恢复
默认,需要重新运行或手动勾选)。
C2C 不可取消,候选最多同时显示八个,以避免曲线和图例失去辨识度。候选的颜色和
标记来自与“回测结果对比”页共用的会话级登记表,因此同一策略验证入池后在对比页
仍是同一个颜色(见 6.7)。图表提供一个与
排名证据一致的主视图和两个代理段诊断视图:
- 完整 L 日累计路径(默认):按严格区间的时间顺序拼接全部非重叠共同代理段
的日 PnL,再从第一天开始累计;因此完整覆盖时横轴正好是
1..L,与周期主排名 使用的历史证据一致。代理段边界用竖向虚线标记。 - 单代理段路径:从“代理段”下拉框选择一段,同时比较全部已勾选
候选与 C2C 的累计路径;口径可切换为净 PnL、成本前 PnL 或成本,并满足
净 PnL = 成本前 PnL - 成本。 - 多代理段中位路径:按代理段内交易日对齐,绘制中位路径;至少有 两个共同代理段时显示 P25/P75 阴影。为避免多层色带遮挡,阴影只显示 C2C 和当前 主候选,其他候选仍显示中位线;提前敲出 / 结算后累计值保持不变直至最长代理段, 避免后半段只剩未敲出代理段;阴影是代理段的描述区间,不是置信区间。
所有比较只使用同严格周期、同一内部代理段标识、段内长度一致且 C2C 与全部已勾选
候选都成功的共同交集;切换净 PnL、成本前 PnL 或成本时会按该曲线口径重新求交集。
固定时刻缺 Bar 的代理段不会补零或前向填充;若失败使共同交集不足 L 日,完整
路径会同时显示实际共同日数与目标 L,不能把缺失日误读为零损益。单代理段路径与
汇总 RMS 均为当前合约数量与价格水平下的金额口径;品种池跨多个具体合约时,完整
路径和多代理段中位路径都使用各段
PnL / (S0 × multiplier × |quantity|) 安全归一化。若 S0、乘数或数量不能形成
有限正分母,或同代理段候选与 C2C 的分母不一致,界面会停用相关聚合图并提示改用
单代理段路径,不会回退到跨合约原始金额曲线。
排名表仍保留每个策略自己的全部配对代理段统计。当已勾选策略的共同交集小于其中 任一策略的独立配对集合时,图表会明确提示“与排名表样本口径不同”;此时应以共同 代理段路径比较曲线,以排名表评估各策略各自能覆盖的完整历史,不应混用两个分母 解释结果。
结果区顶部是一张结论卡,位于排名表之上:它显示排名表当前选中的那一行——策略 名、该行是否本周期最优(或基准 / 数据不足仅供参考)、以及增量收益、增量信噪比、 胜段占比、可比样本四个数字(品种池模式下增量口径不可用,前两项自动换成损益波动与 每日收盘原值)。刚出结果时表格默认选中 rank 1,因此卡片默认显示的就是本周期推荐; 用户改选别的行,卡片随之切换。卡片绑定选中行而不是固定显示周期冠军,是因为右侧 两个动作按钮作用的对象就是选中行,两者必须指同一个策略。跨周期一致性收敛为周期 切换条右端的一枚 pill(一致 / 不一致),完整措辞在悬停提示里。
历史排名不会直接写入回测结果池。“换到当前环境重跑”的两个按钮在结论卡右侧,历史 证据回放因为要先在图上选段,仍留在图表下方:
- 加载分段到展示页(图表下方):从“历史分段”下拉选择该候选跑过的某一段历史, 按原始行情切片重跑并把逐 bar 结果渲染到回测摘要 / 对冲图表 / 每日明细 / 波动率分析。
- 仅回填参数:把策略类型及其专属参数回填到单次回测区,不立即运行, 便于用户检查行情、期权和成本口径后再执行。
- 当前路径验证:使用当前单次回测环境执行推荐策略;只有回测成功后,才把它
作为普通快照保留到“回测结果对比”页。此时它与其它快照使用相同的单路径指标,
可以正常勾选比较。执行范围由排名表首列的勾选决定:没有勾选时只验证当前选中
的那一行;有勾选时按排名顺序逐条批量验证,并在缺同方向每日收盘快照时先补跑
基准。按钮下方的说明会随勾选实时写明这一次点击将要执行的范围。入池的快照会
带上结构化来源(
优选验证·<周期>)以及来源周期、当时排名与批次编号。
批量验证结束后不会自动跳页,也不再用模态框报错 —— 当前选定的周期和勾选状态
保持原样。结论写在结论卡底部的结果条里:全部成功显示绿色的完成条,有失败时
显示黄色的完成条并提供 失败详情 按钮按需展开原因。结果条上的 查看结果对比
会切到结果对比页,并只勾选这一批刚验证出来的快照(缺同方向基准时自动带入),
所以跳转由用户主动发起,且落地即是这批结果的视图。结果池本身在批量结束时就
已更新;如果对比页当时可见,会同步刷新。
这些动作替代历史页内嵌的“当前期限路径”辅助结果,避免把严格区间汇总与单条 路径结果放在同一容器中。若一个有效样本都无法形成,或 CSV / Wind 历史读取失败、 滚动推荐计算抛出异常,整个任务会失败。系统会优先显示缺失具体合约、缺少主力日 或固定时刻等首个真实失败原因;只有没有更具体诊断时才提示扩大历史区间。
ImportError: WindPy:仅在选 Wind 数据源时触发(pricing/wind_data.py:125-129)。模拟和 CSV 模式不需要 Wind。ModuleNotFoundError: tkinter:部分 Linux 发行版默认不带 tkinter,安装python3-tk(Debian/Ubuntu)或python3-tkinter(RHEL)即可。Windows / macOS 官方 Python 自带。SyntaxError: invalid syntax (match/case):Python 版本低于 3.10。
报错示例:价格序列长度不足:期权剩余 22 日 x steps_per_day=1 需要 23 个价格点,实际仅 18 个。
steps_per_day 是引擎最终采用的每日 bar 数:模拟来源取自「模拟采样 bar/日」,
CSV / Wind 则由真实时间索引和交易 session 自动推导。Wind 的「行情采样粒度」
只决定请求口径,不直接写入 steps_per_day。商品期货的 30/60 分钟 Bar 会按
夜盘、上午休市前后和下午等连续交易段分别向上取整,不会用总分钟数简单相除。
CSV / Wind 模式下需要保证
完整交易日组覆盖的期限不少于期权剩余期限;可以放宽日期区间、补全日内行情,
或调小 T_days / T,而不是手工填写每日 bar 数绕过校验。
CSV / Wind 模式下若期权 s0 设为 0 或负数,会触发 _rescale_option_to_real_s0 抛错(hedge_backtest.py:201)。请填入正的参考价。
固定时刻策略要求每个交易日至少两根 bar。Wind 会自动跳过当前代码明确不交易的
目标时刻;其余生效 HH:MM 必须逐交易日覆盖。建议将「行情采样粒度」保留为
「自动(推荐)」;若使用高级手工粒度,应选择能落在全部生效目标时刻上的分钟
bar。CSV 无法可靠识别品种休市时段,因此需提供第一列为完整日期时间且覆盖全部
配置目标时刻的日内行情。
只有 数据来源 = 模拟 且 模拟路径数 > 1 时才会触发 run_multi,否则该 Tab 只显示提示文字。
_structure_worker 会把 nPath > 20000 强制截断为 20000 以加速扫描。这只影响结构图,不影响主回测中真实的 nPath。
普通单次回测为兼容旧行为,在有效收益不足时会回退到 implied σ。历史择优不再提供 σ 来源选项(候选带宽恒用输入波动率),因此该页不会出现 HV 预热不足的问题,也不需要 为此额外拉取预热区间。
GUI 与底层 HedgeBacktest.__init__ 均默认 合约乘数 = 5(hedge_backtest.py:341)。新手第一次跑可能看到「Delta 与实际持仓」图上有明显阶梯——这是按 5 取整造成的,并非 bug。如需连续对冲请改为 0。
不会。保留结果时,系统只调用 summarize_strategy_result 与
result_daily_frame 缓存指标和日级累计曲线;之后的勾选直接读取这些缓存,
不会调用 HedgeBacktest.run()、compare_strategies()、Wind 或 CSV 读取,
也不会启动后台计算。
系统检测到所选快照的实际行情 / 时间索引、期权结构,或头寸 / 数量 / 乘数 / 成本 / 滑点 / 日级聚合口径不一致。此时仍可并列查看场景结果,但“领先”不能只 解释为策略更好。若要严格比较策略,请保持这些设置一致,只修改对冲策略及其 专用参数。
因为它和 策略优选 页的同名指标此前符号相反:对比页用
(本行 - 基准)/|基准|(负值更好),优选页用有界改善(正值更好),两个相邻页面
读法互斥,极易把“更差”看成“更好”。现在对比页统一成正值更好,与本页顶部“当前
最优”卡片的算法一致。数值大小没变,只有符号翻转;两页仍是不同统计量(分母与
样本不同,见 6.7),统一的只是方向。
当前版本的结果池是会话内缓存,不写入磁盘。这样可避免在未定义文件格式和版本 兼容规则前产生不可恢复的旧快照;关闭应用会清空结果。需要长期留档时,可先用 “每日明细 → 导出 CSV”保存单次明细。
gui_app.py— GUI 入口与全部控件pricing/hedge_backtest.py—HedgeBacktest、GUI 使用的每日收盘/固定时刻/统一带宽策略,以及仅供后端 API 兼容的固定频率策略pricing/hedge_analysis.py— 多策略日频聚合比较、严格区间诊断与历史推荐pricing/option_base.py—OptionBase,统一定价/Greeks 接口pricing/Option_Vanilla.py— 香草期权 +blspricepricing/Option_AS.py— 亚式期权pricing/Option_AB.py— 气囊期权pricing/Option_DE.py— 累计/熔断累计系列pricing/Option_SNB.py— 雪球 / 反雪球pricing/trade_calendar.py— 雪球自然日计息与观察日换算使用的离线优先交易日历pricing/wind_data.py— Wind 数据接口(可选)pricing/mc_engine.py— GBM 路径生成引擎(McGbmQ,quasi-MC 反对称采样)pricing/rolling_backtest.py— 滚动回测(Phase 3):按窗口滑动跑多期回测并汇总盈亏分布pricing/constants.py—ANNUAL_DAYS = 243.0