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

基于scipy linregress的时间序列支撑阻力趋势线计算优化问题

股票时间序列支撑位、阻力位趋势线拟合优化方案

原代码异常原因定位

  • 核心逻辑缺陷:原阻力位拟合不断删除低于回归线的样本、支撑位拟合不断删除高于回归线的样本,最终仅用剩余2个点生成趋势线。遇到ENZ、ARTL这类存在短期大幅跳涨/跳空走势的个股时,剩余2个点大概率是极端异常点,完全无法反映整体走势的支撑/阻力水平
  • 噪声未过滤:未对收盘价做平滑处理,小盘股的短期异常波动会直接干扰拟合结果
  • 绘图坐标轴适配问题:使用twiny双X轴未做刻度对齐,容易出现趋势线和日期走势视觉错位的问题

优化后完整代码

import pandas as pd
import pandas_datareader as pdr
import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import linregress
import datetime as dt

# 优化参数配置:可根据个股波动调整
SMOOTH_WINDOW = 3  # 收盘价平滑窗口
EXTREMUM_QUANTILE = 0.05  # 极值筛选分位数,值越小保留的极值点越少

for ticker in ['SNN','AAPL', 'ENZ', 'ARTL']:
    print('Processing ticker '+ str(ticker))
    # 获取数据
    df = pdr.get_data_yahoo(ticker, start = '2020-09-01', end = '2021-09-01', interval = "d")
    df['Ticker'] = ticker
    df_len = len(df)
    df['Number'] = np.arange(df_len)+1
    # 收盘价滚动平滑,过滤短期噪声
    df['smooth_close'] = df['Close'].rolling(SMOOTH_WINDOW, min_periods=1).mean()

    # 阻力位拟合:筛选顶部极值点后拟合,而非裁剪到只剩2个点
    df_high = df.copy()
    # 先初步回归得到基础斜率,筛选高于回归线的前N%极值点
    slope, intercept, r_value, p_value, std_err = linregress(x=df_high['Number'], y=df_high['smooth_close'])
    high_pct = df_high['smooth_close'].quantile(1-EXTREMUM_QUANTILE)
    df_high = df_high.loc[(df_high['smooth_close'] > slope * df_high['Number'] + intercept) & (df_high['smooth_close'] >= high_pct)]
    # 最终用筛选后的极值点拟合,避免仅用2个点的偏差
    slope_resist, intercept_resist, _, _, _ = linregress(x=df_high['Number'], y=df_high['smooth_close'])
    df['resistance'] = slope_resist * df['Number'] + intercept_resist    
    print( '\tresistance:\t' + ' slope: ' + str(round(slope_resist, 3)) + '\tintercept: '+ str(round(intercept_resist,3)))

    # 支撑位拟合:筛选底部极值点后拟合
    df_low = df.copy()
    slope, intercept, r_value, p_value, std_err = linregress(x=df_low['Number'], y=df_low['smooth_close'])
    low_pct = df_low['smooth_close'].quantile(EXTREMUM_QUANTILE)
    df_low = df_low.loc[(df_low['smooth_close'] < slope * df_low['Number'] + intercept) & (df_low['smooth_close'] <= low_pct)]
    slope_support, intercept_support, _, _, _ = linregress(x=df_low['Number'], y=df_low['smooth_close'])
    df['support'] = slope_support * df['Number'] + intercept_support
    print( '\tsupport:\t' + ' slope: ' + str(round(slope_support,3)) +'\tintercept: '+ str(round(intercept_support,3)))

    # 修复绘图逻辑,统一X轴避免错位
    fig, ax = plt.subplots(figsize=(8,5))
    xdate = [x.date() for x in df.index]
    ax.plot(xdate, df.Close, label="收盘价", color='tab:green')
    ax.plot(xdate, df.resistance, label="阻力位", color='tab:red')
    ax.plot(xdate, df.support, label="支撑位", color='tab:blue')
    ax.set_xlabel('日期')
    ax.set_ylabel('价格')
    plt.title(label=ticker)
    plt.legend()
    plt.grid()
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.show()

优化效果说明

  • 对于存在异常波动的ENZ、ARTL等个股,拟合的趋势线不再被极端值带偏,能反映区间内的整体支撑/阻力水平
  • 平滑窗口和分位数参数可根据个股属性灵活调整,小盘股可适当调大窗口、提高分位数阈值,大盘股可降低参数值提升灵敏度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:48:01