# 开发者工具 (/zh/features/tooling/developer-tools)

面对拥有数千个类和函数的库，如何找到所需功能并加以扩展？VBT 提供 API 搜索和 Python 对象检查工具：搜索整个软件包、阅读任意对象的源码与文档，并绘出各函数的依赖。

```python title="Find every function that takes freq, read one, and graph its dependencies"
>>> import inspect
>>> from vectorbtpro.utils.module_ import search_package
>>> from vectorbtpro.utils.source import get_source

>>> def accepts_freq(name, obj):
...     return inspect.isfunction(obj) and "freq" in inspect.signature(obj).parameters

>>> found = search_package("vectorbtpro", accepts_freq)  # (1)
>>> names = sorted({f"{func.__module__}.{func.__name__}" for func in found.values()})
>>> len(names)
14
>>> print("\n".join(names[-6:]))
vectorbtpro.utils.datetime_.readable_datetime
vectorbtpro.utils.datetime_.to_freq
vectorbtpro.utils.datetime_.to_offset
vectorbtpro.utils.datetime_.to_timedelta
vectorbtpro.utils.datetime_.to_timedelta64
vectorbtpro.utils.schedule_.wait

>>> from vectorbtpro.utils.datetime_ import infer_index_freq
>>> print("\n".join(get_source(infer_index_freq).splitlines()[:7]))
def infer_index_freq(
    index: tp.Index,
    freq: tp.Optional[tp.FrequencyLike] = None,
    allow_offset: bool = True,
    allow_numeric: bool = True,
    freq_from_n: tp.Union[None, bool, int] = None,
) -> tp.Union[None, int, float, tp.PandasFrequency]:

>>> ref_index = vbt.RefIndex(incl_modules="vectorbtpro")
>>> graph = ref_index.build_graph(infer_index_freq)  # (2)
>>> print("\n".join(graph.get_dependencies(graph.root, relation="direct")))
vectorbtpro._typing.FrequencyLike
vectorbtpro._typing.PandasFrequency
vectorbtpro.utils.checks.is_number
vectorbtpro.utils.datetime_.auto_detect_freq
vectorbtpro.utils.datetime_.freq_depends_on_index
vectorbtpro.utils.datetime_.parse_index_freq
vectorbtpro.utils.datetime_.to_freq
>>> fig = graph.plot(interactive=False, showlegend=False)
>>> for trace in fig.data:  # (3)
...     if trace.name.endswith("_nodes_hl") and len(trace.x) > 0:
...         labels = [info[1] or info[0] for info in trace.customdata]
...         trace.update(mode="markers+text", text=labels, textposition="top center")
>>> fig.show()
```

1.  遍历软件包所有模块，保留符合条件的模块级函数。类的方法需要单独搜索。
2.  为源码引用建立索引，并沿着函数自身模块中定义的引用继续查找。
3.  名称默认在悬停时显示。此循环在各节点旁打印名称。

infer\_index\_freq 函数及其使用的函数和类型的引用关系图. [Figure data (JSON)](/assets/figures/features/tooling/reference-graph-infer-freq.11ed1169f1ab.json)

十四个模块级函数接受 `freq` 参数。图中将 `infer_index_freq` 和它使用的七个名称放入各自定义它们的模块，帮助您在频率不符合预期时找到检查位置。

## 发现功能 \[#discovery]

大多数有关 VBT 的问题，可以直接从 Python 中找到答案：

| 工具                                             | 解答                           |
| ---------------------------------------------- | ---------------------------- |
| `vbt.phelp(obj)`                               | 函数接受什么参数，以及文档字符串如何说明         |
| `vbt.pdir(obj)`                                | 对象有哪些属性、各自类型及定义位置            |
| `vbt.pprint(obj)`                              | 对象包含什么，以易读的嵌套文本显示            |
| `vbt.ptable(obj)`                              | 数组、DataFrame 或记录数组包含什么，以表格显示 |
| `get_source(obj)`                              | 任意函数、类或模块的源码                 |
| `vbt.get_api_ref(obj)`、`vbt.open_api_ref(obj)` | 对象的 API 文档页                  |
| `vbt.RefIndex`                                 | 对象使用了什么、被什么使用，以及模块如何连接       |
| `vbt.get_capabilities()`                       | 已安装多少指标、数据源、度量和引擎            |

`deep_getattr` 解析由属性和方法调用组成的点分路径，例如
`pf.deep_getattr("trades.expectancy")`。对于自然语言问题，[知识搜索](/zh/features/ai/knowledge-search/)页介绍
`vbt.find_api` 和 `vbt.search`。

陌生对象或参数阻碍研究时，这些工具可以配合使用。先用 `phelp` 查看调用签名，再用 `pdir` 找到相关属性或方法，最后打开源码或 API 参考了解细节。配置化对象通过 `config`
公开构造参数，因此可检查创建数据实例、指标或投资组合时使用的设置。

## 格式化与注解 \[#formatting-and-annotations]

`vbt.pprint` 和 `vbt.phelp` 背后的格式化引擎，以相同方式在终端与 notebook
中呈现配置化对象、字典、数组和签名，详见下方[格式化引擎](#formatting-engine)。函数签名中的注解带有语义：`vbt.Param`、`vbt.Takeable` 和
`vbt.MergeFunc` 告诉参数化及切分装饰器如何处理各参数，详见下方[注解](#annotations)。

## 验证与调试 \[#validation-and-debugging]

*   **相等性：** `vbt.is_deep_equal` 比较嵌套对象、数组及元数据，每个配置化对象也有 `equals`。
*   **警告：** VBT 警告使用统一格式，`vbt.WarningsFiltered()` 可在 `with` 块内屏蔽它们。
*   **哈希：** `vbt.hdict` 和配置化对象可计算哈希，VBT 据此按参数缓存结果。
*   **边界检查：** 自定义 Numba 回调中的无效数组索引可能返回错误数据或导致内核崩溃。在配置文件的 `numba` 下设置 `boundscheck`，可让编译函数改为抛出错误；Numba
    环境变量 `NUMBA_DISABLE_JIT=1` 则关闭 Numba 编译，以便在 Python 层面调试。请在导入 VBT 前设置。
*   **预处理器：** 模拟方法将参数检查与执行分开。传入 `return_preparer=True` 可在运行前检查投资组合的预处理参数，或传入
    `return_prep_result=True`，在 `target_args` 中获得模拟器最终接收的数组。

### 检查模拟器将接收什么 \[#inspect-what-the-simulator-will-receive]

预处理器让您在长回测前检查形状、默认值和转换后的参数。这里两个资产有不同的订单金额，但共享相同手续费：

```python title="Inspect prepared order sizes and fees without running the simulation"
>>> close = pd.DataFrame(
...     {"A": [100.0, 105.0, 103.0], "B": [50.0, 49.0, 52.0]},
...     index=pd.date_range("2025-01-01", periods=3),
... )
>>> prepared = vbt.PF.from_orders(
...     close,
...     size=np.array([[100.0, 200.0]]),
...     size_type="value",
...     fees=0.001,
...     return_prep_result=True,
... )
>>> print(prepared.pf_args["wrapper"].shape)
(3, 2)
>>> print(prepared.target_args["size"])
[[100. 200.]]
>>> print(prepared.target_args["fees"])
[[0.001]]
```

目标形状为三行、两个资产。订单金额保留为单行，共享手续费保留为单个单元格，供模拟器内部灵活索引。这有助于判断意外结果来自输入还是交易逻辑。[回测引擎](/zh/features/backtesting/backtesting-engine/#portfolio-preparers)页展示如何修改预处理结果并运行。

运行时检查也会验证形状、索引和数据类型。您可以在自己的函数中使用相同断言辅助函数，重构后则可用深度相等检查比较嵌套输出。回调行为异常时，先检查一小段输入，再用边界检查或 Python
层面调试追踪其决策。

## 扩展 \[#extending]

VBT 本身使用的正是它公开的工厂。`vbt.IF`
构建指标类，详见[自定义指标](/zh/features/indicators/indicator-development/)；`vbt.SignalFactory`
构建信号生成器。配置化类通过装饰器获得声明式字段、缓存属性和快捷方法；`vbt.evaluate` 在上下文中求表达式值，指标表达式与模板正是这样获取输入。

自定义计算可以保持为函数，也可以包装为带命名输入与参数的指标，或注册编译实现及其分块规则。这样，自定义工作即可像内置计算一样参与参数搜索并生成带标签结果。[计算后端](/zh/features/performance/compute-backends/)和[并行执行](/zh/features/performance/parallel-execution-and-caching/)介绍这些执行选项。逻辑需要当前持仓和现金时，可通过[事件驱动回调](/zh/features/backtesting/event-driven-backtesting/)扩展模拟。

## 实用工具 \[#utilities]

小工具涵盖日常任务：在嵌套对象深处搜索与替换值、按路径读写嵌套键、用正则表达式匹配名称、管理文件与文件夹，以及缩放数组。它们也是 VBT
内部使用的辅助工具。为节省内存，`vbt.settings.wrapping["max_precision"] = 32` 可在结果封装为 pandas 时转换为 32 位浮点数，代价是精度降低。

提供 Python 下载的会员页面使用 Jupytext 格式，因此可以作为 notebook 打开并在本地调整。[教程](/zh/tutorials/)提供完整研究工作流，便于结合单独 API
对象一同检查。

## 引用关系图 \[#reference-graphs]

新增于 v2025.12.31

✅ 分析 VBT 这样的复杂代码库时，跟踪模块、类与函数之间的全部依赖关系并不容易。为此，VBT
现在能为任意代码库的对象引用建立源码索引，并从指定入口生成引用关系图。图中直观展示不同组件如何关联，帮助理解代码的整体结构与流程。

```python title="Generate a reference graph for Pandas and display it in a new browser tab"
>>> ref_index = vbt.RefIndex(container_kinds=["module", "class"], incl_modules="pandas")
>>> ref_graph = ref_index.build_graph("pandas")
>>> ref_graph.plot(
...     interactive="dash",
...     to_dash_kwargs=dict(fit_to_window=True),
...     dash_run_kwargs=dict(jupyter_mode="tab")
... )
```

Pandas 模块、类、可调用对象与数据依赖的引用关系图. [Figure data (JSON)](/assets/figures/features/productivity/reference-graph.0345cbe42aad.json)

!!! info "在线浏览器"
    在 [`API`](/zh/api/) → 引用关系图中探索 VBT 的引用图。

## 注解 \[#annotations]

新增于 v2023.12.23

✅ 编写函数时，可以在参数旁通过注解指定其含义。VBT
现在提供丰富的专用注解，针对不同任务设计。例如，某个参数是否属于待搜索参数，可以直接在函数中声明，无须在[参数化装饰器](/zh/features/optimization/strategy-optimization/#parameterized-decorator)中指定。

```python title="Test a cross-validation function with annotations"
>>> @vbt.cv_split(
...     splitter="from_rolling",
...     splitter_kwargs=dict(length=365, split=0.5, set_labels=["train", "test"]),
...     parameterized_kwargs=dict(random_subset=100, seed=42),
... )
... def sma_crossover_cv(
...     data: vbt.Takeable,  # (1)
...     fast_period: vbt.Param(condition="x < slow_period"),  # (2)
...     slow_period: vbt.Param,  # (3)
...     metric
... ) -> vbt.MergeFunc("concat"):
...     fast_sma = data.run("sma", fast_period, hide_params=True)
...     slow_sma = data.run("sma", slow_period, hide_params=True)
...     entries = fast_sma.real_crossed_above(slow_sma)
...     exits = fast_sma.real_crossed_below(slow_sma)
...     pf = vbt.PF.from_signals(data, entries, exits, direction="both")
...     return pf.deep_getattr(metric)

>>> sma_crossover_cv(
...     vbt.YFData.pull("BTC-USD", start="4 years ago"),
...     np.arange(20, 50),
...     np.arange(20, 50),
...     "trades.expectancy"
... )
split  set    fast_period  slow_period
0      train  25           26               2.822879
       test   25           26               4.740533
1      train  22           37              16.967189
       test   22           37             -16.101936
2      train  30           41             308.879034
       test   30           41              14.445511
3      train  29           49              32.328702
       test   29           49              13.546335
4      train  27           48              20.695292
       test   27           48               6.539824
5      train  22           46              19.143686
       test   22           46              -4.664139
6      train  34           45               5.235739
       test   34           45              -2.697966
dtype: float64
```

1.  传入参数必须可按切分选择子集，即 takeable。
2.  带有条件的参数，要求它小于慢线周期。
3.  慢线周期参数。

## 格式化引擎 \[#formatting-engine]

新增于 1.0.2

✅ VBT 是定义了数千个类、函数和对象的综合库。使用它们时，您可能希望“查看内部”，进一步理解属性与内容。格式化引擎可以将任意内部对象准确格式化为易读字符串。您知道吗，API
文档的一部分正是由该引擎生成的 😉

```python title="Introspect a data instance"
>>> data = vbt.YFData.pull("BTC-USD", start="2020", end="2021")

>>> vbt.pprint(data)  # (1)
YFData(
    wrapper=ArrayWrapper(...),
    data=symbol_dict({
        'BTC-USD': <pandas.core.frame.DataFrame object at 0x7f7f1fbc6cd0 with shape (366, 7)>
    }),
    single_key=True,
    classes=symbol_dict(),
    fetch_kwargs=symbol_dict({
        'BTC-USD': dict(
            start='2020',
            end='2021'
        )
    }),
    returned_kwargs=symbol_dict({
        'BTC-USD': dict()
    }),
    last_index=symbol_dict({
        'BTC-USD': Timestamp('2020-12-31 00:00:00+0000', tz='UTC')
    }),
    tz_localize=datetime.timezone.utc,
    tz_convert='UTC',
    missing_index='nan',
    missing_columns='raise'
)

>>> vbt.pdir(data)  # (2)
                                            type                                             path
attr
align_columns                        classmethod                       vectorbtpro.data.base.Data
align_index                          classmethod                       vectorbtpro.data.base.Data
build_feature_config_doc             classmethod                       vectorbtpro.data.base.Data
...                                          ...                                              ...
vwap                                    property                       vectorbtpro.data.base.Data
wrapper                                 property               vectorbtpro.base.wrapping.Wrapping
xs                                      function          vectorbtpro.base.indexing.PandasIndexer

>>> vbt.phelp(data.get)  # (3)
YFData.get(
    columns=None,
    symbols=None,
    **kwargs
):
    Get one or more columns of one or more symbols of data.
```

1.  类似 Python 的 `print`，美化打印任意 VBT 对象的内容。
2.  类似 Python 的 `dir`，美化打印类、对象或模块的属性。
3.  类似 Python 的 `help`，美化打印函数签名和文档字符串。
