You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用pandas按股票分组计算相邻时序的价格变化率

多股票离散价格变化率实现方案

你的merge_asof实现思路是可行的,针对这个按股票分组匹配前序记录的需求,有两种稳定可复现的实现方式,都能严格避免跨股票匹配的问题。


前置要求

所有计算前必须先对数据做排序,否则会出现前序记录匹配错误:

  • 分组移位方案需要按股票代码+时间戳双字段升序排列
  • merge_asof方案需要左右连接表都按时间戳字段升序排列

方案1:分组移位法(最简洁,性能最优)

这是这类分组相邻行计算场景的首选方案,逻辑直观,代码量最少,适合绝大多数时间序列规整的行情数据场景。
实现步骤:

  1. 按Stock Symbol、Timestamp升序排序数据,重置索引避免旧索引干扰
  2. 按Stock Symbol分组,用shift(1)分别取同股票上一条记录的价格、时间戳
  3. 代入公式计算变化率即可,每只股票的第一条记录因为没有前序值,会自动返回NaN,完全符合需求

可直接运行的示例代码:

import pandas as pd

# 构造测试数据(含多只股票、乱序时间戳场景)
df = pd.DataFrame({
    'Stock Symbol': ['AAPL', 'AAPL', 'MSFT', 'AAPL', 'MSFT'],
    'Timestamp': [10, 12, 11, 15, 13],
    'Price': [100, 101, 200, 103, 201]
})

# 第一步:排序
df = df.sort_values(by=['Stock Symbol', 'Timestamp']).reset_index(drop=True)

# 第二步:取同组前序记录值
df['prev_price'] = df.groupby('Stock Symbol')['Price'].shift(1)
df['prev_ts'] = df.groupby('Stock Symbol')['Timestamp'].shift(1)

# 第三步:计算离散变化率
df['price_change_rate'] = (df['Price'] - df['prev_price']) / (df['Timestamp'] - df['prev_ts'])

# 可选清理临时列
df = df.drop(columns=['prev_price', 'prev_ts'])

上述测试数据的计算结果:

Stock SymbolTimestampPriceprice_change_rate
AAPL10100NaN
AAPL121010.5
AAPL151030.666667
MSFT11200NaN
MSFT132010.5

方案2:merge_asof实现(适合非规整时间序列场景)

如果数据存在时间戳乱序、或者需要严格匹配时间维度最近的前序记录(而非排序后的相邻行),可以用merge_asof实现,参数配置核心是必须指定by参数做股票分组,同时设置direction='backward'只匹配当前时间之前的记录,加上allow_exact_matches=False避免匹配到记录自身。
示例代码:

# 全局按时间戳排序,merge_asof要求连接键有序
df = df.sort_values(by='Timestamp').reset_index(drop=True)

# 构造用于匹配的前序记录表
prev_df = df[['Stock Symbol', 'Timestamp', 'Price']].rename(
    columns={'Timestamp': 'prev_ts', 'Price': 'prev_price'}
).sort_values(by='prev_ts')

# 按股票分组做asof匹配
match_df = pd.merge_asof(
    df,
    prev_df,
    by='Stock Symbol', # *核心分组参数*:严格在同股票范围内匹配,禁止跨股票
    left_on='Timestamp',
    right_on='prev_ts',
    direction='backward', # 只找时间早于当前的记录
    allow_exact_matches=False # 禁止匹配时间完全相同的自身记录
)

# 计算变化率
match_df['price_change_rate'] = (match_df['Price'] - match_df['prev_price']) / (match_df['Timestamp'] - match_df['prev_ts'])

避坑提醒

  • 禁止跳过排序步骤直接计算,否则会出现前序记录匹配错位
  • 用merge_asof时必须配置by='Stock Symbol'参数,否则会全局匹配时间最近的记录,出现跨股票计算的错误
  • 如果时间戳是datetime格式,计算时间差后可以根据需求转成秒/小时等统一单位再做除法

内容的提问来源于stack exchange,提问作者Joey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:27:25