AI在时间序列中的趋势检测
编辑
2
2025-06-23

提示词
假设有一个DataFrame,index是日期,有一列数据是股票的收盘价,收盘价中可能包括多种趋势,需要对其进行趋势检测,找出明显的上涨趋势并可视化,请给出示例代码。
答案
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from scipy.stats import linregress
from sklearn.preprocessing import MinMaxScaler
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. 修正趋势检测函数
def detect_trends(series):
# 方法1:移动平均交叉策略(使用20日均线)
ma20 = series.rolling(20).mean() # 20日移动平均线[1,3](@ref)
# 方法2:线性回归趋势线
X = np.arange(len(series))
slope, intercept, r_value, p_value, std_err = linregress(X, series)
# 方法3:时间序列分解(使用20日周期)
decomposition = sm.tsa.seasonal_decompose(series, period=20) # 20日周期分解[9](@ref)
trend_component = decomposition.trend.dropna()
# 方法4:20日滚动斜率(修复索引错误)
rolling_slopes = []
for i in range(len(series)):
# 取20日窗口
start_idx = max(0, i - 19) # 确保有20个数据点
window = series.iloc[start_idx:i+1]
if len(window) > 1: # 至少有2个点才能计算斜率
x = np.arange(len(window))
slope_value = linregress(x, window.values).slope
rolling_slopes.append(slope_value)
else:
rolling_slopes.append(np.nan) # 不足2个点则填充NaN
return ma20, slope, trend_component, rolling_slopes
# 3. 使用修正后的函数
ma20, overall_slope, trend_comp, rolling_slopes = detect_trends(df['Close'])
# 4. 可视化设计
plt.figure(figsize=(16, 12))
ax1 = plt.subplot(3, 1, 1)
# 原始价格与20日均线
df['Close'].plot(ax=ax1, label='收盘价', alpha=0.6)
ma20.plot(ax=ax1, label='20日均线', color='orange', lw=2)
# 标注价格在均线上方的区域
ax1.fill_between(df.index, df['Close'], ma20,
where=(df['Close'] > ma20),
color='red', alpha=0.3, label='价格高于均线')
# 趋势分解可视化
ax2 = plt.subplot(3, 1, 2, sharex=ax1)
trend_comp.plot(ax=ax2, color='green', label='趋势成分')
ax2.fill_between(trend_comp.index, trend_comp,
where=(trend_comp.pct_change() > 0),
color='red', alpha=0.3, label='上涨区间')
# 20日滚动斜率可视化
ax3 = plt.subplot(3, 1, 3, sharex=ax1)
slope_series = pd.Series(rolling_slopes, index=df.index)
slope_series.plot(ax=ax3, color='blue', label='20日滚动斜率')
ax3.axhline(0, color='black', ls='--')
ax3.fill_between(df.index, rolling_slopes, 0,
where=(np.array(rolling_slopes) > 0),
color='red', alpha=0.3, label='上升趋势')
# 添加趋势强度标记
strong_trend_points = slope_series[slope_series > slope_series.quantile(0.9)]
ax3.scatter(strong_trend_points.index, strong_trend_points.values,
color='darkred', s=50, label='强上升趋势')
# 图表美化
ax1.set_title(f'整体趋势方向:{"上涨" if overall_slope > 0 else "下跌"} (斜率:{overall_slope:.4f})', fontsize=14)
ax1.set_ylabel('价格', fontsize=12)
ax1.legend(loc='upper left')
ax1.grid(alpha=0.3)
ax2.set_title('趋势成分分解 (20日周期)', fontsize=14)
ax2.set_ylabel('趋势值', fontsize=12)
ax2.legend(loc='upper left')
ax2.grid(alpha=0.3)
ax3.set_title('20日滚动斜率分析', fontsize=14)
ax3.set_ylabel('斜率', fontsize=12)
ax3.set_xlabel('日期', fontsize=12)
ax3.legend(loc='upper left')
ax3.grid(alpha=0.3)
plt.tight_layout()
plt.show()
# 5. 输出趋势分析结果
print(f"整体趋势斜率: {overall_slope:.6f} (正值表示上涨趋势)")
print(f"强上升趋势出现次数: {len(strong_trend_points)}次")
print("主要强上升趋势时间段:")
for i in range(0, len(strong_trend_points), 5):
print(f"{strong_trend_points.index[i].strftime('%Y-%m-%d')} - 斜率: {strong_trend_points.iloc[i]:.4f}")
数据导入以及防止画图中文乱码的代码是我加进去的,其余都是ai写的。
图像:
- 0
- 0
-
赞助
支付宝
微信
-
分享