您的位置:首页 > 编程语言 > Python开发

Python量化交易学习笔记(18)——放量突破布林线中轨买入策略

2020-03-31 07:22 676 查看

本文将探索新的策略回测程序,主要是为了尝试不同的技术指标在backtrader平台上的应用,为后续复杂策略的实现做准备。

本文将实现的策略是,当股票放量突破布林线中轨时进行买入,当股票收盘价低于短期均线时卖出。

买入条件中,放量突破布林线中轨具体指的是,当日股票开盘价在布林线中轨下方,收盘价在布林线中轨上方,当日成交量为10日以来的最高量。卖出条件中,短期均线选取为5日线。回测初始资金100000元,单笔操作单位1000股,佣金千分之一,回测时间自2018年1月1日至2020年3月20日。

策略核心代码还是位于策略类的init方法中:

def __init__(self):
self.inds = dict()
for i, d in enumerate(self.datas):
self.inds[d] = dict()
# 布林线中轨
boll_mid = bt.ind.BBands(d.close).mid
# 买入条件
self.inds[d]['buy_con'] = bt.And( \
# 突破中轨
d.open < boll_mid, d.close > boll_mid, \
# 放量
d.volume == bt.ind.Highest(d.volume, period = self.p.p_period_volume, plot = False))
# 卖出条件
self.inds[d]['sell_con'] = d.close < bt.ind.SMA(d.close, period = self.p.p_sell_ma)

这里需要注意的是,技术指标在backtrader里是lines对象,而非数值,所以在使用与或操作时,不能使用python自带的and和or操作符,而只能调用backtrader的And和Or函数。对技术指标做比较时可以使用大于号、小于号等符号,这是因为backtrader对这些符号进行了重写。

回测000001后的最终资产为101107.35元:

可以看到,该策略并非每笔交易都会盈利,但是盈利额度较大,亏损额度较小。由于我们选取的交易单位是1000股,而000001的股价只是10元左右,相当于我们只动用了不到20%的资金,因此总盈利额显得较小,如果提高交易手数,盈利总额也会随之提升。

同时回测000001、000002后的最终资产为100082.86元:


同时回测000001、000002、000004后的最终资产为100247.27元:

回测603999后的最终资产为98871.44元:

可以看到该策略也有总体亏损的情况,直觉上判断,该策略可能比较适合大盘股,对小盘股而言,放量的条件比较容易达到,策略缺乏稳定性。

我们进一步尝试将放量突破的标准选为20日以来的最高值时,回测000001的最终资产为100613.27元,可以看到3笔盈利交易,1笔亏损交易。

当我们把回测起始时间改为2008年1月1日后,回测0000001的最终资产为103137.30元,可以看到也存在大量的亏损交易,但是亏损值都较小。

友情提示:本系列学习笔记只做数据分析,记录个人学习过程,不作为交易依据,盈亏自负。

放量突破布林线中轨买入策略代码:

from __future__ import (absolute_import, division, print_function, unicode_literals)
import datetime  # 用于datetime对象操作
import os.path  # 用于管理路径
import sys  # 用于在argvTo[0]中找到脚本名称
import backtrader as bt # 引入backtrader框架
import pandas as pd

stk_num = 1  # 回测股票数目
# 创建策略
class BollStrategy(bt.Strategy):
# 可配置策略参数
params = dict(
p_period_volume = 10,   # 前n日最大交易量
p_sell_ma = 5,          # 跌破该均线卖出
p_oneplot = False,      # 是否打印到同一张图
pstake = 1000,          # 单笔交易股票数
)
def __init__(self):
self.inds = dict()
for i, d in enumerate(self.datas):
self.inds[d] = dict()
# 布林线中轨
boll_mid = bt.ind.BBands(d.close).mid
# 买入条件
self.inds[d]['buy_con'] = bt.And( \
# 突破中轨
d.open < boll_mid, d.close > boll_mid, \
# 放量
d.volume == bt.ind.Highest(d.volume, period = self.p.p_period_volume, plot = False))
# 卖出条件
self.inds[d]['sell_con'] = d.close < bt.ind.SMA(d.close, period = self.p.p_sell_ma)
# 跳过第一只股票data,第一只股票data作为主图数据
if i > 0:
if self.p.p_oneplot:
d.plotinfo.plotmaster = self.datas[0]
def next(self):
for i, d in enumerate(self.datas):
dt, dn = self.datetime.date(), d._name           # 获取时间及股票代码
pos = self.getposition(d).size
if not pos:                                      # 不在场内,则可以买入
if self.inds[d]['buy_con']:                # 如果金叉
self.buy(data = d, size = self.p.pstake) # 买买买
elif self.inds[d]['sell_con']:                  # 在场内,且死叉
self.close(data = d)                         # 卖卖卖

def notify_trade(self, trade):
dt = self.data.datetime.date()
if trade.isclosed:
print('{} {} Closed: PnL Gross {}, Net {}'.format(
dt, trade.data._name, round(trade.pnl, 2), round(trade.pnlcomm, 2)
))
cerebro = bt.Cerebro()  # 创建cerebro
# 读入股票代码
stk_code_file = '../TQDat/data/tq_stock_code.csv'
stk_pools = pd.read_csv(stk_code_file, encoding = 'gbk')
if stk_num > stk_pools.shape[0]:
print('股票数目不能大于%d' % stk_pools.shape[0])
exit()
for i in range(stk_num):
stk_code = stk_pools['code'][stk_pools.index[i]]
stk_code = '%06d' % stk_code
# 读入数据
datapath = '../TQDat/day/stk/' + stk_code + '.csv'
# 创建价格数据
data = bt.feeds.GenericCSVData(
dataname = datapath,
fromdate = datetime.datetime(2018, 1, 1),
todate = datetime.datetime(2020, 3, 31),
nullvalue = 0.0,
dtformat = ('%Y-%m-%d'),
datetime = 0,
open = 1,
high = 2,
low = 3,
close = 4,
volume = 5,
openinterest = -1
)
# 在Cerebro中添加股票数据
cerebro.adddata(data, name = stk_code)
# 设置启动资金
cerebro.broker.setcash(100000.0)
# 设置佣金为千分之一
cerebro.broker.setcommission(commission=0.001)
cerebro.addstrategy(BollStrategy, p_oneplot = False)  # 添加策略
cerebro.run()  # 遍历所有数据
# 打印最后结果
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.plot()  # 绘图
  • 点赞
  • 收藏
  • 分享
  • 文章举报
码农甲V 发布了23 篇原创文章 · 获赞 1 · 访问量 783 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: