第三章 技术指标基础:移动平均线(SMA/EMA)、布林带、RSI、MACD的原理与计算
各位同学,欢迎来到《交易信号生成算法精讲》的第三讲。
今天咱们聊聊技术指标。说实话,刚入行那会儿,我对着满屏的指标也发懵——均线、布林带、RSI、MACD,每个都号称能预测未来。但做了几年量化后,我的看法变了:指标不是圣杯,它们是工具。就像你不会拿锤子去拧螺丝,对吧?
这一章,我会把四个最基础的指标讲透。不仅讲公式,还会聊聊我踩过的坑。
3.1 移动平均线:最简单的趋势跟踪器
移动平均线,说白了就是过去N天收盘价的平均值。它平滑了价格波动,让你看清趋势方向。
3.1.1 简单移动平均线(SMA)
SMA的计算极其简单:
SMA = (P₁ + P₂ + ... + Pₙ) / N
其中P是收盘价,N是周期数。
举个例子,5日SMA就是最近5天收盘价的平均值。每天滑动窗口,去掉最旧的一天,加入最新的一天。
代码实现:
import numpy as np
def sma(prices, window=20):
"""计算简单移动平均线"""
return np.convolve(prices, np.ones(window)/window, mode='valid')
3.1.2 指数移动平均线(EMA)
EMA给近期数据更高的权重。公式稍微复杂点:
EMA_today = (Price_today × α) + (EMA_yesterday × (1 - α))
其中α = 2 / (N + 1),N是周期数。
你看,EMA是递归的——今天的值依赖昨天的值。这意味着它反应更快,但计算时需要注意初始值。
代码实现:
def ema(prices, window=20):
"""计算指数移动平均线"""
alpha = 2 / (window + 1)
result = [prices[0]] # 初始值用第一个价格
for price in prices[1:]:
result.append(alpha * price + (1 - alpha) * result[-1])
return np.array(result)
3.2 布林带:波动率的可视化
布林带由三条线组成:中轨(SMA)、上轨和下轨。上轨 = 中轨 + K×标准差,下轨 = 中轨 - K×标准差。K通常取2。
布林带的核心理念:价格大概率在上下轨之间波动。当价格触及上轨,可能超买;触及下轨,可能超卖。
计算步骤:
- 计算中轨:20日SMA
- 计算标准差:过去20日收盘价的标准差
- 上轨 = 中轨 + 2×标准差
- 下轨 = 中轨 - 2×标准差
代码实现:
def bollinger_bands(prices, window=20, num_std=2):
"""计算布林带"""
sma_values = sma(prices, window)
std_values = np.array([np.std(prices[i:i+window])
for i in range(len(prices)-window+1)])
upper = sma_values + num_std * std_values
lower = sma_values - num_std * std_values
return sma_values, upper, lower
避坑指南:我曾经在震荡行情中过度依赖布林带。价格反复触碰上下轨,我频繁开仓,结果手续费都亏掉了。记住:布林带在趋势行情中效果更好。
3.3 RSI:动量的量化指标
RSI(相对强弱指数)衡量价格变动的速度和幅度。取值范围0-100,通常超过70视为超买,低于30视为超卖。
计算公式:
RSI = 100 - (100 / (1 + RS))
RS = 平均上涨幅度 / 平均下跌幅度
平均上涨幅度 = 过去N天上涨日的涨幅平均值(下跌日取0)
平均下跌幅度 = 过去N天下跌日的跌幅平均值(上涨日取0)
代码实现:
def rsi(prices, window=14):
"""计算RSI"""
deltas = np.diff(prices)
gains = np.where(deltas > 0, deltas, 0)
losses = np.where(deltas < 0, -deltas, 0)
avg_gain = np.mean(gains[:window])
avg_loss = np.mean(losses[:window])
rsi_values = [100 - (100 / (1 + avg_gain/avg_loss)) if avg_loss != 0 else 100]
for i in range(window, len(deltas)):
avg_gain = (avg_gain * (window-1) + gains[i]) / window
avg_loss = (avg_loss * (window-1) + losses[i]) / window
rs = avg_gain / avg_loss if avg_loss != 0 else float('inf')
rsi_values.append(100 - (100 / (1 + rs)))
return np.array(rsi_values)
我的习惯:RSI的默认周期是14。但不同品种的最佳参数不同。比特币我常用7日RSI,A股我喜欢21日。你想想看,参数调优是门手艺活。
3.4 MACD:趋势与动量的结合
MACD由三部分组成:快线(DIF)、慢线(DEA)、柱状图(MACD柱)。
计算步骤:
- 计算快线:12日EMA - 26日EMA
- 计算慢线:快线的9日EMA
- 柱状图 = 快线 - 慢线
当快线上穿慢线,是买入信号(金叉);下穿是卖出信号(死叉)。柱状图由负转正,也是买入信号。
代码实现:
def macd(prices, fast=12, slow=26, signal=9):
"""计算MACD"""
ema_fast = ema(prices, fast)
ema_slow = ema(prices, slow)
# 对齐长度
min_len = min(len(ema_fast), len(ema_slow))
dif = ema_fast[-min_len:] - ema_slow[-min_len:]
dea = ema(dif, signal)
macd_hist = dif - dea
return dif, dea, macd_hist
我曾经犯过的错:MACD在震荡市中频繁产生假信号。金叉后马上死叉,死叉后又金叉。后来我加了趋势过滤——只在均线多头排列时用金叉信号,效果好了很多。
3.5 指标组合使用策略
单个指标容易出错。我建议组合使用:
| 组合方式 | 适用场景 | 信号确认 |
|---|---|---|
| SMA + RSI | 趋势跟踪 | 价格在SMA上方 + RSI超卖 |
| 布林带 + MACD | 震荡突破 | 价格突破布林带 + MACD金叉 |
| EMA + RSI + MACD | 多指标共振 | 三个指标同时发出同向信号 |
嗯,这里要注意:指标越多,信号越少,但胜率可能更高。我一般用2-3个指标就够了,再多就是过度拟合。
3.6 实战中的注意事项
- 参数优化:不要迷信默认参数。不同品种、不同时间周期,最佳参数不同。
- 滞后性:所有指标都是基于历史数据计算的,天然滞后。你想想看,等指标给出信号,行情可能已经走了一半。
- 假信号:没有指标能100%准确。我见过有人用RSI在单边行情中连续止损5次。
- 数据质量:前复权、后复权、除权除息,不同处理方式会影响指标计算。我习惯用后复权数据。
总结一下:技术指标是工具,不是魔法。理解它们的原理和局限,比盲目使用更重要。下一章,我们会把这些指标组合成完整的交易信号生成系统。
好了,今天就到这里。记住:纸上得来终觉浅,绝知此事要躬行。打开你的Python环境,把代码跑一遍,你会理解得更深。