技术指标在交易中非常有效,但它们都存在一个共同的缺点——虚假交易信号。依赖这些信号进行交易可能导致灾难性的结果。为了解决这个问题,最佳方法是引入两种特性各异的技术指标来构建交易策略,从而过滤掉虚假信号,保留真实交易机会。
本文将介绍如何结合布林带(Bollinger Bands)和随机震荡指标(Stochastic Oscillator),使用Python构建一个量化交易策略。我们将对该策略进行回测,并将其收益与SPY ETF(专门跟踪标普500指数走势的交易所交易基金)的表现进行对比。接下来,让我们深入探讨这一策略的实现过程。
技术指标基础
布林带
在理解布林带之前,需要先了解简单移动平均线(SMA)。简单移动平均线是给定时间周期内股票价格的平均值。布林带则是在股票SMA上方和下方绘制的趋势线,其位置由特定标准差水平决定。
布林带非常适合观察股票在一定时期内的波动性。当上下轨之间的空间或距离较小时,股票波动性较低;当距离较大时,波动性较高。布林带的计算公式如下:
- 上轨 = SMA + 2 × 标准差
- 下轨 = SMA - 2 × 标准差
- 中轨 = SMA(通常取20周期)
随机震荡指标
随机震荡指标是一种基于动量的领先指标,广泛用于识别市场是否处于超买或超卖状态。超买指市场趋势极度看涨,可能即将 consolidation(整理);超卖则表示市场趋势极度看跌,有可能出现反弹。
该指标的值经过归一化处理,始终介于0到100之间。通常,超买和超卖水平分别设为70和30,但实际应用中可略有调整。随机震荡指标包含两个主要组件:
- %K线(快线):反映市场的当前状态(超买或超卖)。计算方式为:(当前收盘价 - 过去N周期最低价) / (过去N周期最高价 - 过去N周期最低价) × 100。常用周期为14。
- %D线(慢线):%K线的移动平均线(通常取3周期),是其平滑版本。
交易策略构建
结合布林带和随机震荡指标,我们构建以下交易策略:
- 买入信号:当随机指标的%K和%D线前一日读数大于30,当前日读数小于30,且当日收盘价低于布林带下轨时触发。
- 卖出信号:当随机指标的%K和%D线前一日读数小于70,当前日读数大于70,且当日收盘价高于布林带上轨时触发。
策略逻辑可简化为:
如果 前一日%K > 30 且 前一日%D > 30 且 当前%K < 30 且 当前%D < 30 且 收盘价 < 布林带下轨 → 买入
如果 前一日%K < 70 且 前一日%D < 70 且 当前%K > 70 且 当前%D > 70 且 收盘价 > 布林带上轨 → 卖出这一策略通过双重确认机制,有效过滤假信号,提高交易可靠性。
Python实现步骤
我们将使用Python从零开始实现该策略,包括数据获取、指标计算、策略回测和绩效评估。主要步骤如下:
- 导入必要库(Pandas、NumPy、Matplotlib等)
- 从数据API获取股票历史数据
- 计算布林带指标
- 计算随机震荡指标
- 编写交易策略逻辑
- 生成交易信号和持仓记录
- 回测策略表现
- 与基准(SPY ETF)对比收益
数据获取与处理
首先导入所需库,然后通过API获取苹果公司(AAPL)自2010年以来的历史价格数据。这里使用EODHD提供的OHLC调整后数据端点,需要替换为您自己的API密钥。
import pandas as pd
import requests
import numpy as np
def get_historical_data(symbol, start_date):
api_key = '您的API密钥'
api_url = f'https://eodhistoricaldata.com/api/technical/{symbol}?order=a&fmt=json&from={start_date}&function=splitadjusted&api_token={api_key}'
raw_df = requests.get(api_url).json()
df = pd.DataFrame(raw_df)
df.date = pd.to_datetime(df.date)
df = df.set_index('date')
return df
aapl = get_historical_data('AAPL', '2010-01-01')指标计算
计算布林带和随机震荡指标的数值:
# 计算简单移动平均线
def sma(data, lookback):
return data.rolling(lookback).mean()
# 计算布林带
def get_bb(data, lookback):
std = data.rolling(lookback).std()
upper_bb = sma(data, lookback) + std * 2
lower_bb = sma(data, lookback) - std * 2
middle_bb = sma(data, lookback)
return upper_bb, lower_bb, middle_bb
# 计算随机震荡指标
def get_stoch_osc(high, low, close, k_lookback, d_lookback):
lowest_low = low.rolling(k_lookback).min()
highest_high = high.rolling(k_lookback).max()
k_line = ((close - lowest_low) / (highest_high - lowest_low)) * 100
d_line = k_line.rolling(d_lookback).mean()
return k_line, d_line
# 应用计算
aapl['upper_bb'], aapl['lower_bb'], aapl['middle_bb'] = get_bb(aapl['close'], 20)
aapl['%k'], aapl['%d'] = get_stoch_osc(aapl['high'], aapl['low'], aapl['close'], 14, 3)
aapl = aapl.dropna()策略实现与回测
根据前述策略逻辑生成交易信号,并进行回测:
def bb_stoch_strategy(prices, k, d, upper_bb, lower_bb):
buy_price = []; sell_price = []; signal = 0
bb_stoch_signal = []
for i in range(len(prices)):
if k[i-1] > 30 and d[i-1] > 30 and k[i] < 30 and d[i] < 30 and prices[i] < lower_bb[i]:
if signal != 1:
buy_price.append(prices[i])
sell_price.append(np.nan)
signal = 1
bb_stoch_signal.append(signal)
# ... 其余策略逻辑
return buy_price, sell_price, bb_stoch_signal
# 生成交易信号
buy_price, sell_price, bb_stoch_signal = bb_stoch_strategy(aapl['close'], aapl['%k'], aapl['%d'], aapl['upper_bb'], aapl['lower_bb'])回测结果显示,从2010年初开始,初始投资10万美元,最终收益约为315,000美元,收益率达315%。相比之下,同期投资SPY ETF的收益为156,261美元,收益率156%。策略表现显著优于基准159%。
策略优化与改进
虽然这一策略表现优异,但实际应用中还需考虑以下因素以提升实用性:
- 交易成本:真实交易中需扣除经纪商佣金,这会影响最终收益。
- 风险控制:加入止损止盈机制,管理单笔交易最大亏损。
- 参数优化:调整布林带周期和标准差倍数,测试不同市场环境下的适应性。
- 多品种测试:在更多股票和不同市场条件下验证策略稳健性。
此外,可以考虑引入机器学习方法动态优化参数,或结合其他指标形成多因子策略,进一步提高胜率和风险调整后收益。
常见问题
布林带的最佳参数设置是什么?
布林带的默认参数为20周期移动平均线和2倍标准差。这一设置适用于大多数趋势行情,但投资者可根据标的波动性调整:高波动性市场可尝试22周期和2.5倍标准差,低波动性环境则可试用18周期和1.5倍标准差。关键是通过历史回测找到最适合特定品种的参数组合。
随机震荡指标在震荡市和趋势市中表现如何?
随机震荡指标在区间震荡市中表现优异,能有效识别超买超卖区域;但在强劲趋势市中可能过早发出反转信号,导致多次止损。因此建议结合趋势过滤指标使用,如ADX(平均趋向指数)或均线排列,只在趋势不明朗时采用该指标的交易信号。
这个策略适合加密货币市场吗?
是的,这一策略经过调整后可适用于加密货币市场。但由于加密资产波动性更高,建议调整参数:布林带标准差倍数可增至2.5-3倍,随机指标超买超卖区域可设为80和20。另需注意加密货币交易24/7连续交易的特点,需相应调整数据处理方式。
回测结果这么好,实盘一定能赚钱吗?
不一定。回测表现优异不代表实盘一定能盈利。历史回测无法完全模拟实盘交易环境,包括滑点、流动性限制、数据延迟等因素。建议先进行模拟盘验证,再逐步投入实盘资金。同时务必进行资金管理,单笔交易风险控制在总资金的1-2%以内。
如何避免策略过度优化?
过度优化会使策略过于契合历史数据而在未来失效。为避免这一问题,可采用以下方法:使用足够长的历史数据(至少10年);进行样本外测试;采用滚动窗口优化参数;保持策略逻辑简洁,避免过多规则;关注策略在经济周期不同阶段的表现稳定性。
总结
布林带与随机震荡指标组合策略通过双重确认机制有效过滤假信号,在历史回测中显示出显著超越基准的收益能力。本文提供了完整的Python实现代码,从数据获取、指标计算到策略回测,为读者提供了可操作的实施框架。
需要注意的是,任何策略都需要根据实际市场环境进行调整和优化,且过去表现不代表未来结果。建议投资者在实盘前充分验证策略,并结合严格的风险管理措施。
量化交易是一个持续学习和优化的过程,本策略可作为入门起点,帮助读者理解多指标组合的基本原理和实现方法。随着经验积累,可逐步探索更复杂的模型和交易系统。