第三章 技术指标计算:MA/EMA、布林带、RSI、MACD

说实话,技术指标这东西,刚入行的时候我觉得挺玄乎的。不就是几条线来回穿吗?后来真金白银往里砸的时候才发现——指标不是预测未来的水晶球,而是帮你把市场情绪「翻译」成数字的工具。

我个人习惯把技术指标分成两类:一类是趋势跟踪的,比如移动平均线、MACD;另一类是震荡类的,比如布林带、RSI。今天咱们就把这四个最常用的指标,从计算到可视化,再到怎么当特征喂给强化学习模型,一次性讲透。

核心观点: 指标不是圣杯,而是特征工程的一部分。你给模型喂什么,它就学什么。指标算得对不对,直接影响策略的生死。

3.1 移动平均线:MA 与 EMA

移动平均线,说白了就是「过去N天的平均价格」。但这里有个坑——你用的是简单平均还是加权平均?

3.1.1 简单移动平均线(SMA)

公式很简单:

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

其中 P 是收盘价,N 是周期。比如 20 日 SMA,就是过去 20 个收盘价加起来除以 20。

嗯,这里要注意:SMA 对每个数据点一视同仁。也就是说,10 天前的价格和昨天的价格权重一样。这合理吗?我个人觉得不太合理——昨天的价格显然比 10 天前的更有参考价值。所以就有了 EMA。

3.1.2 指数移动平均线(EMA)

EMA 给近期的价格更高的权重。公式稍微复杂一点:

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

举个例子,20 日 EMA 的 α = 2 / 21 ≈ 0.095。也就是说,今天的价格只占 9.5% 的权重,剩下的 90.5% 来自昨天的 EMA。这看起来好像近期权重也不高?其实不是——因为昨天的 EMA 本身已经包含了前天的信息,这样层层传递,越近的数据影响越大。

我的经验: 做短线策略时,我更喜欢用 EMA。因为它的反应更快,能抓住更早的信号。做长线趋势跟踪,SMA 反而更稳,不容易被假突破骗线。

3.2 布林带(Bollinger Bands)

布林带由三条线组成:中轨(通常是 20 日 SMA)、上轨(中轨 + 2 倍标准差)、下轨(中轨 - 2 倍标准差)。

你想想看,它想表达什么?就是价格在「正常波动范围」内运动。如果价格突破上轨,说明当前波动异常大,可能超买;跌破下轨,可能超卖。

公式:

中轨 = SMA(close, 20)
上轨 = 中轨 + 2 × std(close, 20)
下轨 = 中轨 - 2 × std(close, 20)

我曾经犯过一个错误:直接用布林带的上下轨作为买卖信号。结果呢?在趋势行情里,价格沿着上轨一直涨,我不断做空,亏得底裤都不剩。后来才明白——布林带在震荡市里好用,在趋势市里就是个反向指标。

避坑指南: 布林带的带宽(上下轨之间的距离)本身也是一个重要特征。带宽收窄,往往意味着即将变盘。我曾经在带宽极度收窄时加仓,结果第二天直接跳空突破,赚了一波大的。

3.3 RSI:相对强弱指标

RSI 衡量的是「上涨幅度占总体波动的比例」。公式:

RSI = 100 - [100 / (1 + RS)]
其中 RS = 平均上涨幅度 / 平均下跌幅度

通常用 14 天周期。RSI 超过 70 算超买,低于 30 算超卖。但这里有个细节——超买不代表马上跌,超卖不代表马上涨。尤其是在大牛市中,RSI 可以在 70 以上待很久。

我个人习惯把 RSI 和价格走势结合起来看。比如价格创新高,但 RSI 没创新高,这叫「顶背离」,往往是反转信号。反过来,价格创新低,RSI 没创新低,叫「底背离」。

关键点: RSI 作为特征时,不要只看数值,要看变化趋势。我一般会计算 RSI 的 5 日移动平均,作为辅助特征。

3.4 MACD:指数平滑异同移动平均线

MACD 由三部分组成:

  • DIF线: 快线(12日EMA) - 慢线(26日EMA)
  • DEA线: DIF的9日EMA
  • MACD柱: (DIF - DEA) × 2

说白了,MACD 就是在看「短期趋势和长期趋势的差距」。DIF 上穿 DEA 叫金叉,下穿叫死叉。但说实话,金叉死叉的胜率也就 50% 左右,不能单靠这个做决策。

我更喜欢看 MACD 柱的变化。柱子的高度代表动能强弱。柱子从负变正,说明多头动能开始占优;从正变负,说明空头动能增强。

3.5 可视化:把指标画出来

光算不行,得看。我习惯用 Matplotlib 把价格和指标画在同一张图上。下面是一个简单的示例:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 假设 df 包含 'close' 列
df['SMA_20'] = df['close'].rolling(20).mean()
df['EMA_20'] = df['close'].ewm(span=20, adjust=False).mean()

# 布林带
df['BB_mid'] = df['close'].rolling(20).mean()
df['BB_std'] = df['close'].rolling(20).std()
df['BB_upper'] = df['BB_mid'] + 2 * df['BB_std']
df['BB_lower'] = df['BB_mid'] - 2 * df['BB_std']

# RSI
delta = df['close'].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(14).mean()
avg_loss = loss.rolling(14).mean()
rs = avg_gain / avg_loss
df['RSI'] = 100 - (100 / (1 + rs))

# MACD
df['EMA_12'] = df['close'].ewm(span=12, adjust=False).mean()
df['EMA_26'] = df['close'].ewm(span=26, adjust=False).mean()
df['DIF'] = df['EMA_12'] - df['EMA_26']
df['DEA'] = df['DIF'].ewm(span=9, adjust=False).mean()
df['MACD_bar'] = 2 * (df['DIF'] - df['DEA'])

画图的时候,我一般把价格和布林带放在上面,RSI 放中间,MACD 放下面。这样一眼就能看到价格位置、超买超卖状态、以及动能变化。

3.6 指标作为特征:给强化学习模型喂数据

指标算好了,怎么用?直接扔给模型?不行。有几个坑必须避开:

  1. 归一化: 不同指标的量纲不同。RSI 是 0-100,MACD 可能是 -5 到 5。不归一化,模型会偏向数值大的特征。
  2. 滞后性: 移动平均线天然滞后。你想想看,20 日 SMA 反映的是过去 20 天的平均,等它给出信号,行情可能已经走了一半。
  3. 多重共线性: SMA 和 EMA 高度相关,同时放进去会让模型不稳定。我一般只选一个。

我个人习惯的特征组合是:

  • 价格相对于布林带上轨/下轨的位置(归一化到 -1 到 1)
  • RSI 的 5 日变化量
  • MACD 柱的符号(正为 1,负为 -1)和绝对值
  • 成交量变化率
小技巧: 不要只用当前值,要加入历史窗口。比如过去 5 天的 RSI 序列,或者过去 10 天的 MACD 柱变化。这样模型才能学到「趋势」和「形态」。

3.7 本章知识体系

下面这张图总结了四个指标的核心逻辑和它们之间的关系:

技术指标知识体系 技术指标 MA / EMA 布林带 RSI MACD 特征工程 趋势跟踪:MA/EMA、MACD 震荡/超买超卖:布林带、RSI 共同目标:提取有效特征,输入强化学习模型

嗯,到这里,四个核心指标的计算、可视化、特征化就讲完了。记住一句话:指标是工具,不是答案。真正决定策略好坏的是你怎么用这些工具,以及怎么把它们组合成有效的特征。

专注资料整理