数据与数值约定
这些是每个模块都遵循的规则。若某个函数另有做法,它自己的文档会说明。
数据帧与时间
原生 fincore::dataframe 是 hmdf::StdDataFrame,索引是带符号 64 位 UTC 纳秒时间戳。因此可表示范围是 1677-09-21T00:12:43.145224192Z 到 2262-04-11T23:47:16.854775807Z;超出范围的日历值会抛 input_error,而不是回绕。日内精度被完整保留,utc_year 向更早的时间取整 —— 纪元前一纳秒属于 1969 年,而不是 1970 年。
索引要求由每个 API 自己决定,而且是有意不同的:
要求 |
出现位置 |
|---|---|
严格升序、无重复 |
风险估计、回测与滚动前推验证 —— 索引重复或乱序会抛 |
不要求有序,按行处理 |
模拟路径与分析输入 —— 保留调用方的行顺序,索引按原样复制 |
按相邻判断唯一性 |
归因对齐:那里“索引已排序”是未写明的前提(记为 F10-D11) |
不要假设函数会替你排序或去重。如果某个 API 需要特定顺序,它会校验并说明。
收益率、单位与年化
除非函数另有说明,收益序列都是小数简单收益:0.01 表示 1%。daily_annualization 为 252。按 sqrt(annualization) 缩放的比率直接使用该因子;annualization_factor(frequency) 把 daily/weekly/monthly/quarterly/yearly 映射为 252/52/12/4/1,并原样返回显式覆盖值 —— 包括 0 或负数,因为校验责任在调用方。
权重、价格与金额沿用调用处的单位,从不做隐式换算。需要基点的函数会明确说明。
缺失值与对齐
NaN 是原生的缺失数值标记;它既不是很小的数,也不是 0。三种行为并存,每个函数都会说明自己用哪一种:
丢弃该观测(涉及两个序列时按配对丢弃)。大多数标量风险与收益指标如此。
整体拒绝非有限输入。压力测试与部分风险内核会拒绝含
NaN的收益,而不是跳过它。传播:窗口只要触到缺失值,该窗口就产出
NaN,而不是部分统计量。
对齐同样显式:严格相等、公共索引、内连接,或文档写明的外连接策略。缺失标签从不被静默替换为 0。
加载列时,hmdf::nan_policy::dont_pad_with_nans 按给定值保留;补齐策略会为缺失位置插入 NaN。请选择与帧自身契约一致的那种,并记住空结果常常以空的类型化列返回,而不是缺失列。
所有权与生命周期
make_series与load_column会复制或接管所有权;函数返回的帧拥有自己的数值。validate_returns返回副本,因此通过结果写入永远不会影响输入。portfolio_inputs在接收时复制,materialize()每次调用都返回新帧。有些访问器返回视图(列视图、
std::string_view)。视图只在其帧存活且未被修改期间有效。analysis_context会缓存已算出的指标,因此单个实例在构造上就是单线程的。帧可以随意共享;上下文只在你自己加锁之后共享。
确定性与摘要
需要比较、存储或重放的结果携带摘要,而不是裸浮点数:
运行时摘要给每个字段加长度前缀,并为每个值标注声明的类型,因此分隔符或
bool与1的混淆都不会让两份不同载荷哈希成同一个值。浮点值序列化为小写 IEEE-754 位模式,因此
NaN载荷与带符号零可以完整往返。部分写出器会把负零规范成正零,因为字节会被哈希。覆盖输入的摘要回答“输入是否相同?”;覆盖输出的摘要回答“结果是否相同?”。因子模型的 fingerprint 哈希的是输入,因此两次运行在比较数值之前就能确认一致。
确定性是按函数而言的,不是全局的:带种子的模拟只保证在本库内复现同一序列,只有文档写明 NumPy 映射的函数才承诺与参考实现给出相同数值。
错误
所有库错误都派生自 fincore_error,并带有分类、代码与结构化字段:
情形 |
类型 |
|---|---|
参数错误、列缺失或类型不符、内嵌 NUL、非法索引 |
|
因子面板或配置格式错误 |
|
指标中的定义域校验(例如超出范围的 cutoff) |
返回 |
结构合法帧内的越界值通常以 NaN 回应(例如 (0, 1) 之外的 cutoff),而结构性问题会抛异常。测试会逐字比较拒绝消息,因此两种不同诊断不会合并成一条通过的断言。
报告与文件
报表文档有自己的模式版本,独立于运行时序列化信封与 artifact bundle 清单。写出器会拒绝不安全的目标 —— 空路径、无法创建的目录、契约禁止覆盖的既有文件 —— 并在文档说明的情况下清理部分输出。CSV 是交换格式;它不携带结果模型的溯源信息,那正是摘要与 JSON 清单的用途。
频率与标签
输入的周期名是规范词;ME、QE、YE 这类字母别名只在输出中出现,使转换后的频率在现代日期范围里对应同一个边界。标签顺序也是契约的一部分:周聚合按日历年与 ISO 周标签排序,而不是按桶起点,因此可能出现 1 月的观测排在同一年的 12 月行之后。