Overlap:LINREG(线性回归均线)技术指标详解

Overlap:LINREG(线性回归均线)技术指标详解

一、LINREG的定义

LINREG(Linear Regression Moving Average,线性回归均线) 是一种基于统计学线性回归理论的趋势跟踪指标。它不是简单地对价格取平均(如SMA),而是使用最小二乘法对一段价格序列拟合出一条"最佳拟合线",用以捕捉该段区间内价格的整体走势。

核心设计理念

线性回归是一种统计工具,用于根据历史价格预测未来价格可能的走向。传统的线性回归在图表上绘制为一条直线,类似趋势线。但线性回归均线并不是画一条直线,而是通过滑动窗口,在每个时间点计算窗口内数据的回归线"终点值",从而形成一条平滑的曲线。

当价格上涨时,线性回归线会试图确定价格相对于当前价格的上升偏差;当价格下跌时,它会试图确定价格的下降偏差。一些分析师认为,当价格高于或低于线性回归线时,价格处于过度延伸状态,将开始向该线回归。

LINREG的核心特征

特征 说明
理论基础 最小二乘法线性回归
指标类型 趋势跟踪/重叠指标
核心原理 对滚动窗口内的价格进行线性拟合,取回归线的终点值
默认参数 length=9或10
计算方式 滚动回归(Rolling Regression)
核心优势 比移动平均线更贴近价格的实际变动路径

LINREG的衍生信息

由于LINREG的计算基于线性回归,它可以衍生出多个有价值的辅助指标:

衍生指标 说明
斜率(Slope) 回归线的变化速率,正=上升趋势,负=下降趋势
角度(Angle) 斜率的弧度或度数表示,更直观地反映趋势陡峭程度
截距(Intercept) 回归线在价格轴上的起点位置
相关系数(R) 衡量价格与回归线的拟合程度,反映趋势强度

二、LINREG的计算方法

1. 核心计算公式

对于长度为 n n n 的滚动窗口,价格序列为 P 1 , P 2 , . . . , P n P_1, P_2, ..., P_n P1,P2,...,Pn,对应的时间索引为 x i = i x_i = i xi=i(通常从 0 开始)。

斜率(Slope, a a a) 的计算公式为:

a = n ∑ ( i ⋅ P i ) − ∑ i ∑ P i n ∑ i 2 − ( ∑ i ) 2 a = \frac{n \sum (i \cdot P_i) - \sum i \sum P_i}{n \sum i^2 - (\sum i)^2} a=n∑i2−(∑i)2n∑(i⋅Pi)−∑i∑Pi

截距(Intercept, b b b) 的计算公式为:

b = ∑ P i − a ∑ i n b = \frac{\sum P_i - a \sum i}{n} b=n∑Pi−a∑i

当前窗口的回归线终点值(即LINREG输出值) 为:

L I N R E G = a ⋅ ( n − 1 ) + b \mathrm{LINREG} = a \cdot (n - 1) + b LINREG=a⋅(n−1)+b

其中 ( n − 1 ) (n - 1) (n−1) 是窗口内最后一个时间点的索引值。

2. 简化公式(时间索引从0开始)

当时间索引 i i i 从 0 开始时, ∑ i \sum i ∑i 和 ∑ i 2 \sum i^2 ∑i2 有如下性质:

∑ i = n ( n − 1 ) 2 \sum i = \frac{n(n - 1)}{2} ∑i=2n(n−1)

∑ i 2 = n ( n − 1 ) ( 2 n − 1 ) 6 \sum i^2 = \frac{n(n - 1)(2n - 1)}{6} ∑i2=6n(n−1)(2n−1)

斜率 a a a 与价格序列的协方差和方差直接相关。对于实际计算,使用通用公式即可。

3. 计算示例

假设窗口长度 n = 5 n=5 n=5,价格序列如下:

时间索引 i 价格 Pi
0 100
1 102
2 105
3 103
4 108

计算各项求和

  • n = 5 n=5 n=5
  • ∑ i = 0 + 1 + 2 + 3 + 4 = 10 \sum i = 0+1+2+3+4 = 10 ∑i=0+1+2+3+4=10
  • ∑ i 2 = 0 + 1 + 4 + 9 + 16 = 30 \sum i^2 = 0+1+4+9+16 = 30 ∑i2=0+1+4+9+16=30
  • ∑ P i = 100 + 102 + 105 + 103 + 108 = 518 \sum P_i = 100+102+105+103+108 =518 ∑Pi=100+102+105+103+108=518
  • ∑ ( i ⋅ P i ) = 0 × 100 + 1 × 102 + 2 × 105 + 3 × 103 + 4 × 108 = 1053 \sum (i \cdot P_i) = 0×100+1×102+2×105+3×103+4×108 =1053 ∑(i⋅Pi)=0×100+1×102+2×105+3×103+4×108=1053

计算斜率 a a a

a = 5 × 1053 − 10 × 518 5 × 30 − 10 2 = 5265 − 5180 150 − 100 = 85 50 = 1.7 a = \frac{5 \times 1053 - 10 \times 518}{5 \times 30 - 10^2} = \frac{5265 - 5180}{150 - 100} = \frac{85}{50} = 1.7 a=5×30−1025×1053−10×518=150−1005265−5180=5085=1.7

计算截距 b b b

b = 518 − 1.7 × 10 5 = 518 − 17 5 = 501 5 = 100.2 b = \frac{518 - 1.7 \times 10}{5} = \frac{518 - 17}{5} = \frac{501}{5} = 100.2 b=5518−1.7×10=5518−17=5501=100.2

计算LINREG值(回归线终点)

L I N R E G = 1.7 × 4 + 100.2 = 6.8 + 100.2 = 107.0 \mathrm{LINREG} = 1.7 \times 4 + 100.2 = 6.8 + 100.2 = 107.0 LINREG=1.7×4+100.2=6.8+100.2=107.0

该值为107.0,略低于最新价格108.0,表明价格略高于回归趋势线的预测。

三、LINREG的使用方法

1. 趋势方向判断------最基础用法

LINREG线的方向直接反映了价格的趋势方向,这是最直观的应用:

LINREG状态 趋势含义 操作倾向
LINREG向上运行 上升趋势 以做多为主,寻找买入机会
LINREG向下运行 下降趋势 以做空为主,寻找卖出机会
LINREG走平 趋势可能减弱或进入盘整 观望,等待方向明确

2. 价格偏离与回归------超买超卖判断

一些分析师认为,当价格高于或低于线性回归线时,价格处于过度延伸状态,将开始向该线回归:

价格与LINREG的关系 市场含义 操作倾向
价格远高于LINREG 价格过度延伸,可能回调 警惕超买,关注卖出机会
价格接近LINREG 价格处于合理位置 观察趋势延续性
价格远低于LINREG 价格过度下跌,可能反弹 关注超卖反弹机会

3. 斜率与角度------趋势强度量化

利用LINREG的衍生信息可以量化趋势强度:

斜率/角度状态 含义 操作策略
斜率为正且持续增大 上升趋势在加速 顺势持仓,趋势强劲
斜率为正但开始减小 上升趋势在减速 警惕趋势减弱
斜率从正转负 趋势由涨转跌 趋势反转信号
角度大于45度 趋势强劲 顺势交易
角度小于20度 趋势疲软 谨慎操作

4. 拟合度(相关系数R)------趋势强弱判断

通过计算相关系数 RR,可以判断当前回归趋势的拟合程度:

R值范围 趋势强度 操作策略
R > 0.7 趋势强,价格与回归线拟合度高 适合顺势交易,信号可靠
0.3 ≤ R ≤ 0.7 趋势中等 顺势操作,但需设置止损
R < 0.3 趋势弱,可能震荡 不宜追单,建议观望

5. 时间序列预测(TSF)

利用tsf=True可以获取下一周期的预测价格,其原理是沿回归线外推一个单位:

T S F = a ⋅ n + b \mathrm{TSF} = a \cdot n + b TSF=a⋅n+b

即用斜率 a a a 乘以 n n n(窗口长度)再加截距 b b b,得到下一个周期的预测值。这一功能常与其他指标(如布林带、MACD)配合使用,形成趋势确认与价格预测的复合策略。

6. 注意事项与局限性

使用LINREG前需了解以下要点

局限性 说明
本质仍是滞后指标 基于历史数据的统计拟合,对突发性价格变化反应滞后
窗口长度敏感 短窗口更灵敏但噪声多,长窗口更平滑但滞后明显
假设线性关系 金融市场是非线性的,线性回归只能近似拟合短期趋势
过度延伸不是精确信号 价格偏离回归线不一定立即回归,可能在强趋势中持续偏离

适用场景总结

市场环境 适用性 说明
趋势行情 最佳适用 回归线能有效跟踪趋势方向
震荡行情 慎用 价格频繁穿越回归线,信号可靠性低
趋势强度判断 适用 通过R值和斜率量化趋势强弱
多指标组合 适用 适合与MACD、布林带等配合使用

四、使用pandas_ta计算LINREG

1. pandas_ta中的LINREG函数

pandas_ta库内置了LINREG指标的完整实现,函数位于overlap模块中。该函数可以输出回归线值及其多种衍生指标。

2. 函数完整参数

python 复制代码
pandas_ta.overlap.linreg(close, length=None, offset=None, **kwargs)

参数详解

参数 类型 默认值 说明
close pd.Series 必需 收盘价序列
length int 10 回归窗口长度
offset int 0 结果偏移周期数
slope bool False 若为True,返回斜率值
intercept bool False 若为True,返回截距值
r bool False 若为True,返回相关系数(拟合度)
angle bool False 若为True,返回斜率角度(弧度)
degrees bool False 若为True,返回斜率角度(度)
tsf bool False 若为True,返回时间序列预测值(未来一周期)

3. 示例代码

python 复制代码
import pandas as pd
import pandas_ta as ta
import numpy as np
import matplotlib.pyplot as plt

# ========== 第一步:准备数据 ==========
np.random.seed(42)
dates = pd.date_range(start='2023-01-01', end='2024-12-31', freq='D')
n = len(dates)

# 生成带趋势和周期波动的价格序列
trend = np.linspace(0, 45, n)
cycle = np.sin(np.linspace(0, 6 * np.pi, n)) * 15
noise = np.random.randn(n) * 3
price_series = 100 + trend + cycle + noise

# 添加趋势变化区间
price_series = price_series.astype(float)
for i in range(300, 450):
    price_series[i] = price_series[300] + (i-300) * 0.2   # 强势上涨段
for i in range(450, 600):
    price_series[i] = price_series[450] - (i-450) * 0.15  # 强势下跌段

df = pd.DataFrame(index=dates[:n])
df['close'] = price_series[:n]
df['high'] = df['close'] + np.abs(np.random.randn(n)) * 2 + 1
df['low'] = df['close'] - np.abs(np.random.randn(n)) * 2 - 1
df['volume'] = np.random.randint(1000000, 25000000, n)

print("=" * 60)
print("数据预览:")
print(df.head())
print("\n" + "=" * 60 + "\n")

# ========== 第二步:计算LINREG(基础用法) ==========
# 使用默认参数 length=10
df['LINREG'] = ta.linreg(df['close'])

print("LINREG计算结果(最近10行):")
print(df[['close', 'LINREG']].tail(10))
print("\n" + "=" * 60 + "\n")

# ========== 第三步:计算衍生指标 ==========
# 同时获取回归线、斜率、角度、相关系数
linreg_result = ta.linreg(
    df['close'], 
    length=10, 
    slope=True, 
    intercept=True, 
    r=True, 
    degrees=True,
    tsf=True
)

# 查看返回的DataFrame结构
print("LINREG衍生指标返回列名称:")
print(linreg_result.columns.tolist())
print("\n" + "=" * 60 + "\n")

# 将计算结果添加到原DataFrame
df['LINREG'] = linreg_result['LINREG']
df['Slope'] = linreg_result['SLOPE']
df['Intercept'] = linreg_result['INTERCEPT']
df['R'] = linreg_result['R']
df['Angle_Deg'] = linreg_result['DEGREES']
df['TSF'] = linreg_result['TSF']

print("LINREG及衍生指标(最近10行):")
print(df[['close', 'LINREG', 'Slope', 'R', 'Angle_Deg', 'TSF']].tail(10))
print("\n" + "=" * 60 + "\n")

# ========== 第四步:不同周期的LINREG对比 ==========
# 短周期 (5)
df['LINREG_5'] = ta.linreg(df['close'], length=5)

# 标准周期 (10)
df['LINREG_10'] = ta.linreg(df['close'], length=10)

# 长周期 (20)
df['LINREG_20'] = ta.linreg(df['close'], length=20)

print("不同周期LINREG对比(最近5行):")
print(df[['close', 'LINREG_5', 'LINREG_10', 'LINREG_20']].tail())
print("\n" + "=" * 60 + "\n")

# ========== 第五步:计算传统均线进行对比 ==========
df['SMA_10'] = ta.sma(df['close'], length=10)
df['EMA_10'] = ta.ema(df['close'], length=10)

print("LINREG vs SMA vs EMA 对比(最近10行):")
print(df[['close', 'LINREG_10', 'SMA_10', 'EMA_10']].tail(10))
print("\n" + "=" * 60 + "\n")

# ========== 第六步:价格穿越信号 ==========
df['price_above_linreg'] = df['close'] > df['LINREG_10']
df['cross_above'] = (df['price_above_linreg'] == True) & (df['price_above_linreg'].shift(1) == False)
df['cross_below'] = (df['price_above_linreg'] == False) & (df['price_above_linreg'].shift(1) == True)

df['signal'] = ''
df.loc[df['cross_above'], 'signal'] = '买入(价格上穿LINREG)'
df.loc[df['cross_below'], 'signal'] = '卖出(价格下穿LINREG)'

print("价格穿越信号统计:")
print(f"买入信号数量:{df['cross_above'].sum()}")
print(f"卖出信号数量:{df['cross_below'].sum()}")

print("\n最近15个穿越信号:")
signals = df[df['signal'] != ''].tail(15)
if not signals.empty:
    print(signals[['close', 'LINREG_10', 'signal']])
print("\n" + "=" * 60 + "\n")

# ========== 第七步:趋势强度分类 ==========
def classify_trend_strength(r_value, slope):
    """根据R值和斜率分类趋势"""
    if r_value > 0.7 and slope > 0:
        return '强上升趋势'
    elif r_value > 0.7 and slope < 0:
        return '强下降趋势'
    elif r_value > 0.3 and slope > 0:
        return '中等上升趋势'
    elif r_value > 0.3 and slope < 0:
        return '中等下降趋势'
    else:
        return '震荡/弱趋势'

df['trend_strength'] = df.apply(
    lambda row: classify_trend_strength(row['R'], row['Slope']), 
    axis=1
)

print("趋势强度分布统计:")
print(df['trend_strength'].value_counts())
print("\n" + "=" * 60 + "\n")

# ========== 第八步:策略回测(价格穿越策略) ==========
# 策略:价格上穿LINREG买入,下穿LINREG卖出
df['position'] = 0
in_position = False

for i in range(1, len(df)):
    if not in_position and df['cross_above'].iloc[i]:
        df.loc[df.index[i], 'position'] = 1
        in_position = True
    elif in_position and df['cross_below'].iloc[i]:
        df.loc[df.index[i], 'position'] = 0
        in_position = False
    else:
        df.loc[df.index[i], 'position'] = df['position'].iloc[i-1]

df['returns'] = df['close'].pct_change()
df['strategy_returns'] = df['position'].shift(1) * df['returns']

total_return_buyhold = (1 + df['returns']).prod() - 1
total_return_strategy = (1 + df['strategy_returns']).prod() - 1
win_rate = (df['strategy_returns'] > 0).sum() / (df['strategy_returns'] != 0).sum() if (df['strategy_returns'] != 0).sum() > 0 else 0

print("=" * 60)
print("策略绩效统计(LINREG穿越策略回测):")
print(f"买入持有策略总收益率:{total_return_buyhold:.2%}")
print(f"LINREG穿越策略总收益率:{total_return_strategy:.2%}")
print(f"策略胜率:{win_rate:.2%}")
print("\n注意:此为简化回测,仅供参考")
print("=" * 60 + "\n")

# ========== 第九步:可视化 ==========
plt.figure(figsize=(14, 12))

# 子图1:价格走势与LINREG对比
plt.subplot(2, 1, 1)
plt.plot(df.index[-200:], df['close'][-200:], label='Close Price', 
         linewidth=1.5, color='black')
plt.plot(df.index[-200:], df['LINREG_10'][-200:], label='LINREG (10) - 线性回归均线', 
         linewidth=1.5, color='blue')
plt.plot(df.index[-200:], df['SMA_10'][-200:], label='SMA (10)', 
         linewidth=1, color='orange', alpha=0.7, linestyle='--')
plt.plot(df.index[-200:], df['EMA_10'][-200:], label='EMA (10)', 
         linewidth=1, color='green', alpha=0.7, linestyle=':')
plt.title('LINREG vs SMA vs EMA 对比 (Last 200 days)', fontsize=14)
plt.ylabel('Price')
plt.legend()
plt.grid(True, alpha=0.3)

# 子图2:不同周期LINREG对比
plt.subplot(2, 1, 2)
plt.plot(df.index[-200:], df['close'][-200:], label='Close Price', 
         linewidth=1, alpha=0.5, color='black')
plt.plot(df.index[-200:], df['LINREG_5'][-200:], label='LINREG (5) - 短线', 
         linewidth=1, alpha=0.7)
plt.plot(df.index[-200:], df['LINREG_10'][-200:], label='LINREG (10) - 标准', 
         linewidth=1.5, color='blue')
plt.plot(df.index[-200:], df['LINREG_20'][-200:], label='LINREG (20) - 长线', 
         linewidth=1.5, color='green')

# 标记穿越信号
buy_signals = df[df['cross_above']]
sell_signals = df[df['cross_below']]
plt.scatter(buy_signals.index[-25:], buy_signals['close'][-25:], 
            color='green', marker='^', s=60, label='买入信号(价格上穿)', alpha=0.8)
plt.scatter(sell_signals.index[-25:], sell_signals['close'][-25:], 
            color='red', marker='v', s=60, label='卖出信号(价格下穿)', alpha=0.8)

plt.title('LINREG:不同周期对比与穿越信号', fontsize=14)
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# ========== 第十步:数据清洗提示 ==========
nan_count = df['LINREG_10'].isna().sum()
print(f"\nLINREG初始NaN数量:{nan_count}")
print("原因:LINREG需要至少length个周期的数据才能计算线性回归")
print("处理建议:df_clean = df.iloc[10:].copy()")
print("\n" + "=" * 60)
print("LINREG使用提示:")
print("1. LINREG是线性回归拟合的终点值曲线,比SMA更贴近价格路径")
print("2. 通过slope参数获取斜率,判断趋势方向和强度")
print("3. 通过r参数获取相关系数(R值),判断趋势强弱(R>0.7为强趋势)")
print("4. 价格偏离LINREG时可能发生回归,但强趋势中可能持续偏离")
print("5. 建议与MACD、布林带等指标配合使用")
print("6. tsf参数可获取下一周期的价格预测值")
print("=" * 60)

五、总结

LINREG(线性回归均线)是一种基于统计学线性回归理论的趋势跟踪指标,其核心价值与定位如下:

维度 特点
核心创新 用滑动窗口线性回归替代简单平均,更贴近价格路径
核心公式 LINREG = a·(n-1) + b,其中a为斜率,b为截距
四大衍生指标 斜率(方向强度)、相关系数(拟合度)、角度(趋势陡峭度)、TSF(价格预测)
默认参数 length=10
最佳应用场景 趋势方向判断、趋势强度量化、多指标组合策略
主要局限 滞后性、窗口长度敏感、假设线性关系

实战使用三原则

  1. 趋势方向看斜率,趋势强弱看R值:斜率正负决定多空方向,R值(>0.7为强趋势)决定持仓信心
  2. 价格回归是概率事件,非精确信号:价格偏离LINREG后可能回归,但在强趋势中可能持续偏离,需结合趋势强度判断
  3. 多周期综合判断:短周期LINREG(5-10)捕捉短期方向,长周期LINREG(20-50)确认主趋势,方向一致时信号更可靠

最后提醒:LINREG的本质是将统计学中的线性回归应用于技术分析,其核心价值在于提供一个比传统均线更"理性"的趋势参考线------它不仅告诉你价格在哪里,还告诉你价格正在以怎样的速度变化。结合斜率、R值等衍生信息,LINREG可以成为一个功能丰富的趋势分析工具,而非仅仅是一条均线。