插件协议

AxData 插件能力协议

本文说明 AxData 插件的能力声明、Manifest 字段、Registry 发现规则和运行边界。开发新插件时建议先读实践手册 plugin-development.md,再回到本文核对字段级协议。

AxData 的定位是本地优先、开源可扩展的量化数据基座。插件是本地安装、本地运行、本地承担风险的 Python 扩展包;AxData 不做中心化插件市场、不做插件审核、不做签名信任体系。核心不应被任何单一上游数据源绑定;插件通过能力声明接入,核心提供统一接口目录、参数校验、字段归一、存储、查询、采集、调度、安装管理和状态展示。没有 axdata-plugin.jsonaxdata-provider.json manifest 的 Python 包不算 AxData 插件;entry point 只是候选入口,缺 manifest 或重复 provider_id 的候选只进入诊断,不进入普通插件列表或有效插件统计。

1. 包边界

推荐包边界如下:

职责是否绑定具体源
axdata-core插件能力协议、Registry、Manifest schema、AXP 管理、归一化工具、存储、查询、通用 Collector/Downloader 框架
axdata面向普通用户的主包,可随包提供预装源插件,可直接 pip install axdata 使用通过预装插件提供基础源
axdata-source-tdxTDX 数据源插件,拥有 TDX 普通行情、F10、服务器列表、缓存和采集 profile
axdata-source-xxx社区或第三方数据源插件,可提供 Provider、Collector、DownloaderProfile 或工具能力可以绑定具体源
axdata-serverHTTP API、Web、采集调度、插件管理、远程访问否,依赖 Registry

axdata-core 必须保持中立。所有数据源能力都来自预装插件或外部插件;Core 只提供数据库、插件协议、注册表、任务平台、存储、查询、API、Web 和 CLI。TDX 能力来自可安装、默认可用、可禁用、可从当前管理状态移除的 TDX 插件;插件不可用时 core 只提示用户安装或检查插件状态。

1.1 能力模型

插件不再等同于“一个数据源”。一个插件可以提供一种或多种能力:

能力说明
providers数据源接口能力,声明接口、参数、字段、样例,并通过 Adapter 做源端临时调用
collectors独立采集器声明,描述用户可安装、启用、调度的本地资产生产任务
downloaders兼容下载 profile,描述如何把接口拆请求、资源组、默认并发和输出建议
tools可选的数据处理、清洗、指标或格式转换能力
dependenciesPython 依赖和可选包内 wheels,用于安装前提示和离线安装
config_schema配置提示,只用于 UI/CLI 展示,不托管第三方 secret

允许的插件形态:

AxData 允许插件自由提供能力,但运行时规则由 core 统一托管:接口路由走 Source Provider Registry,采集能力走 Collector Registry,采集执行走 Collector Runner,写入走 Writer/Quality/Metadata,状态、日志、取消、失败退避和资源组限制由 AxData 统一记录和展示。新采集器不能通过 /v1/request、SDK call、ProviderRegistry interface route 或旧 DownloaderProfile 链路套接口采集;它可以自带取数逻辑。

2. 兼容版本

插件系统有两个独立版本号:

字段作用示例Registry 行为
manifest_versionManifest JSON 文件格式版本1.0不支持则拒绝读取
plugin_api_versionProvider Python 协议版本1.0不兼容则标记 incompatible

二者不能混用。manifest_version 只管元信息文件怎么解析,plugin_api_version 只管 Provider、Adapter、Collector、DownloaderProfile、RequestPlanner 等插件能力代码契约。

兼容规则:

3. Plugin 与 Provider 协议

多能力插件包应只暴露一个插件对象。该对象可以提供 Provider、Collector、DownloaderProfile、Tool 或这些能力的组合。推荐 entry point group 为 axdata.plugins

[project.entry-points."axdata.plugins"]
tdx = "axdata_source_tdx:plugin"

已经存在的 Provider 包仍可继续使用兼容入口 axdata.providers

[project.entry-points."axdata.providers"]
tdx = "axdata_source_tdx:provider"

Registry 实现应同时识别 axdata.pluginsaxdata.providers。旧 Provider 对象可视为只提供 Provider 能力的插件;只有 Collector 或工具能力的新插件不应被迫伪造 Provider。

插件对象协议:

class AxDataPlugin:
    plugin_id: str
    version: str
    plugin_api_version: str

    def provider(self) -> SourceProvider | None: ...
    def collectors(self) -> Sequence[CollectorSpec]: ...
    def downloader_profiles(self) -> Sequence[DownloaderProfile]: ...
    def tools(self) -> Sequence[ToolSpec]: ...
    def dependencies(self) -> Sequence[DependencySpec]: ...
    def required_config(self) -> Sequence[RequiredConfig]: ...  # compatibility projection

当前 Provider 协议继续兼容:

class SourceProvider:
    provider_id: str
    source_code: str
    source_name_zh: str
    version: str
    plugin_api_version: str

    def interfaces(self) -> Sequence[InterfaceSpec]: ...
    def create_adapter(self, options: Mapping[str, object] | None = None) -> SourceAdapter: ...
    def downloader_profiles(self) -> Sequence[DownloaderProfile]: ...
    def required_config(self) -> Sequence[RequiredConfig]: ...  # optional

标识符分工:

标识符是否全局唯一用途示例
provider_id数据源插件身份、启停、卸载、冲突归属、日志归属axdata.source.tdx
source_code否,可共享数据源命名空间、目录分组、接口名前缀建议tdx
interface_name用户调用、HTTP 路由、Registry 精确分发stock_codes_tdx
collector_plugin_id采集器插件身份、启停、卸载和冲突归属axdata.collector.tdx_daily
collector_id采集器系统 ID,供任务模板和调度引用tdx.stock_codes.snapshot
dataset_id采集结果数据集 ID,供 Data Browser 和查询目录引用tdx.stock_codes

provider_id 不等于 source_codeinterface_namecollector_iddataset_id 也不能混用。它们可以显示同一个中文名,但系统 ID 必须分命名空间。

required_config() 是可选声明方法。未实现时等价于返回空列表;实现时只用于生成 manifest 和 UI/CLI 展示配置提示,不代表 AxData 会保存、注入或代理第三方源凭据。

declared_trust_levelhomepagelicensedescription 也是可选展示属性。declared_trust_level 即使由 Provider 代码声明,也仍然只是作者自报,Registry 冲突裁决只能使用 effective_trust_level

4. Adapter 契约

Adapter 负责源端直取,不负责把数据写入 AxData 数据层。源端直取遵守 docs/architecture.mddocs/data-layers.md 的边界:默认不写入 rawstagingcorefactor

建议接口:

class SourceAdapter:
    def call(
        self,
        interface_name: str,
        params: Mapping[str, object] | None = None,
        fields: Sequence[str] | None = None,
        options: Mapping[str, object] | None = None,
    ) -> SourceResult: ...

SourceResult 至少包含:

字段说明
data已转换为 AxData 字段的记录列表
schema返回字段 schema
meta源、接口、耗时、分页、数据日期等元信息

Adapter 可以使用上游原始字段,但对外返回必须是 AxData 字段。源端特色字段只有在接口规范明确声明时才能暴露。

5. Manifest As Build Artifact

Manifest 是 Registry 免 import 读取的唯一元信息产物,但不是人工手写的真相源。

标准流程:

  1. Provider 代码声明接口、参数、字段、样例、下载 profile。
  2. axdata plugin build import Provider,并从 Provider 生成 axdata-provider.json
  3. 同一份 manifest 打进 wheel 作为 package/distribution data。
  4. Registry 发现 entry point 后,先读取 distribution 内的 manifest,不 import Provider 模块。
  5. Registry 用 manifest 做目录展示、版本门禁、信任提示和冲突检查。
  6. 只有当某个接口真的被调用,Registry 才 import Provider 并创建 Adapter。
  7. axdata plugin check 必须校验 manifest 与当前 Provider 代码一致。

Manifest 不允许成为第三个手写真相源。CI 和发布流程应要求 axdata plugin check 通过。

6. Manifest JSON 结构

当前 Provider manifest 文件名为 axdata-provider.json。多能力插件可以使用更通用的 axdata-plugin.json;无论文件名如何,manifest 的真相源都是插件代码生成出的能力声明,而不是手写副本。JSON 顶层字段:

{
  "manifest_version": "1.0",
  "plugin_api_version": "1.0",
  "plugin": {
    "plugin_id": "axdata.plugin.tencent",
    "name_zh": "腾讯财经插件",
    "version": "0.1.0",
    "description": "腾讯财经公开行情接口插件"
  },
  "provider": {
    "provider_id": "axdata.source.tencent",
    "source_code": "tencent",
    "source_name_zh": "腾讯财经",
    "version": "0.1.0",
    "declared_trust_level": "community",
    "homepage": "https://example.com",
    "license": "Apache-2.0",
    "description": "腾讯财经公开行情接口 Provider"
  },
  "interfaces": [],
  "collectors": [],
  "downloaders": [],
  "dependencies": [],
  "config_schema": {
    "required_config": []
  },
  "required_config": [],
  "resources": {
    "samples": []
  },
  "build": {
    "generated_at": "2026-06-22T12:00:00Z",
    "axdata_plugin_api_version": "1.0",
    "manifest_hash": "sha256:..."
  }
}

6.1 PluginManifest

字段类型必填说明
manifest_versionstringManifest JSON 格式版本
plugin_api_versionstring插件能力协议版本
pluginobject插件元信息;当前 Provider manifest 可暂时省略
providerobject条件必填Provider 元信息;插件提供 Provider/interfaces 时必填,只有 Collector/Tool 的插件可省略
interfacesarray接口规格列表;没有 Provider 能力时为空数组
collectorsarray采集任务声明;可由只有采集器的插件提供
downloadersarray兼容下载 profile;用于显式下载和 legacy collectors,不是采集器身份
dependenciesarrayPython 依赖声明和包内 wheel 索引,用于安装前提示
config_schemaobject配置提示 schema,不托管第三方 secret
required_configarray只用于展示的配置提示
resourcesobject样例、文档等资源索引
buildobject构建信息

未知字段处理:

6.2 ProviderInfo

字段类型必填说明
provider_idstring插件唯一身份
source_codestring数据源命名空间
source_name_zhstring中文数据源名
versionstringProvider 包版本
declared_trust_levelstring作者自报信任等级,只能用于展示
homepagestring项目主页
licensestring插件许可证
descriptionstring简介

declared_trust_level 保留为兼容展示字段,不作为安全保证。可取值:

Registry 不得直接用 declared_trust_level 做安全裁决。AxData 不做签名验签系统,也不因为插件自报 official 就授予内置权限。

6.3 InterfaceSpec

{
  "name": "stock_codes_tdx",
  "display_name_zh": "最新股票列表",
  "source_code": "tdx",
  "source_name_zh": "通达信",
  "category": "股票数据/基础数据",
  "menu_path": ["通达信", "股票数据", "基础数据"],
  "asset_class": "stock",
  "request_mode": "source_request",
  "collection": {
    "supported": true,
    "default_profile": "tdx.stock_codes.latest"
  },
  "parameters": [],
  "fields": [],
  "examples": [],
  "reference_sections": [],
  "summary_zh": "按范围获取最新股票列表。",
  "description_zh": "用于接口页面的中文说明;参数和字段仍以 parameters/fields 为准。",
  "params_note_zh": "不传参数时返回默认范围。",
  "params_example_zh": "client.call(\"stock_codes_tdx\")",
  "limits": {
    "default_limit": 5000,
    "max_limit": 100000
  },
  "notes": "源端直取默认不入库。"
}
字段类型必填说明
namestring全局唯一接口名
display_name_zhstring中文展示名
source_codestring所属数据源命名空间
source_name_zhstring中文数据源名
categorystring展示分类
menu_patharray[string]插件声明的完整 Web 菜单路径;Web 只渲染该路径,不为具体数据源补接口树
asset_classstring标准资产类型
request_modestringsource_requestquerystreamcollect
collectionobject兼容下载提示;可指向 DownloaderProfile,但不等于 CollectorSpec
parametersarray参数规格
fieldsarray字段规格
examplesarray真实或可稳定复现的请求样例
reference_sectionsarray接口页静态参考表,例如类别码、枚举映射、字段口径对照;由插件提供,Web 通用渲染
summary_zhstringWeb 接口页顶部中文短摘要;由插件或内置 Provider 提供
description_zhstringWeb 接口页中文正文说明;存在时优先于 notes 展示
params_note_zhstringWeb 参数区中文补充说明
params_example_zhstringWeb 参数区静态 SDK 调用示例;不触发源端请求
limitsobject限制说明
notesstring额外说明

asset_class 标准枚举:

如需新增资产类型,必须先扩展核心规范,再让插件使用。不能由单个插件私自发明新枚举。

6.4 ParameterSpec

{
  "name": "code",
  "display_name_zh": "证券代码",
  "type": "string",
  "required": false,
  "multiple": true,
  "default": null,
  "control": "text",
  "placeholder": "000001.SZ",
  "description": "不填表示全量。"
}
字段类型必填说明
namestring参数名
display_name_zhstring中文名
typestringstringintegernumberbooleandatedatetimeenumarrayobject
requiredboolean是否必填
multipleboolean是否支持多值
defaultany默认值
enumarray枚举候选
controlstringWeb 控件建议
placeholderstring输入提示
descriptionstring说明

日期参数应使用 YYYYMMDD。HTTP 层可以兼容 YYYY-MM-DD,但 Provider 规范里统一写 YYYYMMDD

6.5 FieldSpec

{
  "name": "instrument_id",
  "display_name_zh": "证券代码",
  "type": "string",
  "required": true,
  "unit": null,
  "description": "AxData 统一证券代码,例如 000001.SZ。"
}
字段类型必填说明
namestringAxData 字段名
display_name_zhstring中文名
typestringstringintegernumberbooleandatedatetime
requiredboolean是否理论必填
unitstring/null单位
descriptionstring说明

字段名必须使用 snake_case。不得暴露上游难懂原始列名,除非接口就是调试接口且文档明确说明。

6.6 RequestExample

{
  "title": "按代码查询",
  "request": {
    "interface_name": "stock_codes_tdx",
    "params": {"code": ["000001.SZ", "600000.SH"]},
    "fields": ["instrument_id", "name"]
  },
  "response": {
    "data": [
      {"instrument_id": "000001.SZ", "name": "平安银行"}
    ],
    "schema": [
      {"name": "instrument_id", "type": "string"},
      {"name": "name", "type": "string"}
    ],
    "meta": {"count": 1}
  }
}

样例要求:

6.7 DownloaderProfile

{
  "name": "tdx.stock_suspensions.latest",
  "interface_name": "stock_suspensions_tdx",
  "display_name_zh": "最新停牌列表采集",
  "resource_group": "tdx.quote",
  "mode": "snapshot",
  "default_options": {
    "formats": ["parquet"],
    "server_count": 4,
    "connections_per_server": 2,
    "batch_size": 80
  },
  "default_limits": {
    "max_active_jobs": 1,
    "max_connections_total": 8,
    "request_interval_ms": 0
  },
  "output": {
    "default_dir_name": "stock_suspensions_tdx",
    "file_name_template": "{interface_name}_{data_date}_{run_time}"
  }
}
字段类型必填说明
namestring下载 profile 唯一名
interface_namestring对应接口
display_name_zhstring中文名
resource_groupstring资源组,用于全局调度
modestringsnapshotincrementalhistorystream_recording
default_optionsobject单任务默认执行参数
default_limitsobjectProvider 建议限流,最终由核心调度器裁决
outputobject文件输出建议

resource_group 是插件声明,不是 core 写死常量。例如 TDX Provider 可以声明 tdx.quotetdx.f10tdx.ext;其他 Provider 可以声明自己的资源组。核心调度器只按声明动态建池。

default_limits 是建议值,不是插件的权力边界。管理员配置可以覆盖。DownloaderProfile 只描述一个接口如何被显式下载或被 legacy collector 复用;新采集器应通过 CollectorSpec 的 runner_entry 进入 CollectorRegistry。

6.8 CollectorSpec

CollectorSpec 描述插件提供的采集任务入口。新模型中,采集器插件和数据源 Provider 插件平级:采集器不要求存在对应 Provider,不要求存在 interface_name,也不要求存在 downloader_profile。当前 Provider manifest 中的 collectors 是 legacy 兼容路径,可继续读取,但不得作为新插件推荐形态。

{
  "collector_id": "tdx.daily.close_refresh",
  "display_name_zh": "TDX 收盘后日线刷新",
  "description": "收盘后按股票池采集最新日线并写入 AxData 数据层。",
  "collector_plugin_id": "axdata.collector.tdx_daily",
  "dataset_id": "tdx.daily",
  "asset_class": "stock",
  "category": "daily",
  "resource_group": "tdx.quote",
  "runner_entry": "axdata_collector_tdx_daily.runner:run",
  "default_schedule": {
    "kind": "manual_or_cron",
    "cron": "0 18 * * 1-5"
  },
  "default_params": {
    "adjust": "none"
  },
  "output": {
    "layer": "raw",
    "formats": ["parquet"]
  },
  "quality": {
    "required_columns": ["ts_code", "trade_date"]
  }
}
字段类型必填说明
collector_id / namestring采集器唯一名;name 为旧字段别名
display_name_zhstring中文名
descriptionstring说明
collector_plugin_idstring贡献该采集器的插件 ID
dataset_idstring输出数据集 ID
asset_classstring资产类别
categorystring业务分类
resource_groupstring默认资源组
runner_entrystringCollector Runner 调用的 Python 入口
default_scheduleobject默认调度建议,用户可覆盖
default_paramsobject默认采集参数
config_schemaobject参数和本地配置 schema
outputobject输出层、格式和路径建议
qualityobject质量检查契约
lifecycle_statusstringexperimentalstabledeprecated
interfacesarray[string]deprecated;旧 Provider manifest 兼容字段
downloader_profilestringdeprecated;旧 Provider manifest 兼容字段
required_interfacesarray[string]deprecated;旧 Provider manifest 兼容字段

CollectorSpec 只是声明,不代表插件可以绕过 AxData 统一调度。采集器运行必须进入 AxData Collector Runner,由 core 负责队列、状态、日志、取消、失败退避、资源组限制、写入锁和 metadata 记录。新 runner 路径禁止通过 /v1/request、SDK call、ProviderRegistry interface route 或旧 DownloaderProfile -> Adapter 的接口采集链路。

6.9 DependencySpec

AxData 插件是本地 Python 代码包,依赖风险由用户和插件作者承担。AxData 的职责是安装前检查和提示,不做复杂自动解冲突。

{
  "name": "beautifulsoup4",
  "version_spec": ">=4.12",
  "optional": false,
  "source": "pypi",
  "wheel": "wheels/beautifulsoup4-4.12.3-py3-none-any.whl",
  "description": "解析公告 HTML。"
}
字段类型必填说明
namestringPython distribution 名
version_specstringPEP 440 版本约束
optionalboolean是否可选依赖
sourcestringbundledpypisystem 或说明文本
wheelstring.axp 内置 wheel 路径
descriptionstring依赖用途

依赖策略:

6.10 ConfigSchema 与 RequiredConfig

config_schema 用来表达插件希望用户自行配置的环境变量、配置文件键或其它本地配置提示。已有的 required_config 保留为兼容投影;可以把 config_schema.required_config 与顶层 required_config 映射为同一组 RequiredConfig。新插件优先写 config_schema,旧 Provider manifest 继续兼容顶层 required_config

{
  "name": "TUSHARE_TOKEN",
  "kind": "env",
  "required": true,
  "description": "用户自己的 Tushare token。AxData 不保存、不注入、不代理。"
}

required_config 只用于展示和检查提示。AxData 不托管、不注入、不代理、不保存第三方源凭据。插件如需上游 token,应自行从环境变量、配置文件或它自己的机制读取。

7. Serialization Rules

以下 dataclass 或等价模型必须有稳定的 JSON 序列化和反序列化规则:

规则:

axdata plugin check 至少检查:

8. Registry Discovery

Registry 发现流程:

  1. 使用 importlib.metadata.entry_points(group="axdata.plugins") 找到多能力候选插件,同时兼容读取 axdata.providers 中的旧 Provider 候选。
  2. 对每个 entry point 找到所属 distribution。
  3. 从 distribution 文件中读取 axdata-plugin.json 或兼容读取 axdata-provider.json
  4. 不 import Provider 模块,先解析 manifest。
  5. 检查 manifest_version
  6. 检查 plugin_api_version
  7. 计算 effective_trust_level
  8. 读取 AxData 启用配置。
  9. 将 Provider 能力合并到 Source Provider Registry,建立 interface_name -> provider_id 精确路由表。
  10. 将 Collector 能力合并到 Collector Registry,建立 collector_id -> collector_plugin_id catalog;旧 Provider manifest collectors 以 legacy_source=provider_manifest 导入。

axdata.providers 候选只提供 Provider 能力;axdata.plugins 候选可以没有 Provider,但如果提供 interfaces,则必须声明 provider 信息并满足 Provider 路由规则。

插件状态:

状态含义
installed已安装,但未启用
enabled已启用,可参与 Registry
disabled已禁用,不参与路由
uninstalled预装插件已从当前 AxData 管理状态移除;能力不参与目录、路由或任务模板,但随包代码未必物理删除
failedmanifest 或加载失败
incompatible版本不兼容
conflict接口名冲突,需要用户处理

一个插件失败不得影响其他插件。Registry API 应返回失败原因,供 Web 和 CLI 展示。

provider_id 是 Provider 的唯一身份。Registry 不允许外部 Provider 使用已经注册的预装插件 provider_id 覆盖预装插件,也不允许两个外部插件用同一个 provider_id 静默互相覆盖。发生重复时,后注册的候选必须标记为 failed 并保留原 Provider 的状态和路由。

9. 本地信任与责任模型

AxData 插件是用户本地安装并运行的 Python 代码。AxData 不做中心化插件审核、不做插件市场、不做作者签名验签,也不把 manifest 里的作者声明包装成安全保证。用户从哪里拿插件、是否安装、是否启用,均由用户本地自行决定并承担风险。

Manifest 中的 declared_trust_level 是作者自报,只能用于展示。Registry 实际使用 effective_trust_level,但该字段只服务冲突裁决和 UI 提示,不代表沙箱或安全认证。

effective_trust_level 计算规则:

情况effective trust
AxData 随主包提供的预装能力official
本地安装的外部插件community
来源不明community

如果外部插件自报 official,Registry 必须降级为 community,并可显示“声明为 official,未验证”。AxData 不提供签名升级通道。

Checksum 的作用只限于 .axp 文件完整性和打包一致性检查:

启用插件即表示允许该插件的 Python 代码在当前环境运行。AxData 不应把 manifest 中“是否联网”“是否安全”“是否 official”等作者声明包装成安全保证。真正的运行授权来自用户自己的安装和启用决定。

10. Conflict Resolution

interface_name 必须全局唯一。冲突处理规则:

  1. 先按 effective_trust_level 排序:official 高于 community
  2. 同级时,预装插件高于外部插件。
  3. 用户显式 override 高于默认裁决。
  4. 如果两个同级外部 Provider 撞名,且用户没有显式 override,双方都标记为 conflict,该接口不可用。
  5. 不允许静默覆盖。
  6. 不允许因为一个冲突导致整个 Registry 不可用。

示例:

Provider AProvider B结果
预装插件community预装插件胜出,community 标记 conflict
communitycommunity双方 conflict,等待用户处理
communitycommunity + 用户 overrideoverride 指定方胜出

用户处理方式:

11. Install And Enable

安装不等于启用。

动作含义
installpip、Web、AXP 或随 AxData 提供代码包
enableAxData 配置允许该 Provider 参与 Registry
disableProvider 保留安装,但不参与 Registry
uninstall外部插件删除代码包;预装插件从当前 AxData 管理状态移除并隐藏能力;都不删除用户数据

默认规则:

启用配置属于 AxData,不属于 pip。社区或第三方插件即使能被 pip entry point 发现,只要 AxData 配置未启用,Registry 就不得调用该 Provider;默认能力可由 AxData 明确列入默认 enabled 白名单。

卸载插件不删除 data/metadata/logs/ 中用户已经采集的数据、运行记录或本地任务配置。插件贡献的 interfaces、downloaders、collectors 和 task templates 会随插件禁用或卸载从可用能力中消失;用户创建的 Task 保留,dependency_status 变为 disabledmissinguninstalled 后不可运行;Run History 是历史事实,永远保留。重新安装或重新启用插件后,Task 可以恢复运行。

12. Routing Rules

最终路由必须是精确路由:

interface_name -> Registry -> Provider -> Adapter

旧的 interface_name.endswith("_tdx") 或类似后缀兜底不应继续作为路由依据。处理时可以分两步:

  1. Registry 精确路由和旧兜底并存,确认全部接口都能命中 Registry。
  2. 单独删除旧兜底,并补测试防止回归。

不得让接口名后缀决定 Adapter,否则社区插件可能通过命名误入 TDX 路由。

13. 归一化契约

axdata-core 提供归一化工具,Provider 应优先使用这些工具,而不是各自实现一套。

标准资产类型:

stock / index / etf / fund / bond / future / option / fx / macro

代码与日期:

类型标准
A 股股票000001.SZ600000.SH430047.BJ
交易所筛选SSESZSEBSE
日期YYYYMMDD
日期时间ISO 8601 或明确时区的字符串

字段规则:

进入 core/factor 的数据必须遵守 docs/schema.mddocs/data-layers.md 的分层规则。源端直取可以返回临时数据,但字段也应尽量使用同一归一化规范。

14. Collector Runner 与 Downloader Engine 契约

核心 Runner/Writer 必须中立。新采集器推荐流程:

Collector Trigger -> CollectorRegistry -> runner_entry -> Records -> Writer -> Quality -> Metadata

职责分工:

组件职责
CollectorRegistry管理 collector specs、collector-only 插件、runner entry、dataset_id 和 legacy 导入
CollectorSpec声明采集器 ID、插件 ID、输出数据集、资源组、默认参数、输出和质量契约
runner_entry执行采集器自带取数逻辑并返回 records 或可写结果
Writer按格式、路径和写入模式写文件
Quality做质量检查和统计
Metadata记录 run、stage、参数、输出文件、质量结果和可追溯信息

新 runner 路径禁止通过 /v1/request、SDK call、ProviderRegistry interface route 或旧 DownloaderProfile -> Adapter 的接口采集链路。采集器可以自带上游客户端、读取本地文件或复用公共库;无论数据从哪里来,写入和质量检查都必须回到 AxData Writer/Quality/Metadata。

当前 legacy 下载引擎流程。它服务显式下载和旧 Provider manifest collectors,不是新采集器主路径:

Collector Trigger -> DownloaderProfile -> RequestPlanner -> Adapter -> Records -> Writer -> Quality -> Metadata

职责分工:

组件职责
DownloaderProfilelegacy 字段,声明一个接口如何被下载、默认参数、资源组、输出建议
RequestPlanner把采集需求拆成源端请求计划
Adapter执行源端请求

旧 Provider manifest collectors 可以继续通过 DownloaderProfile -> RequestPlanner -> Adapter 执行,作为过渡兼容。Collector 负责“什么时候跑、排队、状态和失败处理”;legacy Downloader 负责“怎么批量请求、并发、拿数据、写 Parquet 和质检”;Provider/Adapter 负责“怎么请求具体上游”。TDX 的多服务器、长连接、批大小、代码池、题材补漏、文件命名,都属于 TDX 插件的 Provider/Profile/Planner,不应写死在 core。

15. Resource Groups

Provider 可以通过 DownloaderProfile 声明 legacy 下载资源组;独立 CollectorSpec 也应直接声明资源组:

{
  "resource_group": "tdx.quote",
  "default_limits": {
    "max_active_jobs": 1,
    "max_connections_total": 8,
    "request_interval_ms": 0
  }
}

本规范只定义插件如何声明资源组。采集调度器本体放到 docs/collector-scheduling.md 单独设计。

调度原则:

16. 后端 Catalog 契约

长期前端目录不应以 TS 静态文件为真相源。接口目录由插件 manifest 的 menu_path 声明,经 Registry 返回给 Web;Web 只做通用渲染,不为通达信、巨潮、腾讯、新浪等具体数据源硬编码接口树。后端 catalog 应由 Registry 生成,并至少提供:

字段说明
interface_name接口名
display_name_zh中文名
provider_idProvider 身份
source_code数据源命名空间
source_name_zh中文源名
asset_class资产类型
menu_path菜单路径
parameters参数控件
fields字段说明
examples请求样例
reference_sections静态参考表
collection是否支持采集
declared_trust_level作者声明信任等级
effective_trust_levelRegistry 计算信任等级
plugin_statusenabled、disabled、failed、conflict、incompatible
required_config仅展示的配置提示

Web 应能展示 disabled、failed、conflict、incompatible 的原因。

17. CLI 命令

常用 CLI:

axdata plugin list
axdata plugin check
axdata plugin build
axdata plugin enable axdata.source.tencent
axdata plugin disable axdata.source.tencent
axdata plugin info axdata.source.tencent

命令行为:

命令行为
plugin list列出已发现 Provider、状态、版本、effective trust
plugin info展示 manifest、冲突、required_config
plugin check校验 Provider 代码、manifest、样例、profile
plugin build生成 manifest,并可构建 wheel
plugin enable写 AxData 启用配置
plugin disable写 AxData 禁用配置

插件安装可以使用 pip、AXP 或 Web/CLI 提供的安装入口;具体可用命令以当前版本为准。

18. AXP 安装包

.axp 是 Web/CLI 友好的本地安装信封,不是核心插件格式。核心格式仍然是 Python wheel + entry point + embedded manifest。

AXP 也是分发和安装单位,不是能力类型。导出或安装 AXP 后,AxData 仍按 embedded manifest 中的 providerinterfacescollectorsdownloaders 等能力声明分流到 ProviderRegistry 和 CollectorRegistry;不能靠文件名判断它是数据源插件还是采集器插件。

建议结构:

plugin.axp
  manifest.json
  README.md
  LICENSE
  wheels/
    axdata_source_xxx-0.1.0-py3-none-any.whl
  samples/
  checksums.txt

Web 安装现实边界:

.axp 中 manifest 用于安装前预览,checksum 用于完整性和打包一致性检查。AxData 不做签名验签,也不做插件市场。依赖处理规则:

19. 当前支持能力

当前实现已经支持 ProviderRegistry、后端 catalog、精确路由、enable/disable、CLI/API/Web、外部腾讯/巨潮/TDX/TDX Ext 包、.axp 安装和安装管理。独立采集器体系也已进入主路径:

  1. Manifest/Registry 已兼容 collectorsdependenciesconfig_schema,并保持现有 Provider manifest 兼容。
  2. Collector 插件协议已支持独立 CollectorSpec / Collector manifest、collector-only plugin、runner_entrydataset_id 和 legacy Provider manifest 导入。
  3. CollectorRegistry 已成为 /v1/plugins/collectors、CLI plugin collectors 和 Web 采集页的采集器 catalog 事实源;ProviderRegistry 不再作为采集器事实源。
  4. Collector Runner 已新增 runner_entry 路径,统一接入 Writer、Quality 和 Metadata;旧 DownloaderProfile -> RequestPlanner -> Adapter 只作为 legacy 下载引擎保留。
  5. 默认 collector catalog 当前是 TDX 9 个 independent collectors;交易所保留 Source Provider 接口和兼容下载入口,但不再提供默认 CollectorSpec;stock_capital_changes_tdx 保留为源端接口和兼容下载入口,不再作为采集器展示。巨潮、腾讯、东方财富和新浪仍作为 source_request Provider 保留接口,但默认不提供采集器。

维护者可以继续完善全市场 raw/staging -> core 转换、更多独立 Collector plugin、依赖解析体验、PyPI 发布和版本兼容策略。

20. 维护者测试清单

维护插件协议或 Registry 时至少覆盖以下测试: