本文将对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. 「每周论文推荐」 初入深度学习CV领域必读的几篇文章
  2. 面试题-两个数值交换
  3. 人脸识别大规模爆发!
  4. 使用socket创建服务器进程和客户端进程
  5. DCMTK:测试DICOM RT类的读写方法
  6. anaconda安装成功测试_学习笔记120—Win10 成功安装Anaconda 【亲测有效,需注意几点!!!】...
  7. wordpress主题的样式修改
  8. 所有的 iPhone 都已经被破解了!
  9. 【C++leetcode】寻找给定字符串的最大回文子串
  10. 解决mescroll固定位置上拉加载无效果?真的只需一步
  11. 清代徽州家政与乡族社会的善治
  12. 移动跨平台框架ReactNative活动指示器组件【11】
  13. 苹果iPA游戏软件资源下载网站
  14. 冥想5分钟等于熟睡一小时
  15. 手把手教你下载在线地图?!再也不用下了
  16. 扫地机器人返充原理_全自动智能扫地机器人的工作原理分析
  17. centos7 开机提示:ENTERING EMERGENCY MODE. EXIT THE SHELL TO CONTINUE.
  18. 离散数学-3 命题逻辑的推理理论
  19. 雨听 | 英语学习笔记(九)~作文范文:父母应该送孩子出国留学吗?
  20. 微软2013暑假实习生笔试题解析

热门文章

  1. hdu 1166 敌兵布阵(单点更新)
  2. Vue 进阶系列丨自定义指令实现按钮权限功能
  3. A*和MPC实现水下机器人(ROV)避障(MATLAB)
  4. 常见的国产电子元器件厂家
  5. php excel文件在线预览(走过的坑)
  6. Cassandra教程(4)---- 节点间交互(gossip)
  7. Mac内录音频(微信语音导出的一种方式)
  8. 使用IDM实现批量下载Sentinel-2影像(Python)
  9. CDH6.0.1高可用
  10. html中table标签及属性