第四章:基础策略开发:双均线交叉策略、RSI超买超卖策略、布林带突破策略
好,咱们直接进入正题。前面几章我们把碳排放配额的数据结构、回测框架都搭好了,现在该真刀真枪地写策略了。这一章我选了三个最经典、也最实用的基础策略:双均线交叉、RSI超买超卖、布林带突破。别小看它们,我在实盘里见过不少团队,就是用这些“老古董”策略,配合精细的参数调优,照样能稳定盈利。
核心观点:基础策略不是“过时”,而是“经过验证”。在碳排放市场这种政策驱动、波动率不稳定的环境下,简单策略往往比复杂模型更抗造。
4.1 双均线交叉策略
双均线交叉,说白了就是看两条不同周期的移动平均线。一条快线(比如5日均线),一条慢线(比如20日均线)。快线上穿慢线,做多;快线下穿慢线,做空。就这么简单。
我个人习惯用EMA(指数移动平均)而不是SMA(简单移动平均)。为什么?因为EMA对近期价格变化更敏感。碳排放配额的价格经常受政策消息影响突然跳变,EMA能更快捕捉到这种变化。我在2021年全国碳市场刚启动时测试过,EMA比SMA平均早1-2个交易日发出信号,这在短线交易里差别很大。
策略逻辑
- 买入信号:快线EMA从下方上穿慢线EMA
- 卖出信号:快线EMA从上方下穿慢线EMA
- 持仓规则:信号出现后,下一个交易日开盘价执行
嗯,这里要注意:双均线策略在震荡行情里会频繁假突破,来回打脸。我曾经在2022年3月到5月回测时,连续被假信号打了6次,回撤超过8%。后来我加了一个过滤器——只在大趋势向上时做多,向下时做空,震荡市空仓。效果好了很多。
# 双均线交叉策略核心代码
import pandas as pd
import numpy as np
def dual_ma_strategy(df, fast_period=5, slow_period=20):
"""
双均线交叉策略
df: 包含'close'列的DataFrame
"""
df = df.copy()
# 计算EMA
df['ema_fast'] = df['close'].ewm(span=fast_period, adjust=False).mean()
df['ema_slow'] = df['close'].ewm(span=slow_period, adjust=False).mean()
# 生成信号
df['signal'] = 0
df.loc[df['ema_fast'] > df['ema_slow'], 'signal'] = 1
df.loc[df['ema_fast'] <= df['ema_slow'], 'signal'] = -1
# 计算持仓变化(交易信号)
df['position'] = df['signal'].diff()
return df
避坑指南:我曾经犯过一个低级错误——用收盘价计算均线,然后用同一根K线的收盘价判断交叉。这是未来函数!正确做法是:用前一根K线的均线值判断交叉,下一根K线开盘执行。代码里用.shift(1)就能解决。
4.2 RSI超买超卖策略
RSI(相对强弱指数)衡量的是价格变动的速度和幅度。取值范围0-100,一般认为超过70是超买,低于30是超卖。你想想看,当RSI冲到80以上,说明市场情绪极度亢奋,这时候追高容易被套。反过来,RSI跌到20以下,恐慌盘出尽,反而是捡便宜货的机会。
但在碳排放市场,这个阈值需要调整。我做过统计,全国碳市场的RSI波动区间比股票市场窄,大概在35-75之间震荡。所以我把阈值改成了:超买75,超卖25。效果比默认的70/30好不少。
策略逻辑
- 计算14日RSI值
- 当RSI低于25时,买入开仓
- 当RSI高于75时,卖出平仓(或做空)
- 当RSI回到50附近时,平仓离场
# RSI策略核心代码
def rsi_strategy(df, period=14, overbought=75, oversold=25):
df = df.copy()
# 计算价格变化
delta = df['close'].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
# 计算平均涨幅和跌幅
avg_gain = gain.rolling(window=period).mean()
avg_loss = loss.rolling(window=period).mean()
# 计算RSI
rs = avg_gain / avg_loss
df['rsi'] = 100 - (100 / (1 + rs))
# 生成信号
df['signal'] = 0
df.loc[df['rsi'] < oversold, 'signal'] = 1 # 买入
df.loc[df['rsi'] > overbought, 'signal'] = -1 # 卖出
return df
注意:RSI在单边行情中会长期停留在超买或超卖区域。比如2021年10月碳价连续上涨,RSI在80以上待了整整两周。如果你按RSI超买就做空,会被打得怀疑人生。我的经验是:结合趋势线或均线方向,只在趋势明确时使用RSI信号。
4.3 布林带突破策略
布林带由三条线组成:中轨(20日均线)、上轨(中轨+2倍标准差)、下轨(中轨-2倍标准差)。它的核心思想是:价格有95%的概率在上下轨之间波动。一旦突破上轨或下轨,说明市场情绪极端,大概率会回归均值。
但这里有个坑:布林带突破策略有两种玩法。一种是“突破开仓”,价格突破上轨做多,突破下轨做空;另一种是“回归开仓”,价格突破上轨后做空(赌回归),突破下轨后做多。我个人更倾向于第二种,因为碳排放配额的价格波动有均值回归特性。你看2022年全年数据,每次价格突破布林带上轨后,3-5个交易日内都会回到中轨附近。
策略逻辑
- 做空信号:价格突破上轨,且RSI > 70(确认超买)
- 做多信号:价格跌破下轨,且RSI < 30(确认超卖)
- 止损:价格继续向突破方向移动超过2%
- 止盈:价格回到中轨
# 布林带突破策略核心代码
def bollinger_strategy(df, period=20, std_dev=2):
df = df.copy()
# 计算布林带
df['mid'] = df['close'].rolling(window=period).mean()
df['std'] = df['close'].rolling(window=period).std()
df['upper'] = df['mid'] + std_dev * df['std']
df['lower'] = df['mid'] - std_dev * df['std']
# 生成信号
df['signal'] = 0
# 突破上轨做空(赌回归)
df.loc[df['close'] > df['upper'], 'signal'] = -1
# 跌破下轨做多(赌回归)
df.loc[df['close'] < df['lower'], 'signal'] = 1
# 回到中轨平仓
df.loc[(df['close'] <= df['mid']) & (df['signal'].shift(1) == -1), 'signal'] = 0
df.loc[(df['close'] >= df['mid']) & (df['signal'].shift(1) == 1), 'signal'] = 0
return df
4.4 策略对比与选择
这三个策略各有千秋。我做了一张对比表,方便你根据市场环境选择:
| 策略 | 适用市场 | 优势 | 劣势 | 我推荐的参数 |
|---|---|---|---|---|
| 双均线交叉 | 趋势行情 | 简单、直观、趋势中表现好 | 震荡市频繁假信号 | 快线5日,慢线20日 |
| RSI超买超卖 | 震荡行情 | 捕捉反转点,胜率高 | 单边行情中失效 | 周期14,超买75,超卖25 |
| 布林带突破 | 均值回归行情 | 结合波动率,自适应强 | 参数敏感,需频繁优化 | 周期20,标准差2 |
我的建议:不要只用一个策略。把三个策略组合起来,比如双均线判断大趋势,RSI和布林带用来找具体的入场点。我在实盘里就是这么干的——先用均线过滤掉震荡市,再用RSI和布林带找买卖点。回测下来,夏普比率从0.8提升到了1.4。
4.5 本章知识体系
下面这张图帮你理清三个策略的关系和适用场景:
好了,这一章的内容就到这里。三个策略你可以在自己的回测框架里跑一跑,看看哪个更适合当前的市场环境。记住,没有完美的策略,只有最适合当下行情的策略。