该写 Mod
要换数据源、事件源、撮合与风控规则,或给框架加通用 API。
RQAlpha 项目研究站 · Mod 扩展体系
本项目的扩展方式是 Mod:撮合、风控、税费、账户、分析输出、调度、进度条都是可启停的 Mod,官方文档明确建议「不要在 RQAlpha 项目里直接改,而是把 Mod 作为独立项目开发」。更进阶的用法是通过 register_api 给框架加自己的 API——内置的 FuncatAPIMod 就把通达信/同花顺的公式表达能力搬到了 Python 里。
依据官方 Mod 列表整理的模块分层示意;非官方架构图。
rqalpha_mod_xxx 开头,旧文章的命名方式可能与当前加载规则不符来自官方 README 与 index 文档的 Mod 列表,默认在 mod_config.yml 中全部启用。
| Mod | 职责 | 你会用到它的场景 |
|---|---|---|
sys_accounts | 股票与期货的下单 API 实现、持仓模型、股票分红退市等行为控制 | 控制卖空、资金不足时是否自动使用剩余资金下单 |
sys_simulation | 模拟撮合引擎与回测事件源,支撑回测与模拟交易 | 切换撮合引擎、设置滑点与手续费乘数、信号模式 |
sys_risk | 对订单做事前风控校验 | 回测里模拟「下单前被风控拦下」的情形 |
sys_transaction_cost | 股票与期货的交易税费计算逻辑 | 评估费用对策略收益的侵蚀;自定义合约费率 |
sys_analyser | 记录每日下单、成交、组合、持仓,计算风险指标并输出 CSV / 图表 | 决定结果输出到哪、是否画图、基准怎么设 |
sys_scheduler | 提供定时器:按特定周期执行指定逻辑 | 周频/月频调仓,不必自己在 handle_bar 里判断日期 |
sys_progress | 在控制台输出回测进度条 | 长周期回测时判断「还在跑」还是「卡住了」 |
rqalpha/mod_config.yml 顶部写着「WARNING: DO NOT EDIT」,七个系统 Mod 均为 enabled: true;要改行为,请用命令行 -mc 或用户配置文件,而不是改这个文件。三条命令 + 一种传参方式,覆盖日常使用。
1. rqalpha mod list 查看当前已安装的 Mod 及启用状态;
2. rqalpha mod enable xxx 启用某个 Mod(如第三方数据 Mod);
3. rqalpha mod disable xxx 禁用;
4. 运行策略时用 -mc 传该 Mod 的配置项,例如官方示例:rqalpha run -rt p -fq 1m -f strategy.py --account stock 100000 -mc sys_accounts.auto_switch_order_value True。
| 配置位置 | 写法 | 优先级与注意点 |
|---|---|---|
| 命令行 | -mc mod_name.key value(可多个) | 临时试参数最方便;优先级低于策略内配置 |
| 用户配置文件 | config.yml 的 mod: 段 | 适合长期固定;注意 generate-config 生成的模板不包含 Mod 配置项 |
| 代码调用 | run_file(strategy, {"mod": {"sys_analyser": {...}}}) | 适合参数扫描:每次运行生成不同的 mod 配置 |
官方 mod 文档用 rqalpha-mod-hello 做最小示例,结构固定、可照抄。
| 组成 | 内容 | 说明 |
|---|---|---|
| 项目命名 | 仓库/包名 rqalpha-mod-<name>,Python 包名 rqalpha_mod_<name> | 官方推荐 Mod 作为独立项目开发,不改框架源码 |
__init__.py | 定义 __config__ 默认配置 + load_mod() 返回 Mod 实例 | load_mod 是框架加载入口,返回你的 Mod 类实例 |
mod.py | 继承 AbstractMod,实现 start_up(env, mod_config) 与 tear_down(success, exception=None) | start_up 里做注册与监听,tear_down 做收尾 |
| 自定义组合(Portfolio) | 在 start_up 中监听 EVENT.INIT_PORTFOLIO,用 env.set_portfolio() 注册 | 官方说明该事件在数据源与 Broker 初始化完成后触发;注册后框架不再创建默认组合 |
| 扩展 API | 在 start_up 中用 register_api 注册新 API | 官方内置 FuncatAPIMod 用这种方式把通达信/同花顺公式表达能力搬进 Python |
| 打包安装 | 写 setup.py、VERSION.txt、requirements.txt,然后 pip install -e . | 开发态安装便于改代码即时生效 |
rqalpha-mod-tushare(用 Tushare 数据)、rqalpha_mod_sys_stock_realtime(股票实时数据)等;官方也欢迎把自研 Mod 提交进列表,但发布需要遵守约定的格式。Mod 是设计给「替换框架行为」的,不是所有个性化需求都值得写。
要换数据源、事件源、撮合与风控规则,或给框架加通用 API。
只是改参数(滑点、费率、基准、日志)——用 -mc 或配置文件即可。
先 rqalpha mod list 看看是否已有系统 Mod 覆盖;再查生态里是否已有第三方 Mod。
Mod 与框架版本耦合,升级 RQAlpha 后需要回归测试;接口变更以官方文档为准。
Mod 的问题多半是「加载顺序/启用状态/配置层级」三类。
| 现象 | 原因 | 处理 |
|---|---|---|
rqalpha mod enable 后没生效 | Mod 未安装成功,或名称写错(命令里用的是 mod 名,不含 rqalpha-mod- 前缀) | 先 rqalpha mod list 确认在列表里;再看是否 enabled |
pip install -e . 失败 | setup.py 与 requirements.txt 不匹配,或 pip 版本导致 parse_requirements 报错 | 按官方示例处理 pip 兼容分支;确认在 Mod 项目目录内执行 |
| 自定义 Portfolio 后回测报错 | 自定义实现与框架 Portfolio 接口不兼容 | 继承官方 Portfolio 类再覆写;通过 EVENT.INIT_PORTFOLIO 注册而不是手工 new |
| 注册的 API 在策略里找不到 | 注册发生在 start_up 之前/之后时机不对,或策略未使用 from rqalpha.api import * | 在 start_up 内注册;确认导入方式与官方示例一致 |
| 配置项写了不生效 | 与参数优先级冲突(策略内 > 命令行 > 配置文件 > 默认) | 按优先级逐层排查,见运行策略页 |
| 升级框架后 Mod 失效 | 接口或事件名变化 | 对照目标版本的官方文档修正;锁定版本后再升 |
官方开发文档以 rqalpha-mod-hello 为例给出最小示例;下面把它的文件、代码与每一步的预期输出摊开,照着走完就能看到生命周期被调用。
1. 建独立开发环境:conda create rqalpha-mod-hello —— 官方文档的做法是给这个 Mod 单独建一个环境,在其中把 RQAlpha 装好(预期:Mod 的依赖与主环境互不污染,安装问题按安装与数据页的排查表处理);
2. 按官方项目结构建目录:外层仓库名 rqalpha-mod-hello,内含 requirements.txt、setup.py,以及 Python 包目录 rqalpha_mod_hello/(里面放 __init__.py 与 mod.py)——包名用下划线、仓库与 PyPI 名用连字符(预期:目录结构与官方示例一致,框架才能按约定找到加载入口);
3. __init__.py 里写两样东西:默认配置 __config__ = {"url": None},以及加载入口 def load_mod(): from .mod import HelloWorldMod; return HelloWorldMod()(预期:框架导入这个包时会调用 load_mod(),拿到你的 Mod 实例);
4. mod.py 继承 AbstractMod,实现 start_up(self, env, mod_config) 与 tear_down(self, success, exception=None)(预期:官方示例在这两个方法里各打印一行,运行时看到 >>> HelloWorldMod.start_up,结束时看到 >>> HelloWorldMod.tear_down);
5. 补齐 setup.py、VERSION.txt、requirements.txt:setup.py 里读依赖的写法要按 pip 版本分支(pip ≥ 10 用 from pip._internal.req import parse_requirements,pip ≤ 9.0.3 用 from pip.req import parse_requirements),name 写成 rqalpha-mod-hello(预期:pip install -e . 成功;-e 是开发态安装,改项目内文件即时生效);
6. 启用并确认:rqalpha mod enable hello,再 rqalpha mod list(预期:列表里出现 hello 且为启用状态——命令中用的是 Mod 名,不带 rqalpha-mod- 前缀);
7. 跑一次回测或模拟交易(预期:日志里出现在第 4 步写的那两行打印,说明生命周期钩子确实被框架调用)。
load_mod 函数,它返回继承自 AbstractMod 的实例,且该函数所在文件按 rqalpha_mod_xxx 命名;②有自定义参数时实现 __mod_config__ 变量——它是字符串、内容为 yaml 格式(支持注释),RQAlpha 会自动把它扩展进默认配置项;③包名按 rqalpha-mod-xxx 发布到 PyPI 之后,才能用 rqalpha mod enable/disable 管理它。注意 __config__ 与 __mod_config__ 不是同一个东西:前者是包内默认配置字典,后者是给使用者的 yaml 配置模板字符串,别把 yaml 文本写进 __config__。官方「基本概念」文档把重要模块抽成了接口,系统 Mod 就是这些接口的默认实现;下面是接口清单与关闭系统 Mod 时的对照。
接口(rqalpha.interface) | 官方文档给出的说明 | 对应的系统 Mod | 注意点 |
|---|---|---|---|
策略加载模块AbstractStrategyLoader | 加载策略,并把策略运行所需的域环境传递给策略执行代码;扩展它可以实现自定义策略源、自定义 API 载入 | 七个系统 Mod 中没有对应项 | 属于框架启动链路,改它等于改策略的装入方式 |
事件生成模块AbstractEventSource | 回测与实盘都要基于数据源生成事件,该模块负责生成策略执行对应的事件 | sys_simulation(回测/模拟交易支持) | 自建事件源时,事件顺序与频率要和你选的 frequency 对齐 |
数据源模块AbstractDataSource | 日线数据、分钟线数据、财务数据、债务数据等都可以通过该模块扩展和使用 | 无默认 Mod 承担,通常由第三方数据 Mod 或自研 Mod 实现 | 自接数据要自己保证复权、停牌与交易日历口径,框架不代你做 |
券商代理模块AbstractBroker | 下单、账户、撮合逻辑都来自券商与交易所;回测本身就是一个模拟交易所,扩展该模块可自定义 Broker,也可用于扩展实盘 | sys_simulation / sys_accounts | 这是接入实盘的主要入口,也是出错时最难定位的一层 |
仓位模型AbstractPosition | 官方列出该抽象类;mod_config.yml 注明 sys_accounts 负责「载入 Account 和 Postion Model」 | sys_accounts | 替换仓位模型要同时考虑分红、退市等持仓行为 |
价格板 / 持久化 / 前端校验 / 税费判定AbstractPriceBoard、AbstractPersistProvider、AbstractFrontendValidator、AbstractTransactionCostDecider | 官方「基本概念」只列出这些抽象类,未展开说明 | 税费判定对应 sys_transaction_cost;其余三个未出现在 mod_config.yml 的 Mod 清单里 | 文档没写清的部分只能读实现;替换前先确认框架版本 |
| 系统 Mod | 关掉或替换后的直接后果 | 什么时候才值得动它 |
|---|---|---|
sys_accounts | 账户与持仓模型不再由它载入,股票/期货的下单与持仓接口失去默认实现,要由你自行提供 | 要换自己的账户/持仓模型,或只想调资金行为(auto_switch_order_value、financing_rate)——后者用 -mc 即可,不必关 |
sys_simulation | 回测与模拟交易失去默认撮合与事件源,回测跑不起来 | 要替换成自己的模拟撮合/事件源;只调撮合引擎、滑点、手续费乘数时改参数更省事 |
sys_analyser | 记录下单/成交/组合/持仓并输出指标与图表的这一环没有了,-o、--plot、基准等输出随之消失 | 要把结果接进自己的分析管道,或做只关心运行速度的裸回测 |
sys_risk | 下单前不再有默认的事前风控校验 | 要换成自己的风控规则,或专门观察「订单被拦下」时的策略行为 |
sys_transaction_cost | 默认的股票/期货税费计算不再参与,结果里不再含这部分成本,与真实情形不可直接比较 | 要自定义合约费率,或刻意做「不计成本」的对照实验 |
sys_scheduler | 定时器失去默认支持,scheduler.run_daily / run_weekly / run_monthly 不再可用,周期调仓要自己判断日期 | 要换一套调度实现,或调试调度触发时机 |
sys_progress | 控制台不再显示回测进度,长周期回测不易判断「还在跑」还是「卡住了」 | 批量扫描不想刷屏时,直接用 --no-progress 关显示即可,不必关 Mod |
rqalpha mod disable xxx 只是改启用状态,代码仍在环境里,随时可以再启用;上面这些后果按官方接口说明与 mod_config.yml 注释推得,具体行为以官方文档与源码实现为准,不同版本可能有差异。开源版不提供分钟级数据,这是很多人要接自有数据的原因。官方文档给了三条路径(策略内直接读、替换数据源、替换事件源),加上扩展 API 与授权数据服务,一共六条。
| 路线 | 怎么做 | 适用场景 | 代价 | 注意点 |
|---|---|---|---|---|
| 策略内直接读自有文件 | 在策略文件里 import 自己的模块或读本地文件 | 一次性研究、数据量小 | 最低:几行代码 | 路径要写成绝对路径,换目录运行会失效 |
| 替换行情数据源 | 实现数据层接口,替换行情读取(官方 data_source 文档给过替换成第三方数据的示例) | 要接分钟级或其他市场行情 | 中等:要理解数据层接口边界 | 替换后必须重新核对复权、停牌、涨跌停字段是否齐备 |
| 替换基础数据 | 替换合约与交易日历相关的取数 | 标的信息或交易日历与官方数据不同 | 中等 | 标的代码规则(.XSHG/.XSHE 等)要保持一致 |
| 替换事件源 | 实现事件源接口,决定「什么时候触发策略」 | 接实盘、接自定义事件流 | 较高:涉及运行节奏 | 事件源变了,回测与实盘的时序假设要重新确认 |
| 用扩展 API 暴露自有数据 | 通过 register_api 把自有数据注册成策略可调用的接口 | 想让策略像调用内置接口一样用自有数据 | 中等 | 接口名与返回值要符合框架约定,否则策略侧容易写错 |
| 使用授权数据服务 | 安装数据服务包、配置许可后使用(对应 update-bundle 的每日更新) | 要每日更新、要分钟级、要用扩展接口 | 成本:需要授权与配置 | 框架许可与数据许可相互独立,要分开确认 |
在这套体系里 Mod 就是插件:以独立 PyPI 包发布,通过 load_mod() 被框架加载,能替换账户、撮合、数据源、事件源等核心部件,也能注册新 API。区别在于它更贴近框架内部接口,能力大、耦合也更深。
技术上可以,但官方文档明确不建议:建议把 Mod 作为独立项目开发。直接改源码会让后续升级与协作变困难。
可以,这正是 Mod + 数据层接口的典型用途:实现数据源/事件源接口后用 Mod 注册接管。官方文档的 development 章节(data_source / event_source)给出了接口说明。
可以(mod disable),但要清楚后果:例如关掉 sys_analyser 就没有指标输出,关掉 sys_simulation 就没有撮合。除非你在做底层替换,否则建议保持默认全开。
官方描述为「将通达信、同花顺的公式表达能力移植到 Python」,是内置 Mod 中通过 register_api 扩展 API 的实例。若你熟悉通达信公式,可研究它的实现方式来减少改写成本。
注意框架本身的许可边界:非商业用途按 Apache 2.0,商业用途需要米筐科技授权;自研 Mod 的许可由你自己决定,但调用框架的部分仍受其许可约束。详见许可与数据边界页。