分享

pybroker:兼容传统规则和机器学习的高性能量化回测框架(附源码)

 AI量化实验室 2023-10-12 发布于北京

原创文章第226篇,专注“个人成长与财富自由、世界运作的逻辑与投资"。

打算再造一次轮子——写一个自研的AI回测平台

这里不叫框架,叫平台,希望是结果导向,能够写出可用,可迭代的策略

传统的框架已经很多,python生态里就有很多,pyalgotrade, backtrader, vectorBt, qlib等等。

感觉都没有特别合适。

backtrader是传统的回测框架,网上资料比较多,代码很难懂。适合传统规则型的量化回测,因子个数很有限。vectorBt主打速度和向量化,事件驱动做不了,代码也一般。qlib是机器学习导向的平台,传统规则型量化不友好,需要先整理数据集等等。

我想要一种轻量型的引擎,兼容传统规则与机器模型,速度要快,可以搜索参数空间。

目前看,pybroker比较合适,看起来还非常年轻,但理念与我很相近,而且上述几个点,基本都有,代码也比较容易读懂。

pybroker的官方文档:

https://www./en/latest/index.html

github的源码地址:

https://github.com/edtechre/pybroker

目前看还是比较活跃的。

从源代码上看,不到15个文件:

安装比较简单,直接pip即可:pip install -U lib-pybroker

但要特别注意,要求python版本在3.9以上文档示例使用YFinance雅虎财经,国内访问不了。

好在实现自己的DataSource比较容易。

我自己实现了一个csv的数据加载器:

1、继承pybroker的DataSource

2、实现一个私有函数:_fetch_data,返回一个时间范围内的datafame。

包括字段:open, high, low, close, volume,symbol即可。

也就是说,它内部的数据结构也是基于numpy, dataframe以及使用numba的njit加速(与vectorBT的理念类似)。

import pandas as pd
import pybroker
from pybroker.data import DataSource


class CSVDataSource(DataSource):

def __init__(self):
super().__init__()

def _fetch_data(self, symbols, start_date, end_date, _timeframe):
dfs = []
for s in symbols:
df = pd.read_csv('data/{}.csv'.format(s), dtype={'date':str})
dfs.append(df)
df = pd.concat(dfs)
df['date'] = pd.to_datetime(df['date'])
df.sort_values(by='date', ascending=True, inplace=True)
return df[(df['date'] >= start_date) & (df['date'] <= end_date)]


pybrokder吸引我的一点,就是它天然使用机器学习来做量化,但又兼容传统规则型的量化。或者说,pybroker本身就是为了使用机器学习来提升投资绩效的!

你也话会问,那为何为用qlib。

说实话,qlib当初我花了不少时间,qlib的代码写得也很好,微软出品,也有质量保证。但几个点,一是qlib框架为了建quant生态,尽管是松耦合,但还是需要使用它自己的数据存储。另外过于强调模型本身,在回测上花的心思相对少。我甚至把qlib的表达式引擎拆出来单独使用。

它的数据缓存机制很好。

大家知道,做量化回测时,我们可能经常要调整一些东西,那所有数据都要跑一轮。如果能够cache,那会非常方便。这一点上,pybroker是花了心思的。(这里对比起来,qlib做得不好,qlib一看就出自机器学习研究员之手,只关心做模型,不太关心实战以及落地的事情)。

加一行代码:

import pybroker

pybroker.enable_data_source_cache('yfinance'),数据缓存在本地的sqlite数据库中(我之前设想过本地mongo或者hdf5,若只是缓存dataframe,sqlite倒不失为一种选择)。

这个机制有一个好处,就是首次使用时,从服务器加载数据,而不需要预先把数据加载到本地(这样会涉及一个更新的问题,另外就是分发包会很大)。

数据与回测过程,包括模型都会自动cache。

环境初始化很容易:

这里开启strategy的cache,设置初始资金为50万,然后给Strategy传入Datasource,日期范围与config配置项。

重点来了:

pybroker的策略是与symbol关联的。比如buy_low这个函数,作用于“AAPL”和“MSFT”。

而另一个函数short_high作用于“TSLA”:

对比一下Backtrader:

回测规则主体在next函数里,就是说,如果有多个标的,或者说多标的执行的逻辑不一致,那么,这里需要会出现多种交易逻辑,比如self.data1怎么处理,self.data2如何如何,从这个角度,pybroker这种挺好。


我换成自己写的CSVDataSource,然后使用A股指数的数据,做了最简单的buy_and_hold的测试,无比丝滑:

如果已持仓就返回,未持仓则全仓买入。

它的metrics_df没有计算年化收益,夏普比之类的,我使用empyrical自己计算了,未来整合pyfolio或者quantstats都很方便。

所有代码与数据均已经发布到星球中。

明天继续pybroker,做一些策略。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多