4、技术指标计算:移动平均线、MACD、RSI、布林带等常用指标的计算与实现
技术指标这东西,说白了就是给原始价格数据「化妆」。
我刚开始做量化的时候,总觉得指标越多越厉害,恨不得把几十个指标全堆上去。后来被市场狠狠教育了几次才明白——指标不在多,在于你懂它。今天咱们就把最常用的四个指标掰开揉碎,看看它们到底怎么算、怎么用。
4.1 移动平均线(MA)——最朴素的趋势跟踪器
移动平均线是所有技术指标的「祖宗」。它干的事很简单:把过去N天的价格平均一下,抹平噪音,让你看清趋势。
4.1.1 简单移动平均(SMA)
公式长这样:
SMA = (P₁ + P₂ + ... + Pₙ) / N
其中P是收盘价,N是周期数。
代码实现:
def sma(data, window):
"""计算简单移动平均线"""
result = []
for i in range(len(data)):
if i < window - 1:
result.append(None) # 前面不够的数据填None
else:
avg = sum(data[i-window+1:i+1]) / window
result.append(avg)
return result
# 用pandas更简单
import pandas as pd
df['SMA_20'] = df['close'].rolling(window=20).mean()
4.1.2 指数移动平均(EMA)
EMA和SMA的区别在哪?SMA给每天的价格权重一样,EMA则更看重最近的数据。你想想看,昨天的价格和30天前的价格,哪个对今天更有参考价值?显然是昨天。
公式:
EMA_today = (Price_today × α) + (EMA_yesterday × (1 - α))
α = 2 / (N + 1)
def ema(data, window):
"""计算指数移动平均线"""
alpha = 2 / (window + 1)
result = [None] * (window - 1)
# 第一个EMA用SMA初始化
result.append(sum(data[:window]) / window)
for i in range(window, len(data)):
ema_val = alpha * data[i] + (1 - alpha) * result[-1]
result.append(ema_val)
return result
# pandas实现
df['EMA_20'] = df['close'].ewm(span=20, adjust=False).mean()
4.2 MACD——趋势的「放大镜」
MACD全称是「指数平滑异同移动平均线」,名字挺唬人,其实逻辑很简单:
- 快线(DIF)= 短期EMA - 长期EMA(常用12日和26日)
- 慢线(DEA)= DIF的EMA(常用9日)
- 柱状图(MACD柱)= 2 × (DIF - DEA)
说白了,MACD就是在看「短期趋势和长期趋势的差距」。差距拉大,说明趋势强;差距缩小,说明趋势在减弱。
def macd(data, fast=12, slow=26, signal=9):
"""计算MACD指标"""
# 计算快慢EMA
ema_fast = data.ewm(span=fast, adjust=False).mean()
ema_slow = data.ewm(span=slow, adjust=False).mean()
# DIF线
dif = ema_fast - ema_slow
# DEA线(信号线)
dea = dif.ewm(span=signal, adjust=False).mean()
# MACD柱
macd_bar = 2 * (dif - dea)
return dif, dea, macd_bar
# 使用示例
dif, dea, macd_bar = macd(df['close'])
df['DIF'] = dif
df['DEA'] = dea
df['MACD'] = macd_bar
- DIF上穿DEA → 金叉,买入信号
- DIF下穿DEA → 死叉,卖出信号
- MACD柱由负转正 → 多头力量增强
- 顶背离:价格新高但MACD没新高 → 警惕下跌
我个人习惯把MACD和K线形态结合起来看。单看金叉死叉,假信号太多了。我记得有一次做螺纹钢期货,连续三次金叉都被打脸,后来加了成交量过滤,效果才好起来。
4.3 RSI——超买超卖的「体温计」
RSI(相对强弱指标)衡量的是「涨的力度」和「跌的力度」谁更强。取值范围0-100,通常:
- RSI > 70 → 超买,可能回调
- RSI < 30 → 超卖,可能反弹
公式:
RSI = 100 - (100 / (1 + RS))
RS = 平均上涨幅度 / 平均下跌幅度
def rsi(data, window=14):
"""计算RSI指标"""
delta = data.diff()
# 分离上涨和下跌
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
# 计算平均涨幅和平均跌幅(用EMA或SMA)
avg_gain = gain.rolling(window=window).mean()
avg_loss = loss.rolling(window=window).mean()
# 避免除零
rs = avg_gain / avg_loss.replace(0, float('inf'))
rsi = 100 - (100 / (1 + rs))
return rsi
df['RSI_14'] = rsi(df['close'])
4.4 布林带——价格的「安全通道」
布林带由三条线组成:中轨(SMA)、上轨(中轨 + 2倍标准差)、下轨(中轨 - 2倍标准差)。
它的核心思想是:价格大部分时间会在上下轨之间波动,一旦突破轨道,说明市场情绪极端了。
def bollinger_bands(data, window=20, num_std=2):
"""计算布林带"""
# 中轨:SMA
sma = data.rolling(window=window).mean()
# 标准差
std = data.rolling(window=window).std()
# 上下轨
upper_band = sma + num_std * std
lower_band = sma - num_std * std
return sma, upper_band, lower_band
df['BB_MID'] = df['close'].rolling(20).mean()
df['BB_STD'] = df['close'].rolling(20).std()
df['BB_UP'] = df['BB_MID'] + 2 * df['BB_STD']
df['BB_DN'] = df['BB_MID'] - 2 * df['BB_STD']
- 轨道突破:价格突破上轨 → 强势,但可能回调;跌破下轨 → 弱势,但可能反弹
- 带宽收缩:上下轨收窄 → 即将变盘(布林带「开口」信号)
- 百分比B:(价格 - 下轨) / (上轨 - 下轨),量化价格在轨道中的位置
- 带宽指标:(上轨 - 下轨) / 中轨,衡量波动率大小
4.5 指标组合实战——别做「指标收藏家」
很多新手喜欢把十几个指标堆在一起,以为这样胜率更高。结果呢?信号互相矛盾,根本没法交易。
我的建议是:选2-3个互补的指标就够了。比如:
| 组合方案 | 适用场景 | 核心逻辑 |
|---|---|---|
| MA + MACD | 趋势跟踪 | MA判断大方向,MACD找入场点 |
| 布林带 + RSI | 震荡行情 | 布林带找边界,RSI确认超买超卖 |
| MA + 布林带 + 成交量 | 突破交易 | MA确认趋势,布林带看波动,成交量验证 |
4.6 本章知识体系
下面这张图帮你理清四个指标的关系和适用场景:
嗯,以上就是四个核心指标的计算和实现。代码都给出来了,建议你拿到真实数据跑一遍,看看不同参数下指标长什么样。纸上得来终觉浅,绝知此事要coding。
公众号:蓝海资料掘金营,微信deep3321