《BackTrader量化交易图解》第10章:Trade 交易操作

news2024/11/16 13:35:56

文章目录

  • 10 Trade 交易操作
    • 10.1 量化回测分析流程
    • 10.2 Cerebro 类模块
    • 10.3 案例:Trade 交易
    • 10.4 实盘交易机器隐性规则
    • 10.5 Stake 交易数额和 Trade 交易执行价格

10 Trade 交易操作

10.1 量化回测分析流程

从本章开始讲解 BackTrader 的实盘操作。前面的章节讲过,一个完整的量化回测分析/交易流程可以分为四个步骤:

  1. 设置一个回测主函数;
  2. 设置量化回测参数;
  3. 调用量化回测程序,开始 run 运行量化回测分析;
  4. 回测数据分析,或者根据回测推荐结果进行交易。

其中第二步的量化回测参数的设置相对比较复杂,包括设置数据源、起始资金、回测数据、读取数据、添加数据,以及进行数据清洗等于处理工作。然后,添加策略和与策略相关的变量参数、策略分析参数。

第三步的调用量化回测程序和第一步的设置回测主函数类似,都很简单,通常都只有一行代码。

所有的量化策略在进行回测数据分析时, 最重要的指标就是ROI投资回报率。 在实盘操作查看收益图时, 大家最关心的也是ROI投资回报率。ROI指标重点在于检验策略模型的盈利性, 如果ROI投资回报率为负数, 或者低于市场的平均水平, 那么该策略模型后续就不要再使用了, 说明其稳定性和盈利性非常差。

10.2 Cerebro 类模块

cerebro在西班牙语中是“大脑”的意思, 所以变量cerebro是BackTrader量化分析程序的全局主变量, 表示量化引擎源自BackTrader
的Cerebro模块库。Cerebro类的关系属性图如下:

btr_cerebro

10.3 案例:Trade 交易

本实例代码 :Cerebro.py 。

本案例的主流程部分代码如下:

print("\n#1,设置 BT 量化回测程序入口")
cerebro = bt.Cerebro()  # create a "Cerebro" engine instance

print("\n#2,设置BT回测初始参数及策略")
print("\n\t#2-1,设置BT回测初始参数:起始资金等")
dmoney0 = 100000.0
cerebro.broker.setcash(dmoney0)
dcash0 = cerebro.broker.startingcash

print("\n\t#2-2,设置数据文件,需要按时间字段正序排序")
rs0 = os.path.abspath(os.path.dirname(__file__)) + "/../data/"
filename = "002046.SZ.csv"
fdat = rs0 + filename
print("\t@数据文件名:", fdat)

print("\t 设置数据BT回测运算:起始时间、结束时间")
print("\t 数据文件,可以是股票期货、外汇黄金、数字货币等交易数据")
print("\t 格式为:标准OHLC格式,可以是日线、分时数据")

t0stx, t9stx = datetime(2020, 1, 1), datetime(2021, 12, 31)
data = bt.feeds.YahooFinanceCSVData(dataname=fdat, fromdate=t0stx, todate=t9stx)

cerebro.adddata(data)  # Add the data feed

print("\n\t#2-3,添加BT量化回测程序,对应的策略参数")
print("\n\t# 案例当中,使用的是MA均线策略")
cerebro.addstrategy(MyStrategy)

print("\n\t#2-4,添加broker经纪人佣金,默认为:千一")
cerebro.broker.setcommission(commission=0.001)

print("\n\t#2-5,设置每手交易数目为:10,不再使用默认值:1手")
cerebro.addsizer(bt.sizers.FixedSize, stake=10)

print("\n\t#2-6,设置addanalyzer分析参数")
cerebro.addanalyzer(SQN)
#
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="SharpeRatio", legacyannual=True)
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name="AnnualReturn")
#
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="TradeAnalyzer")
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="DW")
#
# 周期回报率,不同时间周期
cerebro.addanalyzer(
    bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years, _name="timReturns"
)
# cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Months,_name='timReturns')
#
# 动态加权回报率 Variability-Weighted Return: Better SharpeRatio with Log Returns
cerebro.addanalyzer(bt.analyzers.VWR, _name="VWR")


print("\n#3,调用BT回测入口程序,开始执行run量化回测运算")
results = cerebro.run()

print("\n#4,完成BT量化回测运算")
dval9 = cerebro.broker.getvalue()
dget = dval9 - dcash0
kret = (dval9 - dcash0) / dcash0 * 100

print("\t 起始资金Starting Portfolio Value:%.2f" % dcash0)
print("\t 资产总值Final Portfolio Value:%.2f" % dval9)
print("\t 利润总额:  %.2f," % dget)
print("\t ROI投资回报率Return on investment: %.2f %%" % kret)

# ---------
print("\n#5,analyzer分析BT量化回测数据")
strat = results[0]
anzs = strat.analyzers
#
dsharp = anzs.SharpeRatio.get_analysis()["sharperatio"]
#
dw = anzs.DW.get_analysis()
max_drowdown_len = dw["max"]["len"]
max_drowdown = dw["max"]["drawdown"]
max_drowdown_money = dw["max"]["moneydown"]
#
print("\t5-1夏普指数SharpeRatio : ", dsharp)
print("\t最大回撤周期 max_drowdown_len : ", max_drowdown_len)
print("\t最大回撤 max_drowdown : ", max_drowdown)
print("\t最大回撤(资金)max_drowdown_money : ", max_drowdown_money)
#
print("\t#5-2,常用量化分析数据")
print("\tSQN指数、AnnualReturn年化收益率,Trade交易分析报告")
print("\t可以通过修改参数,改为其他时间周期:周、月、季度等")
for alyzer in strat.analyzers:
    alyzer.print()
# ----------
print("\n#6,绘制BT量化分析图形")
cerebro.plot(style="candle")

案例输出中有收盘价,还有买卖执行等信息:

2021-08-17, 当前收盘价Close, 9.72
2021-08-18, 买单执行BUY EXECUTED,成交价: 9.57,小计 Cost: 95.70,佣金 Comm 0.10
2021-08-18, 当前收盘价Close, 10.02
2021-08-19, 卖单执行SELL EXECUTED,成交价: 10.08,小计 Cost: 95.70,佣金 Comm 0.10
2021-08-19, 交易操盘利润OPERATION PROFIT, 毛利GROSS 5.10, 净利NET 4.90

本案例是一个完整的量化分析流程, 使用了一个完整的量化交易策略——MA均线策略。
第一步设置一个回测主函数, 代码如下:

print("\n#1,设置 BT 量化回测程序入口")
cerebro = bt.Cerebro()  # create a "Cerebro" engine instance

第二步设置参数, 包括数据源、 起始资金的设置, 然后读取数据、添加数据, 代码如下:

print("\n#2,设置BT回测初始参数及策略")
print("\n\t#2-1,设置BT回测初始参数:起始资金等")
dmoney0 = 100000.0
cerebro.broker.setcash(dmoney0)
dcash0 = cerebro.broker.startingcash

print("\n\t#2-2,设置数据文件,需要按时间字段正序排序")
rs0 = os.path.abspath(os.path.dirname(__file__)) + "/../data/"
filename = "002046.SZ.csv"
fdat = rs0 + filename
print("\t@数据文件名:", fdat)

print("\t 设置数据BT回测运算:起始时间、结束时间")
print("\t 数据文件,可以是股票期货、外汇黄金、数字货币等交易数据")
print("\t 格式为:标准OHLC格式,可以是日线、分时数据")

t0stx, t9stx = datetime(2020, 1, 1), datetime(2021, 12, 31)
data = bt.feeds.YahooFinanceCSVData(dataname=fdat, fromdate=t0stx, todate=t9stx)

cerebro.adddata(data)  # Add the data feed

在设置完量化分析数据源等基础数据后, 添加策略和与策略相关的变量参数。

MyStrategy 类是量化回测策略,需要完成 nextnotify_ordernotify_tradestop 等函数。使用如下代码设置策略:

print("\n\t#2-3,添加BT量化回测程序,对应的策略参数")
print("\n\t# 案例当中,使用的是MA均线策略")
cerebro.addstrategy(MyStrategy)

在设置完量化回测策略后, 还需要设置交易佣金参数, 默认费用为千分之一, 交易数额默认是1手, 但本书案例中的交易数额设置为10手:

print("\n\t#2-4,添加broker经纪人佣金,默认为:千一")
cerebro.broker.setcommission(commission=0.001)

print("\n\t#2-5,设置每手交易数目为:10,不再使用默认值:1手")
cerebro.addsizer(bt.sizers.FixedSize, stake=10)

然后设置常用的分析参数, 如SQN指数、 Sharp指数、 回报率、MaxDown、 交易数据等, 代码如下:

print("\n\t#2-6,设置addanalyzer分析参数")
cerebro.addanalyzer(SQN)
#
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="SharpeRatio", legacyannual=True)
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name="AnnualReturn")
#
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="TradeAnalyzer")
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="DW")
#
# 周期回报率,不同时间周期
cerebro.addanalyzer(
    bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years, _name="timReturns"
)
# cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Months,_name='timReturns')
#
# 动态加权回报率 Variability-Weighted Return: Better SharpeRatio with Log Returns
cerebro.addanalyzer(bt.analyzers.VWR, _name="VWR")

然后调用回测程序,开始运行回测分析:

print("\n#3,调用BT回测入口程序,开始执行run量化回测运算")
results = cerebro.run()

运行完成后,进行回测结果分析,包括回执量化分析表。

10.4 实盘交易机器隐性规则

大家对于BackTrader的使用属于准实盘交易阶段, 准实盘交易和实盘交易最主要的差别在于以下两个方面:

  • 数据源的实时更新。
  • 操作资金的实际投入

如果做实盘交易, 必须使用每天的最新数据。

BackTrader 在原生版本中对股票池的支持有限。为了提升对股票池的回测能力,可以在BackTrader的基础上增加一个外部循环来遍历整个股票池。实盘操作中,一些资金雄厚的金融团队采用全市场模式,即将市场中所有可交易的股票作为股票池。此模式没有预设的股票池限制,所有交易股票都作为输入数据。进一步地,可以在全市场模式基础上进行二次筛选,类似于单因子分析,比如与前几天的收益进行比较。

在量化交易实盘操作中,还存在一些隐性规则需要注意:

  1. 策略测试与参数优化:使用的交易策略应经过充分测试并优化参数。例如,尽管MA均线策略可能默认设定为15天周期,但这并不意味着它是最优的选择。实际操作中需对这些参数进行调整以寻找最佳方案。

  2. 缩短回测周期:为了提高回测分析的速度和效率,可以考虑缩短回测周期。这有助于更快地评估策略的有效性和适应性。

  3. 注意仓位检查:在实施策略时,应持续关注仓位(Position)的变化。仓位管理是量化交易中的关键部分,需要精确控制以避免潜在的风险。

这些考虑因素有助于提高量化交易策略的实际应用效率和成功率。

Position 子模块关系属性示意图如下:

btr_pos

主要相关的子模块库有LineBuffer、 Order、Sizer、 Trade等。使用BackTrader的position类函数还可以看到买入时的价格,随时根据平均仓位成本进行操作。

下面再看看案例策略源码, position函数主要用于next函数:

def next(self):
        # 检查当前股票的仓位position
        if not self.position:
            #
            # 如果该股票仓位为0 ,可以进行BUY买入操作,
            ......
        else:
            # 如果该股票仓位>0 ,可以进行SELL卖出操作,
           ......

在使用BackTrader进行量化交易时,执行买卖操作前需先确认持仓状态(Position)。这样做确保了只在持有股票时才能进行卖出操作,从而提高回测效率。策略逻辑主要在next()函数执行,而数据源和指标参数在init()中设置。

BackTrader默认不支持空头交易,用户必须拥有股票才能卖出。Position函数用于检查持仓状态,确保在持有股票时才执行卖单操作,而买单则无此限制。用户可以灵活设置Position,如设定持仓量或资金阈值以控制卖出,或依据现金比例购买股票。这种灵活性使BackTrader适应多样化的交易策略和风险管理需求。

10.5 Stake 交易数额和 Trade 交易执行价格

每次的交易数额都可以通过参数进行设置。在主流程中, 可以设置每次交易是10手:

print("\n\t#2-5,设置每手交易数目为:10,不再使用默认值:1手")
cerebro.addsizer(bt.sizers.FixedSize, stake=10)

使用固定交易数额的方法在操作上更加直接和简便。对于初学者来说,在设置持仓(Position)和交易数量(Stake)时,推荐采用简单的设置方法,避免过于复杂的操作。

接下来考虑交易执行价格的设置。BackTrader在设定买卖单时,默认会根据当天的收盘价来确定交易价格。市场上的交易价格一旦达到这个设定值,系统就会执行买卖操作。值得注意的是,这个价格并非固定不变,而是有一定的浮动范围,这个范围也是可以设定的。

所有买卖操作都由系统在后台自动完成。用户只需设置交易指令,一旦买入和卖出的价格达到一致,订单就会自动进入交易队列。订单的成交遵循“先到先得”的原则。买单和卖单操作比较复杂, BackTrader采用了一个独立的子模块BuySell来进行操作, 如图11-7所示是BuySell子模块关系属性示意图如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在订单执行时, 系统会输出成交价格、 佣金数额等信息。再看看案例输出信息, 以及图表的买卖点图标信息:

2021-09-29, 设置买单 BUY CREATE, 12.50, name : 002046.SZ
2021-09-30, 买单执行BUY EXECUTED,成交价: 11.84,小计 Cost: 118.40,佣金 Comm 0.12

Analyzer2

代码仓库链接:CPythoner/BackTraderDemo at develop (github.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1377722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编译和链接(1)

目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段: 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3 #define 替换规则 3.2.4 #和## 1. 程序的翻译环境和执…

【昕宝爸爸小模块】深入浅出之Java 8中的 Stream

深入浅出之Java 8中的 Stream 一、🟢典型解析1.1 🟠Java 8中的Stream 都能做什么1.2 🟠Stream的创建 二、✅ Stream中间操作2.1 🟠Filter2.2 🟠Map2.3 🟠limit / skip2.4 🟠sorted2.5 &#x1…

基于LVGL编写的windows串口工具: LCOM

LCOM: Serial Port Tools based on LVGL (PC Software) 一直以来我都想用LVGL做一个真正意义上的PC软件,来验证或者表达LVGL出色的特性,现在我用LCOM做到了! LCOM 是一个基于LVGL编写的串口工具,界面简洁,功能出色&a…

构建基于RHEL8系列(CentOS8,AlmaLinux8,RockyLinux8等)的Nginx1.24.0的RPM包

本文适用:rhel8系列,或同类系统(CentOS8,AlmaLinux8,RockyLinux8等) 文档形成时期:2022-2023年 因系统版本不同,构建部署应略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人…

二十四、同域名下JSESSIONID重叠导致退出

同域名下JSESSIONID重叠导致退出 近期在开发项目的时候发现,如果同域名的情况下,如果把一个单页面无登录系统嵌套进入另外一个系统,那么会出现相互退出的问题。 思考解决方案 一、清除掉嵌套的系统的JSESSIONID,意思就是嵌套系统不设置JSESSIONID 1找寻出问题接口 在无痕…

DHCP与时间同步

目录 一、DHCP 1、DHCP定义 1.什么是DHCP 2.DHCP的好处 3.DHCP的分配方式 4.为什么使用DHCP 5.DHCP模式 2、DHCP的工作过程 3、DHCP动态配置主机地址 1.DHCP服务的优点 2.可分配的地址信息 3.动态分配IP地址 二、时间同步 1、ntp 2、chrony 1、搭建本地本地时间…

011集:复制文件(包括exe、 jpg、png、Word、Excel和PPT等二进制文件)—python基础入门实例

在文本文件的内部以字符形式存储数据,字符是有编码的,例如GBK (简体中文) 、UTF-8等;在二进制文件的内部以字节形式存储数据、没有编码的概念。二进制文件较为常用,例如Windows中的exe、图片 (jpg、png等),以及Word、Excel和PPT等…

多语言生成式语言模型用于零样本跨语言事件论证提取(ACL2023)

1、写作动机: 经过预训练的生成式语言模型更好地捕捉实体之间的结构和依赖关系,因为模板提供了额外的声明性信息。先前工作中模板的设计是依赖于语言的,这使得很难将其扩展到零样本跨语言转移设置。 2、主要贡献: 作者提出了一…

d2l动手学深度学习】 Lesson 13 Dropout层 老板随机丢掉一些做项目的程序员‍,项目的效果会更好!(bushi)

文章目录 1. 什么是Dropout老板随机丢掉一些做项目的程序员🧑‍💻,项目的效果会更好! 2. 代码实现(不用torch)3. 代码实现(使用torch)3. 调节实验3.1 老师上课所设置的dropout1, dro…

探索 hasOwnProperty:处理对象属性的关键(下)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

问界又“翻车”了? 新能源电池“怕冷”成短板

文 | AUTO芯球 作者 | 李欣 2023年12月17日,蔚来创始人李斌亲自下场!驾驶ET7从上海出发,经过超14小时的行驶后,达成一块电池行驶超过1000公里的成绩,这一直播引起外界的广泛关注。 这不禁让人与”懂车帝冬测“联想到…

Vue3 的基本开发+新特性

Vue3 1.Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {data(){return {count:0}},methods:{addCount(){this.count}} } </script> <script setup> import { ref } from vue const count ref(0) const addCount ()> count.val…

文件操作(你真的会读写文件吗?)

文章目录 一、为什么使用文件&#xff1f;二、什么是文件&#xff1f;2.1 程序文件2.2 数据文件2.3 文件名 三、二进制文件和文本文件3.1 二进制文件3.2 文本文件 四、文件的打开和关闭4.1 流和标准流4.1.1 流4.1.2 标准流 4.2 文件指针4.3 fopen和fclose 五、文件的顺序读写5.…

代码随想录刷题第四十八天| 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III

代码随想录刷题第四十八天 今天是打家劫舍三部曲&#xff0c;最后一题树形dp有点难&#xff0c;其他还好 打家劫舍 (LC 198) 题目思路&#xff1a; 代码实现&#xff1a; class Solution:def rob(self, nums: List[int]) -> int:dp [0 for _ in range(len(nums)1)]dp[1…

Open3D 截取感兴趣的点云部分

import time import open3d as o3d; import numpy as np; import matplotlib.pyplot as plt from scipy.signal import find_peaks#坐标 mesh_coord_frame o3d.geometry.TriangleMesh.create_coordinate_frame(size355, origin[0, 0, 0]) #mesh_coord_frame mesh_coord_frame…

机器学习_实战框架

文章目录 介绍机器学习的实战框架1.定义问题2.收集数据和预处理(1).收集数据(2).数据可视化(3).数据清洗(4).特征工程(5).构建特征集和标签集(6).拆分训练集、验证集和测试集。 3.选择算法并建立模型4.训练模型5.模型的评估和优化 介绍机器学习的实战框架 一个机器学习项目从开…

UVa1308/LA2572 Viva Confetti

题目链接 本题是2002年ICPC亚洲区域赛金沢(日本)赛区的H题 题意 我已经把n个圆盘依次放到了桌面上。现按照放置顺序依次给出各个圆盘的圆心位置和半径&#xff0c;问最后有多少圆盘可见&#xff1f;如下图所示。 分析 《训练指南》的题解&#xff1a; 题目说“保证在对输入数据…

87.乐理基础-记号篇-反复记号(一)反复、跳房子

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;86.乐理基础-记号篇-速度记号-CSDN博客 首先是反复记号表总结图&#xff1a; 当前是写前两个记号&#xff0c;其余记号后面写&#xff1a;这些反复记号最主要的目的很简单&#xff0c;还是为了节约纸张&#xff0c…

使用Linux安装Mysql Community Server 8.0.35

一、下载Mysql 官网&#xff1a;https://www.mysql.com/ 第一步&#xff1a;进入Linux官网&#xff0c;点击下载 第二步&#xff1a;点击MySQL Community (GPL) Downloads 第三步&#xff1a;进入页面&#xff0c;选择 MySQL Community Server 第四步&#xff1a;根据自己服务…

SpringBoot集成RabbitMq,RabbitMq消费与生产,消费失败重发机制,发送签收确认机制

RabbitMq消费与生产&#xff0c;消费失败重发机制&#xff0c;发送确认机制&#xff0c;消息发送结果回执 1. RabbitMq集成spring bootRabbitMq集成依赖RabbitMq配置RabbitMq生产者&#xff0c;队列&#xff0c;交换通道配置&#xff0c;消费者示例 2. RabbitMq消息确认机制消息…