一文读懂量化交易中最常用的5种均线,附源码,建议收藏

在量化交易和技术分析中,均线 是最基础也最重要的工具之一。无论你是刚入门的量化新手,还是有实战经验的老股民,理解不同种类的均线及其特点,都是构建策略前的必修课。

今天这篇文章,花姐就来系统介绍一下五种最常见的均线类型------SMA、EMA、WMA(LWMA)、TMA、VMA,以及它们的计算逻辑和实际区别。


一、什么是均线?

简单来说,均线是用来平滑时间序列波动的工具,通过对历史价格的平均,来观察趋势的方向与强度。

我们可以设定一个固定的"回看周期"(如5日、10日、30日等),每往前推进一天,就剔除最早的那个数据点、加入最新的价格,因此叫做"移动平均"。

举个例子👇:

假设我们有一组数据:

复制代码
8, 10, 5, 13, 17, 19, 14, 18, 12

计算5日简单移动平均(SMA):

  • 第一个值:(8 + 10 + 5 + 13 + 17) / 5 = 10.6
  • 第二个值:(10 + 5 + 13 + 17 + 19) / 5 = 12.8
  • 第三个值:(5 + 13 + 17 + 19 + 14) / 5 = 13.6
  • 第四个值:(13 + 17 + 19 + 14 + 18) / 5 = 16.2
  • 第五个值:(17 + 19 + 14 + 18 + 12) / 5 = 16.0

每次计算都是取连续5个数的平均,窗口不断向前滑动,这就是"移动"平均的精髓

想用Python跑一下这个例子的话,用 pandas 非常方便:

python 复制代码
import pandas as pd

data = [8, 10, 5, 13, 17, 19, 14, 18, 12]
s = pd.Series(data)
sma_5 = s.rolling(window=5).mean()

print(sma_5.dropna())  # 输出非NaN的结果

输出就是:

go 复制代码
4    10.6
5    12.8
6    13.6
7    16.2
8    16.0
dtype: float64

关于均线的周期说明

在移动平均线的交易策略中,常用的回看周期包括 5、10、20、30 、60 、120 和 250 。 这些周期可以根据不同的时间维度来设置,比如分钟级、日线、周线等,具体选择取决于交易者的策略偏好: 👉 如果偏向短线交易 ,可以使用较小的周期(如5或10); 👉 如果倾向中期交易 ,则可以选择更长的周期(如20、30、60); 👉 如果倾向趋势交易,则可以选择更长的周期(如120、250)。

不同的周期长度能帮助交易者捕捉不同级别的市场趋势,是技术分析中非常关键的一环,当然也有一些股民为了防止庄家割韭菜,搞假动作,也会采用特殊的周期来做均线,比如7、9、13之类的。


二、五种常见均线类型对比

1. 简单移动平均线(SMA:Simple Moving Average)

SMA 是最基础 、最常用的一种均线,它对所有的数据点赋予相同的权重

公式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> SMA = 周期内所有价格之和 周期数 \text{SMA} = \frac{\text{周期内所有价格之和}}{\text{周期数}} </math>SMA=周期数周期内所有价格之和

优点:

  • 简单直观,计算方便 缺点:
  • 对价格变动反应慢,有"滞后性"

下面是一个使用 AKShare 获取 沪深300指数最近两年数据,并用 matplotlib 绘制 收盘价 + 5日、10日、20日简单移动平均线(SMA) 的完整 Python 示例代码,我们看看SMA的走势如何

python 复制代码
import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# 1. 获取最近2年的日期范围
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)
start_str = start_date.strftime("%Y%m%d")
end_str = end_date.strftime("%Y%m%d")

# 2. 获取沪深300指数的历史行情数据(指数代码:000300.SH)
df = ak.index_zh_a_hist(
    symbol="000300",
    period="daily",
    start_date=start_str,
    end_date=end_str)

# 3. 数据预处理
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)

# 4. 计算移动平均线
df['MA5'] = df['收盘'].rolling(window=5).mean()
df['MA10'] = df['收盘'].rolling(window=10).mean()
df['MA20'] = df['收盘'].rolling(window=20).mean()

# 5. 绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 正确显示负号
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='black', linewidth=1)
plt.plot(df.index, df['MA5'], label='5日均线', color='pink', linewidth=1)
plt.plot(df.index, df['MA10'], label='10日均线', color='orange', linewidth=1)
plt.plot(df.index, df['MA20'], label='20日均线', color='red', linewidth=1)

plt.title('沪深300指数 - 收盘价与移动平均线(近两年)', fontsize=14)
plt.xlabel('日期')
plt.ylabel('指数点位')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

5日、10日、20日简单移动平均线(SMA)与价格的关系,可以反映出市场的短中期趋势强弱和多空力量的转换。通常来说,价格位于三条均线之上,且均线呈多头排列(即5日在线上、10日居中、20日最下方),说明当前市场处于明显的上升趋势中,多头占据主动;相反,若价格位于三线下方,且均线呈空头排列,则市场处于下跌趋势,空头占优。当价格上穿或下穿其中一条或多条均线,往往预示着短期趋势的改变,比如价格突破并站稳20日线,可能代表中期趋势由弱转强,而跌破20日线则需警惕趋势反转风险。另外,当均线之间距离逐渐收窄并形成粘合状态,说明市场进入震荡整理阶段,此时方向尚未明朗,价格对均线的突破往往成为下一波行情的启动信号。因此,价格与5/10/20日均线之间的相对位置、穿越关系和排列顺序,是判断市场短中期趋势的关键依据,适合用于趋势判断、回调买入、止盈止损等多种策略场景。

2. 指数移动平均线(EMA:Exponential Moving Average)

EMA 给近期的价格赋予更高的权重,比 SMA 更快响应价格变化。

计算方式略复杂,但可使用如下公式近似理解:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> EMA = 收盘价 × 权重 + 前一日 EMA × ( 1 − 权重 ) \text{EMA} = \text{收盘价} \times \text{权重} + \text{前一日 EMA} \times (1 - \text{权重}) </math>EMA=收盘价×权重+前一日 EMA×(1−权重)

其中:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 权重 = 2 n + 1 \text{权重} = \frac{2}{n + 1} </math>权重=n+12

优点:

  • 响应更迅速,适合捕捉趋势转折 缺点:
  • 可能对噪声反应过度,产生"假信号"

下面是一个使用 AKShare 获取 沪深300指数最近两年数据,并用 matplotlib 绘制 收盘价 + 20日简单移动平均线(SMA)和 指数移动平均线(EMA)的完整 Python 示例代码,我们看看两者的走势有何差异

python 复制代码
import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# 获取日期范围(最近两年)
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)
start_str = start_date.strftime("%Y%m%d")
end_str = end_date.strftime("%Y%m%d")

# 获取沪深300指数数据
df = ak.index_zh_a_hist(
    symbol="000300",
    period="daily",
    start_date=start_str,
    end_date=end_str)

# 数据预处理
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)

# 计算20日 SMA 和 EMA
df['SMA20'] = df['收盘'].rolling(window=20).mean()
df['EMA20'] = df['收盘'].ewm(span=20, adjust=False).mean()

# 绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 正确显示负号
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='black', linewidth=1)
plt.plot(df.index, df['SMA20'], label='SMA20(简单均线)', color='blue', linewidth=1.5)
plt.plot(df.index, df['EMA20'], label='EMA20(指数均线)', color='red', linestyle='--', linewidth=1.5)

plt.title('沪深300指数 - 收盘价 vs 20日SMA & EMA', fontsize=14)
plt.xlabel('日期')
plt.ylabel('指数点位')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

根据SMA和EMA的20日均线与价格的关系,我们可以发现它们在衡量市场中期趋势时各有侧重:SMA20反应较为平滑,适合识别稳定的趋势方向,而EMA20对价格变动更敏感,更适合捕捉趋势的起点或反转信号。当价格持续运行在SMA20和EMA20上方,说明市场处于健康的上升趋势中,多头力量占优;反之,若价格跌破这两条均线,且均线拐头向下,往往预示着趋势减弱或反转,空头开始掌控主动。如果价格在SMA20附近震荡而EMA20频繁穿越价格,则可能意味着市场进入盘整阶段,趋势方向不明确。此外,EMA20上穿SMA20往往代表短期多头力量增强,有可能引发新一轮上涨,而EMA20下穿SMA20则可能预示市场将进入调整。总的来看,结合SMA20的趋势稳定性与EMA20的响应速度,可以更全面地判断当前价格的中期趋势强弱与潜在拐点。

3. 线性加权移动平均线(LWMA/WMA:Linearly Weighted Moving Average)

WMA 与 EMA 同样是加权平均,但权重是线性递增,比如10日 LWMA 就是第10天权重为10,第9天为9,依此类推。

公式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> WMA = ∑ ( 价格 × 线性权重 ) ∑ ( 权重 ) \text{WMA} = \frac{\sum(\text{价格} \times \text{线性权重})}{\sum(\text{权重})} </math>WMA=∑(权重)∑(价格×线性权重)

优点:

  • 比 EMA 更强调最近数据 缺点:
  • 对极端价格更敏感,容易产生尖锐波动

同样我们把SMA、EMA、WMA绘制到同一张图中,方便我们观察,以下是一个Python示例代码:

python 复制代码
import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import numpy as np

# 1. 获取日期范围(最近两年)
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)
start_str = start_date.strftime("%Y%m%d")
end_str = end_date.strftime("%Y%m%d")

# 2. 获取沪深300指数数据
df = ak.index_zh_a_hist(
    symbol="000300",
    period="daily",
    start_date=start_str,
    end_date=end_str)

# 3. 数据预处理
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)

# 4. 计算20日均线
df['SMA20'] = df['收盘'].rolling(window=20).mean()
df['EMA20'] = df['收盘'].ewm(span=20, adjust=False).mean()

# 5. 计算WMA20(加权移动平均)
def weighted_moving_average(series, window):
    weights = np.arange(1, window + 1)
    return series.rolling(window).apply(lambda prices: np.dot(prices, weights)/weights.sum(), raw=True)

df['WMA20'] = weighted_moving_average(df['收盘'], 20)

# 6. 绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 正确显示负号
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='black', linewidth=1)
plt.plot(df.index, df['SMA20'], label='SMA20(简单均线)', color='blue', linewidth=1.5)
plt.plot(df.index, df['EMA20'], label='EMA20(指数均线)', color='red', linestyle='--', linewidth=1.5)
plt.plot(df.index, df['WMA20'], label='WMA20(加权均线)', color='green', linestyle='-.', linewidth=1.5)

plt.title('沪深300指数 - 收盘价与20日SMA / EMA / WMA 对比图', fontsize=14)
plt.xlabel('日期')
plt.ylabel('指数点位')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

SMA、EMA 和 WMA 是量化交易中最常用的三种均线形式,各自适用于不同的策略场景。SMA 计算简单,适合用于趋势确认、支撑阻力判断等稳健策略,但响应慢,容易滞后于行情;EMA 对新数据加权更高,能更快响应价格变化,常用于构建动量策略、趋势跟踪系统以及短期交易信号捕捉;WMA 在加快响应的同时对最新价格给予最大权重,比 EMA 更敏感,适合用于对价格变动反应要求更快的策略,比如高频信号生成或短周期反转策略。三者在实盘应用中通常配合使用,通过交叉、偏离、组合等方式判断多空转换、跟踪趋势强弱或作为交易信号过滤条件,是构建多因子模型或交易系统的基础工具。

4. 三角移动平均线(TMA:Triangular Moving Average)

TMA 是对 SMA 再进行一次平均,等于"双重平滑"。

计算方式:

  • 第一步:计算 SMA
  • 第二步:对 SMA 再做一次均值(再次滚动)

优点:

  • 曲线平滑、噪声少 缺点:
  • 滞后性最强,反应慢

以下是EMA和TMA绘制20日均线的简单Python示例

python 复制代码
import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# 1. 获取日期范围(最近两年)
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)
start_str = start_date.strftime("%Y%m%d")
end_str = end_date.strftime("%Y%m%d")

# 2. 获取沪深300指数数据
df = ak.index_zh_a_hist(
    symbol="000300",
    period="daily",
    start_date=start_str,
    end_date=end_str)

# 3. 数据预处理
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)

# 4. 计算20日 SMA
df['SMA20'] = df['收盘'].rolling(window=20).mean()

# 5. 计算20日 TMA(对SMA再做一次SMA)
df['TMA20'] = df['SMA20'].rolling(window=20).mean()

# 6. 绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 正确显示负号
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='black', linewidth=1)
plt.plot(df.index, df['SMA20'], label='SMA20(简单移动平均)', color='blue', linewidth=1.5)
plt.plot(df.index, df['TMA20'], label='TMA20(三角移动平均)', color='purple', linestyle='--', linewidth=1.5)

plt.title('沪深300指数 - 收盘价与20日SMA / TMA 对比图', fontsize=14)
plt.xlabel('日期')
plt.ylabel('指数点位')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

EMA 和 TMA 在量化交易中都被广泛用于趋势识别与信号构建,其中 EMA 因为对近期价格反应更敏感,常被用于捕捉短期价格变化,用作交易信号的核心触发条件,尤其适合动量策略、趋势突破和跟踪系统,在多均线交叉、回调入场等场景中表现突出;而 TMA 由于是对简单均线的二次平滑,波动更小、滞后性更强,常用于中长期趋势的确认与噪声过滤,适合在震荡市场中作为趋势滤波器或慢速参考线,避免频繁误判信号;在实盘策略中,两者可以结合使用,例如以 EMA 作为快速信号线,TMA 作为慢速趋势确认,有效平衡信号灵敏度与稳定性,提升交易系统的鲁棒性与容错能力。

5. 可变移动平均线(VMA:Variable Moving Average)

VMA 是一种基于波动率动态调整权重的移动平均。当价格波动大时,它更敏感;当市场平稳时,它变得更平滑。

优点:

  • 能自适应市场环境变化 缺点:
  • 实现稍复杂,需计算波动率或相关指标(如 ATR)

接下来我们用Python绘制一个VMA和EMA的对比图,为什么拿他俩对比,而不和其它的均线对比呢?

原因如下👇:

  • 核心思想相似: VMA 和 EMA 都是"加权"均线,重点是对近期价格赋予更高权重,但 VMA 进一步引入了"波动性因子"或"动态权重调整",根据市场波动自动调整平滑系数,响应更灵活;

  • 对比价值高: EMA 是固定平滑系数,适合稳定市场;VMA 根据市场波动变动权重,适合波动市场。两者的对比可以揭示 VMA 的自适应特性是否能更好地捕捉趋势或避免震荡陷阱;

  • 实际策略中常作为替代品: 很多量化策略在优化EMA参数时,可能会考虑用VMA替换EMA,作为提升信号质量的手段;

以下是代码部分:

python 复制代码
import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# 1. 获取沪深300指数最近两年数据
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)
start_str = start_date.strftime("%Y%m%d")
end_str = end_date.strftime("%Y%m%d")

df = ak.index_zh_a_hist(
    symbol="000300",
    period="daily",
    start_date=start_str,
    end_date=end_str)

df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)

# 2. 计算标准20日EMA
df['EMA20'] = df['收盘'].ewm(span=20, adjust=False).mean()

# 3. 自定义计算20日VMA(根据价格波动动态调整 alpha)
def calc_vma(price_series, base_span=20, fast_alpha=2/(5+1), slow_alpha=2/(40+1)):
    vma = []
    last_vma = price_series.iloc[0]
    for i in range(1, len(price_series)):
        # 计算波动率(这里简单使用前一日涨跌幅作为波动因子)
        delta = abs(price_series.iloc[i] - price_series.iloc[i - 1])
        vol = delta / price_series.iloc[i - 1] if price_series.iloc[i - 1] != 0 else 0
        # 动态 alpha:波动越大,alpha 越接近 fast;波动越小,越接近 slow
        dynamic_alpha = slow_alpha + (fast_alpha - slow_alpha) * min(vol * 100, 1)
        # VMA更新
        last_vma = dynamic_alpha * price_series.iloc[i] + (1 - dynamic_alpha) * last_vma
        vma.append(last_vma)
    vma = [np.nan] + vma  # 与原始价格长度对齐
    return vma

df['VMA20'] = calc_vma(df['收盘'])

# 4. 绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 正确显示负号
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='black', linewidth=1)
plt.plot(df.index, df['EMA20'], label='EMA20(固定权重)', color='red', linewidth=1.5)
plt.plot(df.index, df['VMA20'], label='VMA20(可变权重)', color='blue', linestyle='--', linewidth=1.5)

plt.title('沪深300指数 - EMA vs VMA 对比图', fontsize=14)
plt.xlabel('日期')
plt.ylabel('指数点位')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

VMA在量化中的应用主要体现在它对市场波动的自适应能力,使其在不同波动环境下都能保持较高的信号质量,适合用于趋势跟踪、动量策略和信号过滤等多个方向,相较于固定参数的EMA,VMA能够在行情剧烈波动时自动提高灵敏度,快速响应趋势变化,在行情平稳时又能降低噪声干扰、避免频繁交易,因此非常适合用于构建动态交易信号线、作为均线交叉策略中的灵活一环、或者作为量化模型中平滑处理因子的自适应替代方案,同时VMA还能配合波动率指标(如ATR)进一步优化入场和离场时机,是在实际策略中兼顾响应性与稳定性的优选工具。


四、总结对比表

类型 权重特点 响应速度 是否平滑 适合场景
SMA 平均权重 长期趋势判断
EMA 指数加权 短期转折捕捉
LWMA 线性加权 高频波动场景
TMA 双重平均 最慢 非常高 震荡行情过滤噪声
VMA 动态权重 适中 自适应 高频策略、动态市场

五、如何选择?

不同均线适配不同的风格,在量化中选择哪种均线,核心在于策略目标、交易周期、对信号响应速度的要求

  • SMA 适合用于中长期趋势判断、支撑阻力参考或回测中的基础基准,优点是稳定、简单、可解释性强,缺点是反应滞后,不适合快速市场;

  • EMA 适合用在需要较快反应市场变化的策略中,常用于短期趋势捕捉、动量入场信号构建以及均线交叉策略,适合日内和波段交易;

  • WMA 在响应速度上介于EMA与SMA之间,适合需要权重更偏向近期价格的策略,比如短线均线跟随或价格反转识别;

  • TMA 是对SMA的再次平滑处理,更平滑但滞后更明显,适合震荡市场中用于趋势确认或防止噪声干扰,常用于做信号过滤器或辅助线;

  • VMA 具备自适应性,是最灵活的均线之一,能根据市场波动自动调整响应速度,适合构建具备动态响应能力的趋势策略,特别适用于波动性变化剧烈的市场环境。

总结来说,短线快节奏交易偏向用EMA/WMA,追求稳定信号用SMA/TMA,想提升自适应能力就选VMA,实战中常会组合使用,以平衡反应速度与稳定性。

今天关于量化中均线的介绍就到这里了。

相关推荐
Java技术小馆1 分钟前
面试被问 Java为什么有这么多O
java·后端·面试
brzhang4 分钟前
Flutter 调用原生代码,看这篇就够了:从零教你搭起通信的桥
前端·后端·架构
我是初九9 分钟前
【李沐-动手学深度学习v2】1.Colab学习环境配置
人工智能·python·学习·colab
失败又激情的man14 分钟前
python爬虫之数据存储
前端·数据库·python
崔lc18 分钟前
Springboot项目集成Ai模型(阿里云百炼-DeepSeek)
java·spring boot·后端·ai
一刀到底21122 分钟前
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
python·django·fastapi
MoRanzhi120327 分钟前
245. 2019年蓝桥杯国赛 - 数正方形(困难)- 递推
python·算法·蓝桥杯·国赛·递推·2019
Vertira35 分钟前
如何在 PyTorch 中自定义卷积核参数(亲测,已解决)
人工智能·pytorch·python