如何在Polars中按交易天数指定滚动窗口大小?
在Polars中计算前N个交易日的最低价格(适配非连续日期)
问题背景
从Pandas迁移到Polars处理股票数据时,需要计算前n个交易日的最低价格,但Polars默认的时间窗口基于连续自然日计算,无法适配非连续的交易日(如周末、节假日),导致结果不符合预期。
测试数据
import polars as pl df = pl.from_repr(""" ┌────────────┬───────┐ │ Date ┆ Price │ │ --- ┆ --- │ │ date ┆ i64 │ ╞════════════╪═══════╡ │ 2023-01-01 ┆ 1 │ │ 2023-01-02 ┆ 2 │ │ 2023-01-03 ┆ 3 │ │ 2023-01-05 ┆ 4 │ │ 2023-01-10 ┆ 5 │ │ 2023-01-11 ┆ 6 │ │ 2023-01-12 ┆ 7 │ └────────────┴───────┘ """)
Pandas预期结果
df.to_pandas().Price.rolling(3).min()
输出:
0 NaN 1 NaN 2 1.0 3 2.0 4 3.0 5 4.0 6 5.0 Name: Price, dtype: float64
Polars错误尝试(基于自然日窗口)
df.rolling("Date", period="3d").agg(pl.col("Price").min())
输出(不符合预期):
┌────────────┬───────┐ │ Date ┆ Price │ │ --- ┆ --- │ │ date ┆ i64 │ ╞════════════╪═══════╡ │ 2023-01-01 ┆ 1 │ │ 2023-01-02 ┆ 1 │ │ 2023-01-03 ┆ 1 │ │ 2023-01-05 ┆ 3 │ │ 2023-01-10 ┆ 5 │ │ 2023-01-11 ┆ 5 │ │ 2023-01-12 ┆ 5 │ └────────────┴───────┘
解决方案:使用行数量滑动窗口
Polars完全可以实现与Pandas一致的结果,核心是放弃时间窗口,改用基于行数量的滑动窗口——因为我们需要的是前n条交易记录,而非自然时间范围内的数据。
实现代码
result = df.with_columns( pl.col("Price").rolling(index_size=3, min_periods=3).min().alias("Rolling_Min") ) print(result)
输出结果(与Pandas一致)
┌────────────┬───────┬────────────┐ │ Date ┆ Price ┆ Rolling_Min │ │ --- ┆ --- ┆ --- │ │ date ┆ i64 ┆ f64 │ ╞════════════╪═══════╪════════════╡ │ 2023-01-01 ┆ 1 ┆ null │ │ 2023-01-02 ┆ 2 ┆ null │ │ 2023-01-03 ┆ 3 ┆ 1.0 │ │ 2023-01-05 ┆ 4 ┆ 2.0 │ │ 2023-01-10 ┆ 5 ┆ 3.0 │ │ 2023-01-11 ┆ 6 ┆ 4.0 │ │ 2023-01-12 ┆ 7 ┆ 5.0 │ └────────────┴───────┴────────────┘
参数说明
index_size=3:设置滑动窗口的大小为3行(包含当前行在内的前3条交易记录)min_periods=3:要求窗口至少包含3条数据才计算最小值,否则返回null,与Pandas默认行为完全匹配
常见问题解答
是否需要手动创建索引列?
不需要。Polars的rolling可以直接基于行的位置实现滑动窗口,无需依赖索引,比Pandas的索引依赖更灵活。迁移到Polars是否合适?
完全合适。Polars在大数据量下的性能优势显著,这类时间序列滑动窗口计算可以高效实现,只需调整思路:当需要基于交易记录数量而非自然时间间隔时,选择行窗口而非时间窗口。
内容的提问来源于stack exchange,提问作者SpeedowaGONE
相关产品推荐
相关产品推荐

