第四节:技术指标计算——移动平均线、RSI、布林带、MACD、OBV

技术指标这东西,说白了就是给价格数据“化妆”。原始K线图看起来乱糟糟的,指标能帮我们提炼出趋势、动量、波动率这些关键信息。我个人习惯,在轮动模型里不会堆砌太多指标,选三四个互补的就够了。

今天咱们把五个最常用的指标过一遍。我会把计算公式、代码实现、以及实战中容易踩的坑都讲清楚。

4.1 移动平均线:SMA 与 EMA

移动平均线是最基础的指标。它把价格“抹平”,让我们看清趋势方向。

简单移动平均线(SMA)

SMA 就是取最近 N 天的收盘价,算个算术平均。公式很简单:

SMA = (P₁ + P₂ + ... + Pₙ) / N

举个例子,5日SMA就是最近5天收盘价加起来除以5。代码实现:

def sma(close, window=20):
    return close.rolling(window=window).mean()

嗯,这里要注意:SMA 对每个数据点一视同仁。也就是说,10天前的价格和昨天的价格权重一样。这其实不太合理——昨天的价格显然比10天前更重要。

指数移动平均线(EMA)

EMA 解决了这个问题。它给近期的价格更高的权重。公式稍微复杂一点:

EMA_today = (Price_today × α) + (EMA_yesterday × (1 - α))
其中 α = 2 / (N + 1)

你看,今天的EMA由两部分组成:今天的价格乘以一个权重α,加上昨天的EMA乘以(1-α)。α越大,对近期价格反应越敏感。

def ema(close, window=20):
    return close.ewm(span=window, adjust=False).mean()
我的经验:在轮动模型里,我通常用EMA而不是SMA。EMA反应更快,能更早捕捉到趋势变化。但如果你做长周期轮动(比如月度调仓),SMA反而更稳定,不容易被短期噪音干扰。

4.2 相对强弱指标(RSI)

RSI 衡量的是“涨的力度”和“跌的力度”谁更强。取值范围0到100,一般认为70以上超买,30以下超卖。

计算分三步:

  1. 计算每日涨跌幅:今天收盘 - 昨天收盘
  2. 分别计算N天内平均涨幅和平均跌幅
  3. RSI = 100 - 100 / (1 + 平均涨幅/平均跌幅)
def rsi(close, window=14):
    delta = 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
    return 100 - (100 / (1 + rs))
避坑指南:我曾经在震荡行情里死磕RSI,结果频繁被假信号打脸。RSI在趋势行情里很好用,但在横盘震荡时,它会反复穿越70和30线,让你左右挨打。所以用RSI之前,先判断一下市场状态。

4.3 布林带(Bollinger Bands)

布林带由三条线组成:中轨是SMA,上下轨分别是中轨加减两倍标准差。它告诉我们价格相对于历史波动率的位置。

def bollinger_bands(close, window=20, num_std=2):
    sma = close.rolling(window=window).mean()
    std = close.rolling(window=window).std()
    upper = sma + num_std * std
    lower = sma - num_std * std
    return sma, upper, lower

布林带的核心思想:价格大概率在上下轨之间运行。当价格触及上轨,可能超买;触及下轨,可能超卖。但要注意——强势行情里,价格会沿着上轨一直走,这时候做空就惨了。

我的用法:我不单独看布林带,而是结合RSI一起用。比如价格突破上轨且RSI大于80,说明上涨动能很强,我不会急着卖。只有当价格跌破中轨时,我才会考虑减仓。

4.4 MACD 指标

MACD 由三部分组成:快线(DIF)、慢线(DEA)、柱状图(MACD柱)。它本质上是两条EMA的差值。

计算步骤:

  1. 计算12日EMA和26日EMA
  2. DIF = 12日EMA - 26日EMA
  3. DEA = DIF的9日EMA
  4. MACD柱 = (DIF - DEA) × 2
def macd(close, fast=12, slow=26, signal=9):
    ema_fast = close.ewm(span=fast, adjust=False).mean()
    ema_slow = close.ewm(span=slow, adjust=False).mean()
    dif = ema_fast - ema_slow
    dea = dif.ewm(span=signal, adjust=False).mean()
    macd_bar = (dif - dea) * 2
    return dif, dea, macd_bar

MACD 最常用的信号是金叉和死叉。DIF上穿DEA是金叉,看涨;下穿是死叉,看跌。但说实话,金叉死叉在震荡市里准确率不高。

我个人的偏好:我更关注MACD柱的背离。比如价格创新低,但MACD柱的底部在抬高,这叫底背离,往往是反转信号。我在2022年10月那波反弹里,就是靠底背离抓住了机会。

4.5 成交量指标(OBV)

OBV 把成交量和价格结合起来。它的逻辑很简单:价格上涨时,成交量是“正”的;价格下跌时,成交量是“负”的。OBV 就是把这些正负成交量累加起来。

def obv(close, volume):
    obv = volume.copy()
    obv[close.diff() > 0] = volume[close.diff() > 0]
    obv[close.diff() < 0] = -volume[close.diff() < 0]
    obv[close.diff() == 0] = 0
    return obv.cumsum()

OBV 的核心用法是看“背离”。如果价格在涨,但OBV在跌,说明上涨没有成交量支持,可能是虚涨。反过来,价格在跌,OBV在涨,说明有人在悄悄吸筹。

注意:OBV 的数值本身没有意义,有意义的是它的趋势方向。另外,OBV 对成交量数据质量要求很高,如果数据有缺失或异常,OBV 会完全失真。我曾经因为数据源的问题,OBV 算出来一条直线,排查了半天才发现是成交量字段搞错了。

4.6 知识体系总览

下面这张图把五个指标的核心逻辑串起来了。你可以看到,每个指标解决一个不同的问题:

技术指标知识体系 技术指标 移动平均线 RSI 布林带 MACD OBV 识别趋势方向 衡量超买超卖 判断波动率位置 捕捉趋势信号 验证量价关系 实战组合建议 趋势判断:SMA/EMA + MACD 动量确认:RSI + 布林带 量价验证:OBV

4.7 实战中的组合用法

指标不是越多越好。我见过有人一个策略里塞了十几个指标,结果信号互相矛盾,根本没法交易。我的建议是:

  • 趋势类选一个:SMA 或 EMA,二选一就行
  • 动量类选一个:RSI 或 MACD,看个人偏好
  • 波动率类选一个:布林带
  • 量价类选一个:OBV

这样四个指标各司其职,互不重叠。你想想看,如果趋势和动量都看涨,波动率也支持,成交量也在配合,那这个信号的可靠性就高多了。

一个小技巧:在轮动模型里,我通常把指标信号量化成0到1的分数,然后加权求和。比如趋势信号占40%,动量占30%,波动率占20%,量价占10%。这样既综合了多个维度的信息,又不会因为某个指标的假信号而误判。

好了,技术指标的计算就讲到这里。这些代码你直接复制到自己的回测框架里就能用。记住,指标只是工具,关键还是理解它背后的逻辑——为什么涨?为什么跌?成交量在说什么?把这些想明白了,指标才能为你所用。