失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Python量化交易学习笔记(20)——保护点卖出策略

Python量化交易学习笔记(20)——保护点卖出策略

时间:2021-12-11 11:08:07

相关推荐

Python量化交易学习笔记(20)——保护点卖出策略

本文主要记录保护点卖出策略,给买入的股票设立保护点,随着股票收盘价的提升,保护点不断提高,股价一旦跌破保护点,即卖出股票。

示例的买入条件为,5日线金叉60日线,且股价进行小幅回踩(较金叉日收盘价下跌1%)。卖出条件为,股价跌破保护点。保护点首先设置为买入当天收盘价减去一个资金回撤值(率),示例把回撤率设置为5%。后续如果股票的收盘价上升,则用新的收盘价更新保护点,如果股票的收盘价下跌,则保留原有保护点。回测初始资金100000元,单笔操作单位1000股,佣金千分之一,回测时间自1月1日至3月20日。

策略核心代码位于策略类的next方法中:

def next(self):# 无场内资产if not self.position:# 未提交买单if None == self.order:# 金叉到达了买点if self.buy_con:# 计算订单有效期时间,如果超过有效期,股价仍未回踩,则放弃下买入订单valid = self.data.datetime.date(0)if self.p.buy_valid_date:valid = valid + datetime.timedelta(days=self.p.buy_valid_date)# 计算回踩后的买入价格price = self.datas[0].close[0] * (1.0 - self.p.buy_limit_percent)print('Buy order created: {}: close: {} / limit price: {} / valid: {}'.format(self.datetime.date(), self.datas[0].close[0], price, valid) )# 用有效时间及回踩买点提交买入订单self.order = self.buy(exectype = bt.Order.Limit, price = price, valid = valid)#o = self.buy()print('*' * 50)elif self.order is None:# 提交stoptrail订单self.order = self.sell(exectype=self.p.stoptype,trailamount=self.p.trailamount,trailpercent=self.p.trailpercent)

在买入时,程序中使用了backtrader的Limit类型订单,在Limit订单创建时,会设置一个price及有效日期valid,如果到达日期valid后,股价还没有匹配上price,订单就会被取消。匹配price包括两种情况:

如果开盘价低于price,那么订单就会用开盘价被立即执行如果开盘价高于price,但是当日最低价低于price,那么订单将会以price的价格被执行

从Limit订单的描述可以看出,正好符合我们所说的股价回踩买入规则。

在卖出时,程序使用了backtrader的StopTrail订单,回撤可以用回撤值(trailamount)或者回撤率(trailpercent)来表示,这里我们选择用5%的回撤率来做回测。StopTrail将按下面的逻辑进行工作:

使用当日收盘价作为price值price按照回撤率回撤计算后的价格,被作为触发价格(trigger price),即我们所说的保护点。比如price=100,trailpercent=5%,那么trigger price=100*(1-5%)=95代理在下一根K线迭代计算时,会计算是否达到trigger price如果达到trigger price,卖单将被执行如果没有达到trigger price,那么trigger price将用当前的收盘价按照之前选定的回撤率进行重新计算如果股价上涨,那么trigger price将会被更新为新的trigger price如果估计不变或者下跌,那么trigger price不更新

从StopTrail订单的描述可以看出,保护点会随着股价的上升不断更新,不断提高,一旦股价跌破保护点,就会进行卖出,这样可以有效的保护我们的利润。同时可以看到,即使股价一直下跌,StopTrail订单也可以有效止损。

回测000001后的最终资产为10.97元。

回测000002后的最终资产为103236.59元。

回测603999后的最终资产为99510.06元。

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

保护点卖出策略代码:

# 创建策略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框架class St(bt.Strategy):params = dict(buy_limit_percent = 0.01,buy_valid_date = 5,stoptype=bt.Order.StopTrail,trailamount=0.0,trailpercent=0.05,p_high_period = 5,p_fast = 5,p_slow = 60,)def __init__(self):slowSMA = bt.ind.SMA(period = self.p.p_slow)self.buy_con = bt.And(bt.ind.CrossUp(bt.ind.SMA(period = self.p.p_fast), slowSMA),#slowSMA == bt.ind.Highest(slowSMA, period = self.p.p_high_period, plot = False))self.order = Nonedef notify_order(self, order):if order.status in [pleted]:print('Completed order: {}: Order ref: {} / Type {} / Status {} '.format(self.data.datetime.date(0),order.ref, 'Buy' * order.isbuy() or 'Sell',order.getstatusname()))self.order = Noneif order.status in [order.Expired]:self.order = Noneprint('{}: Order ref: {} / Type {} / Status {}'.format(self.data.datetime.date(0),order.ref, 'Buy' * order.isbuy() or 'Sell',order.getstatusname()))def next(self):# 无场内资产if not self.position:# 未提交买单if None == self.order:# 金叉到达了买点if self.buy_con:# 计算订单有效期时间,如果超过有效期,股价仍未回踩,则放弃下买入订单valid = self.data.datetime.date(0)if self.p.buy_valid_date:valid = valid + datetime.timedelta(days=self.p.buy_valid_date)# 计算回踩后的买入价格price = self.datas[0].close[0] * (1.0 - self.p.buy_limit_percent)print('Buy order created: {}: close: {} / limit price: {} / valid: {}'.format(self.datetime.date(), self.datas[0].close[0], price, valid) )# 用有效时间及回踩买点提交买入订单self.order = self.buy(exectype = bt.Order.Limit, price = price, valid = valid)#o = self.buy()print('*' * 50)elif self.order is None:# 提交stoptrail订单self.order = self.sell(exectype=self.p.stoptype,trailamount=self.p.trailamount,trailpercent=self.p.trailpercent)if self.p.trailamount:tcheck = self.data.close - self.p.trailamountelse:tcheck = self.data.close * (1.0 - self.p.trailpercent)print('Sell stoptrail order created: {}: \close: {} / \Limit price: {} / check price {}'.format(self.datetime.date(), self.data.close[0],self.order.created.price, tcheck))print('-' * 10)else:if self.p.trailamount:tcheck = self.data.close - self.p.trailamountelse:tcheck = self.data.close * (1.0 - self.p.trailpercent)print('update limit price: {}: \close: {} / \Limit price: {} / check price {}'.format(self.datetime.date(), self.data.close[0],self.order.created.price, tcheck))cerebro = bt.Cerebro() # 创建cerebro# 先找到脚本的位置,然后根据脚本与数据的相对路径关系找到数据位置# 这样脚本从任意地方被调用,都可以正确地访问到数据modpath = os.path.dirname(os.path.abspath(sys.argv[0]))datapath = os.path.join(modpath, '../TQDat/day/stk/603999.csv')# 创建价格数据data = bt.feeds.GenericCSVData(dataname = datapath,fromdate = datetime.datetime(, 1, 1),todate = datetime.datetime(, 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)# 设置启动资金cerebro.broker.setcash(100000.0)# 设置交易单位大小cerebro.addsizer(bt.sizers.FixedSize, stake = 1000)# 设置佣金为千分之一cerebro.broker.setcommission(commission=0.001)cerebro.addstrategy(St) # 添加策略cerebro.run() # 遍历所有数据# 打印最后结果print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())cerebro.plot(style = 'candlestick') # 绘图

为了便于相互交流学习,新建了微信群,感兴趣的读者请加微信。

如果觉得《Python量化交易学习笔记(20)——保护点卖出策略》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。