本文将对backtrader的仓位管理进行介绍,具体以同时回测交易3只股票为例,查看每日仓位情况。

策略

  • 买入条件:5日线金叉60日线

  • 卖出条件:5日线死叉60日线

示例

仓位信息输出的核心代码位于策略类的next的方法中:

    def next(self):for i, d in enumerate(self.datas):dt, dn = self.datetime.date(), d._name           # 获取时间及股票代码pos = self.getposition(d)if not len(pos):                                 # 不在场内,则可以买入if self.inds[d]['cross'] > 0:                # 如果金叉self.buy(data = d, size = self.p.pstake) # 买买买elif self.inds[d]['cross'] < 0:                  # 在场内,且死叉self.close(data = d)                         # 卖卖卖# 打印仓位信息print('**************************************************************', file = self.log_file)print(self.data.datetime.date(), file = self.log_file)for i, d in enumerate(self.datas):pos = self.getposition(d)if len(pos):print('{}, 持仓:{}, 成本价:{}, 当前价:{}, 盈亏:{:.2f}'.format(d._name, pos.size, pos.price, pos.adjbase, pos.size * (pos.adjbase - pos.price)),file = self.log_file)

部分输出结果为:

...
*************************************************************************************************
2019-06-24
000001, 持仓:100, 成本价:13.69, 当前价:13.69, 盈亏:0.00
*************************************************************************************************
2019-06-25
000001, 持仓:100, 成本价:13.69, 当前价:13.43, 盈亏:-26.00
*************************************************************************************************
2019-06-26
000001, 持仓:100, 成本价:13.69, 当前价:13.37, 盈亏:-32.00
*************************************************************************************************
2019-06-27
000001, 持仓:100, 成本价:13.69, 当前价:13.71, 盈亏:2.00
*************************************************************************************************
2019-06-28
000001, 持仓:100, 成本价:13.69, 当前价:13.78, 盈亏:9.00
*************************************************************************************************
2019-07-01
000001, 持仓:100, 成本价:13.69, 当前价:13.93, 盈亏:24.00
*************************************************************************************************
2019-07-02
000001, 持仓:100, 成本价:13.69, 当前价:14.18, 盈亏:49.00
*************************************************************************************************
2019-07-03
000001, 持仓:100, 成本价:13.69, 当前价:14.01, 盈亏:32.00
*************************************************************************************************
2019-07-04
000001, 持仓:100, 成本价:13.69, 当前价:13.99, 盈亏:30.00
*************************************************************************************************
2019-07-05
000001, 持仓:100, 成本价:13.69, 当前价:13.92, 盈亏:23.00
000002, 持仓:100, 成本价:29.45, 当前价:29.45, 盈亏:0.00
*************************************************************************************************
2019-07-08
000001, 持仓:100, 成本价:13.69, 当前价:13.59, 盈亏:-10.00
000002, 持仓:100, 成本价:29.45, 当前价:29.15, 盈亏:-30.00
...

输出图形为:

解析

上面的代码用到了多只股票同时进行策略回测,具体内容可以参见笔记(17)。

在backtrader中,使用类Position来管理仓位。Position的重要属性包括:

  • price:资产成本单价

  • size:仓位大小

  • adjbase:资产当前收盘价格

几点说明:

  • 在类Strategy中,可以使用属性position或者方法getposition(self, data=None, broker=None)来访问仓位信息。

  • 当使用getposition(self, data=None, broker=None)方法时,如果不指定参数data值,该方法会默认返回datas[0]的仓位信息,若指定参数data,则返回对应资产的仓位信息,如示例所示。

        for i, d in enumerate(self.datas):pos = self.getposition(d)
  • 仓位信息positions实际保存在代理broker中,positions是一个Python的字典,key是一个种子数据Data Feed,value是一个类Position的对象。也就是说,positions[datas[0]]就表示第一只股票datas[0]对应的仓位信息,positions[datas[1]]就表示第二只股票datas[1]对应的仓位信息,依次类推。

  • 类Position重写了__len__方法,可以使用len(position)来判断仓位大小是否为0。

  • 类Position重写了__str__方法,可以通过print(position)来打印仓位的具体信息。

仓位信息示例代码:

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 pdstk_num = 3  # 回测股票数目
# 创建策略
class SmaCross(bt.Strategy):# 可配置策略参数params = dict(pfast=5,  # 短期均线周期pslow=60,   # 长期均线周期poneplot = False,  # 是否打印到同一张图pstake = 100 # 单笔交易股票数目)def __init__(self):self.log_file = open('position_log.txt', 'w') # 用于输出仓位信息self.inds = dict()for i, d in enumerate(self.datas):self.inds[d] = dict()self.inds[d]['sma1'] = bt.ind.SMA(d.close, period=self.p.pfast)  # 短期均线self.inds[d]['sma2'] = bt.ind.SMA(d.close, period=self.p.pslow)  # 长期均线self.inds[d]['cross'] = bt.ind.CrossOver(self.inds[d]['sma1'], self.inds[d]['sma2'], plot = False)  # 交叉信号# 跳过第一只股票data,第一只股票data作为主图数据if i > 0:if self.p.poneplot: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)if not len(pos):                                 # 不在场内,则可以买入if self.inds[d]['cross'] > 0:                # 如果金叉self.buy(data = d, size = self.p.pstake) # 买买买elif self.inds[d]['cross'] < 0:                  # 在场内,且死叉self.close(data = d)                         # 卖卖卖# 打印仓位信息print('*****************************************************************************', file = self.log_file)print(self.data.datetime.date(), file = self.log_file)for i, d in enumerate(self.datas):pos = self.getposition(d)if len(pos):print('{}, 持仓:{}, 成本价:{}, 当前价:{}, 盈亏:{:.2f}'.format(d._name, pos.size, pos.price, pos.adjbase, pos.size * (pos.adjbase - pos.price)),file = self.log_file)def stop(self):self.log_file.close()passcerebro = bt.Cerebro()  # 创建cerebro# 读入股票代码
stk_code_file = '../TQDat/TQDown2020v1/data/tq_wrk_code2019.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(2019, 1, 1),todate = datetime.datetime(2019, 12, 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.00)
cerebro.addstrategy(SmaCross, poneplot = False)  # 添加策略
cerebro.run()  # 遍历所有数据
# 打印最后结果
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.plot(style = "candlestick")  # 绘图

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

Python量化交易学习笔记(33)——backtrader仓位管理相关推荐

  1. Python量化交易学习笔记(1)

    Python量化交易学习笔记(1) http://zwpython.com/ http://www.topquant.vip/?p=2275 [更多参见] <zwPython,目前最好的py开发 ...

  2. Python量化交易学习笔记(36)——backtrader多股回测避坑3

    本文继续记录多股回测时可能遇到的异常情况. 坑描述 多股回测时,当日期达到所有股票的技术指标都能够计算出有效值后,backtrader才开始进行回测.由于这种逻辑的存在,如果某些股票在回测周期的最后几 ...

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

    本文将探索新的策略回测程序,主要是为了尝试不同的技术指标在backtrader平台上的应用,为后续复杂策略的实现做准备. 本文将实现的策略是,当股票放量突破布林线中轨时进行买入,当股票收盘价低于短期均 ...

  4. Python量化交易学习笔记(2)——A股数据下载

    由于笔者只接触过A股交易,因此本系列笔记仅针对A股交易展开.笔者的计算机为Windows 10 64位操作系统. TOP极宽量化总群(124134140)群文件中提供了大量的学习资料,一眼看去有点懵圈 ...

  5. Python量化交易学习笔记(46)——通达信日线数据获取

    序 从2020年初开始接触量化,马上就要满一年了.在这一年里,想过去做量化,想过去做机器学习,想过去做少儿编程教育.就这样大概折腾了小半年时间,最后在CSDN上看到这样一句话:"你把时间投在 ...

  6. Python量化交易学习笔记(19)——连续下跌买入止盈止损卖出策略

    好友提出要验证连续下跌买入止盈止损卖出策略,本文对该策略回测和实现做分析记录. 买入条件中,连续下跌定义为收盘价连续4日低于前1日的收盘价.卖出条件中,止盈率设置为10%,止损率设置为5%.回测初始资 ...

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

    本文主要记录保护点卖出策略,给买入的股票设立保护点,随着股票收盘价的提升,保护点不断提高,股价一旦跌破保护点,即卖出股票. 示例的买入条件为,5日线金叉60日线,且股价进行小幅回踩(较金叉日收盘价下跌 ...

  8. Python量化交易学习笔记(21)——A股股票列表更新

    在zwPython2020中,股票数据下载更新时,所读取的股票列表文件的目录位置为"zwPython\TQDat\TQDown2020v1\data\tq_wrk_code.csv" ...

  9. Python量化交易学习笔记(25)——Data Feeds扩展

    背景:需要扩展data feeds的场景 在backtrader中,data feeds中包含了被普遍认为是业界标准的几个字段: datetime open high low close volume ...

最新文章

  1. 四本关于意识问题的英文新书
  2. flask 继承模版的基本使用1
  3. WinCE 5.0 WIFI 无线网卡的配置和建立连接(转)
  4. 顶会ICML 2021杰出论文奖空降!
  5. Activiti 用户任务并行动态多实例(多用户执行流程)
  6. java 静态初始化数据_Java 静态数据初始化的示例代码
  7. 路直路弯,面对挫折脚步不放慢
  8. C#设计模式(20)——策略者模式(Stragety Pattern)
  9. [转]Bash的输入输出重定向
  10. 计算机学院特色迎新标语,开学迎新口号
  11. telnet不起作用
  12. java基于springboot+vue学生考勤签到请假管理系统84y43
  13. 行政区域村级划分数据库_最新行政区划省市区街道乡镇数据库 每月更新版
  14. 【java】web在线打开PDF文件
  15. gsm在linux下工作原理,GSM模块详解 从工作原理到应用案例
  16. inkscape裁剪
  17. 开发第一步之SMTP协议发送邮件,获取手机的详细信息
  18. 自然底数e究竟“自然”在哪?
  19. Python数据分析入门书籍推荐!!!强烈推荐,新手必看
  20. Unity(如何把方形图片整成圆形)

热门文章

  1. iOS UIButton按钮图片在上文字在下
  2. itunes禁止自动启动服务器,解决itunes提示“无法验证服务器init.itunes.apple.com”的方法...
  3. 【毕设课设】【毕设课设】JAVA web健身房管理系统(源码+文档+数据库)
  4. ubuntu如何调整界面大小
  5. Docker在私有库中拉取镜像时报错:ERROR: The image for the service you‘re trying to recreate has been removed. If y
  6. Android ios颜色背景渐变实现
  7. python簇状柱形图_python学习之路--可视化利器matplotlib(上)
  8. 介绍一款HCIA、HCIP、HCIE的刷题软件
  9. iOS开发之获取实时海拔高度
  10. UNIXC002 网络基础