ENTRY SIGNALS
Optopsy 入场信号:85 个指标工厂怎么接到策略上
信号的作用是限制「什么时候入场」。这里有一个最容易误解的点:信号跑在股票行情数据上,而不是期权链上——仅有的例外是 IV Rank。
- 85 个信号工厂函数:另有 6 个组合/工具函数与
Signal类,__all__里信号相关共 91 个名字。 - 输入是股票数据:需要
underlying_symbol、quote_date、close三列。 - 一个例外:
iv_rank_above/iv_rank_below跑在期权链上,需要implied_volatility列。 - 可以自由组合:
&/|运算符、sustained连续条件、custom_signal外部标志位。
underlying_symbol / quote_date / close(可选 high/low/volume)rsi_below(14, 30),返回布尔序列signal_dates()把布尔序列转成有效的(标的,日期)对entry_dates / exit_dates;例外:IV Rank 用期权链optopsy/signals/ 源码绘制的示意图;非官方流程图。SIGNAL GROUPS
Optopsy 七组信号:类别、默认参数与数据要求
下表按源码目录分组,给出代表函数与官方默认参数。完整清单以官方 entry-signals 文档为准。
| 组 | 代表函数 | 官方默认参数示例 | 数据要求 | 适用场景 | 注意点 |
|---|---|---|---|---|---|
| 动量类 | rsi_below、macd_cross_above、stoch_below、cci_above、uo_above、squeeze_on 等 | RSI:period=14、threshold=30 / 70;MACD:12/26/9 | 至少需要 close | 用超买超卖或动量转折决定入场时点 | 组内 16 对函数,是数量最多的一组;阈值是官方默认值,不代表适用你的标的 |
| 均线类 | sma_above、ema_cross_above、hma_cross_above、kama_cross_above、alma_cross_above 等 | SMA:period=20;各类交叉:fast=10、slow=50 | 至少需要 close | 用趋势方向做过滤 | 9 对函数;交叉类信号在震荡行情里会频繁触发 |
| 波动率类 | atr_below、bb_below_lower、kc_above_upper、donchian_above_upper、natr_above、massi_above | ATR:period=14、multiplier=1.0;布林带:length=20、std=2.0 | 理想上需要 high / low(缺失时用 close 兜底) | 在低波动或高波动区间才卖/买期权 | 这一组最容易受 close 兜底影响,见本页后段 |
| 趋势强度类 | adx_above、aroon_cross_above、supertrend_buy、psar_buy、chop_below、vhf_above | ADX:period=14、threshold=25;Supertrend:period=7、multiplier=3.0 | 同样理想上需要 high / low | 只在趋势明确时才开方向性仓位 | 与均线类容易重复表达同一件事,组合时注意共线性 |
| 量能类 | mfi_above、obv_cross_above_sma、cmf_above、ad_cross_above_sma | MFI:period=14、threshold=80 / 20;OBV:sma_period=20 | 必须有 volume 列 | 用资金流确认价格信号 | 缺 volume 时这组不可用 |
| 隐含波动率类 | iv_rank_above、iv_rank_below | threshold=0.5、window=252 | 需要期权链的 implied_volatility 列 | 在 IV 处于高位时卖出期权、低位时买入 | 这是仅有跑在期权链上的一组 |
| 日历类 | day_of_week | 参数为星期序号:0=周一 … 4=周五 | 只需 quote_date | 把入场限制在特定星期 | 常与其他信号组合用于事件前后的窄窗口 |
| 自定义类 | custom_signal | flag_col 指定布尔列名 | 任何含 underlying_symbol、quote_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 Line | 缺 volume 时这一组根本不可用(不是退化) | 提供 volume 列 | 与 high/low 缺失是两类不同问题,别混为一谈 |
| IV Rank | 隐含波动率排名 | 缺 implied_volatility 列时不可用 | 在期权链数据里提供该列 | 它是仅有跑在期权链上的信号,输入源本就不同 |
依据官方 entry-signals 文档末尾的提示(列出受影响指标清单)与本项目对 optopsy/signals/ 源码的核验整理。
怎么判断自己会不会踩到
检查你的股票数据有没有 high 与 low 列。如果只有 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) | 函数式 OR | op.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_symbol、quote_date、close),生成日期集合后再传给期权策略。仅有的例外是 IV Rank(iv_rank_above / iv_rank_below),它跑在期权链上,需要 implied_volatility 列。
一共有多少个信号?
按 __all__ 实际计数:信号相关的导出名字共 91 个,其中 85 个是信号工厂函数,另有 6 个组合/工具函数(signal_dates、and_signals、or_signals、sustained、signal、custom_signal)与 Signal 类。官方 README 写「80+」,足够准确但偏保守。
signal_dates() 是必须的吗?
是。信号函数返回的是布尔序列,而策略要的是「哪些日期可以入场」。signal_dates() 负责这个转换。跳过这一步直接把布尔列传给策略是跑不通的。
能不能用我自己的选股结果当入场条件?
可以。两条路:①把选股结果整理成含 underlying_symbol、quote_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 的下降幅度是否符合预期,再决定放宽信号还是接受更小的样本。