第四章:技术指标计算——移动平均线、布林带、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天收盘后才能计算出这个值。

我的经验: 做日内策略时,我一般用5、10、20这三个周期。做日线级别,我喜欢用20、60、120。周期太短噪音多,太长又太迟钝。你想想看,是不是这个理?

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
避坑指南: 我曾经在计算EMA时,直接用ewm(alpha=2/(window+1)),结果发现和TradingView对不上。后来查了文档才发现,ewmspan参数内部已经帮你算好了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
实战要点: 布林带最常用的参数是(20, 2)。但我在做螺纹钢期货时发现,波动率大的品种,用2.5倍标准差更合适,否则频繁触碰上下轨,信号太多。

这里有个小技巧:布林带的宽度(上轨-下轨)本身就是个很好的波动率指标。宽度扩大,说明市场在“躁动”;宽度收窄,说明市场在“蓄力”。


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用30和70作为超卖超买线。但我发现,在趋势行情中,RSI会长时间停留在超买区。所以我现在做趋势策略时,会把阈值放宽到20和80,甚至15和85。

为什么会这样?因为趋势行情里,强者恒强。你看到RSI到70就做空,结果可能被趋势甩下车。嗯,这个坑我踩过不止一次。


4.4 MACD:趋势与动量的结合体

MACD由三部分组成:快线(DIF)、慢线(DEA)、柱状图(MACD柱)。

计算逻辑:

  1. 计算快线:EMA(close, 12) - EMA(close, 26)
  2. 计算慢线:EMA(DIF, 9)
  3. 计算柱状图: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,有的乘以2。我个人习惯乘以2,这样柱状图看起来更明显,信号也更清晰。

MACD最经典的用法是“金叉死叉”:DIF上穿DEA是买入信号,下穿是卖出信号。但说实话,单纯用金叉死叉做交易,胜率并不高。我一般会结合背离来用——价格创新低但MACD没创新低,这叫底背离,是强反转信号。


4.5 知识体系总览

为了让你更直观地理解这四个指标的关系,我画了一张图:

技术指标知识体系 技术指标 移动平均线 布林带 RSI MACD SMA / EMA 上轨 / 下轨 超买 / 超卖 金叉 / 死叉 核心用途 趋势方向判断 波动率与位置 动量与反转 趋势与动量

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实现,我都给你讲清楚了。下一章我们会聊到策略逻辑设计,到时候这些指标就会派上大用场。

记住一句话:指标是工具,不是圣杯。真正赚钱的策略,靠的是对市场的理解,而不是指标的堆砌。


专注资料整理