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

文章目录

  • 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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis系列:01 数据类型及操作

redis的数据类型有哪些 string,list,set,sorted_set,hash 操作 sting: set name maliao get name exists name expire name 5 ttl name del name setex name 10 maliao 设置key和过期时间 setnx name maliao 当key不存在时才添加list: lpush letter a lpush le…

二极管选型怎么选?常用参数要熟练~

同学们大家好,今天我们继续学习杨欣的《电子设计从零开始》,这本书从基本原理出发,知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例,可以说是全面系统地介绍了电子设计所需的知识…

【LeetCode】206. 反转链表(简单)——代码随想录算法训练营Day01

题目链接:206. 反转链表 题目描述 206. 反转链表 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2: 输入&#xff1…

公司寄快递教程

公司寄快递用哪个更划算?这个问题有最优解吗?恐怕没有......很简单,回答这个问题之前,我们先来看看公司寄快递的背景。 一、大背景 所谓的大背景是由国内快递行业的发展现状所决定的。众所周知,这十年来,国…

Centos安装Datax

Centos7安装DataX 一、DataX简介二、DataX的数据源支持三、安装DataX1、下载DataX2、解压3、检验是否安装成功4、使用 四、实践案例1、环境信息2、编写同步的配置文件(user_info.json)3、执行同步4、验证同步结果 一、DataX简介 DataX 是阿里云 DataWorks数据集成 的开源版本&a…

Minitab的单因子方差分析的结果

单因子方差分析概述 当有一个类别因子和一个连续响应并且想要确定两个或多个组的总体均值是否存在差异时,可使用 单因子方差分析。如果经检验,发现至少有一组存在差异,请使用单因子方差分析中的比较对话框来标识存在显著差异的组对。 例如&…

C++ 之LeetCode刷题记录(九)

😄😊😆😃😄😊😆😃 开始cpp刷题之旅,多学多练,尽力而为。 先易后难,先刷简单的。 58. 最后一个单词的长度 给你一个字符串 s,由若干…

代码随想录第第五十七天—回文子串,最长回文子序列

leetcode 647. 回文子串 题目链接:回文子串 版本一:动态规划 dp数组及下标的含义 dp[i][j]:区间范围[i, j] (左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。确定递推公式…

Notepad++安装步骤

Notepad是一款文本编辑工具,支持27种编程语言,通吃C,C ,Java ,C#, XML, HTML, PHP,JS 等,该软件拥有完整的中文化接口及支持多国语言编写的功能,不仅可以用来制作一般的纯文字说明文件,还非常适合编写计算机程序代码&a…

大数据StarRocks(五) :数据类型

StarRocks 支持数据类型:数值类型、字符串类型、日期类型、半结构化类型、其他类型。您在建表时可以指定以下类型的列,向表中导入该类型的数据并查询数据。 5.1 数值类型 SMALLINT2 字节有符号整数,范围 [-32768, 32767] INT4 字节有符号整…

leetcode 动态规划(爬楼梯、零钱兑换、完全平方数)

70. 爬楼梯&#xff08;进阶版&#xff09; 卡码网&#xff1a;57. 爬楼梯(opens new window) 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;给定 n 是一个正…

RedisTemplate使用zadd报错java.lang.StackOverflowError

代码当中使用RedisTemplate操作String、List都是正常的&#xff0c;但是操作zadd就会报错&#xff0c;有人说是这两个依赖的版本不一致的问题&#xff0c;但是项目中还有其他地方要用到&#xff0c;所以改版本号行不通&#xff0c; <dependency><groupId>org.redis…

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、搭建本地本地时间…

SpringSecurity入门demo(一)集成与默认认证

一、集成与默认认证&#xff1a; 1、说明&#xff1a;在引入 Spring Security 项目之后&#xff0c;没有进行任何相关的配置或编码的情况下&#xff0c;Spring Security 有一个默认的运行状态&#xff0c;要求在经过 HTTP 基本认证后才能访问对应的 URL 资源&#xff0c;其默认…

对于软件测试的认识和了解

对软件测试的认识&#xff1a; 软件测试要求开发人员避免测试自己开发的程序。从心理学角度讲&#xff0c;这是很有道理的。特别是一个相对复杂的系统&#xff0c;开发人员在刚刚开发完成的时候&#xff0c;尚沉浸于对自己设计的回味之中。此时去测试的话往往会侧重于程序本身的…

啥,凭什么Python中函数的返回值可以有多个?

你好&#xff0c;我是安然无虞。 文章目录 函数函数定义格式函数调用默认参数和变长参数默认参数变长参数 变量的作用域 函数 编程语言中的函数&#xff0c;是一段可以被重复使用的代码片段&#xff0c;使用函数能够减少冗余的代码。 函数定义格式 def 函数名(形参列表):函数…

JavaScript高级程序设计读书记录(十二):函数

函数是ECMAScript中最有意思的部分之一&#xff0c;这主要是因为函数实际上是对象。每个函数都是Function 类型的实例&#xff0c;而 Function 也有属性和方法&#xff0c;跟其他引用类型一样。因为函数是对象&#xff0c;所以函数名就是 指向函数对象的指针&#xff0c;而且不…

Python 解决安装三方包失败的问题

pip 安装三方包失败&#xff0c;常见的情况有三种&#xff1a;不能访问源所在服务器&#xff1b;Python 版本不支持&#xff1b;和本地版本冲突。 不能访问源服务器 对于这张问题&#xff0c;有两种解决方法 # 方法一 pip config set global.index-url <源服务器> pip…

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

文章目录 一、为什么使用文件&#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.…

多无人机集群智能flocking

matlab2020可运行 GitHub - pareshbhambhani/MultiAgent-Flocking-framework: This is part of the current research I am working on.