第四章:技术指标计算——移动平均线、布林带、RSI与MACD
各位同学,欢迎来到第四章。前几章我们聊了数据获取和清洗,那都是“原材料”的准备工作。从这章开始,咱们要真正上手“烹饪”了——也就是计算技术指标。
说实话,技术指标这东西,市面上有成百上千种。但我个人习惯,做CTA策略时,真正高频使用的就那么几个:移动平均线、布林带、RSI和MACD。别小看它们,经典之所以经典,是因为它们经过了无数实盘的检验。
今天我就把这四个指标的计算逻辑、Python实现以及我在项目中踩过的坑,一次性给你讲透。
4.1 移动平均线:趋势跟踪的基石
移动平均线,说白了就是“过去N天的平均价格”。它是最简单的趋势指标,但也是最有效的。
4.1.1 简单移动平均线(SMA)
SMA的计算公式很简单:
SMA = (P1 + P2 + ... + Pn) / n
其中P是收盘价,n是周期。
Python实现:
import pandas as pd
def calculate_sma(data, window=20):
"""
计算简单移动平均线
:param data: DataFrame,必须包含'close'列
:param window: 窗口大小,默认20
:return: 添加了SMA列的DataFrame
"""
df = data.copy()
df['SMA_' + str(window)] = df['close'].rolling(window=window).mean()
return df
嗯,这里要注意一点:rolling()函数默认是右对齐的,也就是说第20天的SMA值,用的是第1天到第20天的数据。这个逻辑在回测里是没问题的,因为我们在第20天收盘后才能计算出这个值。
4.1.2 指数移动平均线(EMA)
EMA和SMA最大的区别在于:EMA给近期的价格更高的权重。说白了,它更“敏感”。
计算公式:
EMA_today = (Price_today * k) + (EMA_yesterday * (1 - k))
其中 k = 2 / (n + 1)
Python实现:
def calculate_ema(data, window=20):
"""
计算指数移动平均线
"""
df = data.copy()
df['EMA_' + str(window)] = df['close'].ewm(span=window, adjust=False).mean()
return df
ewm(alpha=2/(window+1)),结果发现和TradingView对不上。后来查了文档才发现,ewm的span参数内部已经帮你算好了alpha,直接用span=window最省心。
4.2 布林带:波动率的可视化工具
布林带由三条线组成:中轨(SMA)、上轨(中轨 + k倍标准差)、下轨(中轨 - k倍标准差)。
它解决了一个核心问题:当前价格处于什么“位置”?
计算公式:
中轨 = SMA(close, n)
上轨 = 中轨 + k * std(close, n)
下轨 = 中轨 - k * std(close, n)
Python实现:
def calculate_bollinger_bands(data, window=20, num_std=2):
"""
计算布林带
"""
df = data.copy()
df['BB_middle'] = df['close'].rolling(window=window).mean()
df['BB_std'] = df['close'].rolling(window=window).std()
df['BB_upper'] = df['BB_middle'] + num_std * df['BB_std']
df['BB_lower'] = df['BB_middle'] - num_std * df['BB_std']
return df
这里有个小技巧:布林带的宽度(上轨-下轨)本身就是个很好的波动率指标。宽度扩大,说明市场在“躁动”;宽度收窄,说明市场在“蓄力”。
4.3 RSI:超买超卖的“温度计”
RSI,全称Relative Strength Index,相对强弱指标。它衡量的是过去N天内,价格上涨的幅度占总波动幅度的比例。
计算公式:
RSI = 100 - (100 / (1 + RS))
其中 RS = 平均上涨幅度 / 平均下跌幅度
Python实现:
def calculate_rsi(data, window=14):
"""
计算RSI指标
"""
df = data.copy()
delta = df['close'].diff()
gain = delta.where(delta > 0, 0)
loss = (-delta).where(delta < 0, 0)
avg_gain = gain.rolling(window=window).mean()
avg_loss = loss.rolling(window=window).mean()
rs = avg_gain / avg_loss
df['RSI_' + str(window)] = 100 - (100 / (1 + rs))
return df
为什么会这样?因为趋势行情里,强者恒强。你看到RSI到70就做空,结果可能被趋势甩下车。嗯,这个坑我踩过不止一次。
4.4 MACD:趋势与动量的结合体
MACD由三部分组成:快线(DIF)、慢线(DEA)、柱状图(MACD柱)。
计算逻辑:
- 计算快线:EMA(close, 12) - EMA(close, 26)
- 计算慢线:EMA(DIF, 9)
- 计算柱状图:2 * (DIF - DEA)
Python实现:
def calculate_macd(data, fast=12, slow=26, signal=9):
"""
计算MACD指标
"""
df = data.copy()
df['EMA_fast'] = df['close'].ewm(span=fast, adjust=False).mean()
df['EMA_slow'] = df['close'].ewm(span=slow, adjust=False).mean()
df['DIF'] = df['EMA_fast'] - df['EMA_slow']
df['DEA'] = df['DIF'].ewm(span=signal, adjust=False).mean()
df['MACD_bar'] = 2 * (df['DIF'] - df['DEA'])
return df
MACD最经典的用法是“金叉死叉”:DIF上穿DEA是买入信号,下穿是卖出信号。但说实话,单纯用金叉死叉做交易,胜率并不高。我一般会结合背离来用——价格创新低但MACD没创新低,这叫底背离,是强反转信号。
4.5 知识体系总览
为了让你更直观地理解这四个指标的关系,我画了一张图:
4.6 综合应用:一个简单的信号生成器
光说不练假把式。咱们把四个指标组合起来,写一个简单的信号生成函数:
def generate_signals(data):
"""
综合多个指标生成交易信号
"""
df = data.copy()
# 计算所有指标
df = calculate_sma(df, 20)
df = calculate_ema(df, 20)
df = calculate_bollinger_bands(df)
df = calculate_rsi(df)
df = calculate_macd(df)
# 信号逻辑
df['signal'] = 0
# 做多条件:价格在布林带下轨附近 + RSI超卖 + MACD金叉
buy_condition = (
(df['close'] <= df['BB_lower'] * 1.01) &
(df['RSI_14'] < 30) &
(df['DIF'] > df['DEA'])
)
df.loc[buy_condition, 'signal'] = 1
# 做空条件:价格在布林带上轨附近 + RSI超买 + MACD死叉
sell_condition = (
(df['close'] >= df['BB_upper'] * 0.99) &
(df['RSI_14'] > 70) &
(df['DIF'] < df['DEA'])
)
df.loc[sell_condition, 'signal'] = -1
return df
好了,这一章的内容就到这里。四个指标的计算方法和Python实现,我都给你讲清楚了。下一章我们会聊到策略逻辑设计,到时候这些指标就会派上大用场。
记住一句话:指标是工具,不是圣杯。真正赚钱的策略,靠的是对市场的理解,而不是指标的堆砌。