生生不息

生生不息

AI使用Pelt算法检测趋势变化

2025-06-23
AI使用Pelt算法检测趋势变化

提示词

有一个DataFrame,包含日期和股票的收益价,请用Pelt算法对其进行变点检测。

答案

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import ruptures as rpt

plt.style.use('seaborn-v0_8')
#指定字体,防止中文出现乱码,windows系统指定为‘SimHei’
plt.rcParams['font.sans-serif'] = ['SimHei']
#这行代码让中文的负号“-”可以正常显示
plt.rcParams["axes.unicode_minus"]=False

# 1. 创建示例数据(含异常值,替换为你的实际数据)
df = pd.read_excel('../数据/2-1.xlsx')
df = df[['日期', '收盘']]
df.columns = ['date','Close']
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace = True)

# 2. 数据预处理
signal = df['Close'].values  # 提取收盘价信号

# 3. PELT变点检测配置
model = "rbf"  # 检测均值和方差变化[8](@ref)
algo = rpt.Pelt(model=model).fit(signal)
penalty = 3 * np.log(len(signal))  # 动态惩罚系数
change_points = algo.predict(pen=penalty)

# 4. 可视化结果
plt.figure(figsize=(14, 7))
plt.plot(df.index, df['Close'], label='收盘价', lw=1.5)

# 标记变点(排除最后一个索引)
for cp in change_points[:-1]:
    plt.axvline(x=df.index[cp], color='red', ls='--', alpha=0.7, 
                label='变点' if cp == change_points[0] else None)

# 添加分段着色
prev_cp = 0
colors = ['#E6F3FF', '#FFE9E6', '#F0F0FF']
for i, cp in enumerate(change_points[:-1]):
    plt.axvspan(df.index[prev_cp], df.index[cp], 
                facecolor=colors[i%3], alpha=0.3)
    prev_cp = cp

plt.title('股票收盘价变点检测 (PELT算法)', fontsize=14)
plt.ylabel('价格', fontsize=12)
plt.grid(alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()

# 5. 输出变点信息
print(f"检测到变点数量: {len(change_points)-1}")
print("变点日期及价格详情:")
cp_df = pd.DataFrame({
    '变点日期': df.index[change_points[:-1]],
    '收盘价': df['Close'].iloc[change_points[:-1]].values,
    '窗口长度': np.diff([0]+change_points[:-1])  # 各段长度
})
print(cp_df)

数据导入以及防止画图中文乱码的代码是我加进去的,其余都是ai写的。

图像: