pandas-ta · 未来函数

pandas-ta 未来函数审计:哪些指标列不能直接进回测

指标算对了,回测仍然可能是错的——只要其中一列用到了未来数据。本节给出一个不依赖阅读源码的判定方法(逐时点增量重算),公开本站的逐列实测读数,并给出从指标到信号的完整审计清单。

核验日期 2026-10-10逐时点重算实测120 行样本 × 60 次比对
截断到 t 重算
与全量结果比对第 t 行
一致 → 因果
不一致 → 含未来数据
依据本站逐时点增量重算实测绘制的因果性判定流程示意;非官方审计规范。
pandas-ta · 判定方法

pandas-ta 的指标列有没有用未来数据?怎么用代码判断

不要去猜指标公式。用数据本身做实验:把数据截断到时刻 t,只算到 t,再和「一次算完全部数据」在第 t 行的取值比。如果对不上,就说明这一列的值会因为后来的数据而变化。

def is_causal(df, fn, col):
    """fn: 传入 DataFrame 返回 Series/DataFrame 的调用;col: 要检查的列名。"""
    full = fn(df)[col]
    diffs = 0
    for t in range(warmup, len(df)):
        part = fn(df.iloc[: t + 1])[col]      # 只喂到 t
        if not np.isclose(part.iloc[-1], full.iloc[t], equal_nan=True):
            diffs += 1
    return diffs        # 0 表示这一列是因果的(不含未来数据)
为什么用这个方法说明局限
不需要读实现只依赖「输入变了输出会不会变」这一条可观测性质需要能反复调用,计算量随数据长度增长
能定位到列多列指标(如 Ichimoku)可以逐列判定,而不是整块下结论列数多时耗时明显
能当回归测试升级版本后重跑一次,就能发现新引入的非因果列需要一份有代表性的数据样本
注意点本方法判定的是实现层面的因果性—有些指标在数学定义上就用未来窗口(如 DPO),会被正确地判为非因果
预热期(warm-up)要跳过:截断数据太短时很多指标本来就没有值,比对没有意义。本站的做法是从「所有列都已出值」的位置开始比对。
pandas-ta · 实测结果

pandas-ta 哪些指标列通过、哪些不通过?

下表是本站对 120 行合成 OHLCV 数据、逐个时点增量重算的实测结果(比对区间为第 61–120 个时点,共 60 次比对)。

指标检查的列不一致时点数判定
sma(length=20)SMA_200因果,可安全使用
rsi(length=14)RSI_140因果
macd()MACD_12_26_9 等 3 列0因果
bbands(length=20)5 列0因果
supertrend()4 列0因果
tsi()2 列0因果
tsignals()输出即原 df 的各列0不改变原数据
ichimoku()ITS_9 / IKS_26 / ISA_9 / ISB_26各 0这四列在默认 append_span=False 下不做前瞻位移
ichimoku()ICS_26(Chikou Span)34非因果:默认 include_chikou=True,会向后位移
dpo()DPO_2049非因果:默认 centered=True,用中心化窗口
其它振荡类(willr / stoch / cci 等)未逐项检查—本站没有覆盖全部指标,请对你实际用到的那几个单独跑一遍
多列指标的逐列差异按列分别统计,而不是整块判定—同一个指标里可能只有部分列非因果,必须逐列看
重要限定:这只是本站在该数据样本与当前版本上的读数。它足以说明「DPO 与 Ichimoku 的 Chikou 这两处需要处理」,但不能证明「其余所有指标在所有参数下都因果」——想确认你自己用到的那几个,请按上一节的代码跑一遍。
pandas-ta · 怎么处理

pandas-ta 的非因果列,三种处理方式怎么选?

判定出来后不一定要放弃这个指标,但绝不能把它原样当成信号。下表给出三种处置方式与适用情形。

处置方式怎么做适用情形代价
① 关掉前瞻参数df.ta.dpo(length=20, centered=False);df.ta.ichimoku(include_chikou=False)你只是不想要未来信息,指标本身仍要保留指标含义会变,与教科书里的同名指标不再等价,要重新解释
② 自行位移对齐把整列 shift(n) 到「在信息可得时点才可见」的位置,n 从实现里推导保留原定义,但需要一个明确的可用时点位移量算错会引入新的偏差;建议用上一节的判定代码回归
③ 从信号池剔除不把这些列放进信号逻辑,只在事后研究中使用指标本身是「事后描述型」(例如 Chikou 用于回顾)放弃这部分信息在信号里的作用
  1. 先确认它到底在哪个时点才可得 对非因果列,用判定代码找出「第 t 行的值在第几行之后才稳定」——这个差值就是需要位移的量。实测中 DPO 与 Chikou 的位移都由定义决定(中心化窗口、向后 kijun 根)。
  2. 再决定是关参数还是做位移 如果只想要趋势信息,直接关前瞻参数最省事;如果要对齐教科书定义,就做位移并在注释里写清位移依据。
  3. 最后在回测里做一次对照 同一策略跑两遍:一遍带非因果列、一遍不带。如果两者绩效差距很大,说明原策略的核心收益来自未来信息,这个结论比任何参数优化都重要。
pandas-ta · 从指标到信号

指标值算对了,信号就写对了吗?

指标因果不等于信号因果。下面这张表是从指标值到下单动作之间最容易错位的四个环节。

环节常见错误为什么会出错正确做法
成交时点用当根 K 线的收盘价成交,但信号也来自当根收盘价收盘价在收盘那一刻才知道,你不可能用同一个价格成交信号在 t 根收盘生成,成交记为 t+1 根开盘(或 t 根收盘加滑点,但要明确写出来)
位移符号以为 shift(1) 是「往前看」,实际是「往后挪」pandas 的 shift(1) 把值下移一行,等于「让 t 行看到 t−1 行的值」在代码注释里写清「shift 后第 t 行代表 t−1 时刻的信息」,用一段断言验证首行是 NaN
预热期从最开头的一根 K 线就开始下单前 N 根里指标是 NaN,比较结果不可靠丢弃预热期内的信号,并记录丢了多少根
参数越多越危险在历史上反复调参直到曲线好看参数越多,越容易拟合噪声用样本外区间或滚动窗口验证,并保留一份调参记录
指标层与信号层要分开审计:先证明每个指标列是因果的(上一节),再证明从列到信号的映射满足「用 t 时刻可得的信息决定 t+1 时刻的动作」。两件事都做完,才谈得上「回测结果可以看」。
pandas-ta · 审计清单

接回测之前要做哪些审计?

把下面七项做成一张检查表,每次改策略都过一遍。前四项是数据层,后三项是信号层。

#检查项判据不通过的典型后果
1列名契约必需列齐全、索引为递增日期且无重复静默不加列或整列 NaN
2缺口处理在算指标之前完成 dropna,或明确记录保留策略依赖 rolling 的指标大面积 NaN
3复权口径一致指标与收益计算使用同一套价格口径指标看到的波动与实现的收益不是同一件事
4预热期隔离预热期内的信号被丢弃并计数最早一批信号建立在 NaN 之上
5指标因果性用增量重算代码逐列检查并留读数回测结果被未来数据抬高
6成交时点信号时点与成交时点的关系被显式写出并断言同根收盘价既发信号又成交
7样本外验证至少留出一段未参与调参的区间参数过拟合,上线后失效
8交易成本建模佣金、滑点、冲击成本至少给出一组假设并写在结论里回测收益被高估,与实盘差距无法解释
9极端行情检查把涨跌停、停牌、跳空区间单独看一遍结果策略在特殊区间失效但在全样本上看不出来
10信号密度检查统计每期产生多少信号,确认不是「几乎每根都发信号」信号过密通常意味着阈值失效或存在信息泄露
11可复现性检查在干净环境里用锁定版本重跑一次,比对结果结论无法复现,等于没有结论
本站不提供回测框架的选择建议,也不对任何策略的收益做评价。上面这份清单只解决一件事:让回测里不存在你自己都不知道的信息泄露。
FAQ

pandas-ta 未来函数常见问答:哪些列有问题、怎么自己验证

下面的回答都指向可核验的官方文件或本站实测;与官方表述冲突时,以官方仓库与文档为准。

pandas-ta 有未来函数吗?

有,但集中在可预期的位置:实测 DPO 在默认 centered=True 下、Ichimoku 在默认 include_chikou=True 下的 ICS_26 列会被判为非因果。其余本站检查过的常用指标(SMA/RSI/MACD/BBands/Supertrend/TSI)在实测中均无不一致。

DPI/DPO 这类指标是不是有 bug?

不是。DPO 的定义本身就是中心化窗口(用未来若干根 K 线做参照),非因果是它的定义特征。问题只在于你不能把它原样当成可交易的信号。

多周期数据会对不齐吗?

会。把日线指标与周线指标放在同一张表上时,周线值在一周内是不变的(或只在周末更新),对齐方式决定了下单时看到的是哪一期数值。本站不给统一答案,但要求把对齐规则写进代码注释并做断言。

怎么自己验证我用的指标?

用本页给出的判定代码:把数据截断到时刻 t 重新计算,与全量结果比对第 t 行的取值。60 次比对里只要出现不一致,就说明该列受到未来数据影响。

Ichimoku 的 ISA / ISB 也有问题吗?

在默认 append_span=False 的实测中,ISA_9 与 ISB_26 的不一致时点数为 0;被判为非因果的是 ICS_26(Chikou Span)。若你把 append_span 打开做前瞻位移,需要重新判定。

用 shift(1) 处理一下就行吗?

可能不够。位移量应当由「该列的值在第几行之后才稳定」推导,而不是凭经验写 1。用判定代码求出的差值才是依据;位移后建议再回归一次。

预热期要留多长才够?

以「最长窗口 + 信号窗口」为下限。本站实测 SMA(20) 的起始非空值在第 20 根,ATR(14) 在第 15 根,而 MACD 需要先跑满慢线再加信号窗口。保守做法是把预热期设为最长窗口的两倍,并统计被丢弃的信号条数写进记录。

本站的回测建议是什么?

本站不给策略建议,也不评价任何策略收益。只提供一份七项审计清单,用来确认你的回测里不存在你自己都不知道的信息泄露。

下一步:怎么和 TA-Lib 的结果对账?

审计完未来函数之后,下一个常被问到的问题是「为什么我的结果和 TA-Lib 不一样」。下一节给出逐列读数。