def get_boll(security, start_date=None, end_date=None, time_count=10):
hs_data=get_price(security,start_date=start_date,end_date=end_date,frequency='daily',fields=None,skip_paused=False,fq='pre')
stock_data = get_price(securirty, end_date= end_date, frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(hs_data['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=2,nbdevdn=2,matype=0)
stock_data = pd.DataFrame({'upper': upper, 'middle': middle, 'lower': lower}, index= stock_data.index)
stock_data = stock_data.dropna()
stock_data['close'] = hs_data['close']
return stock_data
def show_boll(stock_data):
plt.figure(figsize=(20, 5))
plt.grid()
plt.plot(stock_data['upper'], '-', color='r')
plt.plot(stock_data['lower'], '-', color='r')
plt.plot(stock_data['middle'], '-.', color='b')
plt.show()
布林线指标,即BOLL指标,其英文全称是“Bollinger Bands”,布林线(BOLL)由约翰·布林先生创造,其利用统计原理,一般而言,股价的运动总是围绕某一价值中枢(如均线、成本线等)在一定的范围内变动,布林线指标正是在上述条件的基础上,引进了“股价信道”的概念,其认为股价信道的宽窄随着股价波动幅度的大小而变化,而且股价信道又具有变异性,它会随着股价的变化而自动调整,求出股价的标准差及其信赖区间,从而确定股价的波动范围及未来走势,利用波带显示股价的安全高低价位。
根据统计学中的标准差原理设计,股价的波动利用标准差方式来表达,配合均线做为中位线,从而变成了偏离情况的写照。
(1)、计算MA
MA=N日内的收盘价之和÷N
(2)、计算标准差MD
MD=平方根N日的(C-MA)的两次方之和除以N
(3)、计算MB、UP、DN线、K倍
MB=(N-1)日的MA
UP=MB K×MD
DN=MB-K×MD
"""导入常用模块"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import talib
from jqdata import *
from jqlib.technical_analysis import *
from environment import * # 导入大树工作室开发的回测模块
import seaborn as sns
sns.set(font='serif')
securirty = '000300.XSHG'
Boll_data = []
HS_data = []
trade_date = get_trade_days(start_date= '2018-9-01', end_date= '2019-03-01')
time_count=20
HS_data = get_price(security='000300.XSHG',
start_date='2018-9-01',
end_date='2019-03-01',
frequency='daily',
fields=None,
skip_paused=False,
fq='pre')
stock_data = get_price(securirty, end_date= '2019-03-01' , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_data['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=2,nbdevdn=2,matype=0)
stock_data = pd.DataFrame({'upper': upper, 'middle': middle, 'lower': lower}, index= stock_data.index)
stock_data = stock_data.dropna()
stock_data['close'] = HS_data['close']
plt.figure(figsize=(20, 5))
plt.grid()
plt.plot(stock_data['close'], '-', color='g')
plt.plot(stock_data['upper'], '-', color='r')
plt.plot(stock_data['lower'], '-', color='r')
plt.plot(stock_data['middle'], '-.', color='b')
plt.title('沪深300指数与Boll通道图')
plt.legend(['指数价格', 'Boll上轨', 'Boll中轨', 'Boll下轨'], loc=2)
plt.show()
上图展示沪深300指数与其Boll通道表现,图例的通道以及价格走势,明显可知,这是一种类价值回归,也与波动性有一定挂钩。对期货不陌生的投资者应该最为了解,因为在CTA部分策略中,最常使用这类的指标。综上所述,我们本次内容,就深入了解Boll指标,做进行布林带探索的[稀饭?哥伦布魏]!
Boll指标用法可谓五花八门,因为三线合一,不同的搭配有不同的口味,而且三线又可各自组合,使得使用起来更加多变。仔细思考,向上突破下轨,向上突破上轨,站于中轨,二次站于中轨等等,只要不脱轨,就很不错了。
本次研究的脉络为:
[稀饭?哥伦布魏]以简单方式带大家分享Boll。择时交易,方式非常容易理解,就是对Boll参数进行筛选,筛选的参数有三类,中轨均线参数,上下轨标准差倍数。
展示常规情况下的中轨配置以及上下轨标准差2倍数,本次的稀饭会比较多清汤,但是会加点肉,因为最近猪瘟还是蛮严重的,所以严选最差猪肉!
"""初始化以下内容"""
context = Context() # 账户对象
order = Order(context) # 下单对象
trade = Trade(context, order) # 回测对旬
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = 20
n = 2
m = 2
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
"""执行策略"""
trade.trade(handle)
从正常角度看,整个数据表现得不是很理想,猪肉的质量有点差,猪毛(回撤:0.4754)占面积略大,而且猪肉可食用部位(策略收益:-0.4332)也比较少。咱们还是用多参数来下锅吧。
trade_list = []
Boll_list = [10, 15, 20, 25, 30, 35, 40, 45, 50]
for _Boll in Boll_list:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = _Boll
n = 2
m = 2
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_ratio_compare('Boll', Boll_list, trade_list, 3, 3)
虽然是猪肉,但是还是有好位置的,现在数据表出参数10,整个参数中唯一一个整收益的,还是蛮吃惊的,怎么会出现这样情况呢?因为Boll是类于波动率,进出场都和波动息息相关,只有波动和股价恰到好处,才是最合适的刷单或是价差空间,可谓一物降一物的感觉。
中轨参数已经得到相对于其他数据比较优秀的参数,接着就是上下轨的设置,烤猪肉要木叉子,基本两根为主,能够固定方向,把控肉质。吃个稀饭,还烤肉,也是不容易啊。
_list = []
trade_list = []
Boll_list = [10, 15, 20, 25, 30, 35, 40, 45, 50]
Boll_list_n = [0.5, 1, 1.5, 2]
for _Boll in Boll_list:
for n_Boll in Boll_list_n:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
_list.append(str(_Boll) ',' str(n_Boll))
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = _Boll
n = n_Boll
m = 2
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_all_ratio('Boll', Boll_list, trade_list)
数据表给予的信息蛮有非巧合性的,最优的Boll参数依旧为10。最优上轨标准差倍数为0.5,该参数的各项数据对比的排名基本为首位,但是回撤问题一直围绕着,得思考思考,就要考虑下轨问题。不过还是让[稀饭?哥伦布魏]有点尴尬而不失礼节的买了该配置的叉子。
_list = []
trade_list = []
Boll_list = [10, 15, 20, 25, 30, 35, 40, 45, 50]
Boll_list_m = [0.5, 1, 1.5, 2]
for _Boll in Boll_list:
for m_Boll in Boll_list_m:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
_list.append(str(_Boll) ',' str(m_Boll))
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = _Boll
n = 2
m = m_Boll
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_all_ratio('Boll', Boll_list, trade_list)
[稀饭?哥伦布魏]尴尬一笑,依旧是如此的场景,单一参数,策略正收益,最优下轨参数为2,差评地方为回撤貌似加大许多。
上节内容,应该明白发生什么事情,猪肉还是要好好买好好烤。这节内容,会比较严肃介绍。因为是风险厌恶择优的分析,以个人的风险厌恶程度来分析,做比较。
_list = []
trade_list = []
Boll_list = [10, 15, 20, 25, 30, 35, 40, 45, 50]
Boll_list_n = [0.5, 1, 1.5, 2]
Boll_list_m = [0.5, 1, 1.5, 2]
for _Boll in Boll_list:
for m_Boll in Boll_list_m:
for n_Boll in Boll_list_n:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
_list.append(str(_Boll) ',' str([n_Boll,m_Boll]))
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = _Boll
n = n_Boll
m = m_Boll
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_all_ratio('Boll', Boll_list, trade_list)
排头数据列表给予的信息比较明确,最优Boll参数为10,最优上轨标准差倍数为0.5,最优下轨标准差倍数为[0.5, 2],为何上轨标准差倍数是单个,而最优下轨标准差倍数是两个。从看收益来解释,正常的投资,是想保稳定收益,出场可以说是最简单也是最难的,因为心态和欲望控制、风险厌恶程度,因此上轨选择最稳定,而且小空间上轨等于中轨,有点价值回归的味道。下轨为何会两个,这就关系到风险程度以及市场情绪变化、质变,下轨0.5与2是四倍的关系,从回撤角度,2的回撤几乎快是0.5的一倍,胜率提高了0.1,但是收益下降了一倍多,这就是进场风险选择的关键,总所周知,对于股价,每个人都希望走得稳定,但是却不能如愿,一旦股价走向极端,恰恰是引起质变效果,市场的情绪变化导致我们的心理变化,一波冲击波的情绪量瞬间扩大动能,然而使股价回归的另一波动能却不一定能使得股价回归,因为承接力以及大盘环境因素、股价自身情况。Boll的运用,可以从多方面去切入,既然是中位线与价格的标准差,可以尝试使用标准差为重心去思考,如何使得中位线与偏离程度能更合适搭配我们的策略,配合量能去做搭配。总的一句话:波动之间最稳定的是平稳,而且不能急躁,慢工出细活。
Boll是以波动率和价值回归为基础,数据告诉我们,谨慎是最安全的,以敏感的Boll参数10配合稳定小空间上下轨标准差倍数参数0.5,实际运用中,参数0.5的运用可能受限,但是可以在更小的周期里面运用。
市场的变化,是情绪得变化,多重变化,会引起质变,极端市场的行情,在Boll中是一种机会,但是也是一种风险,因为股票的性质会市场对待的情绪改变了。
"""初始化以下内容"""
context = Context() # 账户对象
order = Order(context) # 下单对象
trade = Trade(context, order) # 回测对旬
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
time_count = 10
n = 0.5
m = 0.5
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= 50)
stock_data = get_price(stock, end_date= context.current_dt , frequency= 'daily', fields= 'close', skip_paused= True, fq= 'pre', count= (len(HS_da['close']) time_count-1))
upper, middle, lower = talib.BBANDS(stock_data['close'].values, timeperiod=time_count,nbdevup=n,nbdevdn=m,matype=0)
if lower[-2] > HS_da['close'][-2] and lower[-1] < HS_da['close'][-1]:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif lower[-1] > HS_da['close'][-1] or upper[-1] < HS_da['close'][-1]:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
"""执行策略"""
trade.trade(handle)
!
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...