第四节:技术指标计算——让数据开口说话
技术指标这东西,说白了就是给价格数据做「体检」。我刚开始做量化的时候,总觉得指标越多越好,恨不得把几十个指标全堆上去。后来被市场狠狠教育了几次才明白——指标不在多,在于你懂它。
今天咱们就聊聊四个最常用的技术指标:MA、MACD、RSI、布林带。我会把计算逻辑讲透,再配上Pandas的高效实现。嗯,这些都是我实战中反复打磨过的代码。
4.1 移动平均线(MA)——最朴素的趋势跟踪器
移动平均线,说白了就是「过去N天的平均价格」。它把价格波动平滑了,让你看清趋势方向。
计算逻辑:
- 简单移动平均(SMA):等权平均
- 指数移动平均(EMA):越近的数据权重越大
我个人习惯用EMA,因为它对价格变化反应更快。举个例子,你想想看,如果今天突然暴跌,SMA要等好几天才能反映出来,但EMA当天就会明显变化。
import pandas as pd
import numpy as np
# 计算SMA和EMA
def calculate_ma(df, window=20):
df = df.copy()
df['SMA'] = df['close'].rolling(window=window).mean()
df['EMA'] = df['close'].ewm(span=window, adjust=False).mean()
return df
# 实战用法
df = pd.DataFrame({'close': [100, 102, 101, 105, 108, 107, 110]})
result = calculate_ma(df, window=3)
print(result)
4.2 MACD——趋势与动量的二合一
MACD是我最喜欢的指标之一。它由三部分组成:快线(DIF)、慢线(DEA)、柱状图(MACD柱)。
计算步骤:
- 计算12日EMA和26日EMA
- DIF = 12日EMA - 26日EMA
- DEA = DIF的9日EMA
- MACD柱 = (DIF - DEA) × 2
为什么乘以2?这是为了放大柱状图的视觉效果,方便观察。我在项目中遇到过,如果不乘2,柱状图在图表上几乎看不见。
def calculate_macd(df, fast=12, slow=26, signal=9):
df = df.copy()
# 计算EMA
ema_fast = df['close'].ewm(span=fast, adjust=False).mean()
ema_slow = df['close'].ewm(span=slow, adjust=False).mean()
# DIF线
df['DIF'] = ema_fast - ema_slow
# DEA线
df['DEA'] = df['DIF'].ewm(span=signal, adjust=False).mean()
# MACD柱
df['MACD'] = 2 * (df['DIF'] - df['DEA'])
return df
4.3 RSI——判断超买超卖的利器
RSI(相对强弱指标)衡量的是「上涨幅度占总体波动的比例」。取值范围0-100,一般认为超过70是超买,低于30是超卖。
计算逻辑:
- 计算每日价格变化:涨了多少,跌了多少
- 分别计算N日内的平均涨幅和平均跌幅
- RS = 平均涨幅 / 平均跌幅
- RSI = 100 - (100 / (1 + RS))
你想想看,如果连续涨了10天,平均涨幅远大于平均跌幅,RSI就会很高。这时候市场可能已经过热了。
def calculate_rsi(df, period=14):
df = df.copy()
# 计算价格变化
delta = df['close'].diff()
# 分离涨幅和跌幅
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
# 计算平均涨幅和平均跌幅
avg_gain = gain.rolling(window=period).mean()
avg_loss = loss.rolling(window=period).mean()
# 计算RS和RSI
rs = avg_gain / avg_loss
df['RSI'] = 100 - (100 / (1 + rs))
return df
4.4 布林带——价格波动的「安全通道」
布林带由三条线组成:中轨(MA)、上轨(中轨+2倍标准差)、下轨(中轨-2倍标准差)。它告诉你价格在什么范围内波动是「正常的」。
计算步骤:
- 计算N日移动平均线(中轨)
- 计算N日价格标准差
- 上轨 = 中轨 + K × 标准差
- 下轨 = 中轨 - K × 标准差
K值通常取2,这意味着价格有95%的概率落在通道内。如果价格突破通道,往往意味着趋势要加速了。
def calculate_bollinger(df, window=20, num_std=2):
df = df.copy()
# 中轨
df['MA'] = df['close'].rolling(window=window).mean()
# 标准差
df['STD'] = df['close'].rolling(window=window).std()
# 上下轨
df['Upper'] = df['MA'] + num_std * df['STD']
df['Lower'] = df['MA'] - num_std * df['STD']
return df
4.5 信号生成——把指标变成交易指令
指标算出来只是第一步,关键是怎么用。我一般会生成三种信号:买入、卖出、持有。
常见信号逻辑:
| 指标 | 买入信号 | 卖出信号 |
|---|---|---|
| MA | 价格上穿MA | 价格下穿MA |
| MACD | DIF上穿DEA | DIF下穿DEA |
| RSI | RSI低于30后上穿30 | RSI高于70后下穿70 |
| 布林带 | 价格触及下轨后反弹 | 价格触及上轨后回落 |
def generate_signals(df):
df = df.copy()
# 初始化信号列
df['Signal'] = 0
# MACD金叉死叉
df.loc[(df['DIF'] > df['DEA']) &
(df['DIF'].shift(1) <= df['DEA'].shift(1)), 'Signal'] = 1
df.loc[(df['DIF'] < df['DEA']) &
(df['DIF'].shift(1) >= df['DEA'].shift(1)), 'Signal'] = -1
# RSI超买超卖
df.loc[(df['RSI'] < 30) &
(df['RSI'].shift(1) >= 30), 'Signal'] = 1
df.loc[(df['RSI'] > 70) &
(df['RSI'].shift(1) <= 70), 'Signal'] = -1
return df
4.6 知识体系总览
下面这张图把本章的核心内容串起来了。你可以看到,从原始数据到最终信号,每一步都有明确的逻辑。
这张图展示了从原始数据到最终决策的完整链路。四个指标各有侧重,但最终都要落到信号生成这一步。我个人建议,刚开始做回测时,先选两个指标练手,等熟悉了再逐步增加。
好了,技术指标的计算就聊到这儿。记住,指标是工具,不是圣杯。真正重要的是你如何理解市场、如何设计策略。下一节我们会把这些指标组合起来,做一个完整的轮动模型回测。