
欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 250+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!
你是否想过,一个简单的交易策略能在 25 年的市场波动中存活下来?今天我们来拆解一个结合 Gann 高低点回调和布林带波动率的量化策略,看看它是如何在生物科技股 BIIB 上实现 571% 回报的。
这个策略的核心理念很简单:在市场犹豫时入场,在情绪过热时离场。
策略使用 Gann 高低点理论,观察价格与前一日高点的关系。当满足以下条件时入场:
这种形态意味着价格在关键阻力位下方犹豫,压力正在积蓄。
策略使用布林带作为离场信号。当开盘价突破布林带上轨时,说明市场情绪已经过热,此时果断离场。
import pandas as pd
import numpy as np
import yfinance as yf
import vectorbt as vbt
# 下载 BIIB 股票数据
symbol = "BIIB"
start_date = "2000-01-01"
end_date = "2026-01-01"
interval = "1d"
# 使用 yfinance 下载历史数据
df = yf.download(symbol, start=start_date, end=end_date, interval=interval)
# 保存到本地 CSV 文件
df.to_csv("BIIB_clean.csv", index=False)
GANN_SHIFT = 1# 回看周期为 1 天
defcalculate_gann_trend(df, shift=GANN_SHIFT):
"""
计算 Gann 高低点趋势和参考价格
"""
df = df.copy()
# 获取前一根 K 线的高点、低点、开盘价
df['Gann_High'] = df['High'].shift(shift)
df['Gann_Low'] = df['Low'].shift(shift)
df['Prev_High'] = df['High'].shift(shift)
df['Prev_Low'] = df['Low'].shift(shift)
df['Prev_Open'] = df['Open'].shift(shift)
# 判断趋势方向
df['Gann_UpTrend'] = df['Close'] > df['Gann_Low'] # 收盘价高于前低为上升趋势
df['Gann_DownTrend'] = df['Close'] < df['Gann_High'] # 收盘价低于前高为下降趋势
return df
defgann_open_below_highest_after_below(df, shift=GANN_SHIFT):
"""
判断入场条件:开盘价连续两天低于前一日高点
"""
df = calculate_gann_trend(df, shift)
return (df['Open'] < df['Prev_High']) & (df['Prev_Open'] < df['Prev_High'])
BB_PERIOD = 20# 布林带周期
BB_STD = 2# 标准差倍数
defcalculate_bollinger_bands(df, period=BB_PERIOD, std_multiplier=BB_STD):
"""
计算布林带:中轨、上轨、下轨
"""
df = df.copy()
# 中轨:20 日移动平均线
df['BB_MA'] = df['Close'].rolling(window=period).mean()
# 上轨:中轨 + 2 倍标准差
df['BB_Upper'] = df['BB_MA'] + std_multiplier * df['Close'].rolling(window=period).std()
# 下轨:中轨 - 2 倍标准差
df['BB_Lower'] = df['BB_MA'] - std_multiplier * df['Close'].rolling(window=period).std()
return df
defbb_open_above_upper(df, period=BB_PERIOD, std_multiplier=BB_STD):
"""
判断离场条件:开盘价突破布林带上轨
"""
df = calculate_bollinger_bands(df, period, std_multiplier)
return df['Open'] > df['BB_Upper']
# 生成入场信号
df["Open_Below_Highest_after_Below"] = gann_open_below_highest_after_below(df)
entry_conditions = ['Open_Below_Highest_after_Below']
df['entry_signal'] = df[entry_conditions].all(axis=1)
# 生成离场信号
df["BB_Open_Above_Upper"] = bb_open_above_upper(df)
exit_conditions = ['BB_Open_Above_Upper']
df['exit_signal'] = df[exit_conditions].all(axis=1)
# 信号延迟一天执行(避免未来函数)
shift_entries = df['entry_signal'].shift(1).astype(bool).fillna(False).to_numpy()
shift_exits = df['exit_signal'].shift(1).astype(bool).fillna(False).to_numpy()
# 使用 vectorbt 进行回测
pf = vbt.Portfolio.from_signals(
close=df['Open'], # 使用开盘价成交
entries=shift_entries, # 入场信号
exits=shift_exits, # 离场信号
init_cash=100_000, # 初始资金 10 万美元
fees=0.001, # 手续费 0.1%
slippage=0.002, # 滑点 0.2%
freq='1d'# 日频交易
)
# 输出回测统计数据
print(pf.stats())
# 绘制资金曲线
pf.plot().show()
经过 25 年(2000 年至 2025 年)的回测,策略表现如下:
这个策略并不追求"圣杯",而是遵循一套朴素的交易哲学:
正如原文所说:"市场奖励耐心,远比奖励聪明更多。"
这篇文章介绍了一个结合 Gann 理论和布林带的量化交易策略。通过 Python 和 vectorbt 库,我们可以快速实现策略回测。虽然这个策略在 25 年间取得了不错的收益,但 76% 的最大回撤也提醒我们:任何策略都有风险,历史表现不代表未来收益。
如果你对量化交易感兴趣,建议从以下几个方面深入学习:掌握 pandas 和 numpy 进行数据处理,学习 yfinance 获取金融数据,以及使用 vectorbt 进行策略回测。
免责声明:本文仅供学习交流,不构成任何投资建议。投资有风险,入市需谨慎。
核心权益如下:
星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐