💬 一个真实的故事
小刘是个技术分析爱好者,每天看盘第一件事就是看MACD和KDJ。他坚信"金叉买入、死叉卖出"是稳赚不赔的真理。2023年初,他看到某只股票的MACD在低位形成了金叉,兴奋地把全部积蓄投了进去——结果这只股票又跌了30%,金叉变成了"假金叉"。
小刘崩溃了,他去问一个做量化研究的朋友:"MACD不是最靠谱的指标吗?为什么我会亏?"朋友问他:"你知道MACD的DIF线是怎么算出来的吗?"小刘摇头。朋友又问:"你知道为什么在震荡市里MACD的假信号特别多吗?"小刘又摇头。
朋友叹了口气说:"你就像一个司机,只知道踩油门和刹车,但完全不懂发动机是怎么工作的。这样开车,不出事故才是奇迹。"
这个故事告诉我们:技术指标不是魔法咒语,它们只是价格数据的数学变换。理解它们的计算原理,才能知道什么时候该信、什么时候不该信。
核心洞察:所有技术指标都是对价格数据的"二次加工"。MACD看的是趋势动能,RSI看的是涨跌力度,布林带看的是波动范围。它们各有盲区,组合使用才能相互验证。
⚡ 核心知识:三大指标的数学本质
1. MACD:趋势动能的"雷达"
MACD(Moving Average Convergence Divergence,指数平滑异同移动平均线)是最著名的趋势指标之一。它的核心思想是:用两条不同周期的指数移动平均线的差值,来衡量趋势的动能和方向。
MACD由三个部分组成:
- DIF线(快线):12日EMA减去26日EMA。DIF向上穿越0轴,说明短期趋势强于长期趋势;向下穿越则说明相反。
- DEA线(慢线/信号线):DIF的9日EMA。它是DIF线的"平滑版",用来过滤DIF的噪音。
- MACD柱状图(Histogram):DIF减去DEA。柱状图从负变正(即DIF上穿DEA)就是"金叉";从正变负就是"死叉"。
MACD计算流程:
flowchart TD
A[收盘价] --> B[计算12日EMA]
A --> C[计算26日EMA]
B --> D[DIF = EMA12 - EMA26]
D --> E[计算DEA = DIF的9日EMA]
D --> F[柱状图 = DIF - DEA]
E --> G[金叉/死叉判断]
F --> G
style A fill:#f97316,stroke:#fff,color:#fff
style G fill:#06b6d4,stroke:#fff,color:#fff
为什么MACD在震荡市会失灵?因为震荡市的价格围绕均值上下波动,没有明确的趋势方向。此时DIF和DEA会频繁交叉,产生大量假信号。MACD是趋势指标,只有在趋势明确的市场中才有效。
2. RSI:涨跌力度的"温度计"
RSI(Relative Strength Index,相对强弱指数)由威尔斯·威尔德(Welles Wilder)于1978年提出。它的核心思想是:用一段时间内上涨幅度和下跌幅度的比值,来衡量市场的超买超卖状态。
RSI的计算步骤如下:
- 计算每日价格变动:今日收盘价 - 昨日收盘价
- 分离涨跌:上涨日的变动记为Gain,下跌日的变动记为Loss(取绝对值)
- 计算平均涨幅和平均跌幅:通常用14日简单移动平均或指数移动平均
- 计算RS:RS = 平均涨幅 / 平均跌幅
- 计算RSI:RSI = 100 - (100 / (1 + RS))
RSI的取值范围是0到100。传统上:
- RSI > 70:被认为"超买",可能回调。但在强趋势市场中,RSI可以长期维持在70以上。
- RSI < 30:被认为"超卖",可能反弹。但在熊市中,RSI可以长期低于30。
- RSI = 50:多空力量均衡,市场没有明确方向。
关键认知:RSI的超买超卖信号在震荡市中比较有效,在强趋势市中经常"失效"。这不是指标的问题,而是使用者没有理解指标的适用场景。
3. 布林带:波动范围的"轨道"
布林带(Bollinger Bands)由约翰·布林格(John Bollinger)于1980年代发明。它的核心思想是:价格的波动范围可以用均值加减若干个标准差来描述。
布林带由三条线组成:
- 中轨(MB):通常为20日简单移动平均线(SMA),代表价格的"中心趋势"。
- 上轨(UP):中轨 + 2倍标准差。价格触及上轨,说明当前价格相对于近期均值偏高。
- 下轨(DN):中轨 - 2倍标准差。价格触及下轨,说明当前价格相对于近期均值偏低。
布林带的核心交易逻辑:
- "触轨反弹":价格触及上轨后回落,或触及下轨后反弹。这适用于震荡市。
- "轨道突破":价格突破上轨并持续运行,说明趋势很强;突破下轨并持续运行,说明下跌趋势很强。
- "收口与开口":布林带收口(上下轨靠近)意味着波动率降低,可能酝酿大行情;开口意味着波动率增大,趋势可能加速。
布林带的本质:它不是预测工具,而是"波动率可视化工具"。它告诉你当前价格相对于历史波动处于什么位置,但不能告诉你未来会怎么走。
4. 指标使用的重要原则
掌握了计算原理后,你还需要知道如何正确使用这些指标,避免落入常见陷阱。
| 原则 | 说明 |
| 指标不是水晶球 | 所有指标都是基于历史价格的计算,不能预测未来。它们只是提供一种观察角度。 |
| 没有万能指标 | 每个指标都有适用场景和盲区。MACD适合趋势市,RSI适合震荡市,布林带适合波动率分析。 |
| 参数不是固定的 | 默认参数(如MACD的12/26/9)是针对美股设计的。A股可能需要调整参数以适应不同的波动特征。 |
| 多指标相互验证 | 单一指标的信号可靠性有限。建议至少用2-3个不同类型的指标进行交叉验证。 |
| 结合量价分析 | 指标信号配合成交量放大/萎缩,可以大大提高判断的准确性。 |
🤖 与AI一起练习
练习1:让AI从零写MACD
Prompt模板:
请用纯Python(不调用talib或pandas的EMA函数)
实现MACD指标的计算,要求:
1. 手动实现EMA的计算公式
2. 输入:收盘价列表(list或numpy数组)
3. 输出:DIF、DEA、MACD柱状图三个序列
4. 默认参数:fast=12, slow=26, signal=9
5. 给出计算过程的详细注释
6. 用一组示例数据验证结果正确性
练习2:让AI解释参数影响
Prompt模板:
请解释MACD的三个参数(fast, slow, signal)
分别控制什么,以及:
1. 如果把fast从12改为5,指标会变得怎样?
2. 如果把slow从26改为60,指标会变得怎样?
3. 这些参数调整后,适用于什么类型的市场?
请用具体的数值例子说明。
练习3:让AI设计指标组合策略
Prompt模板:
我想设计一个使用MACD + RSI + 布林带的组合策略。
要求:
1. MACD提供趋势方向(只做多头趋势)
2. RSI提供入场时机(不超买时入场)
3. 布林带提供止损位置(跌破下轨止损)
请给出完整的策略逻辑、参数建议和Python代码框架。
并指出这个策略在哪些市场环境下可能失效。
🔧 动手实践:从零实现三大指标
下面这段代码展示了如何不依赖任何现成库,纯用Python和NumPy实现MACD、RSI和布林带。这是理解指标本质的最好方式。
import numpy as np
import pandas as pd
# ==========================================
# 工具函数:手动计算EMA
# ==========================================
def ema_manual(data, period):
"""
手动计算指数移动平均线(EMA)
EMA_today = alpha * Price_today + (1-alpha) * EMA_yesterday
alpha = 2 / (period + 1)
"""
alpha = 2 / (period + 1)
ema = np.zeros_like(data, dtype=float)
ema[0] = data[0] # 首日EMA用首日价格初始化
for i in range(1, len(data)):
ema[i] = alpha * data[i] + (1 - alpha) * ema[i-1]
return ema
# ==========================================
# 指标1:MACD
# ==========================================
def macd_manual(close, fast=12, slow=26, signal=9):
"""
手动计算MACD指标
返回:DIF, DEA, Histogram
"""
print(f"📈 计算MACD (fast={fast}, slow={slow}, signal={signal})...")
# 1. 计算两条EMA
ema_fast = ema_manual(close, fast)
ema_slow = ema_manual(close, slow)
# 2. DIF = 快线 - 慢线
dif = ema_fast - ema_slow
# 3. DEA = DIF的EMA(信号线)
dea = ema_manual(dif, signal)
# 4. MACD柱状图
histogram = dif - dea
print(f" DIF最新值: {dif[-1]:.4f}")
print(f" DEA最新值: {dea[-1]:.4f}")
print(f" 柱状图最新值: {histogram[-1]:.4f}")
# 判断金叉死叉
if histogram[-2] < 0 and histogram[-1] > 0:
print(" ✅ 最新信号: 金叉(买入)")
elif histogram[-2] > 0 and histogram[-1] < 0:
print(" ❌ 最新信号: 死叉(卖出)")
else:
print(" ⏸ 最新信号: 无交叉")
return dif, dea, histogram
# ==========================================
# 指标2:RSI
# ==========================================
def rsi_manual(close, period=14):
"""
手动计算RSI指标
RSI = 100 - (100 / (1 + RS))
RS = 平均涨幅 / 平均跌幅
"""
print(f"\n🌡 计算RSI (period={period})...")
# 1. 计算每日价格变动
delta = np.diff(close)
# 2. 分离涨跌
gains = np.where(delta > 0, delta, 0)
losses = np.where(delta < 0, -delta, 0)
# 3. 计算平均涨幅和平均跌幅(使用Wilder平滑法)
avg_gains = np.zeros_like(gains, dtype=float)
avg_losses = np.zeros_like(losses, dtype=float)
# 第一个平均值用简单平均
avg_gains[period-1] = np.mean(gains[:period])
avg_losses[period-1] = np.mean(losses[:period])
# 后续使用平滑公式
for i in range(period, len(gains)):
avg_gains[i] = (avg_gains[i-1] * (period - 1) + gains[i]) / period
avg_losses[i] = (avg_losses[i-1] * (period - 1) + losses[i]) / period
# 4. 计算RS和RSI
rs = avg_gains / (avg_losses + 1e-10) # 防止除零
rsi = 100 - (100 / (1 + rs))
# 前period-1天没有有效RSI值,用NaN填充
full_rsi = np.full_like(close, np.nan, dtype=float)
full_rsi[1:] = rsi # delta比close少一个元素
print(f" RSI最新值: {full_rsi[-1]:.2f}")
if full_rsi[-1] > 70:
print(" 🔴 状态: 超买区")
elif full_rsi[-1] < 30:
print(" 🔵 状态: 超卖区")
else:
print(" ⚪ 状态: 中性区")
return full_rsi
# ==========================================
# 指标3:布林带
# ==========================================
def bollinger_manual(close, period=20, std_dev=2):
"""
手动计算布林带
中轨 = SMA(close, period)
上轨 = 中轨 + std_dev * 标准差
下轨 = 中轨 - std_dev * 标准差
"""
print(f"\n📌 计算布林带 (period={period}, std={std_dev})...")
# 1. 计算中轨(SMA)
middle = np.convolve(close, np.ones(period)/period, mode='valid')
# 2. 计算标准差
rolling_std = np.array([
np.std(close[i:i+period])
for i in range(len(close) - period + 1)
])
# 3. 计算上下轨
upper = middle + std_dev * rolling_std
lower = middle - std_dev * rolling_std
# 对齐长度(前面period-1天没有值)
full_middle = np.full_like(close, np.nan, dtype=float)
full_upper = np.full_like(close, np.nan, dtype=float)
full_lower = np.full_like(close, np.nan, dtype=float)
full_middle[period-1:] = middle
full_upper[period-1:] = upper
full_lower[period-1:] = lower
print(f" 中轨最新值: {full_middle[-1]:.4f}")
print(f" 上轨最新值: {full_upper[-1]:.4f}")
print(f" 下轨最新值: {full_lower[-1]:.4f}")
# 判断价格位置
if close[-1] > full_upper[-1]:
print(" 🔴 价格状态: 突破上轨")
elif close[-1] < full_lower[-1]:
print(" 🔵 价格状态: 跌破下轨")
else:
print(" ⚪ 价格状态: 轨道内运行")
return full_middle, full_upper, full_lower
# ==========================================
# 测试:用示例数据验证
# ==========================================
if __name__ == "__main__":
print("=" * 55)
print("🌟 技术指标从零实现演示")
print("=" * 55)
# 生成示例数据:模拟股价走势
np.random.seed(42)
returns = np.random.normal(0.001, 0.02, 100) # 日均收益0.1%,波动2%
prices = 100 * np.exp(np.cumsum(returns)) # 从100元起价
print(f"\n示例数据: 100个交易日,起始价100元")
print(f"最终价格: {prices[-1]:.2f}元")
# 计算三大指标
dif, dea, hist = macd_manual(prices)
rsi = rsi_manual(prices)
mid, up, low = bollinger_manual(prices)
# 汇总输出
print(f"\n{'=' * 55}")
print("📋 综合信号汇总")
print(f"{'=' * 55}")
signals = []
if hist[-2] < 0 and hist[-1] > 0:
signals.append("MACD金叉")
elif hist[-2] > 0 and hist[-1] < 0:
signals.append("MACD死叉")
if not np.isnan(rsi[-1]):
if rsi[-1] < 30:
signals.append("RSI超卖")
elif rsi[-1] > 70:
signals.append("RSI超买")
if prices[-1] < low[-1]:
signals.append("跌破布林带下轨")
elif prices[-1] > up[-1]:
signals.append("突破布林带上轨")
if signals:
print("当前信号: " + " | ".join(signals))
else:
print("当前信号: 无明显信号")
print(f"\n{'=' * 55}")
print("✅ 演示完成!")
print("你现在理解了这些指标的本质,")
print("可以自信地修改参数、组合使用、甚至创造新指标。")
print(f"{'=' * 55}")
交互式指标参数探索器
调整下面的参数,看看MACD和RSI的数值会如何变化。这个模拟器使用简化的计算公式,帮助你直观理解参数的作用。