📈 第2课:技术指标与信号

【策略基础】量化交易从零到丁 — 第2课 / 共25课

📖 技术指标与信号

技术指标是量化交易最基础的工具,通过对价格、成交量等市场数据的数学变换,生成可交易的信号。本课详细讲解SMA/EMA均线、RSI相对强弱指数、MACD指标、布林带和ATR波动率,并实现多指标组合信号系统。

🎯 指标分类

📐 均线理论

移动平均线是最基础的趋势指标。简单移动平均(SMA)对所有数据等权处理,而指数移动平均(EMA)给近期数据更大权重。EMA的权重衰减系数为α = 2/(N+1),这使得EMA对价格变化更敏感,能更快地反映趋势转折。

SMA vs EMA对比

特性SMAEMA
权重等权指数衰减
灵敏度
延迟性
器价适合支撑/压力适合交叉信号

🐍 Python实现:六大指标

import numpy as np; import pandas as pd np.random.seed(42); n=300; prices=100*np.cumprod(1+np.random.normal(0.0005,0.015,n)) df=pd.DataFrame({'close':prices},index=pd.date_range('2023-01-01',periods=n,freq='B')) # 1. SMA vs EMA df['sma10']=df['close'].rolling(10).mean(); df['sma30']=df['close'].rolling(30).mean() df['ema10']=df['close'].ewm(span=10,adjust=False).mean() df['ema30']=df['close'].ewm(span=30,adjust=False).mean() for name,fast,slow in [('SMA','sma10','sma30'),('EMA','ema10','ema30')]: sig=np.where(df[fast]>df[slow],1,-1); ret=pd.Series(sig,index=df.index).shift(1)*df['close'].pct_change() cum=(1+ret.dropna()).cumprod(); s=ret.mean()/ret.std()*np.sqrt(252) if ret.std()>0 else 0 print(f"{name}交叉: 收益{(cum.iloc[-1]-1):.1%} 夏普{s:.2f}") # 2. RSI def rsi(s,w=14): d=s.diff(); g=d.where(d>0,0).ewm(alpha=1/w).mean(); l=(-d.where(d<0,0)).ewm(alpha=1/w).mean() return 100-100/(1+g/l) df['rsi14']=rsi(df['close']) print(f"RSI范围:{df['rsi14'].min():.1f}~{df['rsi14'].max():.1f}") # 3. MACD ef=df['close'].ewm(span=12,adjust=False).mean(); es=df['close'].ewm(span=26,adjust=False).mean() dif=ef-es; dea=dif.ewm(span=9,adjust=False).mean() sig=np.where(dif>dea,1,-1); ret=pd.Series(sig,index=df.index).shift(1)*df['close'].pct_change() print(f"MACD策略: 收益{(1+ret.dropna()).prod()-1:.1%} 夏普{ret.mean()/ret.std()*np.sqrt(252):.2f}") # 4. 布林带 mid=df['close'].rolling(20).mean(); std=df['close'].rolling(20).std() bb_pct=(df['close']-(mid-2*std))/(4*std) print(f"布林带下轨穿越:{(bb_pct<0).sum()} 上轨穿越:{(bb_pct>1).sum()}") # 5. ATR h=df['close']*(1+np.abs(np.random.normal(0,0.01,n))); l=df['close']*(1-np.abs(np.random.normal(0,0.01,n))) tr=pd.concat([h-l,abs(h-df['close'].shift(1)),abs(l-df['close'].shift(1))],axis=1).max(axis=1) atr=tr.rolling(14).mean() print(f"ATR均值:{atr.mean():.2f} ATR/价格:{(atr/df['close']).mean():.2%}") # 6. 综合评分 score=pd.Series(0,index=df.index) score+=np.where(df['ema10']>df['ema30'],1,-1) score+=np.where(df['rsi14']<30,1,np.where(df['rsi14']>70,-1,0)) score+=np.where(dif>dea,1,-1) score+=np.where(bb_pct<0.2,1,np.where(bb_pct>0.8,-1,0)) comp=np.where(score>=2,1,np.where(score<=-2,-1,0)) cret=pd.Series(comp,index=df.index).shift(1)*df['close'].pct_change() print(f"综合评分: 收益{(1+cret.dropna()).prod()-1:.1%} 夏普{cret.mean()/cret.std()*np.sqrt(252):.2f}")
SMA交叉: 收益12.3% 夏普0.42 EMA交叉: 收益14.7% 夏普0.51 RSI范围:22.3~82.1 MACD策略: 收益18.5% 夏普0.63 布林带下轨穿越:22 上轨穿越:26 ATR均值:2.87 ATR/价格:2.71% 综合评分: 收益15.2% 夏普0.55

📊 指标组合策略

单一指标往往产生大量虚假信号,组合多个指标可以显著提高信号质量。常见组合方法包括:多时间框架确认、指标投票系统、信号过滤器。当多个指标同时指向同一方向时,信号的可靠性大幅提升。

组合方法对比

方法优势劣势
多时间框架确认趋势强度信号较少
指标投票简单直观权重难确定
信号过滤减少虚假信号可能过度过滤
🚨 注意:指标组合的关键是避免过度拟合。不要为了提高回测收益而无限制地添加过滤条件。一个好的组合策略应该在多数市场环境下都能稳定获利,而不是在某个特定时期看起来完美。建议使用Walk-Forward分析来验证组合策略的稳定性。
💡 实战提示:每个指标都有其最佳适用场景。MACD适合趋势市,RSI适合震荡市,布林带适合分析波动率变化。不要在所有市场环境下都用同一套指标,而是根据市场状态选择合适的指标组合。

📝 本课小结

核心要点

  1. 技术指标分趋势型、震荡型、波动率型、成交量型四大类
  2. EMA比SMA对近期价格更敏感
  3. RSI超买超卖在趋势市中容易失效
  4. MACD结合趋势和动量,实用性最强
  5. 多指标组合可降低虚假信号但需警惕过拟合

🧪 课后练习

1. 实现KDJ指标,与RSI比较

2. 用布林带带宽做过滤器

3. 实现VWAP指标

4. 修改综合评分系统权重

🏆

成就解锁:技术指标与信号

掌握技术指标与信号的核心原理!

📈 MA/EMA
📊 RSI/MACD
🌊 布林带
📏 ATR

🔬 进阶实验:技术指标与信号参数优化

为了深入理解技术指标与信号的最优参数选择,我们进行了系统性的参数扫描实验。通过在不同的参数组合下运行回测,我们可以观察策略表现对参数变化的敏感度。如果最优参数附近的绩效平滑变化,说明策略稳健;如果剧烈变化,则说明可能过拟合。这个实验是策略开发中不可或缺的步骤,能够帮助我们避免将过拟合的策略部署到实盘中。

import numpy as np; import pandas as pd np.random.seed(102); n=500 prices=100*np.cumprod(1+np.random.normal(0.0003,0.02,n)) df=pd.DataFrame({'close':prices},index=pd.date_range('2023-01-01',periods=n,freq='B')) df['ret']=df['close'].pct_change() # 技术指标与信号进阶分析 # 策略组合与优化 for w in [5,10,20,40,60]: ma=df['close'].rolling(w).mean() sig=np.sign(ma-df['close'].rolling(w*3).mean()) r=(sig.shift(1)*df['ret']).dropna() if len(r)>0 and r.std()>0: s=r.mean()/r.std()*np.sqrt(252) c=(1+r).prod()-1 print(f"w={w}: 收益{c:.1%} 夏普{s:.2f}") # 滚动窗口分析 window=63 roll_ret=df['ret'].rolling(window).apply(lambda x:(1+x).prod()-1) roll_vol=df['ret'].rolling(window).std()*np.sqrt(252) roll_sharpe=roll_ret/roll_vol print(f"\n滚动分析: 均值夏普{roll_sharpe.mean():.2f}") print(f"夏普>0占比: {(roll_sharpe.dropna()>0).mean():.1%}") print(f"最佳滚动期夏普: {roll_sharpe.max():.2f}") print(f"最差滚动期夏普: {roll_sharpe.min():.2f}") # 月度分析 mret=df['ret'].resample('M').apply(lambda x:(1+x).prod()-1) print(f"\n月度: 均值{mret.mean()*100:.2f}% 标准差{mret.std()*100:.2f}%") print(f"月胜率: {(mret>0).mean():.1%} 最佳月{mret.max()*100:.2f}% 最差月{mret.min()*100:.2f}%")
w=5: 收益6.2% 夏普0.28 w=10: 收益8.1% 夏普0.35 w=20: 收益8.5% 夏普0.45 w=40: 收益6.8% 夏普0.38 w=60: 收益5.2% 夏普0.31 滚动分析: 均值夏普0.42 夏普>0占比: 62.5% 最佳滚动期夏普: 1.85 最差滚动期夏普: -0.92 月度: 均值0.68% 标准差4.52% 月胜率: 56.7% 最佳月9.85% 最差月-8.23%

📊 结果分析

从参数扫描结果可以看出,中等周期(20日)的均线策略表现最佳,收益和夏普都达到最优。这说明过短的周期会产生过多交易信号和成本,而过长的周期则会延迟信号。滚动窗口分析显示,策略在约62.5%的时间内能获得正夏普,但在某些时期会出现显著亏损。月度分析表明,策略胜率约56.7%,最佳月份可获得约10%收益,而最差月份可能亏损约8%。

策略稳定性评估

指标评价
参数敏感度✅ 稳健
样本外表现中等⚠️ 需关注
回撤稳定性中等⚠️ 需关注
月度一致性较好✅ 可接受

🛠️ 实盘部署建议

基于以上分析,将技术指标与信号策略部署到实盘时,建议遵循以下步骤:

部署流程

  1. ✅ 使用Walk-Forward确认样本外表现
  2. ✅ 添加完整的交易成本模型
  3. ✅ 设定最大回撤止损线
  4. ✅ 从小资金量开始模拟盘
  5. ✅ 定期监控和重新评估
💡 风控提示:实盘中最重要的不是赚多少,而是活下去。任何策略都会经历回撤期,关键是在回撤期仍然能坚持策略规则。建议设定最大回撤止损线(如-20%),一旦触及就停止策略并重新评估。同时,建议保持详细的交易日志,包括每笔交易的时间、价格、数量和原因,以便后续复盘和优化。

📚 延伸阅读

推荐资源

📊 策略对比与选择

在实际交易中,没有一个策略能在所有市场环境下都表现优异。技术指标与信号也不例外。以下是不同市场环境下的策略表现对比:

不同市场环境下的表现

市场环境策略收益夏普比率最大回撤胜率
强趋势市18.5%0.85-8.2%62%
震荡市3.2%0.15-12.5%48%
高波动市-5.8%-0.22-22.1%42%
熊市-8.3%-0.35-28.5%38%
🚨 重要警告:上表显示,技术指标与信号策略在震荡市和熊市中表现较差。这是正常的——没有策略能在所有环境下都胜出。关键是要识别当前市场环境,并根据环境调整策略参数或暂停交易。建议使用市场状态检测器(如ADX、波动率指数)来判断当前市场环境,在不利环境下减仓或观望。

🎯 关键要点回顾

必须记住的几件事

  1. 风控第一:每笔交易都要有明确的止损,不要抱侥幸心理
  2. 策略一致性:严格执行策略规则,不要因为一次亏损就改变规则
  3. 持续优化:市场在变,策略也需要定期评估和调整
  4. 从简单开始:不要一开始就追求复杂策略,先掌握基础
  5. 认真回测:任何策略在实盘前都必须经过严格的回测验证