量化交易PyBroker

Py

本次课程主要是给大家介绍一个新晋的基于 Python 的量化投资框架 PyBroker,该框架主要目标是实现在量化投资中利用更好的利用机器学习技术来构建策略,当然其还支持传统的基于规则的策略设计。目前其作者正在积极开发中,相信该框架会成为众多基于 Python 的量化投资框架中占据一席之地。

本次课程会围绕以下部分内容给大家做一个介绍:

  1. 什么是量化投资框架
  2. PyBroker 是什么
  3. PyBroker 要解决的问题
  4. 为什么选择 PyBroker
  5. PyBroker 的安装及使用
  6. 定制数据源及查看回测结果
  7. 注意事项

什么是量化投资框架

量化投资框架(Quantitative Investment Framework)是一个系统化的方法,用于开发、测试和实施量化投资策略。这种框架通过结合数学模型、统计分析和计算机算法,旨在发现并利用市场中的定价错误和机会,从而实现稳定的投资回报。量化投资框架通常包括以下几个关键组件:

  1. 数据处理:框架需要处理大量的金融数据,如股票价格、交易量、公司财报等。数据处理包括数据的收集、清洗、存储和更新。
  2. 特征工程:基于金融数据创建特征,如技术指标(如移动平均、相对强弱指数等)、基本面指标(如市盈率、市净率等)和其他市场因素。这些特征将用于量化模型的训练和预测。
  3. 量化策略:根据对市场的观察和研究,制定投资策略。策略可以包括股票选择、资产配置、交易信号生成等。策略可以是基于规则的,也可以是基于机器学习的。
  4. 回测:使用历史数据验证策略的表现。回测需要注意过拟合问题,同时要考虑交易成本、滑点、流动性等实际约束。
  5. 优化和参数调整:根据回测结果优化策略,调整参数以提高策略的稳定性和收益表现。
  6. 风险管理:量化框架需要考虑风险管理,包括风险度量、止损策略、风险敞口控制等。
  7. 交易执行:将策略的交易信号转化为实际交易。交易执行需要考虑成本最优化、市场影响和最佳执行策略等因素。

量化投资框架可以帮助投资者系统地开发和部署量化策略,提高投资效率并降低人为因素带来的风险。在选择或构建量化投资框架时,投资者需要关注框架的灵活性、稳定性、易用性和扩展性。

PyBroker 是什么

关于 PyBroker 的介绍,我们还是来看其项目 GitHub 主页的介绍最为权威:Algorithmic Trading in Python with Machine Learning。其主要是在 Python 中利用机器学习方法来进行量化投资的框架,当然它也自带基于传统方法的量化投资策略回测。此处可以提一下,由微软开源的 Qlib 量化投资平台,后面有机会也会给大家介绍。

PyBroker 在 20230118 发布了其第一个版本,截至撰文时,已经发布了 29 个迭代版本,说明目前其作者正在积极开发和维护中。其目前的版本已经可以完成基本的策略设计和回测!

项目仓库地址:https://github.com/edtechre/pybroker

项目文档地址:https://www.pybroker.com/

PyBroker 要解决的问题

我们来看 PyBroker 想帮我们解决的问题:

Are you looking to enhance your trading strategies with the power of Python and machine learning? Then you need to check out PyBroker! This Python framework is designed for developing algorithmic trading strategies, with a focus on strategies that use machine learning. With PyBroker, you can easily create and fine-tune trading rules, build powerful models, and gain valuable insights into your strategy’s performance.

一句话总结就是想给利用机器学习技术赋能量化投资框架!

为什么选择 PyBroker

目前市面上量化投资框架众多,其中有开源的和闭源的,也有基于各种编程语言的。对大部分个人使用者而言,一个基于 Python 的开源量化投资框架一般是最佳选择。目前市面上使用较广的是 Backtrader,在 AKShare 的文档中也有相关的示例代码,但是由于目前以下几点原因:

  1. Backtrader 有较长的开源历史,里面的代码为了使用 Python 2/3 的兼容性,导致设计的时候较为复杂,不利于初学者学习其源码
  2. 其里面使用众多的元编程技术,导致学习其源码和调试比较不方便
  3. 虽然项目使用者较多,但是其开发及维护比较滞后

鉴于以上的原因,本次主要给大家介绍 PyBroker 这款刚开源的框架,目前其作者也正在积极开发中,目前个人总结的 PyBroker 的优点:

  1. 由于站在 Python 3.9 以后的时点,项目开发历史包袱小,开源采用 Python 新特性,且充分利用第三方库的优势,比如并行计算,numba 加速等
  2. 作者对项目的设计比较合理,能够兼容传统的策略和机器学习策略的设计及回测
  3. 相关的文档比较详细,很多问题都有提供相关的示例代码

PyBroker 的安装及使用

PyBroker 的环境配置

目前 PyBroker 的官网介绍,其支持 Python 3.9 及之后的版本,无论在 Windows,Linux 和 macOS 平台都支持,目前尚不支持 Python 3.11 版本。据测试,主要还是由于 numba 库目前尚未完全支持 Python 3.11,不过我们可以在 numba 库的 GitHub 中发现,其对应 Python 3.11 的版本即将发布。目前 Python 3.11 相较于之前的 Python 有大约 15% 以上的效率提升,还是建议大家升级体验。

当我们移除项目中 numba 加速部分的代码时,可以成功在 Python 3.11.3 最新正式版中顺利运行,但对于一般使用的小伙伴建议在 Python 3.10.x 最新版使用即可(开发尝鲜)

所以在此处推荐大家利用 conda 工具来创建特定的 Python 版本的虚拟环境,在顺利安装 miniconda/anaconda 的基础上,通过在 Anaconda Prompt 中输入:conda create -n env_pybroker python=3.10 来进行虚拟环境的创建。

在创建好指定 Python 版本的虚拟环境后,我们通过:conda activate env_pybroker 来激活并进入到创建好的虚拟环境中,通过 pip install lib-pybroker 来进行 PyBroker 的安装,这里请注意与我们常见的方式不同的是,我们是通过 lib-pybroker 这个库名字进行安装的!此处我们可以查看下已经安装的库:

Package            Version
------------------ ---------
aiohttp 3.8.1
aiosignal 1.3.1
alpaca-py 0.8.1
alpaca-trade-api 2.3.0
appdirs 1.4.4
async-timeout 4.0.2
attrs 23.1.0
beautifulsoup4 4.12.2
certifi 2022.12.7
cffi 1.15.1
charset-normalizer 2.1.1
cryptography 40.0.2
deprecation 2.1.0
diskcache 5.6.1
frozendict 2.3.7
frozenlist 1.3.3
html5lib 1.1
idna 3.4
joblib 1.2.0
lib-pybroker 1.1.6
llvmlite 0.39.1
lxml 4.9.2
msgpack 1.0.3
multidict 6.0.4
multitasking 0.0.11
numba 0.56.4
numpy 1.23.5
packaging 23.1
pandas 1.5.3
pip 23.0.1
progressbar2 4.2.0
pycparser 2.21
pydantic 1.10.7
python-dateutil 2.8.2
python-utils 3.5.2
pytz 2023.3
PyYAML 6.0
requests 2.28.2
setuptools 66.0.0
six 1.16.0
soupsieve 2.4.1
sseclient-py 1.7.2
typing_extensions 4.5.0
urllib3 1.26.15
webencodings 0.5.1
websocket-client 1.5.1
websockets 10.4
wheel 0.38.4
yarl 1.9.1
yfinance 0.2.18

我们发现其依赖的库还是挺多的,其中数据来源主要是 yfinance 和 alpaca,因为 alpaca 是需要注册且大量调取需要收费,所以建议在尝鲜阶段,推荐利用 PyBroker 库主要封装的 yfinance 来获取标的的数据。

PyBroker 的测试

目前 PyBroker 还在快速迭代开发中,在我们 import pybroker 后还不能通过 pybroker.__version__ 来查看其目前使用的版本。那我们可以通过其在 PyPI 的地址来查看:https://pypi.org/project/lib-pybroker/ 当前支持安装的最新版,且在本地通过 pip install lib-pybroker --upgrade 来升级到最新版。从目前来看我们只需要在相应的 conda 虚拟环境中通过

import pybroker

如果没有报错,我们可以当作目前的环境配置和 PyBroker 安装没有问题

PyBroker 的案例演示

当我们配置及测试好相应的开发环境后,可以通过 PyBroker 提供的示例代码来初步领略其使用逻辑,我们先来看其基于规则的策略(Rule-based Strategy),先来看其代码:

from pybroker import Strategy, YFinance, highest

def exec_fn(ctx):
   # Require at least 20 days of data.
   if ctx.bars < 20:
      return
   # Get the rolling 10 day high.
   high_10d = ctx.indicator('high_10d')
   # Buy on a new 10 day high.
   if not ctx.long_pos() and high_10d[-1] > high_10d[-2]:
      ctx.buy_shares = 100
      # Hold the position for 5 days.
      ctx.hold_bars = 5
      # Set a stop loss of 2%.
      ctx.stop_loss_pct = 2

strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='7/1/2022')
strategy.add_execution(
   exec_fn, ['AAPL', 'MSFT'], indicators=highest('high_10d', 'close', period=10))
result = strategy.backtest()

其主要代码的含义如下:

这段代码是一个使用 pybroker 库的简单股票交易策略示例。pybroker 是一个用于编写和回测交易策略的 Python 库。以下是代码的逐行解释:

首先,我们从 pybroker 导入 Strategy 类、YFinance 类和 highest 函数

其次,在 3-15 行。定义执行函数 exec_fn,它将在每个交易周期运行。

  1. 其中 5-6 行。如果历史数据少于 20 天,不执行任何操作。
  2. 其中 8 行:计算过去 10 天的最高价。
  3. 其中 10-15 行。如果没有持有多头仓位,并且最近 10 天的最高价高于前一天,进行以下操作:

1. 买入 100 股

2. 持有仓位 5 天

3. 设置 2%的止损

然后,在第 17 行创建一个新的策略对象,使用 Yahoo Finance 数据,指定开始和结束日期。

接着,在第 18-19 行为策略添加执行函数,指定要交易的股票(苹果和微软),并添加计算过去 10 天最高价的指标。

最后,在第 20 行,对策略进行回测,并将结果保存在 result 变量中。

我们在这个简单的策略中使用了一个基本的交易信号:当股票达到过去 10 天的最高价时买入。然后,它会持有股票 5 天,并设置一个 2% 的止损以限制潜在的损失。

使用 pybroker 库,我们可以轻松地对这个策略进行回测,评估其在过去的表现。

定制数据源及查看回测结果

目前国内利用 yfinance 来获取财经数据是不稳定的,我们想通过 AKShare 来进行测试,这里给大家提供一个利用 AKShare 来获取数据的示例代码,我们在代码中打印出了策略回测后可以获取的各种指标,主要是 ['bootstrap', 'end_date', 'metrics', 'metrics_df', 'orders', 'portfolio', 'positions', 'start_date', 'trades'] 等指标。我们在代码中对以上的指标给出了详细解释,以下代码供大家参考:

import akshare as ak  # 导入 AKShare 开源财经数据接口库
import pandas as pd
from pybroker import Strategy, highest
from pybroker.data import DataSource  # 导入 DataSource 这个抽象基类


class AKDataSource(DataSource):
    def __init__(self):
        # 初始化基类的 __init__ 方法
        super().__init__()

    # 重写 DataSource 抽象基类的 _fetch_data 方法
    def _fetch_data(self, symbols, start_date, end_date, _timeframe):
        df = pd.DataFrame()  # 创建空 DataFrame 以存储多个 symbol 的数据
        # 遍历 symbols 中的每个 symbol,这里就是每个股票
        for symbol in symbols:
            temp_df = ak.stock_zh_a_hist(
                symbol=symbol,
                # 由于传入的 start_date 和 end_date 为 datatime.datetime 格式
                # 所以在此处需要做格式转换,以符合 AKShare 接口的传参规则
                start_date=start_date.strftime("%Y%m%d"),
                end_date=end_date.strftime("%Y%m%d"),
                adjust="hfq",
            )
            # 给每个股票数据(DataFrame)带上 symbol,这里是股票的代码
            temp_df["symbol"] = symbol
            # 讲所有数据拼接到一起,注意在 pandas 2.0 中已经移除 pandas.DataFrame.append 方法
            # 建议使用 pd.concat 方法
            df = pd.concat([df, temp_df], ignore_index=True)

        # 将从 AKShare 获取的数据进行字段重命名以符合 PyBroker 的需求
        df.rename(
            columns={
                "日期": "date",
                "开盘": "open",
                "最高": "high",
                "最低": "low",
                "收盘": "close",
            },
            inplace=True,
        )
        # 筛选出我们需要的字段
        df = df[
            [
                "symbol",
                "date",
                "open",
                "high",
                "low",
                "close",
            ]
        ]
        # 将 date 字段转换为日期时间格式
        df["date"] = pd.to_datetime(df["date"])
        # 可以省略,因为已经在 for 循环中遍历
        df = df[df["symbol"].isin(symbols)]
        # 可以省略,因为已经在 AKShare 获取数据时筛选
        df = df[(df["date"] >= start_date) & (df["date"] <= end_date)]
        return df


def exec_fn(ctx):
    # Require at least 20 days of data.
    if ctx.bars < 20:
        return
    # Get the rolling 10 day high.
    high_10d = ctx.indicator("high_10d")
    # Buy on a new 10 day high.
    if not ctx.long_pos() and high_10d[-1] > high_10d[-2]:
        ctx.buy_shares = 100
        # Hold the position for 5 days.
        ctx.hold_bars = 5
        # Set a stop loss of 2%.
        ctx.stop_loss_pct = 2


strategy = Strategy(AKDataSource(), start_date='1/1/2022', end_date='7/1/2022')
strategy.add_execution(
    exec_fn, ["300059", "000555"], indicators=highest("high_10d", "close", period=10)
)
result = strategy.backtest()

# 打印出 result 中所有可以查看的属性
print("打印出 result 中所有可以查看的属性")
print([item for item in dir(result) if not item.startswith("__")])

# 回测的开始日期
print("回测的开始日期:result.start_date")
print(result.start_date)

# 回测的结束日期
print("回测的结束日期:result.end_date")
print(result.end_date)

# 一个包含每个时间点(bar)的投资组合余额的 DataFrame
print("一个包含每个时间点(bar)的投资组合余额的 DataFrame:result.portfolio")
print(result.portfolio)

# 一个包含每个时间点(bar)的仓位余额的 DataFrame
print("一个包含每个时间点(bar)的仓位余额的 DataFrame:result.positions")
print(result.positions)

# 一个包含所有已下订单的 DataFrame
print("一个包含所有已下订单的 DataFrame:result.orders")
print(result.orders)

# 一个包含所有已执行交易的 DataFrame
print("一个包含所有已执行交易的 DataFrame:result.trades")
print(result.trades)

# 评估指标
print("评估指标:result.metrics")
print(result.metrics)

# 评估指标的 DataFrame 格式,同上内容
print("评估指标的 DataFrame 格式,同上内容:result.metrics_df")
print(result.metrics_df)

# 随机自助法(bootstrap)评估指标,需要在 strategy.backtest(calc_bootstrap=True) 才有值
print("随机自助法(bootstrap)评估指标,需要在 strategy.backtest(calc_bootstrap=True) 才有值:result.bootstrap")
print(result.bootstrap)

我们在上述代码中编写了一个 AKDataSource 的类,其继承自 DataSource 这个抽象基类并重写了 _fetch_data 方法,这样我们就可以在里面定制我们的数据源及数据格式。其回测代码与示例代码中基本一致,最后我们输出了可以查看的策略回测结果,我们可以来看下其输出,如下:

Backtesting: 2022-01-01 00:00:00 to 2022-07-01 00:00:00
Loading bar data...
Loaded bar data: 0:00:00
Computing indicators...
100% (2 of 2) |##########################| Elapsed Time: 0:00:02 Time: 0:00:02
100% (118 of 118) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Test split: 2022-01-04 00:00:00 to 2022-07-01 00:00:00
Finished backtest: 0:00:05

1. 打印出 result 中所有可以查看的属性
['bootstrap', 'end_date', 'metrics', 'metrics_df', 'orders', 'portfolio', 'positions', 'start_date', 'trades']

2. 回测的开始日期:result.start_date
2022-01-01 00:00:00

3. 回测的结束日期:result.end_date
2022-07-01 00:00:00

4. 一个包含每个时间点(bar)的投资组合余额的 DataFrame:result.portfolio
cash equity margin market_value pnl fees
date
2022-01-04 100000.00 100000.00 0.0 100000.00 0.00 0.0
2022-01-05 100000.00 100000.00 0.0 100000.00 0.00 0.0
2022-01-06 100000.00 100000.00 0.0 100000.00 0.00 0.0
2022-01-07 100000.00 100000.00 0.0 100000.00 0.00 0.0
2022-01-10 100000.00 100000.00 0.0 100000.00 0.00 0.0
... ... ... ... ... ...
2022-06-27 80890.74 84461.74 0.0 84461.74 -15538.26 0.0
2022-06-28 249.78 84973.58 0.0 84973.58 -15026.42 0.0
2022-06-29 82862.92 82862.92 0.0 82862.92 -17137.08 0.0
2022-06-30 82862.92 82862.92 0.0 82862.92 -17137.08 0.0
2022-07-01 82862.92 82862.92 0.0 82862.92 -17137.08 0.0
[118 rows x 6 columns]

5. 一个包含每个时间点(bar)的仓位余额的 DataFrame:result.positions
long_shares short_shares ... margin unrealized_pnl
symbol date ...
000555 2022-02-22 100 0 ... 0.0 -45.00
2022-02-23 100 0 ... 0.0 48.00
300059 2022-03-31 71 0 ... 0.0 -749.76
2022-04-01 71 0 ... 0.0 2134.97
2022-04-06 71 0 ... 0.0 1635.13
2022-04-07 71 0 ... 0.0 -134.90
2022-04-08 71 0 ... 0.0 2134.97
2022-04-13 68 0 ... 0.0 -699.72
2022-04-14 68 0 ... 0.0 2542.52
2022-04-15 68 0 ... 0.0 2836.96
2022-04-18 68 0 ... 0.0 368.56
2022-04-19 68 0 ... 0.0 -699.72
2022-05-05 64 0 ... 0.0 -41.60
000555 2022-05-11 100 0 ... 0.0 -52.00
300059 2022-05-23 62 0 ... 0.0 443.92
000555 2022-06-07 100 0 ... 0.0 -27.00
300059 2022-06-07 55 0 ... 0.0 -787.05
000555 2022-06-08 100 0 ... 0.0 22.00
300059 2022-06-13 57 0 ... 0.0 -426.36
000555 2022-06-16 100 0 ... 0.0 -3.00
2022-06-22 100 0 ... 0.0 -51.00
2022-06-23 100 0 ... 0.0 23.00
2022-06-24 100 0 ... 0.0 48.00
2022-06-27 100 0 ... 0.0 35.00
2022-06-28 100 0 ... 0.0 63.00
300059 2022-06-28 48 0 ... 0.0 483.84
[26 rows x 7 columns]

6. 一个包含所有已下订单的 DataFrame:result.orders
type symbol date shares limit_price fill_price fees
id
1 buy 000555 2022-02-22 100 NaN 47.74 0.0
2 sell 000555 2022-02-24 100 NaN 46.79 0.0
3 buy 300059 2022-03-31 71 NaN 1391.85 0.0
4 buy 000555 2022-04-06 26 NaN 41.61 0.0
5 sell 000555 2022-04-06 26 NaN 40.78 0.0
6 buy 000555 2022-04-07 26 NaN 39.75 0.0
7 sell 000555 2022-04-07 26 NaN 38.96 0.0
8 sell 300059 2022-04-11 71 NaN 1364.01 0.0
9 buy 300059 2022-04-13 68 NaN 1424.08 0.0
10 sell 300059 2022-04-20 68 NaN 1385.51 0.0
11 buy 300059 2022-05-05 64 NaN 1469.70 0.0
12 sell 300059 2022-05-06 64 NaN 1440.31 0.0
13 buy 000555 2022-05-11 100 NaN 34.82 0.0
14 sell 000555 2022-05-12 100 NaN 34.12 0.0
15 buy 300059 2022-05-23 62 NaN 1486.60 0.0
16 buy 000555 2022-05-24 33 NaN 34.25 0.0
17 sell 300059 2022-05-24 62 NaN 1456.87 0.0
18 sell 000555 2022-05-24 33 NaN 33.57 0.0
19 buy 000555 2022-06-07 100 NaN 35.34 0.0
20 buy 300059 2022-06-07 55 NaN 1578.28 0.0
21 sell 300059 2022-06-08 55 NaN 1546.71 0.0
22 sell 000555 2022-06-09 100 NaN 34.63 0.0
23 buy 300059 2022-06-13 57 NaN 1559.75 0.0
24 sell 300059 2022-06-14 57 NaN 1528.56 0.0
25 buy 300059 2022-06-15 52 NaN 1676.44 0.0
26 sell 300059 2022-06-15 52 NaN 1642.91 0.0
27 buy 000555 2022-06-16 100 NaN 35.90 0.0
28 buy 300059 2022-06-16 50 NaN 1619.24 0.0
29 sell 300059 2022-06-16 50 NaN 1586.86 0.0
30 sell 000555 2022-06-17 100 NaN 35.18 0.0
31 buy 000555 2022-06-22 100 NaN 35.36 0.0
32 buy 300059 2022-06-28 48 NaN 1680.02 0.0
33 sell 000555 2022-06-29 100 NaN 35.85 0.0
34 sell 300059 2022-06-29 48 NaN 1646.42 0.0

7. 一个包含所有已执行交易的 DataFrame:result.trades
type symbol entry_date exit_date ... agg_pnl bars pnl_per_bar stop
id ...
1 long 000555 2022-02-22 2022-02-24 ... -95.48 2 -47.74 loss
2 long 000555 2022-04-06 2022-04-06 ... -117.12 0 -21.64 loss
3 long 000555 2022-04-07 2022-04-07 ... -137.79 0 -20.67 loss
4 long 300059 2022-03-31 2022-04-11 ... -2114.21 5 -395.29 loss
5 long 300059 2022-04-13 2022-04-20 ... -4736.97 5 -524.55 bar
6 long 300059 2022-05-05 2022-05-06 ... -6618.19 1 -1881.22 loss
7 long 000555 2022-05-11 2022-05-12 ... -6687.83 1 -69.64 loss
8 long 300059 2022-05-23 2022-05-24 ... -8531.21 1 -1843.38 loss
9 long 000555 2022-05-24 2022-05-24 ... -8553.82 0 -22.61 loss
10 long 300059 2022-06-07 2022-06-08 ... -10289.93 1 -1736.11 loss
11 long 000555 2022-06-07 2022-06-09 ... -10360.61 2 -35.34 loss
12 long 300059 2022-06-13 2022-06-14 ... -12138.72 1 -1778.12 loss
13 long 300059 2022-06-15 2022-06-15 ... -13882.22 0 -1743.50 loss
14 long 300059 2022-06-16 2022-06-16 ... -15501.46 0 -1619.24 loss
15 long 000555 2022-06-16 2022-06-17 ... -15573.26 1 -71.80 loss
16 long 000555 2022-06-22 2022-06-29 ... -15524.26 5 9.80 bar
17 long 300059 2022-06-28 2022-06-29 ... -17137.08 1 -1612.82 loss
[17 rows x 13 columns]

8. 评估指标:result.metrics
EvalMetrics(trade_count=17, initial_market_value=100000.0, end_market_value=82862.92, total_pnl=-17137.100000000002, unrealized_pnl=0.020000000000436557, total_return_pct=-17.137100000000004, total_profit=49.0, total_loss=-17186.1, total_fees=0.0, max_drawdown=-19176.570000000007, max_drawdown_pct=-18.79328287509082, win_rate=5.88235294117647, loss_rate=94.11764705882352, winning_trades=1, losing_trades=16, avg_pnl=-1008.0647058823531, avg_return_pct=-1.8423529411764705, avg_trade_bars=1.5294117647058822, avg_profit=49.0, avg_profit_pct=1.39, avg_winning_trade_bars=5.0, avg_loss=-1074.13125, avg_loss_pct=-2.044375, avg_losing_trade_bars=1.3125, largest_win=49.0, largest_win_pct=1.39, largest_win_bars=5, largest_loss=-2622.76, largest_loss_pct=-2.71, largest_loss_bars=5, max_wins=1, max_losses=15, sharpe=-0.18081585459472152, profit_factor=0.3647314736144434, ulcer_index=3.6788571265843757, upi=-0.04267875769735601, equity_r2=0.7614119151342339, std_error=5382.460496217223)

9. 评估指标的 DataFrame 格式,同上内容:result.metrics_df
name value
0 trade_count 17.000000
1 initial_market_value 100000.000000
2 end_market_value 82862.920000
3 total_pnl -17137.100000
4 unrealized_pnl 0.020000
5 total_return_pct -17.137100
6 total_profit 49.000000
7 total_loss -17186.100000
8 total_fees 0.000000
9 max_drawdown -19176.570000
10 max_drawdown_pct -18.793283
11 win_rate 5.882353
12 loss_rate 94.117647
13 winning_trades 1.000000
14 losing_trades 16.000000
15 avg_pnl -1008.064706
16 avg_return_pct -1.842353
17 avg_trade_bars 1.529412
18 avg_profit 49.000000
19 avg_profit_pct 1.390000
20 avg_winning_trade_bars 5.000000
21 avg_loss -1074.131250
22 avg_loss_pct -2.044375
23 avg_losing_trade_bars 1.312500
24 largest_win 49.000000
25 largest_win_pct 1.390000
26 largest_win_bars 5.000000
27 largest_loss -2622.760000
28 largest_loss_pct -2.710000
29 largest_loss_bars 5.000000
30 max_wins 1.000000
31 max_losses 15.000000
32 sharpe -0.180816
33 profit_factor 0.364731
34 ulcer_index 3.678857
35 upi -0.042679
36 equity_r2 0.761412
37 std_error 5382.460496

10. 随机自助法(bootstrap)评估指标,需要在 strategy.backtest(calc_bootstrap=True) 才有值:result.bootstrap
None

我们可以查看到其输出了很多做策略回测时查看的相关指标,我们在上述代码中已经做了简单的解释,我们会在后续的课程中,进一步给大家介绍其具体指标计算的原理及含义。

注意事项

  1. 由于 PyBroker 发布时间较短,可能存在一定的代码缺陷或计算问题,在回测中请小心使用
  2. 其目前升级迭代较快,需要问题会在升级中解决,请尽量升级到最新版本使用
量化交易PyBroker

发表评论

您的电子邮箱地址不会被公开。

滚动到顶部