第 4 章 · 01 informative 装饰器与多周期数据


文档摘要

第 4 章 · 01 informative 装饰器与多周期数据 本节摘要:很多稳健策略需要「多周期共振」——用大周期(如 1h)判断趋势,用小周期(如 5m)寻找入场点。freqtrade 提供两种引入辅助数据的机制:基础的 + ,以及更优雅的 装饰器。本节讲透这三者:如何声明要预拉取的辅助对、如何把大周期 DataFrame 合并回小周期 DataFrame、合并后的列命名规则,以及 装饰器的几种用法。读完本节,你能在策略里融合「BTC/USDT 1h 趋势 + 当前对 5m 入场」这类多周期逻辑。 内容来源:原项目文档 ,汉化并套用体系化模板。 学习目标 阅读完本节,你应当能够: 区分辅助数据(informative)与白名单交易对的不同。 用 声明要预拉取的辅助对。

第 4 章 · 01 informative 装饰器与多周期数据

本节摘要:很多稳健策略需要「多周期共振」——用大周期(如 1h)判断趋势,用小周期(如 5m)寻找入场点。freqtrade 提供两种引入辅助数据的机制:基础的 informative_pairs() + merge_informative_pair(),以及更优雅的 @informative 装饰器。本节讲透这三者:如何声明要预拉取的辅助对、如何把大周期 DataFrame 合并回小周期 DataFrame、合并后的列命名规则,以及 @informative 装饰器的几种用法。读完本节,你能在策略里融合「BTC/USDT 1h 趋势 + 当前对 5m 入场」这类多周期逻辑。

内容来源:原项目文档 docs/strategy-customization.md,汉化并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 区分**辅助数据(informative)**与白名单交易对的不同。
  2. informative_pairs() 声明要预拉取的辅助对。
  3. merge_informative_pair() 把大周期数据合并回小周期 DataFrame。
  4. 理解合并后的列命名规则(column_timeframe 后缀)。
  5. @informative 装饰器优雅地生成辅助指标。
  6. 区分 @informative 同对多周期辅助币种两种用法。

一、为什么需要多周期

单周期策略有个常见痛点:5m 上的 RSI 信号太频繁,假信号多。一个经典解法是「周期共振」——只在 1h 趋势向上时,才采纳 5m 的做多信号。这就需要在一个策略里同时拿到两个周期的数据

freqtrade 把「辅助数据」(informative pairs)与「交易对」(whitelist)区分开:

  • 交易对:会下载行情、跑策略、可能下单。
  • 辅助对/周期:只下载行情供策略读,不会下单(除非它同时也在白名单里)。

二、informative_pairs():声明要预拉什么

最基础的方式——重写 informative_pairs 方法,返回一个 (pair, timeframe) 元组列表:

def informative_pairs(self): return [ ("BTC/USDT", "1h"), # BTC 1 小时,做大盘趋势参考 ("ETH/USDT", "15m"), # ETH 15 分钟,做板块强弱参考 ]

引擎看到这个声明后,会在主循环里额外为这些组合下载行情并缓存,供你在 populate_indicators 里通过 self.dp.get_pair_dataframe(pair, timeframe) 取用。

💡 声明 ≠ 使用:声明了不取用,只是浪费一点带宽;忘了声明却取用,会拿到空数据或报错。先想好用什么 → 写进 informative_pairs → 在 populate_indicators 里取用,三步成环。

三、merge_informative_pair():手动合并

辅助数据拉来后,要把大周期的列合并到小周期 DataFrame 上。merge_informative_pair 处理这件麻烦事:

from freqtrade.strategy import merge_informative_pair def populate_indicators(self, dataframe, metadata): # 1. 算 5m 上的指标 dataframe["rsi"] = ta.RSI(dataframe) # 2. 取 BTC 1h 数据 informative = self.dp.get_pair_dataframe("BTC/USDT", "1h") informative["rsi_1h"] = ta.RSI(informative) # 3. 合并到 5m 主 DataFrame dataframe = merge_informative_pair( dataframe, informative, self.timeframe, "1h", ffill=True, ) return dataframe

合并后,DataFrame 会多出 rsi_1hclose_1hopen_1hdate_1h 等列。

列命名规则

合并后的列名 = 原列名 + _ + 时间周期:

原列 合并后(1h informative)
close close_1h
rsi_1h(已带后缀) rsi_1h_1h(注意双后缀)
date date_1h

⚠️ 命名冲突坑:如果你在 informative 上算的指标列名已经带 _1h 后缀,合并后会变成 rsi_1h_1h——可读性差。建议 informative 上的指标不要预先加后缀,让 merge_informative_pair 自动加。

ffill 的含义

ffill=True(默认)做「前向填充」——1h 一根 K 线对应 12 根 5m K 线,1h 那根的 RSI 值会被复制到对应区间的所有 5m 行上。没有 ffill 的话,5m 行上的 rsi_1h 大部分是 NaN。

💡 ffill 是关键:没有它,5m 行几乎拿不到 1h 指标(只有每小时对齐那一根有值)。多数场景保持 ffill=True

四、@informative 装饰器:优雅写法

手动 get_pair_dataframe + merge_informative_pair 三步走比较啰嗦。@informative 装饰器把这三步自动化——你写一个返回指标 DataFrame 的方法,装饰器自动处理声明、拉取、合并、命名。

用法 1:同对多周期

from freqtrade.strategy import informative @informative("1h") def populate_indicators_1h(self, dataframe, metadata): dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) dataframe["ema50"] = ta.EMA(dataframe, timeperiod=50) return dataframe

装饰器会:

  1. 自动把 ("当前对", "1h") 加入 informative_pairs。
  2. 自动拉 1h 数据,调这个方法算指标。
  3. 自动 merge 回主 DataFrame,列名加 _1h 后缀(rsi_1hema50_1h)。

populate_indicators 里就可以直接用 dataframe["rsi_1h"] 了。

用法 2:辅助币种

@informative("1h", "BTC/USDT") def populate_indicators_btc_1h(self, dataframe, metadata): dataframe["rsi"] = ta.RSI(dataframe) return dataframe

这样无论当前策略在跑哪个对,都会拉 BTC/USDT 1h 数据,合并出 rsi_1h_BTC/USDT 列(注意:辅助币的列名会带上币种标识)。

用法 3:完整签名

@informative( timeframe="1h", fmt="{base}_{column}_{timeframe}", # 列名格式 ffill=True, ) def populate_indicators_1h(self, dataframe, metadata): ...

fmt 控制列名格式,可用占位符 {base}{column}{timeframe}{quote}{base}_{quote}

五、在信号里使用多周期

合并好后,populate_entry_trend 里就能用「共振」条件:

def populate_entry_trend(self, dataframe, metadata): dataframe.loc[ # 5m 信号:RSI 超卖 (qtpylib.crossed_above(dataframe["rsi"], 30)) # 1h 守卫:大周期趋势向上(EMA50 上方) & (dataframe["close_1h"] > dataframe["ema50_1h"]) & (dataframe["rsi_1h"] > 50) & (dataframe["volume"] > 0), "enter_long", ] = 1 return dataframe

含义:5m 出现 RSI 超卖反弹(信号),且 1h 处于多头趋势(close 在 EMA50 上方、RSI 大于 50)——小周期信号被大周期趋势确认

💡 多周期的本质:不是让信号变多,而是让信号变——大周期做「方向过滤」,小周期做「时机选择」。胜率通常会显著提升,代价是信号变少。

六、性能与回测注意

  • 多周期会拉更多数据:每个辅助组合都是一份独立 OHLCV。回测前要 download-data 把这些周期也下下来。
  • startup_candle_count 按主周期算:辅助周期需要的热身根数 = 主周期根数 × 周期比。如 5m 启动 200 根,1h 辅助实际需要 ~17 根(200/12),自动满足。
  • @informative 在回测中开销小:装饰器是声明式的,回测会一次性算好缓存。

⚠️ 避免未来函数:merge_informative_pair 默认会对齐时间,确保 1h 的指标只用「已收盘」的 1h K 线值,不会偷看未来。但如果你手动用 dataframe["rsi_1h"].shift(-1) 这类负 shift,就会引入未来函数——回测神准、实盘崩盘。第 6 章会专门讲。

本节要点回顾

  1. 辅助 vs 交易对:辅助数据只下载供读、不下单;informative_pairs 声明要预拉的辅助对。
  2. merge_informative_pair:把大周期列合并回小周期 DataFrame,列名加 _<tf> 后缀,默认 ffill=True 前向填充。
  3. 列命名:合并后 closeclose_1h;若 informative 指标已带后缀会叠加成 _1h_1h,建议 informative 不预加后缀。
  4. @informative 装饰器:声明式自动处理声明/拉取/合并/命名;支持同对多周期、辅助币种、自定义 fmt
  5. 多周期用法:大周期做方向过滤,小周期做时机选择——信号变精、胜率提升。
  6. 未来函数陷阱:merge 默认对齐已收盘 K 线,但负 shift 会引入未来函数;回测神准实盘崩盘。

下一节,我们看 freqtrade 把「机械规则」变灵活的关键——回调函数全解。


发布者: 作者: 灏天文库 转发
评论区 (0)
U