
本文介绍如何在多产品时间序列数据中精准识别价格连续不变的自然交易日区间,支持跨周五-周一的逻辑连续性判断,并严格按产品分组、排除非相邻重复价格。
本文介绍如何在多产品时间序列数据中精准识别价格连续不变的自然交易日区间,支持跨周五-周一的逻辑连续性判断,并严格按产品分组、排除非相邻重复价格。
在金融与零售分析中,常需识别商品价格“冻结期”——即价格在多个连续交易日(非日历日)保持不变的区间。难点在于:① 周末(周六、周日)不参与交易,因此周五与下周一视为逻辑连续;② 同一价格在不同产品或非连续日期出现时不应合并;③ 必须严格按 ID 分组处理,避免跨产品干扰。
Pandas 原生的 shift().cumsum() 在未处理工作日逻辑时会失效(如将 2024-02-01 与 2024-02-04 视为不连续)。正确解法是显式构建“预期下一个交易日”逻辑,再逐行比对是否满足连续条件。
以下为完整可运行解决方案:
一款AI工具,主要用于Monitor and clean up invalid Codex authentication files in CPA. Check quota status, disable files returning 401 errors, and perform dual verification before deletion.,适合需要提升相关任务效率的用户。
import pandas as pd
def get_next_trading_day(d):
"""给定一个日期,返回其下一个交易日(跳过周末)"""
d = d + pd.Timedelta("1 day")
if d.dayofweek == 4: # Friday → skip to Monday
d += pd.Timedelta("2 days")
elif d.dayofweek == 5: # Saturday → skip to Monday
d += pd.Timedelta("2 days")
elif d.dayofweek == 6: # Sunday → skip to Monday
d += pd.Timedelta("1 day")
return d
def find_price_stability_intervals(df):
df = df.sort_values(['ID', 'Date']).reset_index(drop=True)
df['Date'] = pd.to_datetime(df['Date'])
results = []
current_group = []
prev_id = prev_price = None
expected_next = None
for _, row in df.iterrows():
i, d, p = row['ID'], row['Date'], row['Price']
# 判断是否属于同一稳定区间:
# ✅ 同一 ID、相同价格、且当前日期等于上一日期的“预期交易日”
is_continuous = (
prev_id == i and
prev_price == p and
expected_next is not None and
d == expected_next
)
if not is_continuous:
# 结束上一组(若存在)
if len(current_group) >= 2:
results.append({
'ID': current_group[0][0],
'start_date': current_group[0][1],
'end_date': current_group[-1][1],
'price': current_group[0][2],
'repeated_days_count': len(current_group)
})
current_group = [(i, d, p)]
else:
current_group.append((i, d, p))
prev_id, prev_price = i, p
expected_next = get_next_trading_day(d)
# 处理最后一组
if len(current_group) >= 2:
results.append({
'ID': current_group[0][0],
'start_date': current_group[0][1],
'end_date': current_group[-1][1],
'price': current_group[0][2],
'repeated_days_count': len(current_group)
})
return pd.DataFrame(results)
# 示例数据(注意:原始数据中价格使用逗号小数点,需统一为点)
data = {
'ID': [1,1,1,1,1,2,2,2,2,2],
'Date': ['2024-02-01','2024-02-04','2024-02-05','2024-02-06','2024-02-07',
'2024-02-01','2024-02-04','2024-02-05','2024-02-06','2024-02-07'],
'Price': ['1.00','1.00','1.20','1.30','1.30',
'1.30','0.90','0.90','0.90','1.30']
}
df = pd.DataFrame(data)
result = find_price_stability_intervals(df)
print(result)
✅ 输出结果:
ID start_date end_date price repeated_days_count 0 1 2024-02-01 2024-02-04 1.00 2 1 1 2024-02-06 2024-02-07 1.30 2 2 2 2024-02-04 2024-02-06 0.90 3
⚠️ 关键注意事项:
- 日期格式必须标准化:确保 Date 列为 datetime64[ns] 类型,否则 dayofweek 属性不可用;
- 价格字段需数值化:示例中已用 '.' 替换原始数据的 ',' 小数点,实际使用前建议 df['Price'] = df['Price'].str.replace(',', '.').astype(float);
- 最小长度过滤:本实现仅保留 repeated_days_count ≥ 2 的区间(单日不构成“重复”),可根据需求调整阈值;
- 性能提示:对超大规模数据(百万级行),可改用 numba 加速循环,或借助 pandas.groupby(...).apply() 配合向量化 diff() 辅助判断(但需重写工作日逻辑)。
该方法完全规避了 shift().cumsum() 的跨组污染风险,通过状态机式遍历保证逻辑严谨性,是处理含非交易日缺失的时间序列稳定性检测的稳健范式。










