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,价格序列如下:
| 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走平 | 趋势可能减弱或进入盘整 | 观望,等待方向明确 |
2. 价格偏离与回归——超买超卖判断
一些分析师认为,当价格高于或低于线性回归线时,价格处于过度延伸状态,将开始向该线回归:
| 价格远高于LINREG | 价格过度延伸,可能回调 | 警惕超买,关注卖出机会 |
| 价格接近LINREG | 价格处于合理位置 | 观察趋势延续性 |
| 价格远低于LINREG | 价格过度下跌,可能反弹 | 关注超卖反弹机会 |
3. 斜率与角度——趋势强度量化
利用LINREG的衍生信息可以量化趋势强度:
| 斜率为正且持续增大 | 上升趋势在加速 | 顺势持仓,趋势强劲 |
| 斜率为正但开始减小 | 上升趋势在减速 | 警惕趋势减弱 |
| 斜率从正转负 | 趋势由涨转跌 | 趋势反转信号 |
| 角度大于45度 | 趋势强劲 | 顺势交易 |
| 角度小于20度 | 趋势疲软 | 谨慎操作 |
4. 拟合度(相关系数R)——趋势强弱判断
通过计算相关系数 RR,可以判断当前回归趋势的拟合程度:
| 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. 函数完整参数
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. 示例代码
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 |
| 最佳应用场景 | 趋势方向判断、趋势强度量化、多指标组合策略 |
| 主要局限 | 滞后性、窗口长度敏感、假设线性关系 |
实战使用三原则:
最后提醒:LINREG的本质是将统计学中的线性回归应用于技术分析,其核心价值在于提供一个比传统均线更“理性”的趋势参考线——它不仅告诉你价格在哪里,还告诉你价格正在以怎样的速度变化。结合斜率、R值等衍生信息,LINREG可以成为一个功能丰富的趋势分析工具,而非仅仅是一条均线。

