量化策略百战案例 ByQuant.com
量化策略百战案例之布林带策略
策略介绍
布林带策略是一种常见的技术分析工具,用于判断价格走势的波动性和可能的拐点。
该策略基于布林带指标,该指标由三条线组成:中轨线,上轨线和下轨线。中轨线是一条简单移动平均线,上轨线和下轨线则是在中轨线的基础上加减标准差得到的。
布林带策略是一种基于统计学原理的技术指标,用来衡量价格波动的幅度和价格的相对位置。
策略原理
- 当价格上涨时,如果价格触及或突破上轨线,则说明市场处于超买状态,可能会出现价格回撤的机会。可以考虑卖出或者持有空头仓位。
- 当价格下跌时,如果价格触及或突破下轨线,则说明市场处于超卖状态,可能会出现价格反弹的机会。可以考虑买入或者持有多头仓位。
- 如果价格在中轨线附近波动,说明市场趋势不明确,可以考虑持币观望。
布林带的主要作用是帮助交易者判断价格的相对高低和可能的转折点。当价格接近或触及上轨线时,意味着市场可能过热,价格可能会回落;当价格接近或触及下轨线时,意味着市场可能过冷,价格可能会反弹。
布林带策略的交易信号通常基于价格突破上轨线或下轨线。当价格突破上轨线时,可能是一个买入信号;当价格突破下轨线时,可能是一个卖出信号。此外,交叉信号也可以考虑,例如中轨线和价格的交叉。
算法公式
布林带计算公式如下:
中轨线(中线)= N日的移动平均线
上限线 = 中线 + K倍的标准差
下限线 = 中线 - K倍的标准差
其中,N表示计算移动平均线的周期,K表示标准差的倍数。
布林带是一种用于统计市场价格波动的技术指标,通过计算一组移动平均线的标准差来确定价格的上下限。
import byquant as by
alldata = by.data.quote('symbol',start='2021-01-01',end='2023-06-30', freq='1d', limit=1000)
alldata.tail()
open | high | low | close | volume | |
---|---|---|---|---|---|
datetime | |||||
2023-06-23 04:00:00 | 185.299772 | 187.307056 | 184.760492 | 186.428238 | 53079300 |
2023-06-26 04:00:00 | 186.578051 | 187.796407 | 184.980202 | 185.020157 | 48088700 |
2023-06-27 04:00:00 | 185.639310 | 188.135938 | 185.419605 | 187.806381 | 50730800 |
2023-06-28 04:00:00 | 187.676554 | 189.643899 | 187.347013 | 188.994781 | 51216800 |
2023-06-29 04:00:00 | 188.825013 | 189.813684 | 188.685203 | 189.334320 | 46347300 |
data=alldata.copy()[-280:]
data['upper'], data['middle'], data['lower'] = by.ta.BBANDS(data,period=20)
print(data['upper'])
datetime
2022-05-18 04:00:00 NaN
2022-05-19 04:00:00 NaN
2022-05-20 04:00:00 NaN
2022-05-23 04:00:00 NaN
2022-05-24 04:00:00 NaN
...
2023-06-23 04:00:00 188.984002
2023-06-26 04:00:00 188.478973
2023-06-27 04:00:00 188.863380
2023-06-28 04:00:00 189.643299
2023-06-29 04:00:00 190.228470
Name: upper, Length: 280, dtype: float64
by.chart.line(data=data['upper'], label="upper")
by.chart.line(data=data['middle'], label="middle")
by.chart.line(data=data['lower'], label="lower")
by.chart.close()
策略逻辑
- 计算布林带指标的中轨线,上轨线和下轨线。
- 当价格突破上轨线时,发出卖出信号。
- 当价格突破下轨线时,发出买入信号。
- 设置止损和止盈条件,控制仓位风险。
import numpy as np
data['buy'] = data['sell'] = np.NaN
data.loc[(data['close'] > data['upper']) & (data['close'].shift(1) < data['upper'].shift(1)), 'sell'] = 1
data.loc[(data['close'] < data['lower']) & (data['close'].shift(1) > data['lower'].shift(1)), 'buy'] = 1
ta1_plot = by.chart.addplot(data['upper'], type='line', color='red') #scatter
ta2_plot = by.chart.addplot(data['middle'], type='line', color='blue') #scatter
ta3_plot = by.chart.addplot(data['lower'], type='line', color='green') #scatter
buy_signal_plot = by.chart.make_addplot(data['buy'], type='scatter', markersize=50, marker='^', color='green') #scatter
sell_signal_plot = by.chart.make_addplot(data['sell'], type='scatter', markersize=50, marker='v', color='red') #scatter
by.chart.kline(data,type='line',addplot=[ta1_plot,ta2_plot,ta3_plot,buy_signal_plot,sell_signal_plot])
策略回测
class BBandsStrategy(by.Strategy):
# 自定义参数
params = (
("period", 20),
)
def __init__(self):
self.order = None
self.lines.top = by.ta.BBands(self.datas[0], period=self.p.period).top
self.lines.bot = by.ta.BBands(self.datas[0], period=self.p.period).bot
def next(self):
try:
if self.data.close[0] < self.lines.bot[0] and self.data.close[-1] > self.lines.bot[-1]:
# 执行买入
self.order = self.buy()
if self.data.close[0] > self.lines.top[0] and self.data.close[-1] < self.lines.bot[-1]:
# 执行卖出
self.order = self.sell()
except Exception as e:
print(e.args)
pass
by.Backtest(data,strategy=BBandsStrategy,out='p').byrun() # plot / pyfolio | quantstats / plotly / bokeh / seaborn
Start date | 2022-05-18 | |
---|---|---|
End date | 2023-06-29 | |
Total months | 13 | |
Backtest | ||
Annual return | 0.119% | |
Cumulative returns | 0.132% | |
Annual volatility | 0.089% | |
Sharpe ratio | 1.34 | |
Calmar ratio | 1.64 | |
Stability | 0.47 | |
Max drawdown | -0.072% | |
Omega ratio | 1.29 | |
Sortino ratio | 2.23 | |
Skew | 0.76 | |
Kurtosis | 2.57 | |
Tail ratio | 1.13 | |
Daily value at risk | -0.011% | |
Gross leverage | 0.00 | |
Daily turnover | 1.114% |
Worst drawdown periods | Net drawdown in % | Peak date | Valley date | Recovery date | Duration |
---|---|---|---|---|---|
0 | 0.07 | 2022-10-28 | 2023-01-05 | 2023-02-02 | 70 |
1 | 0.03 | 2023-02-15 | 2023-03-01 | 2023-03-16 | 22 |
2 | 0.03 | 2022-09-12 | 2022-09-30 | 2022-10-28 | 35 |
3 | 0.02 | 2023-04-03 | 2023-04-12 | 2023-04-18 | 12 |
4 | 0.01 | 2023-04-28 | 2023-05-04 | 2023-05-05 | 6 |
Stress Events | mean | min | max |
---|---|---|---|
Covid | 0.00% | -0.01% | 0.02% |
Top 10 long positions of all time | max |
---|---|
Symbol | 0.57% |
Top 10 short positions of all time | max |
---|
Top 10 positions of all time | max |
---|---|
Symbol | 0.57% |
策略优缺
优点:
-
提供了价格波动的参考范围:布林带的上轨和下轨界定了价格波动的参考范围。可以根据价格是否接近上轨或下轨来判断市场的高低位,从而作出相应的交易决策。
-
可用于识别超买和超卖信号:当价格突破上轨时,意味着市场可能已经超买,可以考虑卖出标的。相反,当价格跌破下轨时,意味着市场可能已经超卖,可以考虑买入标的。
-
可用于识别趋势反转:布林带的中轨线可以用来识别市场的趋势。当价格连续向上突破中轨线时,可能暗示着市场趋势向上;相反,当价格连续向下跌破中轨线时,可能暗示着市场趋势向下。
缺点:
-
延迟性:与其他基于移动平均线的策略类似,布林带策略存在延迟性。由于使用历史价格数据计算移动平均线和标准差,策略的信号通常滞后于市场价格的实际变动。这可能导致错过一部分行情或产生一些假信号。
-
假信号:在市场没有明确趋势或处于震荡状态时,布林带策略可能会产生一些假信号,导致频繁交易和亏损。特别是在价格波动较大的市场中,布林带的上下轨线可能被频繁突破,但并不一定代表真实的买入或卖出机会。
-
参数选择:布林带策略的性能很大程度上取决于所选择的参数设置,包括计算移动平均线和标准差的窗口大小等。选择不恰当的参数可能导致信号太频繁或太稀少,从而影响策略的有效性。
-
单一指标:布林带策略仅仅依赖于移动平均线和标准差的计算,缺乏其他技术指标的辅助,可能无法全面反映市场的复杂变化。
布林带策略具有趋势判断、买入与卖出信号、风险控制和灵活性的优点,但也存在延迟性、假信号、参数选择和单一指标等缺点。
在实际应用中,可以结合其他技术指标和策略进行综合分析和决策。
完整代码及在线回测
https://byquant.com/bylab?s=bbands
培训支持
谢谢参与!
ByQuant量化策略培训系列课程