EARLY EXIT · COST MODELS
早退、手续费与滑点:把成交假设调到接近真实的水平
只按「到期结算」回测,等于假设你永远能持有到最后一天。Optopsy 提供三个早退参数、一整套手续费结构和四种滑点模型,让假设更接近现实——但也更容易配错。
- 符号有约束:
stop_loss必须负数,take_profit必须正数,max_hold_days必须正整数。 - exit_type 有优先级:同一天多条件触发时,止损 > 止盈 > 最长持有。
- 滑点默认是 mid:最乐观的一种;做敏感性分析时至少要跑一次
spread。 fill_ratio方向反直觉:0.0偏向不利一端,1.0偏向有利一端且官方明确说不现实。
bid 与 ask 构成价格区间optopsy/pricing.py 绘制;非官方图,不代表真实成交结果。EARLY EXIT RULES
Optopsy 早退参数说明:符号约束、触发条件与优先级
Optopsy 的早退逻辑实现方式是:在入场到计划出场之间扫描中间报价日,找到最先满足条件的日期就提前平仓。
| 参数 | 类型 / 约束 | 触发条件 | 对结果的影响 | 适用场景 | 注意点 |
|---|---|---|---|---|---|
stop_loss | float 或 None;必须为负数 | 未实现盈亏小于等于该阈值时提前平仓 | 截断单笔亏损幅度,通常会降低尾部亏损也削掉部分反弹 | 给卖方策略加保护 | 写成 -0.50 表示亏损 50% 时平仓;写成正数会被校验拒绝 |
take_profit | float 或 None;必须为正数 | 未实现盈亏大于等于该阈值时提前平仓 | 锁定利润,同时可能错过后续更大涨幅 | 卖方策略的常见做法(如赚到 50% 就平) | 写成 0.50;写 50 会被拒绝 |
max_hold_days | int 或 None;必须为正整数 | 持有自然日数达到阈值时平仓,不看盈亏 | 控制资金占用周期,让交易笔数更均匀 | 想让持仓周期可控、避免长期占用 | 用自然日而不是交易日计数 |
| 三者的关系 | 可单独或同时启用 | 按优先级取先触发的那个 | 同时启用时结果由最先触发的那一个决定 | 组合出更细的持仓管理规则 | 优先级固定为 stop_loss > take_profit > max_hold |
依据官方 parameters 文档的早退参数说明与 optopsy/exits.py 的阈值判断实现整理。
exit_type 的四个取值(raw=True 时出现在输出列里):stop_loss 触发止损;take_profit 触发止盈;max_hold 达到最长持有;expiration 表示没有触发早退、按计划出场。用 trades['exit_type'].value_counts() 一眼就能看出你的规则实际是哪一条在起作用。
CONFIGURE
Optopsy 怎么配早退规则并验证:三步方法
写法取自官方 examples 文档的 Early Exit Examples 一节;本站未在 Python 3.12+ 环境实跑。
import optopsy as op
trades = op.short_puts(
data,
max_entry_dte=45,
exit_dte=0,
take_profit=0.50,
raw=True,
)
先只加一个止盈规则。要判断某条规则是否真的生效,raw=True 是必需的——分组统计里看不到 exit_type。
预期输出:逐笔明细里出现 exit_type 列
print(trades["exit_type"].value_counts())
如果全是 expiration,说明你的阈值一次都没触发——可能是阈值太远,或数据里中间报价太少。这是判断「规则有没有起作用」的最快方式。
预期输出:四类取值各自的数量分布
print(trades.groupby("exit_type")["pct_change"].describe())
这一步能看出止盈是不是真的锁住了收益、止损是不是真的截断了尾部。注意样本量:某一类的笔数太少时,它的均值不稳定。
预期输出:按出场原因分组的收益率统计
trades = op.short_puts(
data,
max_entry_dte=45,
stop_loss=-1.0,
take_profit=0.50,
max_hold_days=21,
raw=True,
)
print(trades["exit_type"].value_counts())
官方明确:同一天多个条件同时满足时,优先级固定为止损 > 止盈 > 最长持有。启用多条规则后,exit_type 的分布会告诉你实际是哪条在主导。
预期输出:max_hold 与 expiration 的比例通常反映你的持仓周期设置
多腿策略的额外要求
四腿这类多腿策略做早退时,要求所有腿在同一个中间日期都有报价,先算出合计的未实现盈亏再判断阈值。如果某条腿当天没有报价,那天就不能作为早退候选日——这会让多腿策略的早退触发比单腿更少。
日历 / 对角的默认不同
普通策略的 exit_dte 默认是 0(持有到期),而日历与对角默认是 7。这两类策略的 DTE 参数结构也不同(用 front_dte_* / back_dte_*),换策略时要重新确认。
COMMISSION
Optopsy 手续费设置:四种字段与 float 简写的关系
手续费在开仓与平仓两侧都会计算。库支持两种写法:一个浮点数,或者一个完整的费用结构对象。
| 字段 / 写法 | 类型 | 默认 | 含义 | 适用场景 | 注意点 |
|---|---|---|---|---|---|
commission=0.65 | float | — | 简写:等价于 per_contract=0.65 | 只按张数收佣金的券商 | 最常用;但无法表达固定费用 |
per_contract | float | 0.0 | 每张期权合约的费用 | 主流券商的美式期权计费方式 | 四腿策略一张组合里有四张合约,费用会累加 |
per_share | float | 0.0 | 每股费用 | Covered / 领口类含股票腿的策略 | 股票腿按股计费,与期权腿不同 |
base_fee | float | 0.0 | 每笔交易的固定费用 | 有固定平台费的券商 | 开仓与平仓各收一次 |
min_fee | float | 0.0 | 每笔交易的最低费用 | 有最低收费门槛的券商 | 当按比例算出的费用低于它时,按它收 |
| 不设置 | None | 默认不收费 | 回测结果不含任何交易成本 | 只做策略结构对比时 | 这是最容易高估收益的默认值,做结论前务必至少加一次手续费 |
依据官方 parameters 文档的 Commission 一节与 optopsy/pricing.py 的佣金计算函数整理。
为什么这件事重要:手续费与滑点是期权回测里最容易让结果变好看的两处「静默假设」。默认既不收佣金、又用中间价成交,等于假设你在一个无摩擦市场里交易。本站不提供任何收益结论,但要提醒:任何未设置成本的对比,都只能说明策略结构差异,不能说明能否盈利。
SLIPPAGE MODELS
Optopsy 滑点模式说明:四种模式的方向、公式与默认值
滑点决定「用买卖价之间的哪个价格成交」。默认的 mid 是最乐观的一种。
| 模式 | 买入成交价 | 卖出成交价 | 趋势方向 | 额外参数 | 适用场景 | 注意点 |
|---|---|---|---|---|---|---|
mid(默认) | 买卖价中点 | 买卖价中点 | 最乐观 | 无 | 先跑通流程、做结构对比 | 假设你能精确在中间价成交,现实中不一定 |
spread | 买入侧不利一端(ask) | 卖出侧不利一端(bid) | 更保守 | 无 | 做保守情形的敏感性分析 | 作为保守上界很有用,但可能过于悲观 |
liquidity | 按成交量动态决定 | 按成交量动态决定 | 介于中间与保守之间 | fill_ratio、reference_volume | 想把流动性差异纳入考虑 | 需要数据里有 volume 或 open_interest 列,否则不可用 |
per_leg | 随腿数增加向不利方向偏移 | 随腿数增加向不利方向偏移 | 腿越多越保守 | fill_ratio、per_leg_slippage | 多腿策略、不想依赖成交量数据时 | 不需要 volume 列;所有腿使用同一个有效比率 |
依据官方 parameters 文档的滑点表与 optopsy/pricing.py 的成交价计算函数整理。
fill_ratio 的方向反直觉(官方表格里只带过一句):0.0 表示不利一端——买入按卖价、卖出按买价;0.5 是默认的中点;1.0 表示有利一端——买入按买价、卖出按卖价,官方明确标注这一档不现实。所以调这个参数时,想更保守应该调小,不是调大。
fill_ratio(配合 per_leg) | 1 腿时有效比率 | 2 腿 | 3 腿 | 4 腿 | 换算成「保留多少价差优势」 |
|---|---|---|---|---|---|
| 0.25 | 0.250 | 0.323 | 0.396 | 0.469 | 1 腿约 75%,2 腿约 68%,3 腿约 60%,4 腿约 53% |
| 0.50(默认起点) | 0.500 | 0.573 | 0.646 | 0.719 | 腿数越多越向不利一端靠 |
| 0.80 | 0.800 | 0.873 | 0.946 | 1.000(封顶) | 四腿时已达到最保守档 |
公式与数字出自官方 parameters 文档:effective_ratio = min(fill_ratio + per_leg_slippage × (num_legs − 1), 1.0),默认 per_leg_slippage=0.073;官方给出的示例是 fill_ratio=0.25 那一行。
另外两个默认值:reference_volume=1000(liquidity 模式下判断「什么算流动性好」的成交量阈值,官方按标的分档建议 500–1000 / 1000–2000 / 5000+),以及 per_leg_slippage=0.073(per_leg 模式下每多一条腿增加的偏移量)。
DEFAULTS AND TROUBLESHOOTING
Optopsy 默认值总表与成本类六种常见问题
先记住默认值,才知道你「什么都没设」的时候实际在假设什么。
| 参数 | 默认值 | 默认值的含义 | 想更保守该往哪调 |
|---|---|---|---|
max_entry_dte | 90 | 入场剩余到期日不超过 90 天 | 调小以获得更短周期的样本 |
exit_dte | 0(日历/对角逐默认 7) | 持有到期 | 调大以提前出场 |
min_bid_ask | 0.05 | 只要买卖价差不低于 5 美分就保留 | 调大以只保留流动性更好的合约 |
dte_interval | 7 | 按 7 天为一档分组 | 改成 14 或 30 得到更粗的分组 |
delta_interval | 0.05 | 按 0.05 的 Delta 宽度分组 | 调大以合并分组、提升每组的样本量 |
slippage | 'mid' | 按中间价成交(最乐观) | 改成 'spread' 得到保守上界 |
fill_ratio | 0.5 | 中间位置 | 调小(方向反直觉) |
reference_volume | 1000 | 1000 张视为流动性分界 | 按标的调大(如 SPX 用 5000) |
commission | None | 不收任何费用 | 至少设成你的券商真实费率 |
raw | False | 返回分组统计而非逐笔明细 | 想看 exit_type 时必须设为 True |
drop_nan | True | 丢弃结果里的缺失行 | 一般保持默认 |
全部默认值出自官方 parameters 文档的 Default Values Reference 两段代码块。
| 现象 | 原因 | 怎么确认 | 处置 |
|---|---|---|---|
报参数类型错误(如 stop_loss) | 符号或类型不符合约束:止盈必须正、止损必须负、持有天数必须正整数 | 读报错里的字段名与约束说明 | 按符号要求改写,不要用 abs() 绕过 |
设了 liquidity 但报缺列 | 数据里没有 volume 也没有 open_interest | 检查数据列名 | 补列,或改用 per_leg(它不依赖成交量) |
| 滑点调大后结果反而变好 | fill_ratio 方向理解反了 | 对照本页的 fill_ratio 说明 | 想保守就调小 fill_ratio |
| 加了手续费后交易笔数变了 | 手续费影响的是 P&L 与权益,正常情况下不应改变选股 | 对比加费用前后的 trade_log 笔数 | 若笔数变化,说明模拟层因资金不足截断了后续交易(ruin 截断),需要检查 capital 设置 |
| 早退一次都没触发 | 阈值太远,或中间报价日不足,或多腿策略存在腿缺报价的日期 | exit_type 的取值分布 | 放宽阈值;多腿策略先确认每条腿的数据覆盖 |
| 多腿策略早退很少 | 要求所有腿在同一日期都有报价 | 单独检查每条腿的报价日期覆盖 | 放宽 min_bid_ask 或换流动性更好的标的 |
依据官方参数文档的约束说明与本项目对 exits.py / pricing.py 的核验整理。
FAQ
Optopsy 早退与成本常见问题
stop_loss 为什么要写负数?
因为它的语义是「未实现盈亏跌到或低于这个值」。官方参数文档明确要求它是负数(如 -0.50 表示亏损 50%),写正数会被 Pydantic 校验直接拒绝。同理 take_profit 必须正数,max_hold_days 必须是正整数。
同一天同时触发止损和止盈会怎样?
不可能同时发生(一个是亏损、一个是盈利),但同日可能同时满足止盈与最长持有。官方规定优先级为止损 > 止盈 > 最长持有,取优先级最高的那个,并写入 exit_type 列。
默认不设手续费会有什么影响?
回测结果完全不含交易成本,这会系统性高估收益,尤其是高频、多腿的策略(四腿策略一次要付四张合约的费用,开平仓两侧都要付)。做任何结论前至少要把你的券商真实费率填进 commission。
mid、spread、liquidity、per_leg 该选哪个?
mid 是默认值也是最乐观的,适合先跑通流程;spread 是最保守的,适合做敏感性上界;liquidity 想按成交量模拟但需要数据里有 volume 或 open_interest;per_leg 适合多腿策略且不需要成交量数据。实务上建议至少同时跑 mid 与 spread 看区间。
fill_ratio 越大越好还是越小越好?
方向是反的:0.0 表示不利一端成交(买在卖价、卖在买价),1.0 表示有利一端成交且官方明确标注不现实。所以想让假设更保守,应该调小这个值,而不是调大。
per_leg 的有效比率是怎么算的?
公式是 effective_ratio = min(fill_ratio + per_leg_slippage × (num_legs − 1), 1.0),默认 per_leg_slippage=0.073,并且所有腿使用同一个有效比率(官方称为包价定价)。官方给出的示例是 fill_ratio=0.25 时,1 腿 0.250、2 腿 0.323、3 腿 0.396、4 腿 0.469。
加了这些参数之后回测结果算不算靠谱?
更接近现实,但仍然是一组简化假设。官方免责声明明确说明回测未考虑全部现实因素(流动性约束、执行滑点、指派风险、市场变化等),历史结果不代表未来。本站不提供任何收益判断或投资建议。