EARLY EXIT · COST MODELS

早退、手续费与滑点:把成交假设调到接近真实的水平

只按「到期结算」回测,等于假设你永远能持有到最后一天。Optopsy 提供三个早退参数、一整套手续费结构和四种滑点模型,让假设更接近现实——但也更容易配错。

  • 符号有约束stop_loss 必须负数,take_profit 必须正数,max_hold_days 必须正整数。
  • exit_type 有优先级:同一天多条件触发时,止损 > 止盈 > 最长持有。
  • 滑点默认是 mid:最乐观的一种;做敏感性分析时至少要跑一次 spread
  • fill_ratio 方向反直觉0.0 偏向不利一端,1.0 偏向有利一端且官方明确说不现实。
买卖价两端bidask 构成价格区间
mid / spread中点成交 vs 不利一侧成交(更保守)
liquidity按成交量动态决定落在区间内的位置
per_leg腿数越多,越向不利一侧偏移
依据官方参数文档的滑点表与 optopsy/pricing.py 绘制;非官方图,不代表真实成交结果。

EARLY EXIT RULES

Optopsy 早退参数说明:符号约束、触发条件与优先级

Optopsy 的早退逻辑实现方式是:在入场到计划出场之间扫描中间报价日,找到最先满足条件的日期就提前平仓。

参数类型 / 约束触发条件对结果的影响适用场景注意点
stop_lossfloat 或 None;必须为负数未实现盈亏小于等于该阈值时提前平仓截断单笔亏损幅度,通常会降低尾部亏损也削掉部分反弹给卖方策略加保护写成 -0.50 表示亏损 50% 时平仓;写成正数会被校验拒绝
take_profitfloat 或 None;必须为正数未实现盈亏大于等于该阈值时提前平仓锁定利润,同时可能错过后续更大涨幅卖方策略的常见做法(如赚到 50% 就平)写成 0.50;写 50 会被拒绝
max_hold_daysint 或 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_holdexpiration 的比例通常反映你的持仓周期设置

  • 多腿策略的额外要求

    四腿这类多腿策略做早退时,要求所有腿在同一个中间日期都有报价,先算出合计的未实现盈亏再判断阈值。如果某条腿当天没有报价,那天就不能作为早退候选日——这会让多腿策略的早退触发比单腿更少。

    日历 / 对角的默认不同

    普通策略的 exit_dte 默认是 0(持有到期),而日历与对角默认是 7。这两类策略的 DTE 参数结构也不同(用 front_dte_* / back_dte_*),换策略时要重新确认。

    COMMISSION

    Optopsy 手续费设置:四种字段与 float 简写的关系

    手续费在开仓与平仓两侧都会计算。库支持两种写法:一个浮点数,或者一个完整的费用结构对象。

    字段 / 写法类型默认含义适用场景注意点
    commission=0.65float简写:等价于 per_contract=0.65只按张数收佣金的券商最常用;但无法表达固定费用
    per_contractfloat0.0每张期权合约的费用主流券商的美式期权计费方式四腿策略一张组合里有四张合约,费用会累加
    per_sharefloat0.0每股费用Covered / 领口类含股票腿的策略股票腿按股计费,与期权腿不同
    base_feefloat0.0每笔交易的固定费用有固定平台费的券商开仓与平仓各收一次
    min_feefloat0.0每笔交易的最低费用有最低收费门槛的券商当按比例算出的费用低于它时,按它收
    不设置None默认不收费回测结果不含任何交易成本只做策略结构对比时这是最容易高估收益的默认值,做结论前务必至少加一次手续费

    依据官方 parameters 文档的 Commission 一节与 optopsy/pricing.py 的佣金计算函数整理。

    为什么这件事重要:手续费与滑点是期权回测里最容易让结果变好看的两处「静默假设」。默认既不收佣金、又用中间价成交,等于假设你在一个无摩擦市场里交易。本站不提供任何收益结论,但要提醒:任何未设置成本的对比,都只能说明策略结构差异,不能说明能否盈利。

    SLIPPAGE MODELS

    Optopsy 滑点模式说明:四种模式的方向、公式与默认值

    滑点决定「用买卖价之间的哪个价格成交」。默认的 mid 是最乐观的一种。

    模式买入成交价卖出成交价趋势方向额外参数适用场景注意点
    mid(默认)买卖价中点买卖价中点最乐观先跑通流程、做结构对比假设你能精确在中间价成交,现实中不一定
    spread买入侧不利一端(ask)卖出侧不利一端(bid)更保守做保守情形的敏感性分析作为保守上界很有用,但可能过于悲观
    liquidity按成交量动态决定按成交量动态决定介于中间与保守之间fill_ratioreference_volume想把流动性差异纳入考虑需要数据里有 volumeopen_interest,否则不可用
    per_leg随腿数增加向不利方向偏移随腿数增加向不利方向偏移腿越多越保守fill_ratioper_leg_slippage多腿策略、不想依赖成交量数据时不需要 volume 列;所有腿使用同一个有效比率

    依据官方 parameters 文档的滑点表与 optopsy/pricing.py 的成交价计算函数整理。

    fill_ratio 的方向反直觉(官方表格里只带过一句):0.0 表示不利一端——买入按卖价、卖出按买价;0.5 是默认的中点;1.0 表示有利一端——买入按买价、卖出按卖价,官方明确标注这一档不现实。所以调这个参数时,想更保守应该调小,不是调大。

    fill_ratio(配合 per_leg1 腿时有效比率2 腿3 腿4 腿换算成「保留多少价差优势」
    0.250.2500.3230.3960.4691 腿约 75%,2 腿约 68%,3 腿约 60%,4 腿约 53%
    0.50(默认起点)0.5000.5730.6460.719腿数越多越向不利一端靠
    0.800.8000.8730.9461.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=1000liquidity 模式下判断「什么算流动性好」的成交量阈值,官方按标的分档建议 500–1000 / 1000–2000 / 5000+),以及 per_leg_slippage=0.073per_leg 模式下每多一条腿增加的偏移量)。

    DEFAULTS AND TROUBLESHOOTING

    Optopsy 默认值总表与成本类六种常见问题

    先记住默认值,才知道你「什么都没设」的时候实际在假设什么。

    参数默认值默认值的含义想更保守该往哪调
    max_entry_dte90入场剩余到期日不超过 90 天调小以获得更短周期的样本
    exit_dte0(日历/对角逐默认 7持有到期调大以提前出场
    min_bid_ask0.05只要买卖价差不低于 5 美分就保留调大以只保留流动性更好的合约
    dte_interval7按 7 天为一档分组改成 14 或 30 得到更粗的分组
    delta_interval0.05按 0.05 的 Delta 宽度分组调大以合并分组、提升每组的样本量
    slippage'mid'按中间价成交(最乐观)改成 'spread' 得到保守上界
    fill_ratio0.5中间位置调小(方向反直觉)
    reference_volume10001000 张视为流动性分界按标的调大(如 SPX 用 5000)
    commissionNone不收任何费用至少设成你的券商真实费率
    rawFalse返回分组统计而非逐笔明细想看 exit_type 时必须设为 True
    drop_nanTrue丢弃结果里的缺失行一般保持默认

    全部默认值出自官方 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

    midspreadliquidityper_leg 该选哪个?

    mid 是默认值也是最乐观的,适合先跑通流程;spread 是最保守的,适合做敏感性上界;liquidity 想按成交量模拟但需要数据里有 volumeopen_interestper_leg 适合多腿策略且不需要成交量数据。实务上建议至少同时跑 midspread 看区间。

    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。

    加了这些参数之后回测结果算不算靠谱?

    更接近现实,但仍然是一组简化假设。官方免责声明明确说明回测未考虑全部现实因素(流动性约束、执行滑点、指派风险、市场变化等),历史结果不代表未来。本站不提供任何收益判断或投资建议。

    下一步:按报错原文定位问题

    报错排查页把七类真实场景按「报错原文 → 原因 → 修复动作」组织,含装到 legacy 包、Pydantic 类型拒绝与缺列三类最高频问题。