功能
记录与映射数组
将稀疏事件和区间存为记录,再筛选、归约和重新分组
订单、交易、回撤和形态匹配属于事件,而非时间序列:大多数 K 线没有事件,有些则同时有多个。VBT 将这类稀疏事件和区间存储为带列映射的记录,让您无需为每个字段创建稠密数组,就能跨数千列筛选、归约、重新分组和绘图。
close = vbt.GBMOHLCData.pull("S", start="2024-01-01", end="2025-01-01", seed=42).close
np.random.seed(42)
slippage = pd.DataFrame(
np.random.uniform(0, 0.005, size=(len(close), 1000)),
index=close.index,
)
pf = vbt.PF.from_random_signals(close, n=10, seed=42, slippage=slippage)
orders = pf.orders
print(orders.count().sum())20000fill_vs_close = orders.price.values / close.values[orders.idx.values] - 1
cost = orders.map_array(
np.where(orders.side.values == 0, fill_vs_close, -fill_vs_close)
)
cost.max().describe().round(4) count 1000.0000
mean 0.0048
std 0.0002
min 0.0035
25% 0.0047
50% 0.0048
75% 0.0049
max 0.0050
Name: max, dtype: float64readable = cost.to_readable()
readable.loc[readable["Value"].idxmax()]Id 1
Column 165
Index 2024-03-12 00:00:00+00:00
Value 0.004999
Name: 3301, dtype: object两万个订单占用两万行,而不是 366 根 K 线乘以 1,000 列再乘以每个字段。最差成交是第 165 列的第二个订单,发生于 2024 年 3 月 12 日。
记录
记录数组是结构化 NumPy 数组,每个事件一行,具有列、K 线、价格和规模等字段。记录类将其与数据的时间索引和列标签一起封装,让同一对象同时了解原始位置及其对应日期。订单、日志、交易、持仓、回撤和形态匹配都是记录。
区间是带有起点和终点的记录。任意布尔掩码都能转换为区间,将时段变成可衡量的对象:
btc = vbt.YFData.pull("BTC-USD", start="2020-01-01", end="2025-01-01")
rsi = btc.run("rsi", window=14).rsi.rename("RSI")
overbought = vbt.Ranges.from_array(rsi > 70)
print(overbought.count(), overbought.coverage.round(3)) 42 0.128longest = overbought.apply_mask(overbought.duration.top_n_mask(3))
longest.readable[["Start Index", "End Index", "Status"]] Start Index End Index Status
0 2023-01-11 00:00:00+00:00 2023-01-30 00:00:00+00:00 Closed
1 2023-10-20 00:00:00+00:00 2023-11-14 00:00:00+00:00 Closed
2 2024-11-06 00:00:00+00:00 2024-11-25 00:00:00+00:00 Closedlongest.duration.valuesarray([19, 25, 19])记录也可根据您自己的数据构建。带有日期和交易标的的 DataFrame 或字典列表,可以转换为具有类型的记录;索引记录正是通过这种方式将稀疏订单传入模拟。
映射数组
映射数组为每条记录保存一个值,同时保留记录的列和 K 线位置。记录对象的每个字段都可作为映射数组访问,例如 pf.trades.pnl 或
pf.drawdowns.duration;map_array 则可附加您计算的任意数值。映射数组支持通过 mean、max、idxmax、count
或任意编译函数按列或组归约,通过 top_n_mask 等掩码筛选,并在需要表格时用 to_pd 或 to_readable 转换为 pandas。to_pd 将每个值放到其记录对应的
K 线上。同一列的多条记录共享一根 K 线时,会保留最后一条并发出警告。传入 reduce_func_nb(例如 "sum")可合并它们,传入 repeat_index=True
可全部保留,或用 ignore_index=True 将值无日期堆叠。
这让您能够针对回测提出更具体的问题:几乎没有浮盈的亏损交易持续了多久?哪些订单成本最高?先筛选记录或映射值,再对选定事件运行相同归约。结果保留资产和参数标签。交易分析展示了如何将此流程用于多空交易及其价格偏移。
索引与重新分组
记录保持按列排序,列映射记住每列记录的起始位置,因此选择某列或分组(例如 pf.trades["BTC-USD"])无需扫描全部记录。分组可在事后更改:同一组交易记录通过
group_by=False 按资产报告,也可通过其他分组方式按策略报告。如需跨列按时间查看,请按索引列对可读表格排序。
例如,先分别报告三个资产,再将 A 和 B 合并为一个研究分组:
group_close = pd.DataFrame({"A": [10.0, 11.0, 12.0], "B": [20.0, 18.0, 19.0], "C": [30.0, 33.0, 36.0]}, index=pd.date_range("2026-01-01", periods=3))
group_pf = vbt.PF.from_orders(group_close, size=np.array([1, 0, -1])[:, None])
trade_pnl = group_pf.trades.status_closed.pnl
trade_pnl.sum()A 2.0
B -1.0
C 6.0
Name: sum, dtype: float64trade_pnl.sum(group_by=["Group 1", "Group 1", "Group 2"])group
Group 1 1.0
Group 2 6.0
Name: sum, dtype: float64同一组记录现在回答了不同的报告问题。您可以按行业、策略系列或每列的其他标签分组。如需让资产在模拟运行时共享资金,请使用共享现金。
自定义记录类
您自己的事件可以有自己的类。定义包含所需字段的 NumPy dtype,附加标题和值映射,让可读表格显示名称而非代码,再继承 vbt.Records 或
vbt.Ranges,即可获得筛选、映射字段、统计和绘图功能。记录像其他 VBT 对象一样可以保存到磁盘并加载。在 Numba 代码中,用 record["price"]
这样的方括号读取记录字段,无论是否开启编译都能工作。
✅ 此前 OHLC 数据用于模拟,但分析只使用收盘价。现在,大多数类都能跟踪全部 OHLC 数据,让定量和定性分析更加准确。
data = vbt.YFData.pull("BTC-USD", start="2020-01", end="2020-03")
pf = vbt.PF.from_random_signals(
open=data.open,
high=data.high,
low=data.low,
close=data.close,
n=10,
seed=42
)
pf.trades.plot().show()版权所有 © 2021–2026 Oleg Polakow。保留所有权利。
本站内容与文档供使用和评估 VectorBT PRO 以及教育用途。任何其他用途,包括开发或支持竞争产品或服务,均须事先取得书面同意。