【PA交易】BackTrader(一): 如何使用实时tick数据和蜡烛图
背景和需求
整合Tick数据是PA交易的回测与实盘基本需求。多数交易回测框架往往缺乏对大规模Tick数据直接而全面的支持。Tick数据因其体量庞大(例如,某棕榈油主力合约四年间的数据达8GB)为结合价格趋势与PA分析带来挑战,凸显了实时动态数据源的重要性。实时数据不仅能应对数据规模问题,还能减少因数据时序差异引发的回测或实盘错误,确保分析准确性。
这里提及的8GB棕榈油合约Tick数据已转存MySQL数据库格式,并在文末以笔者整理后的SQL导出文件形式提供下载,数据仅供研究与测试,勿用作商业用途。
概述
在探索Backtrader时,我注意到将其与Tick数据集成至回测流程颇为简便,故撰写系列笔记以记录并分享这一过程。本笔记基于当前版本Backtrader编写。未来或许有更优框架或Backtrader自身改进Tick数据处理方式,目前而言,本系列文章提供的Tick数据与K线结合的免费解决方案,是非常易于上手的免费选择之一。
本系列《BackTrader如何使用实时tick数据和蜡烛图》预计将分成上中下三篇:
- 上篇:本文,较水,对背景和DataFeed做出介绍,同时介绍tick数据如何读取到回测策略流程中。完整读完后可以做到将tick数据加入到BackTrader策略中。
- 中篇:待完成,主要介绍如何将tick结合KBar同时读取到回测策略流程中。
- 下篇:待完成,主要介绍跨周期回测,可看做Multiple Timeframes结合tick的实操记录。
《BackTrader如何使用实时tick数据和蜡烛图》系列小文,属于PA交易和量化交易文集。PA交易和量化交易文集将会主要专注于低频Python实现。对于一些高频部分目前暂不涉及。鉴于高频本身对于网络和硬件要求较高,多数朋友(包括笔者)可能都没有交易所托管或者购买高性能计算的计划,并且目前笔者也没有转向高频C++的计划和需求。
PS:题外话:笔者十多年艹C艹经验都懒得用C艹。
笔者交易市场主要为国内商品期货市场,个人平时主要做农产品基本面分析,后续计划考虑进行对包括油厂、美农、拉尼娜等各类数据进行一些因子挖掘工作。个人精力有限,有相关爱好的朋友有缘可以寻找合作机会。
BackTrader
之所以选择BackTrade主要原因有以下几点:
- 相比于pyAlgoTrade:目前Gabriel Becedillas大神已经全面转到 basana 开发,不再更新pyAlgoTrade。巴萨那主要专注于加密币,担心代码中一些跟币圈相关的词汇会迷惑。
- 相比于vnpy:VeighNa封装过多,缺乏灵活性。使用其集成平台那就会失去灵活性,图省事的话不如使用其他一些集成平台了。另外,记得林园大佬说过一句话,一家公司发生减持,管他什么原因呢,不买就是了。同理,vnpy.cn还是vnpy.com分不清就都不用了吧。
本文适合已经至少完成了BackTrade的Quickstart Guide - Backtrader有需求的朋友阅读,如果还对BackTrader一窍不通,可以花上15分钟简单阅读以下官方的文档,并实操一下,简单单步调试一下源码。
DataFeed
BackTrader的数据源主要由Data Feeds - Backtrader模块进行处理, 其中大量使用了元编程技巧。底层实现中元类(metaclasses)。DataFeed底层主要核心数据通过LineBuffer进行封装。LineBuffer数据由LineRoot持有,自LineRoot以下的继承关系如下图所示:
其中代码逻辑比较简单的是PandasData,我们可以把它看做一个自定义DataFeed的示例,根据这个类的实现自己定制数据源。
Lines
DataFeed中数据是通过LineBuffer和策略模块进行共享,在上层OHLC中定义了7个标准的数据LineBuffer:
class OHLC(DataSeries):lines = ('close', 'low', 'high', 'open', 'volume', 'openinterest',)class OHLCDateTime(OHLC):lines = (('datetime'),)
因为类hierarchy的限制,我们拓展DataFeed需要从AbstractDataBase或者DataBase层面进行集成,否则将会面临大量底层逻辑代码的重复实现。如上类图所见,包括PandasData在内的绝大多数BackTrader内置数据源类型都是继承于DataBase。
下面我们首先基于class PandasData(feed.DataBase)实现一个基础的tick数据加入到策略运行过程的示例,之后使用动态tick数据。这个实现实现非常简单,并不需要太多高深的编程技能。
测试CSV
为简化测试开发流程, 便于说明理解,使用我上传的CSV文件DCE.m2501.tick.202402,大小2M,比较适合框架开发过程的测试:https://download.csdn.net/download/u012677852/89460596?spm=1001.2014.3001.5503https://download.csdn.net/download/u012677852/89460596?spm=1001.2014.3001.5503
这个文件是笔者采集的实盘豆粕合约数据,因为不是主力合约,数据量较小适合测试开发使用。
对于如何验证网络实盘tick数据,可以参考我的文章:【PA交易】前端根据内盘商品期货Tick数据合并日线Bar-CSDN博客
下文及后文如有需要,一律直接使用该文件名,不再特殊说明。
静态读入tick数据
如前所述,为了能够支持策略运行过程中使用tick数据源,首先定义一个数据类继承自bt.feed.DataBase。因为我们此步骤仅仅使用静态数据进行调通,所以类定义如下:
class MyDataFeedStatic(bt.feed.DataBase):
因为我们是tick数据,其中的数据字段是类继承结构上层OHLC中没有定义的Line,所以我们需要使用一个tuple声明他们:
lines = (('price', 'vol', 'amount', 'ccl', 'bid', 'bidVol', 'ask', 'askVol'))
之后为了简便起见,直接将测试CSV读取的DF保存在类中,并且指定一个_idx表示当前读取到的DF的行索引, 如下所示:
class MyDataFeedStatic(bt.feed.DataBase):lines = (('price', 'vol', 'amount', 'ccl', 'bid', 'bidVol', 'ask', 'askVol'))def __init__(self, df):super(MyDataFeedStatic, self).__init__()self.df = dfself._idx = 0
之后需要重载_load方法, 该方法由AbstractDataBase的load方法调用, 具体相关调用逻辑可以参考BackTrader源码。我们这里简单的逐行使用读取DF数据的方式实现这个方法:
def _load(self):if self._idx >= len(self.df):# exhausted all rowsreturn Falsefor datafield in self.getlinealiases():if datafield == 'tickdt':continueif datafield in TICK_DATA_COLUMNS:line = getattr(self.lines, datafield)line[0] = self.df[datafield].iloc[self._idx]# print(f'load {datafield} success')# -------------------------------------------# 添加日期时间tstamp = self.df['tickdt'].iloc[self._idx]self.lines.datetime[0] = date2num(tstamp)self._idx += 1return True
注意测试文件中的datatime使用的是tickdt作为列名,在BackTrader底层中会依赖datatime字段,这里因为数据中本来没有dataname字段,所以必须填充这个Line。
此时,一个简单的基于tick的数据源已经实现了,我们来使用它。首先装载过程,只需要预先读取一个DF,并传入即可:
df = pd.read_csv('./datas/DCE.m2501.tick.202402.csv')
df['tickdt'] = pd.to_datetime(df['tickdt'])
data_feed = sfeed.MyDataFeedStatic(df)
cerebro.adddata(data_feed)
之后在策略构造函数中,为了后续使用方便,可以给每条管线起一个别名:
class TestStrategy(bt.Strategy):def __init__(self):# Ticks 字段self.tickdt = self.datas[0].datetimeself.price = self.datas[0].priceself.vol = self.datas[0].closeself.amount = self.datas[0].amountself.ccl = self.datas[0].cclself.bid = self.datas[0].bidself.bidVol = self.datas[0].bidVolself.ask = self.datas[0].askself.askVol = self.datas[0].askVolself.local_tz = get_localzone()
之后在next方法中就可以访问到具体每个Tick的数据了:
def log(self, txt, dt=None):''' 本地化时间输出 '''utc_datetime = self.datetime if dt is None else dtdate = utc_datetime.date(0, tz=self.local_tz)time = utc_datetime.time(0, tz=self.local_tz)print('%s %s: %s' % (date, time, txt))def next(self):self.log('Tick price, %.2f' % self.price[0], self
输出:
2024-02-01 17:00:00.059001: Tick price, 3127.00
2024-02-01 17:00:00.558999: Tick price, 3126.00
2024-02-01 17:00:01.058996: Tick price, 3126.00
2024-02-01 17:00:01.557997: Tick price, 3126.00
.....
实时运行
当我们运行策略时,会发现策略的next方法并不是紧跟着数据源的_load方法运行。这是因为当前的策略运行不是实时模式。还需要在数据源类MyDataFeedStatic中Override一个方法:
class MyDataFeedStatic(...):def islive(self):return True
这样策略将以实时模式运行,_load()函数中打印日志可以看到每次load运行之后才会运行策略的next函数。
题外话
这里的DF读写仅仅是一个模拟数据逐条实时传入的方式。考虑到数据源的复杂性,作为分享,这是我所使用的基础架构:
架构中抽象出一个数据模块,这个模块负责全部的数据处理,无论数据来自于CSV、数据库还是CTP。而MyDataFeed实际充当了一个数据模块和策略运行之间的Bridge角色(adapter)。MyDataFeed会在_load函数中向数据模块索要数据,如果数据没有就绪,则会阻塞操作(可以在当前示例代码中添加sleep(0.5)模拟CTP)。这样无论回测还是实盘,在数据管理都实现了一致性,即:一个策略的书写可以兼容不同场景,当我们回测夏普优秀,SimNow模拟回报丰厚的时候,我们可以通过切换数据模块参数的方式将策略快速无缝切换到实盘。
继续阅读
下篇文章将会首先将本文中的简单读取DF改为一个模拟上述架构中的简单的数据读取器。之后实现Tick和K Bar同时传递到策略中。
更多测试数据:
如果需要更多测试数据,可以下载这里的tic数据文件,已经整理成MySQL表,这里是导出的SQL,后续会更新更多其他测试数据:
内盘期货棕榈, 主力1、5、9月合约2020年到2024年TICK数据:
链接:https://pan.baidu.com/s/1UTt9Ei0dSaQ971Iq-YPIGA?pwd=j7hq
提取码:j7hq
(仅限测试开发学习使用, 请勿商用)
相关文章:

【PA交易】BackTrader(一): 如何使用实时tick数据和蜡烛图
背景和需求 整合Tick数据是PA交易的回测与实盘基本需求。多数交易回测框架往往缺乏对大规模Tick数据直接而全面的支持。Tick数据因其体量庞大(例如,某棕榈油主力合约四年间的数据达8GB)为结合价格趋势与PA分析带来挑战,凸显了实时…...

HTML(16)——边距问题
清楚默认样式 很多标签都有默认的样式,往往我们不需要这些样式,就需要清楚默认样式 写法: 用通配符选择器,选择所有标签,清除所有内外边距选中所有的选择器清楚 *{ margin:0; padding:0; } 盒子模型——元素溢出 作…...

【Godot4自学手册】第四十二节实现拖拽进行物品交换和数量叠加
这一节我们主要学习背包系统中的物品拖拽后,物品放到新的位置,或交换物品位置,如果两个物品属于同一物品则数量相加。具体效果如下: 一、修改item.tscn场景 给item.tscn场景的根节点Item添加Label子节点,命名为Numv…...
存储系统概述
目录 层次结构 存储器的分类 存储器的编址和端模式 存储器端模式 存储器的技术指标 1. 存储容量 示例: 2. 访问速度 访问速度的表现形式: 示例: 3. 功耗 示例: 4. 可靠性 可靠性指标: 示例:…...

Trilium windows上修改笔记目录,创建多个笔记空间方法
一开始使用trilium会非常的不舒服,不像是obsidian可以创建多个笔记空间,指定多个笔记目录。这里摸索到了解决方案 修改目录的方法一 ——修改系统环境变量 打开控制面板-系统-高级系统设置 新增如上条目 修改目录的方法二——直接写bat脚本运行 新建位…...

<Rust><iced>在iced中显示gif动态图片的一种方法
前言 本文是在rust的GUI库iced中在窗口显示动态图片GIF格式图片的一种方法。 环境配置 系统:window 平台:visual studio code 语言:rust 库:iced、image 概述 在iced中,提供了image部件,从理论上说&…...

【Unity设计模式】状态编程模式
前言 最近在学习Unity游戏设计模式,看到两本比较适合入门的书,一本是unity官方的 《Level up your programming with game programming patterns》 ,另一本是 《游戏编程模式》 这两本书介绍了大部分会使用到的设计模式,因此很值得学习 本…...
圆的面积并三角形面积并
三角形面积并 #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int maxn 110; #define x first #define y second typedef pair<double, double> PDD; const d…...
Spring Data JPA介绍与CRUD实战演练
文章目录 一、Spring Data JPA 简介二、Spring Data JPA 与 MyBatis Plus 比较设计哲学和抽象层次SQL 控制学习曲线和技术要求性能与优化综合考虑 三、SpringDataJpa实战演练1. 创建user表2. 搭建Spring Boot开发环境3. pom.xml文件内容4. application.yml文件内容5. Applicati…...

Python网络爬虫实战6—下一页,模拟用户点击,切换窗口
【前期提要】感兴趣的可以看看往期文章哈~ Python网络爬虫5-实战网页爬取 Python网络爬虫4-实战爬取pdf Pyhon网络爬虫3-模拟用户点击 Python网络爬虫实战2-下载url下的pdf Python网络爬虫基础1 1.需求背景 针对长虹美菱电器说明书网页形式,编写爬虫代码ÿ…...

Notepad++插件 Hex-Edit
Nptepad有个Hex文件查看器,苦于每次打开文件需要手动开插件显示Hex,配置一下插件便可实现打开即调用 关联多个二进制文件,一打开就使用插件的方法,原来是使用空格分割!!!...

Matlab要这样批量读取txt数据!科研效率UpUp第10期
假如我们有多组txt格式的数据: 其数据格式是这样的: 想要批量读取这些数据,并把他们画在一张图上,该怎么操作呢? 之前有分享load函数的版本,本期进一步分享适用性更强的readtable函数的实现方法。 首…...

buuctf----firmware
- -一定不能再ubutu22进行,我是在18(血泪教训) binwalk安装 buuctf firmware(binwalk和firmware-mod-kit的使用)_buu firmware-CSDN博客 参考博客 指令 sudo apt-get update sudo apt-get install python3-dev python3-setuptools python3-pip zlib1g-dev libmagic-dev pi…...

ssl证书90天过期?保姆级教程——使用acme.sh实现证书的自动续期
腾讯云相关文档相关参考-有的点不准确 前言 最近https到期了,想着手动更新一下https证书,结果发现证书现在的有效期只有90天,于是想找到一个自动更新证书的工具,发现了acme.sh,但是网上的文章质量参差不齐࿰…...

由于bug造成truncate table卡住问题
客户反应truncate table卡主,检查awr发现多个truncate在awr报告期内一直没执行完,如下: 检查ash,truncate table表的等待事件都是“enq: RO - fast object reuse”和“local write wait” 查找“enq: RO - fast object reuse”&am…...

Charles抓包工具系列文章(二)-- Repeat 回放http请求
一、什么是http请求回放 当我们对客户端进行抓包,经常会想要重试http请求,或者改写原有部分进行重新请求,都需要用到回放http请求。 还有一种场景是压力测试,对一个请求进行重复请求多少次,并加上适当的并发度。 这里…...

jemeter基本使用
后端关验签,设置请求头编码和token 配置编码和token...

【Golang】Steam 创意工坊 Mod 文件夹批量重命名
本文将介绍一个使用Go语言编写的脚本,其主要功能是解析XML文件并基于解析结果重命名文件夹。这个脚本适用于需要对文件夹进行批量重命名,并且重命名规则依赖于XML文件内容的情况。 脚本功能概述 Steam创意工坊下载的Mod文件夹批量重命名为id名称 运行前…...
求职刷题力扣DAY33--贪心算法part04
DAY 33 贪心算法part04 1. 452. 用最少数量的箭引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可…...

aws的eks(k8s)ingress+elb部署实践
eks(k8s)版本1.29 ingress 版本1.10.0 负载均衡elb 1. 创建Ingress-Nginx服务 部署项目地址【点我跳转】推荐自定义部署 可绑定acm证书什么的自己属性 这里就是aws上面Certificate Manager产品上面创建证书 导入 创建都行 对应集群版本推荐阵列GitH…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...