ENTRY SIGNALS

Optopsy 入场信号:85 个指标工厂怎么接到策略上

信号的作用是限制「什么时候入场」。这里有一个最容易误解的点:信号跑在股票行情数据上,而不是期权链上——仅有的例外是 IV Rank。

  • 85 个信号工厂函数:另有 6 个组合/工具函数与 Signal 类,__all__ 里信号相关共 91 个名字。
  • 输入是股票数据:需要 underlying_symbolquote_dateclose 三列。
  • 一个例外iv_rank_above / iv_rank_below 跑在期权链上,需要 implied_volatility 列。
  • 可以自由组合& / | 运算符、sustained 连续条件、custom_signal 外部标志位。
股票 OHLCV 数据underlying_symbol / quote_date / close(可选 high/low/volume)
信号工厂函数rsi_below(14, 30),返回布尔序列
signal_dates()把布尔序列转成有效的(标的,日期)对
传给策略作为 entry_dates / exit_dates;例外:IV Rank 用期权链
依据官方 entry-signals 文档与 optopsy/signals/ 源码绘制的示意图;非官方流程图。

SIGNAL GROUPS

Optopsy 七组信号:类别、默认参数与数据要求

下表按源码目录分组,给出代表函数与官方默认参数。完整清单以官方 entry-signals 文档为准。

代表函数官方默认参数示例数据要求适用场景注意点
动量类rsi_belowmacd_cross_abovestoch_belowcci_aboveuo_abovesqueeze_onRSI:period=14threshold=30 / 70;MACD:12/26/9至少需要 close用超买超卖或动量转折决定入场时点组内 16 对函数,是数量最多的一组;阈值是官方默认值,不代表适用你的标的
均线类sma_aboveema_cross_abovehma_cross_abovekama_cross_abovealma_cross_aboveSMA:period=20;各类交叉:fast=10slow=50至少需要 close用趋势方向做过滤9 对函数;交叉类信号在震荡行情里会频繁触发
波动率类atr_belowbb_below_lowerkc_above_upperdonchian_above_uppernatr_abovemassi_aboveATR:period=14multiplier=1.0;布林带:length=20std=2.0理想上需要 high / low(缺失时用 close 兜底)在低波动或高波动区间才卖/买期权这一组最容易受 close 兜底影响,见本页后段
趋势强度类adx_abovearoon_cross_abovesupertrend_buypsar_buychop_belowvhf_aboveADX:period=14threshold=25;Supertrend:period=7multiplier=3.0同样理想上需要 high / low只在趋势明确时才开方向性仓位与均线类容易重复表达同一件事,组合时注意共线性
量能类mfi_aboveobv_cross_above_smacmf_abovead_cross_above_smaMFI:period=14threshold=80 / 20;OBV:sma_period=20必须有 volume用资金流确认价格信号缺 volume 时这组不可用
隐含波动率类iv_rank_aboveiv_rank_belowthreshold=0.5window=252需要期权链的 implied_volatility在 IV 处于高位时卖出期权、低位时买入这是仅有跑在期权链上的一组
日历类day_of_week参数为星期序号:0=周一 … 4=周五只需 quote_date把入场限制在特定星期常与其他信号组合用于事件前后的窄窗口
自定义类custom_signalflag_col 指定布尔列名任何含 underlying_symbolquote_date 与标志列的 DataFrame接入模型输出、人工标注或外部事件表整数 0/1 与可空布尔均可;NaN 视为 False

依据官方 entry-signals 文档的信号分组表与各组默认参数整理;函数数量按 __all__ 分类计数(信号相关名字共 91 个,其中 85 个为信号工厂函数)。

官方 README 写「80+ Entry Signals」,这个说法成立且偏保守:按 Optopsy 的 __all__ 实际计数,信号工厂函数是 85 个,加上 6 个组合/工具函数与 Signal 类,信号相关导出共 91 个名字。

HOW TO USE

Optopsy 怎么把信号接到策略上:四步方法

Optopsy 的信号使用是一条固定的三段式流程:准备股票数据 → 造信号 → 转日期 → 传给策略

写法取自官方 entry-signals 与 examples 文档;本站未在 Python 3.12+ 环境实跑。

  • 准备股票行情数据
    import optopsy as op
    
    stocks = op.load_cached_stocks("SPY")
    # 或用自己的数据:
    # stocks = pd.DataFrame({
    #     "underlying_symbol": "SPY",
    #     "quote_date": my_dates,
    #     "close": my_prices,
    # })

    最少需要标的、日期、收盘价三列。要用 high/low/volume 类信号时把这些列也带上。load_cached_stocks() 读的是内置 CLI 下载的股票缓存,需要 optopsy[data]

    预期输出:一个含 underlying_symbol / quote_date / close 的 DataFrame

  • 构造信号(可组合)
    entry = op.signal(op.rsi_below(14, 30)) & op.signal(op.sma_above(50))

    op.signal() 把工厂函数包成可组合对象,& 是「同时满足」,| 是「满足其一」。也可以用函数式的 and_signals / or_signals

    预期输出:一个 Signal 对象

  • 转成有效日期集合
    entry_dates = op.signal_dates(stocks, entry)

    signal_dates() 把布尔序列转成(标的,日期)对。这一步是必需的:策略要的是日期集合,不是布尔列。

    预期输出:一个可按标的分组的日期集合

  • 把日期传给策略
    options = op.load_cached_options("SPY")
    results = op.long_calls(
        options,
        entry_dates=entry_dates,
        max_entry_dte=45,
        exit_dte=0,
    )

    策略只会在你给的那些日期建仓,其余报价日被忽略。同一套写法也可以传 exit_dates

    预期输出:结果行数通常明显少于不加信号时

  • 连续条件:sustained

    要求条件连续成立 N 根才触发,例如「RSI 连续 5 天低于 30」。写法是 op.sustained(op.rsi_below(14, 30), days=5)。它对样本量影响很大——连续条件越长,可用入场日越少。

    自定义函数也能当信号

    任何签名是 (pd.DataFrame) -> pd.Series[bool] 的函数都可以直接传给 signal_dates(),也可以和内置信号用 op.signal() 组合。这给了你接自己逻辑的口子。

    SILENT IMPRECISION

    Optopsy 官方一句话带过的精度问题:close 兜底

    官方文档在末尾用一句提示说明了这件事,影响面却比那句话看起来大。

    官方原文要点:依赖最高报价与最低报价的信号,在缺少 high / low 列时会退化为用 close 代替,并且明确建议提供真实 OHLCV 数据以获得准确结果。

    受影响信号组受影响的指标退化后会怎样正确做法注意点
    动量类Stochastic(%K/%D)、Williams %R、CCI、Stochastic RSI这些指标本质用区间位置衡量,只用 close 会让数值系统性偏移提供真实 high / low指标数值会变,触发日期也会跟着变
    波动率类ATR、Keltner Channel、Donchian Channel、NATR真实波幅被低估,通道宽度失真同上用虚拟的 high=low=close 会低估波动
    趋势强度类ADX、Aroon、Supertrend、PSAR、Choppiness方向强度判断变钝,交叉信号变密或变稀同上趋势类信号本来就容易假触发,退化会加剧
    量能类MFI、OBV、CMF、A/D Linevolume 时这一组根本不可用(不是退化)提供 volume与 high/low 缺失是两类不同问题,别混为一谈
    IV Rank隐含波动率排名implied_volatility 列时不可用在期权链数据里提供该列它是仅有跑在期权链上的信号,输入源本就不同

    依据官方 entry-signals 文档末尾的提示(列出受影响指标清单)与本项目对 optopsy/signals/ 源码的核验整理。

    怎么判断自己会不会踩到

    检查你的股票数据有没有 highlow 列。如果只有 close,那么上表前三组的信号结果都是近似值——它不会报错,只会安静地给你一个不太准的入场日期集合。

    为什么官方要设计兜底

    为了让「只有收盘价数据」的用户也能跑通流程,而不是直接失败。这是易用性上的合理取舍,但使用者必须知道取舍的代价。本站把它单独列出来,正是因为官方只用一句话带过。

    COMBINATORS

    Optopsy 组合与自定义:怎么把信号拼成自己的入场规则

    写法含义示例适用场景注意点
    op.signal(a) & op.signal(b)两个条件同时成立(AND)op.signal(op.rsi_below(14,30)) & op.signal(op.sma_above(50))把「超卖」和「趋势向上」叠加条件越多,可用入场日越少,样本下降很快
    op.signal(a) | op.signal(b)满足其一即可(OR)op.signal(op.macd_cross_above()) | op.signal(op.bb_below_lower())想扩大入场机会OR 会让样本增加但也会混入风格不同的入场点
    and_signals(a, b, c)函数式 AND,等价于链式 &op.and_signals(op.rsi_below(14,30), op.sma_above(50), op.atr_below(14,0.75))条件较多时更易读与运算符写法语义相同
    or_signals(a, b)函数式 ORop.or_signals(op.macd_cross_above(), op.bb_below_lower())同上同上
    sustained(signal, days)要求连续 N 根成立op.sustained(op.rsi_below(14,30), days=5)过滤单日噪声、要求条件持续days 越大样本越少;官方示例里用过 3 与 5
    custom_signal(df, flag_col)从任意具有布尔标志列的 DataFrame 造信号op.custom_signal(my_flags, flag_col="go")接入模型输出、事件表、人工标注整数 0/1 与可空布尔均可;NaN 视为 False
    自定义函数直接传任何 (DataFrame) -> Series[bool] 的函数def price_above_400(data): return data["close"] > 400逻辑无法用内置信号表达时同样需要先经 signal_dates() 转换

    依据官方 entry-signals 文档的 Combinators 与 Custom Signal 两节整理。

    一个实务提醒:信号越复杂,样本越少。当入场条件叠加到三四个时,某些 DTE × Delta 分组的 count 可能降到个位数。这时候分组统计里的均值已经不具备参考意义——一定要先看 count 再看其他列。

    SIGNAL TROUBLESHOOTING

    Optopsy 信号类六种常见问题与处置

    现象原因怎么确认处置
    加了 entry_dates 后结果直接为空信号的触发日期与期权链的报价日期没有交集打印 entry_dates 的日期范围与期权链 quote_date 的范围对比对齐两者时间区间;注意日期粒度与时间戳归一化
    结果比预期少很多条件叠加过多或用了较长的 sustained逐个条件单独跑一次,看各自触发多少天放宽阈值或降低 days
    信号都触发不了数据里缺列(如量能类缺 volume看报错或检查数据列名补列,或换用不依赖该列的信号
    指标数值与别处算的对不上缺少 high/low 时用 close 兜底检查股票数据是否含 high / low提供真实 OHLCV,见本页的兜底警告
    custom_signal 触发得莫名其妙标志列不是布尔类型,或含 NaN(被当作 False)打印标志列的 value_counts(dropna=False)显式转成布尔并决定 NaN 的语义
    IV Rank 信号报缺列在股票数据上跑 IV Rank,而它需要期权链的隐含波动率确认传入的数据是期权链且含 implied_volatility改用期权链数据作为该信号的输入

    依据官方 entry-signals 文档的输入要求与本项目对 signals/ 源码的核验整理。

    FAQ

    Optopsy 入场信号常见问题

    信号是在期权数据上算还是在股票数据上算?

    在股票行情数据上算。信号函数接收的是股票 OHLCV(最少要 underlying_symbolquote_dateclose),生成日期集合后再传给期权策略。仅有的例外是 IV Rank(iv_rank_above / iv_rank_below),它跑在期权链上,需要 implied_volatility 列。

    一共有多少个信号?

    __all__ 实际计数:信号相关的导出名字共 91 个,其中 85 个是信号工厂函数,另有 6 个组合/工具函数(signal_datesand_signalsor_signalssustainedsignalcustom_signal)与 Signal 类。官方 README 写「80+」,足够准确但偏保守。

    signal_dates() 是必须的吗?

    是。信号函数返回的是布尔序列,而策略要的是「哪些日期可以入场」。signal_dates() 负责这个转换。跳过这一步直接把布尔列传给策略是跑不通的。

    能不能用我自己的选股结果当入场条件?

    可以。两条路:①把选股结果整理成含 underlying_symbolquote_date 与布尔标志列的 DataFrame,用 custom_signal();②写一个 (DataFrame) -> Series[bool] 签名的函数直接传给 signal_dates()。两条路都可以和内置信号用 op.signal() 组合。

    high/low 列会有什么后果?

    所有依赖最高报价/最低报价的信号会退化为用 close 代替,官方文档明确说明这一点并建议提供真实 OHLCV。受影响的是随机指标、Williams %R、CCI、ATR、Keltner、Donchian、ADX、Aroon、Supertrend、PSAR、Choppiness 等。它不会报错,只会让结果偏。

    信号越多结果越好吗?

    不是。每增加一个条件,可用入场日就会减少,某些 DTE × Delta 分组的样本数可能降到个位数——这时分组统计的均值已不具参考意义。建议先看 count,再决定要不要保留这么多条件。本站不提供任何策略优劣判断。

    为什么加上信号之后有些 DTE 区间没有结果了?

    因为信号把入场日期限制在一个子集里,原本靠大量报价日凑出来的 DTE 分桶可能不再有足够样本。这是正常现象,不是 bug。先确认 count 的下降幅度是否符合预期,再决定放宽信号还是接受更小的样本。

    下一步:怎么把早退、手续费与滑点配成接近真实

    早退与成本页讲清三个早退参数的符号约束与 exit_type 优先级、手续费结构,以及四种滑点模式的差异与 fill_ratio 的反直觉方向。