始于 2006 年(前身 galaxy)、2012 年起以 Hikyuu 之名开源的量化研究框架,发布 3.0.0。这一版把组合引擎重写为
MultiSystem:策略与组合同构、可任意深度嵌套,用三种运行模式覆盖多策略信号汇总、资金配置与共享账户;同时把 Python 侧能并行的路径全部释放 GIL,让嵌套组合放大后的计算量仍压在设计窗口内。此外补齐融资融券记账与多空双向,并把行情到绩效整条链上的空值与金融计算收归为一套全局契约:缺失产NaN,不产0也不产inf。3.0 属破坏性版本,迁移清单见发布说明。
一、Hikyuu 是什么
Hikyuu 是一个 C++/Python 开源量化研究框架,Apache-2.0 协议,GitHub 上已有 3.6k star。它不做券商对接、不做自动下单,只把一件事做透:让策略研发到回测这一段,金融语义是完整且可校验的。
它的血统比 GitHub 仓库长得多:前身是作者 2006 年起开发、托管在 SourceForge 上的 galaxy,2012 年迁到 GitHub 并以 Hikyuu 之名开源——托管平台换了整整一代。二十年里内核重写过几轮,那套"按系统化交易的必答问题切分结构"的想法没有变——一次大版本重构发生在第二十年,不是追新,而是结构到了必须扩的那一步。
一句立项至今没有变过的立意:不让一个"能跑通"却不成立的策略,被当成结论。
为此它按理论问题而非工程模块切分结构——一个策略必须回答市场状态、条件、信号、仓位、退出与成交价;一个组合必须回答选谁、分多少钱、按什么评分。每一环都是可替换的部件(EV / CN / SG / ST / PG / MM / SP / SE / AF / MF),替换后结算与校验仍然成立。数据侧支持 HDF5 / MySQL / ClickHouse / SQLite 四种存储,Python 侧与 numpy、pandas、TA-Lib 互通。
3.0 是 2.x 系列六年来的第一个大版本号变更,动的是三件最硬的事:组合语义、计算吞吐,以及从行情到绩效整条链上的金融计算。
第一件决定框架能表达什么,第二件决定它跑不跑得动,第三件决定跑出来的东西算不算数。三者缺一:表达不了的策略只能自己写调度;跑不动的组合回测等于没有;而如果成本、除权、空值在链条上有一处没被建模,前两件做得越好,只是越快得到一个错误结论。
二、组合即策略:从"一条曲线"到一棵可嵌套的组合树
过去十年,量化框架的默认形态是"一个策略跑一条资金曲线"。多策略怎么做?多数人的答案是跑 N 次、把结果拼起来看。问题是:拼起来的曲线不对应任何真实账户——资金在策略之间怎么划、划多少、划完还能不能收回、某个策略被清仓后现金去哪了,全在框架之外。
Hikyuu 3.0 的答案是 MultiSystem:组合不是策略的容器,组合本身就是策略。
-
一套语义,两种粒度:组合节点持有完整的交易语义,可以像子系统一样被驱动、被评估、被嵌套;嵌套深度不限。
-
三种运行模式,覆盖三类真实账户结构:
-
A 信号聚合(
PF_SignalAggregate):子系统只当信号源,父组合汇总信号后统一下单,适合"多视角看同一批标的"; -
B 资金配置(
PF_Simple):父组合按评分划配额,子系统在配额内自主交易,适合 FOF / MOM 式调仓; -
C 共享账户(
PF_WithoutAF):子系统直接在父账户上按自身资金管理交易,兼容旧Portfolio行为。
-
-
模式可混搭:子系统可以是任意模式的另一个
MultiSystem,父子的账户拓扑、清仓语义与调仓节拍都有明确约定,而不是靠约定俗成的默认值。
配套的资金分配体系也重做为三层可替换算法(AllocateFundsBase):L1 决定"分多少权重",L2 决定"换算成什么目标持仓",L3 做"下单前的风控裁剪"。新增的 AF_FixedAmount(绝对金额分配)与 AF_MultiFactor(评分驱动分配)只是这两个位置的示例实现;自定义分配器只需实现 _allocate(date, tm, contexts, query, mode) 一个钩子。风控参数 max_single_position / max_total_position 在权重层按比例缩减,fixed_amount 在金额层按整数个额度截断——超出上限时的行为是确定的,不是"尽量"。
组合的运行期状态可序列化,聚合对象支持 pickle;MomentResult.pendingOnNextOpen、axis_mode / adjust_cycle / adjust_mode / trade_on_close 等参数在 readyForRun 时快照生效,回测中途改参数不会再悄悄改变语义。
对一个团队而言,这意味着策略池可以被整体回测,也可以被单独核算;对个人而言,意味着"多策略"不再是一个需要自己写调度代码的工程问题。
三、极致性能:不是跑分,是组合能不能落地的前提
组合引擎有个绕不开的代价:计算量按嵌套层数放大。一个 20 个子系统的组合,每个子系统再挂 5 个品种,一轮调仓要驱动的状态就是单策略的百倍量级;如果因子还在 Python 层逐股循环,研究循环会被等待时间直接切断。
所以 3.0 在性能上做的不是微调。快的原因在结构,不在调参:
-
数据是连续的地址块,不是对象数组。 K 线在内存里按字段连续存放,指标按整段做向量化运算;Python 侧拿到的是 numpy 视图,不产生逐条对象的构造开销。
-
指标是 DAG 节点,同一条子表达式只算一次。 多个指标共用同一个子表达式时框架会合并节点,组合嵌套时父子系统共享的市场数据与公共因子也不会被重复计算——这是"组合越复杂、相对优势越大"的来源。
-
3.0 把 GIL 释放铺到了 Python 侧能并行的所有路径上。 K 线与日历的整段磁盘加载、多因子纯 C++ 计算、指标批量计算、账户查询、因子读写、分析与批量辅助接口,都能在 Python 多线程下真正并行,而不是排队等解释器;指标转 numpy 改为连续缓冲批量拷贝,Python 序列转
vector增加 numpy 快速路径。
指标算法也做了针对性重写:EXIST / EVERY / BARSLASTS 的重复重扫改递推,IC 截面与 SPEARMAN 复用临时缓冲,SAFTYLOSS 全量并行,滚动幂和改环形缓冲,SMA 增量从框架起点开始,BLOCKSETNUM 二分定位。多因子新增 get_scores_np / iter_scores 大截面接口——整个截面只构建一个结构化数组,避免每条记录一个 Python 对象。
一句话概括这套性能的意义:单看功能,多数框架都能拼出同样的回测;差距在于拼出来之后还跑不跑得动。 全市场多因子选股从"泡杯咖啡等结果"变成"改一行参数就看见结果"——研究循环里能试的假设数量是另一个量级,这比单次回测的任何数字都更影响产出。
四、从单边到双向:多空与融资融券的完整记账
A 股量化长期是单边市场,很多框架的做空支持停留在"允许负持仓"的程度——能开不能记,一遇除权、送股、分红就错。
3.0 把空头当作一等公民补齐:
-
Strategy新增support_short,order卖出超过多头持仓的部分自动"先平后开"融券开空,另有buy_short/sell_short直接下单; -
记账侧:保证金不足时拒绝下单并只借入缺口,而不是静默注资把收益基数污染掉;新增借券、归还、借券成本、归还成本四类钩子(
get_borrow_cash_cost/get_return_cash_cost/get_borrow_stock_cost/get_return_stock_cost); -
空头与借券持仓随送股、缩股同步调整,并向出借人补偿现金红利(新增
BORROW_ADJUST/SHORT_ADJUST/DIVIDEND_COMPENSATION三类记录,全部可在账本里查到); -
资金管理侧:
MM_Nothing的开空数量按账户净权益计算,借券货款不再膨胀开空额度; -
滑点侧:四个随机滑点模型新增
adverse_only,可选"只施加不利偏移"或"零均值执行噪声";SP_FixedPercent/SP_FixedValue及随机模型均支持多空不对称参数(short_p/short_mean等),平空一侧可以被单独定价。
写空头策略的人都知道,真正难的不是信号,是分红、除权、保证金这几笔账。3.0 把它们从"你自己在策略里补"变成"框架替你记,且记在账本上"。
五、正确性优先:一条链上的金融计算,与一整套 NaN / ±Inf 契约
量化框架的误差很少来自算法。它来自链条:行情 → 复权 → 指标 → 因子 → 信号 → 撮合 → 记账 → 绩效。功能可以一个个拼,链条不能拼——每个环节各自处置空值,误差就在接缝处累积,而且不会报错。
三种最常见的错法,写策略的人都遇到过:
-
用
0.0表示缺失:与合法零撞车,"这只股票没有数据"被读成"它的价格是 0",均线被悄悄拉低; -
除零、零方差产
inf:一次inf进入 20 日滚动窗口,后面 20 天全是inf,再往下的因子、排序、信号全部作废; -
NaN参与布尔判断:NaN在 C++ 与 Python 里都是 truthy,"条件是否成立"变成"条件多半成立",信号凭空多出来。
这三种错都不会抛异常,只会让结果悄悄偏移——偏多少,取决于你哪天才发现。错误不暴露,是这个领域最贵的 bug。
Hikyuu 把这件事做成全局契约,而不是各部件自选:
-
未定义状态一律产
Null(NaN):除零、零方差、全缺失、零基准,都不返回0.0,也不返回inf——0.0会与合法零撞车,inf会污染下游聚合; -
聚合只累加有限值,分母只数有效项:均值至少 1 个有效值、离差至少 2 个,全缺才产
Null。缺失既不吞掉有效数据,也不假装有数据; -
序列化按 IEEE 位模式:NaN / ±Inf / 符号零无损往返,归档跨版本读取后语义不变;
-
交易入口同样受约束:数量非有限或 ≤ 0、成交价非正即放弃下单,非有限的
maxTradeNumber直接拒绝,调仓周期为负抛异常; -
新写的部件自动继承同一口径——这是"契约"与"文档提醒"的区别:不靠使用者记得,靠框架执行与入口守卫。
3.0 沿这条链逐段收紧的地方,都写在发布说明里:
-
指标层:非有限值统一视为缺失。
BARSLASTCOUNT、条件族有效性判断、滚动和与统计量、IIR滤波、零方差族、INSUM跨股聚合不再被 NaN / Inf 永久污染;零除与零方差返回Null,ZSCORE常数序列返回NaN,WINNER/TS_RANK/MRR/ROC族无效输入返回Null;MA/STDEV的 NaN 语义统一为 Welford 有效均值与偏差。 -
因子层:
IC/ICIR权重和为 0 时输出NaN,退化截面与归一化配置按规则传播,不再给出一个"看起来合理"的中间值。 -
信号层:
SignalBase同日多次写入改为按数值合并为净额(净额为正只留买入、为负只留卖出、约为 0 不保留);cycle参数改为标记"依赖组合注入的调仓日",不再隐式改变计算范围。 -
组合层:
AF_FixedWeightList的空、全零、非有限权重改为抛异常——一个权重和为零的组合不该被静默算出来。 -
交易层:委托数量改按滑点后的实际成交价计算,卖单先按
maxTradeNumber截断、买单再按可用现金钳制;止损止盈拒绝非正或非有限参数;环境与条件的组合运算把非有限值按无效处理。 -
记账层:账户重建改为回放全部交易记录类型;本金基准为 0 时返回
Null,未平仓total_profit返回NaN,报表显示N/A而不是 0。
这条链上还有三处口径在 3.0 被整体改掉,同样影响历史回测结果:
复权改为固定基准。 前复权锚定数据最后一日,后复权锚定数据起点,复权结果与查询区间无关;Stock::getKData 与 kdata.getKData 结果一致。同时修复后复权 KData 子查询二次复权、扩区拼接尾部偏移、周线及以上聚合首日量额双计。复权调整为只对价格复权,成交量与成交额保持原始值,与 Wind、聚宽等主流数据源口径一致。
绩效统计口径统一。 收益项以净资产(现金 + 多头市值 − 空头市值 − 借入现金)为分子、累计净投入(入金 − 出金 + 入券 − 出券)为分母;时间统计统一采用自然日、年化因子 365;区间不足 2 天、无投入本金或净资产非正时,年化项按定义返回空值;未定义项统一为 NaN,报表显示 N/A。
交易成本模型重定义。 TC_FixedA 现始终对应当前 A 股费率(过户费按成交金额万 0.1 全市场双向收取、卖出印花税万 5);原先按成交数量收取过户费的模型更名为 TC_FixedAPre2015,TC_FixedA2015 / TC_FixedA2017 冻结为历史口径。
这些不是文档承诺。核心代码里 1300+ 处显式校验拦住规则与输入边界,doctest 用例 1600+ 个、断言 1.6 万条,按"一模块一套件、一边界一用例"组织,空输入、Null<T>()、非有限值与越界异常都在覆盖内;small-test 不依赖真实行情即可在三平台 CI 跑通。
代价是有的:同一策略跑出的收益,通常低于理想化回测——费用扣了、成交等了、权息调了、NaN 老老实实留在了该留的地方。宁可让回测数字难看,也不让一个能跑却错误的结果变成可用的策略。 这也是同一策略在不同框架上跑出不同收益的常见原因:没被建模的环节,结果就取决于使用者是否记得补。
六、破坏性变更与迁移清单
3.0 是破坏性版本。以下四类需要动手改:
|
变更 |
影响 |
处理方式 |
|---|---|---|
|
|
|
时间轴改用 |
|
|
子类钩子由 |
自定义 AF 按三层钩子( |
|
参数键风格 |
统一为小写下划线( |
旧归档不会自动迁移,反序列化后需显式 |
|
归档兼容 |
|
重新生成归档,历史对比需重建基线 |
完整的变更清单(新增特性、优化、缺陷修复、破坏性变更)见项目文档 https://gitee.com/fasiondog/hikyuu/releases/tag/3.0.0。
免责声明:Hikyuu 为开源金融技术研究工具,仅供个人学习、学术研究与数据分析使用,不构成任何投资建议或交易指导,不提供也不内置证券交易服务。框架仅提供通用接口扩展能力,用户自行对接的交易接口及其操作行为,由用户自行承担全部风险与法律责任。
更多信息,参见:
-
项目主页: https://hikyuu.org
-
gitee 地址:https://gitee.com/fasiondog/hikyuu
-
github 地址:https://github.com/fasiondog/hikyuu
-
hub 地址: https://gitee.com/fasiondog/hikyuu_hub
相关链接
-
Hikyuu 的详细介绍: 点击查看