清洗策略版本参考
清洗策略写作 预设@版本,例如 default@2026-13。预设决定「哪些改动可以自动执行」,版本决定「用哪一套规则和阈值」。本页按执行顺序列出每个版本的全部步骤和参数,并给出清洗报告中每个决定 id、问题代码的含义。报告的字段结构与采纳 / 拒绝的用法见清洗策略与清洗报告。
1. 策略一览
| 策略 | 说明 | 如何选择 |
|---|---|---|
default@2026-13 | 平台当前默认。保留 2026-12 的全部步骤,把 10% 缺失占比拒绝改为按缺失位置判断(见缺失判断规则),并逐项列出健康分扣分。 | 不传 version 时使用(除非密钥或组织另有设置)。 |
default@2026-12 | 已弃用,将在公告后移除。保留 2026-11 的全部步骤,并固定预测起点:末尾至多 3 个空值按未知处理,不再删除。 | options.cleaning.version: "2026-12";响应带 cleaning_version_deprecated 提醒。 |
default@2026-11 | 已弃用,将在公告后移除。保留 2026-10 的全部步骤,另加逐段补值、补值的物理约束、工作日网格 B 与更多数据检查。 | options.cleaning.version: "2026-11";响应带 cleaning_version_deprecated 提醒。 |
default@2026-10 | 已弃用,将在公告后移除。最初的冻结规则集,输出由回归基线逐字节锁定。 | options.cleaning.version: "2026-10";响应带 cleaning_version_deprecated 提醒。 |
strict@2026-13(已弃用:strict@2026-10、strict@2026-11、strict@2026-12) | 与同版本的 default 运行同一套规则,但只自动执行结构性决定,其余降为提议。 | options.cleaning.preset: "strict",可同时指定 version。 |
raw@2026-10 | 不清洗,只做严格的结构校验,数据原样交给模型。 | options.cleaning.preset: "raw"。 |
raw 不经过清洗服务,结构校验规则与版本无关,见第 7 节。
2. 版本承诺
- 带日期的版本是冻结的。 已发布版本的规则、阈值和默认参数不再修改。
- 同样的输入得到同样的输出。 数据、选项、策略
id相同时,清洗结果和决定id都相同。唯一与模型有关的一步是最小长度检查,它取决于所选模型的最小上下文。 - 规则调整以新版本发布。 平台默认改用新版本时会公告;被替换的旧版本先标记为已弃用,仍可显式选择(响应带
cleaning_version_deprecated提醒),在公告的日期之后才移除。 - 默认值按层解析。 预设和版本分别按「请求 > 密钥默认 > 组织默认 > 平台默认」取第一个设置了的值。平台默认目前是
default@2026-13;2026-10、2026-11与2026-12已弃用,将在公告后移除。密钥或组织的默认值由平台配置,目前没有自助设置入口。 - 实际生效的策略总会回显。 成功响应的
effective_policy写明id、preset、version与source(request、key、org、platform之一,取设置了预设或版本的最高层级)。记录effective_policy.id即可复现同一次清洗。
3. 选择版本与 2026-11 参数
只有需要默认 2026-13 以外的版本时,才在 options.cleaning 中传 version。下面七个参数从 2026-11 起提供,默认版本下同样可用,也放在 options.cleaning 中:
{
"model": "hora-1.0",
"h": 24,
"freq": "1h",
"series": [
{"unique_id": "pv-01", "ds": "2026-06-01T00:00:00Z", "y": 0.0},
{"unique_id": "pv-01", "ds": "2026-06-01T01:00:00Z", "y": null}
],
"options": {
"cleaning": {
"preset": "default",
"impute_method": "auto",
"nonnegative": "true",
"bounds": {"lower": 0, "upper": 500},
"structural_zero": "auto",
"business_days": "off"
}
}
}(series 已截断,实际请求需要满足模型的最小上下文。)
| 参数 | 取值 | 默认 | 作用 |
|---|---|---|---|
impute_method | auto、linear、pchip、seasonal | auto | auto 为每个缺口单独选方法(见逐段补值);指定方法无法执行时回退到线性,并在报告中写明原因。 |
seasonal_period | 整数 2 至 10000(网格步数) | 按频率推断 | 指定季节周期。指定时只要求序列覆盖至少 2 个周期,不再检验自相关。 |
nonnegative | auto、true、false | auto | auto:观测值至少 8 个且没有负数时,补值截到 0 以上。true:总是截断,并标记负的观测值。false:关闭。 |
bounds | {"lower": …, "upper": …} | 无 | 声明的物理范围:补值截到范围内,范围外的观测值被标记(out_of_bounds)。至少给一个边界,且 lower ≤ upper。 |
structural_zero | auto、off | auto | auto:几乎总为 0 的季节相位上,补值保持为 0。 |
business_days | auto、on、off | auto | auto:没有周末日期的日频数据使用工作日网格 B。on:日频数据强制使用 B。off:保持自然日。 |
long_gap | fill、mask | fill | 模型如何读取超过短缺口上限的内部长缺口(long_gap 问题)。fill:读取补值。mask:补值与报告不变,但支持缺失屏蔽的模型把这些位置当作缺失读取。见长缺口:填补还是屏蔽。 |
长缺口:填补还是屏蔽
清洗总会填补所有缺口,使报告与清洗后的序列完整。对于内部长缺口,long_gap 决定模型读取什么:
fill(默认):模型读取补值,与报告中展示的一致。当补值是合理的替代时保留它,例如序列在缺口期间延续稳定的季节模式。mask:模型把这些位置当作缺失,依据缺口前后的观测值预测。当长缺口是停机、检修或其他真实数值未知、不应影响预测的时段时,可考虑使用。mask主要适用于离最近数据较远的长缺口;如果长缺口紧挨着最后一个观测值结束,除非在自己的数据上回测表明更好,否则建议保留fill。
短缺口(不超过短缺口上限)在两种方式下都会为所有模型填补。使用 mask 时,每个实体的 model_input[] 条目会给出 long_gap_points(交给模型的上下文中被屏蔽的长缺口位置数)与 long_gap_handling(模型实际如何读取这些位置)。API 提供的 SequenxAI Omni(hora-1.0)支持缺失屏蔽:这些位置以缺失值交给模型,long_gap_handling 为 "mask"。"fill" 只用于不支持缺失屏蔽的模型,此时模型改为读取补值(long_gap_handling: "fill"、long_gap_reason: "model_without_mask",并附一条 long_gap_mask_unavailable 提醒),请求不会失败;当前 API 提供的模型不会出现这种情况。两种取值计费相同:被屏蔽的位置从未被观测,不计入计费输入点。传入时,所选取值会在 cleaning_report.policy.long_gap 中回显。建议先在自己的数据上用回测比较两种方式,再决定使用哪一种。
参数校验:
- 在
2026-10下传这七个参数中的任意一个(nonnegative: "auto"除外),返回 422CLEANING_OPTION_UNSUPPORTED,不会被静默忽略:
{
"error": {
"code": "CLEANING_OPTION_UNSUPPORTED",
"message": "Cleaning options require policy version 2026-11",
"details": {
"options": ["business_days"],
"policy": "default@2026-10",
"requires_version": "2026-11"
}
}
}2026-10下nonnegative传"true"或"false"同样返回CLEANING_OPTION_UNSUPPORTED,details为options与supported。- 取值非法(例如
lower大于upper)返回 422VALIDATION_ERROR。 options.cleaning内未列出的字段返回 422VALIDATION_ERROR(details.errors[].field指出字段),不会被忽略。- 未知的
version返回 422CLEANING_OPTION_UNSUPPORTED,details.allowed列出可选版本。 raw预设不接受任何参数,也不接受accept/decline。freq: "B"只在2026-11及之后的版本下有效;2026-10返回FREQ_UNSUPPORTED,raw下返回RAW_INPUT_INVALID。
从 2026-11 起,cleaning_report.policy 会回显解析后的参数:impute_method、structural_zero、business_days 未传时回显 auto;seasonal_period、bounds 与 long_gap 只在传入时出现。2026-10 的 policy 保持原有结构。可以先用 /v1/clean 免费预演这些参数的效果。
4. default@2026-10 的处理步骤
每个实体(unique_id)独立按下面的顺序处理。报告中的位置列表最多列出 50 条,超出时 truncated 为 true。
4.1 解析时间戳与时区
- 支持的时间戳格式见时间戳格式。日月顺序无法从数据判断时,以
AMBIGUOUS_DATE_FORMAT拒绝,请传options.ds_format。 - 带偏移的时间戳按偏移读取;不带偏移的按
options.timezone读取,未传时按 UTC 读取并报告naive_timestamps_assumed_utc。 - 遇到无法解析的时间戳时以
VALIDATION_ERROR拒绝(2026-10只报告第一条)。 - 夏令时相关情况只报告、不修改:
dst_missing、dst_duplicate、dst_nonexistent_time、mixed_timezone。对全部按 UTC 读取的逐小时或更细的数据,如果在 3、4、9、10、11 月的周日 0 点至 3 点(UTC)出现恰好一小时的缺口或重复,也会给出dst_missing/dst_duplicate提示和dst_suspected警告。
4.2 排序
行没有按时间排序时稳定排序(决定 time.reorder,问题 out_of_order)。
4.3 识别缺失值
- 缺失标记文本。 文本单元格为
na、n/a、nan、null、none、?、#n/a、#value!或空字符串(不区分大小写)时置为空值(决定value.tokens)。 - 单独的破折号
-、--:可能是 0 也可能是缺失,默认按缺失处理,并提议按 0 处理(决定value.dash_token,proposed)。 - 缺失值代码。 候选值为
9999、-9999、99999、-99999、-999、999999、65535、-32768。当该值落在其他观测值的范围之外、与最近边界的距离超过「其他观测值 1% 至 99% 分位的跨度」与「10 倍 MAD」中的较大者,且占比不超过 5% 时,自动置为空值;否则只提议,数值保持不变(决定value.sentinel)。
这两类文本规则只针对文本形式的单元格(例如上传的 CSV);JSON 请求中 y 为数字或 null,通常不会触发。
4.4 确定频率
- 传了
freq时直接使用。 - 省略时推断:先判断是否为按月 / 季 / 年对齐的日历频率(相邻间隔的中位数至少约 28 天,且至少 90% 的时间戳落在同一个月内日期上,如 1 号、月末或固定某一天);否则取相邻间隔的众数,间隔相差在 2% 或 1 秒以内视为同一间隔。
- 众数占比至少 90% 为高置信度;70% 至 90% 为低置信度,给出
freq_low_confidence警告但不拒绝;低于 70% 以FREQ_INFERENCE_FAILED拒绝。 - 第二常见的间隔占全部间隔至少 25%,且不少于最常见间隔的三分之二时,视为有歧义,以
FREQ_AMBIGUOUS拒绝。省略freq时各实体推断出不同频率,同样返回FREQ_AMBIGUOUS。
4.5 对齐网格
- 时间戳略偏离格点时对齐到最近的格点(决定
grid.snap,问题timestamp_jitter)。容差:固定步长为步长的 2%(且不超过半个步长),例如逐小时数据为 72 秒;日历频率为 ±12 小时。 - 超出容差的行删除(决定
grid.off_grid,问题off_grid,警告off_grid_dropped)。偏离网格的行超过该实体行数的 10% 时,以FREQ_INFERENCE_FAILED拒绝。
4.6 去重
对齐后同一格点有多行时保留最后一行(决定 time.duplicates,操作 keep_last)。各行值相同时类别为 structural;值不同时类别为 drop,并给出 duplicate_conflict 警告。值冲突的重复至少 3 处且超过该实体行数的 5% 时,额外报告 entity_column_suspected:可能多条序列混在了同一个 unique_id 下。
4.7 裁剪首尾空值
序列开头和结尾的空值直接删除(决定 gap.edge_trim,问题 edge_null)。全部为空的实体以 SERIES_EMPTY 拒绝。从 2026-12 起,末尾空值的处理不同,见固定预测起点。
4.8 模型上下文窗口
历史不会为适配模型而被截断。某个实体长于所选模型的最大上下文时,在清洗前(按不重复的时间戳)或清洗后(按规则网格,含补齐的点)返回 422 SERIES_TOO_LONG;请只发送最近的点。因此引擎的 window.context 决定与 context_window 问题不会出现在 API 响应里。模型的上限见模型与能力上限。
4.9 长缺口拆分
- 观测值之间的缺口达到阈值时,只保留最后一个长缺口之后的最新一段(决定
gap.split)。 - 阈值:传了
options.gap_split_min_steps时取该值(0关闭拆分);否则取「补值上限加一(即 4 步)」「3 个季节周期」「序列跨度的 5%」三者中最大的。 - 季节周期步数:亚日频为一天的步数,日频到周频之间为一周的步数,日历频率为一年的步数,周频及更长的固定步长为 1。
- 最新一段必须至少覆盖模型的最小上下文,且自动阈值下至少覆盖 3 个季节周期,否则不拆分。
- 被丢弃的观测值不超过一半时自动执行;超过一半时只提议(问题
segment_split_skipped),改为补齐缺口。 clean_series: false时不做拆分。
4.10 缺失占比检查
缺失占比 =(网格上缺少的时间戳 + 空值)÷ 网格总点数,在补值之前计算。低于 1% 为 Healthy,1% 至 10% 为 Warning,达到 10% 为 Critical,以 SERIES_DISCONTINUOUS 拒绝(阻断 health_critical)。2026-13 替换了这一检查,见缺失判断规则。
健康分 health.score(0 至 100)= 100 − min(40, 400 × 缺口占比) − min(20, 200 × 缺失占比) − min(15, 5 × 值冲突的重复数) − min(15, 100 × 异常值占比),四舍五入。Critical 实体的分数不超过 49。
4.11 插入空格点
网格上缺少的时间戳作为空格点插入(决定 grid.regrid,问题 gap)。
4.12 检测异常值(只标记,从不修改)
- 滚动中位数 / MAD:窗口长度为点数的 1/50,限制在 21 至 101 之间并取奇数;窗口内至少 5 个观测值且 MAD 大于 0 时,评分 0.6745 × |x − 中位数| ÷ MAD 超过 3.5 的点被标记(问题
outlier,警告outlier_flagged_not_modified)。 - 日历频率的数据在至少 3 个完整年度周期时,先减去同一季节其他年份的中位数再检测,规律性的年度峰值不会被当作异常。
- 异常值保持原值交给模型;
metrics.outlier_points_suppressed始终为 0。
4.13 检测平台段与量级跳变(只标记)
- 平台段
flat_run。 连续相同的非零观测值达到最小长度时标记。最小长度为半个季节周期,固定步长限制在 8 至 288 步之间,日历频率下限为 4 步。所有观测值都是非负整数且 90% 分位不超过 20 时(小计数序列),不做该检测。 - 量级跳变
level_shift。 相邻两个窗口的中位数相差约 1000 倍(对数差在 3 ± 0.25 以内)时标记,常见于单位换算错误。窗口长度为点数的 1/4,限制在 5 至 48 之间。
4.14 补值
- 所有缺失(插入的空格点与空值)按两侧观测值线性插值(决定
gap.impute,操作linear)。 - 连续缺失超过补值上限 3 步时仍会补齐,但给出问题
long_gap与警告long_gap_filled。 imputed动作的gaps[]为每个缺口写明范围、method、tier与reason。2026-10的层级只用于说明缺口长短,不改变方法(P 为第 4.9 节的季节周期步数,n 为序列点数):
| 层级 | 缺口长度 | reason |
|---|---|---|
T0 | ≤ 3 步 | within_gap_fill_max_steps |
T1 | ≤ P | no_seasonal_method |
T2 | ≤ max(3P, n 的 5%) | no_seasonal_method |
T3 | 更长 | exceeds_long_gap_max |
clean_series: false时不补值;只要需要任何修复,就以TIMESTAMP_IRREGULAR或SERIES_DISCONTINUOUS拒绝(阻断cleaning_required)。
4.15 最小长度
清洗后点数少于模型的最小上下文时,以 SERIES_TOO_SHORT 拒绝(阻断 too_short_for_model)。
5. default@2026-11 的新增步骤
2026-11 按同样顺序执行第 4 节的全部步骤,阈值不变,并在以下位置增加规则。
解析时间戳(第 4.1 步)
所有无法解析的时间戳在一次 VALIDATION_ERROR 中全部列出:details.cleaning_report.blocking[0] 为 unparseable_timestamp,带请求中的行号 rows(最多 50 条)与最多 5 个示例。
数字格式检查(第 4.3 步)
文本单元格不是普通数字时,按类型报告,数值保持缺失,不做猜测(read_as: "missing"):
| 问题代码 | 示例 |
|---|---|
thousands_separator | 1,234.5 |
decimal_comma | 12,5 |
ambiguous_separator | 1,234(千位分隔还是小数逗号无法判断) |
non_numeric_value | 12kW |
number_format_mixed | 同一序列中同时出现千位分隔与小数逗号 |
工作日网格 B(第 4.4 步)
business_days: "auto"且省略freq时,满足以下全部条件的日频数据使用工作日网格:平均每个日期不超过 1.05 个时间戳;没有周六、周日的日期;工作日日期至少 15 个;跨度至少 21 天;工作日覆盖率(有数据的工作日 ÷ 跨度内的工作日)至少 90%。日期按实体的本地时间判断(options.timezone,否则取数据中最常见的偏移)。- 使用
B时周末不算缺口,预测时间戳跳过周末(决定grid.business_days,类别structural;问题business_days_pattern,count为跳过的周末天数)。不含节假日日历:工作日的节假日缺失仍按缺口处理。 business_days: "on"对日频数据强制使用B(未传freq或freq为日频时),周末的行按偏离网格删除;未传freq且数据不是日频时报告business_days_not_applicable。"off"始终保持自然日。- 也可以直接传
freq: "B"。auto下显式传入freq时不做工作日检测。 - 拒绝
grid.business_days:<unique_id>即按自然日处理,周末成为缺口。
真实输出示例:从 2026-09-07(周一)起连续 20 个工作日,未传 freq:
"freq": {"inferred": "B", "used": "B", "source": "inferred",
"status": "HIGH_CONFIDENCE", "confidence": 1.0, "candidates": []}
{"id": "grid.business_days:fx", "rule": "grid.business_days", "class": "structural",
"status": "applied", "action": "business_day_grid",
"before": {"freq": "D"}, "after": {"freq": "B"}, "reversible": true,
"evidence": {"weekday_dates": 20, "weekend_dates": 0, "span_days": 26,
"coverage": 1.0, "skipped_weekend_days": 6, "source": "detected"}}
// h=3 的预测时间戳:2026-10-05、2026-10-06、2026-10-07(周一至周三)2026-10 处理同一份数据时推断为自然日(低置信度),6 个周末日成为缺口,缺失占比超过 10%,以 SERIES_DISCONTINUOUS 拒绝。
常数序列检查(第 4.12 步之后)
观测值从不变化时给出 constant_series 警告;全为 0 时给出 all_zero_series。
季节性检验
每个实体的报告带 series[].seasonality:{period, source, acf, cycles, accepted, reason}。
- 候选周期
period由频率决定:亚日频为一天的步数(逐小时为 24),日频到周频之间为一周的步数(日频为 7),工作日为 5,周频及更长的固定步长为一年的步数(周频为 52),日历频率为一年的步数(月频为 12)。候选周期小于 2 时没有周期。 - 按频率得到的周期需要序列覆盖至少 3 个周期,且滞后一个周期的自相关(只用两端都有观测的点对)至少 0.3,才被采用。
- 通过
seasonal_period指定的周期只要求覆盖至少 2 个周期。
逐段补值
每个缺口单独选方法(impute_method: "auto"):
| 条件 | 方法 | reason |
|---|---|---|
| 缺口 ≤ 3 步,且缺口前后各至少 2 个观测值 | pchip | short_gap |
| 缺口 ≤ 3 步,但一侧观测值不足 2 个 | linear | short_gap_few_neighbours |
| 缺口更长,季节周期被采用,且每个缺失相位在前后各 7 个周期内至少有 2 个同相位观测值 | seasonal | seasonal_period_accepted |
| 缺口更长,季节周期被采用,但同相位历史不足 | linear | insufficient_history |
| 缺口更长,季节周期未被采用 | linear | no_seasonality:<原因>,原因同 seasonality.reason |
pchip:Fritsch–Carlson 单调三次插值,经过所有观测点;每一段都落在两端观测值之间,不会过冲。seasonal:取同一相位在前后各 7 个周期内观测值的中位数,再把缺口两端观测值与各自中位数的偏差线性过渡叠加上去,使补值与两端衔接。- 指定
linear或pchip时每个缺口都用该方法(reason: method_option)。指定seasonal时需要覆盖至少 2 个周期的周期(不要求自相关)和足够的同相位历史;否则回退为线性,reason为seasonal_unavailable(没有可用周期)或insufficient_history。 - 层级
tier的阈值与第 4.14 节相同,但 P 取seasonality.period;没有周期时,超过 3 步的缺口都记为T1。 - 多个缺口用了不同方法时,
gap.impute的操作为mixed,evidence.methods给出每种方法补了多少点。
补值的物理约束
约束只作用于补出来的值,观测值从不修改。按以下顺序执行:
- 结构性零值(
constraint.structural_zero,操作zero)。某个季节相位至少有 7 个周期的观测,且其中至少 90% 为 0(例如光伏夜间出力)时,该相位的补值设为 0。需要序列至少覆盖 7 个周期;所有相位都满足时视为常数序列,不执行。structural_zero: "off"关闭。 - 非负(
constraint.nonnegative,操作clip_at_zero)。见第 3 节nonnegative参数。 - 范围(
constraint.bounds,操作clip_to_bounds)。截到声明的bounds内。
每条实际改变了补值的约束都生成一条决定(类别 fabricate,reversible: true),可按 id 拒绝。受影响的缺口在 gaps[].constraints 中列出规则,actions[imputed].constraints 给出每条规则改变的点数。违反约束的观测值只被标记:negative_in_nonnegative(nonnegative: "true" 时的负观测值;或 auto 下观测值至少 99% 非负、仅有少数负值时,此时不做截断)与 out_of_bounds。
真实输出示例:逐小时光伏数据,共 8 天,第 6 天出力减半,2026-06-06T16:00Z 至 2026-06-07T05:00Z 缺失 14 个点(跨夜):
"seasonality": {"period": 24, "source": "frequency", "acf": 0.9307, "cycles": 8.0,
"accepted": true, "reason": "accepted"}
"gaps": [{"range": {"start": "2026-06-06T16:00:00Z", "end": "2026-06-07T05:00:00Z", "points": 14},
"method": "seasonal", "tier": "T1", "reason": "seasonal_period_accepted",
"constraints": ["constraint.structural_zero", "constraint.nonnegative"]}]
{"id": "constraint.structural_zero:pv-01", "rule": "constraint.structural_zero",
"class": "fabricate", "status": "applied", "action": "zero",
"before": {"imputed_points": 14}, "after": {"changed": 12}, "reversible": true,
"evidence": {"period": 24, "phases": [0, 1, 2, 3, 4, 5, 6, 18, 19, 20, 21, 22, 23],
"zero_share": 0.9, "min_cycles": 7}}
{"id": "constraint.nonnegative:pv-01", "rule": "constraint.nonnegative",
"class": "fabricate", "status": "applied", "action": "clip_at_zero",
"before": {"imputed_points": 14}, "after": {"changed": 1}, "reversible": true,
"evidence": {"source": "auto"}}
// 补值:17.1,随后 13 个点为 0(夜间保持为 0)default@2026-10 处理同一份数据时,这 14 个点按线性插值补齐(tier: T1,reason: no_seasonal_method),夜间的补值大于 0。
固定预测起点(2026-12)
2026-12 保留上述 2026-11 的全部规则,只改变第 4.7 步:即使最后几个 y 为空(例如某个时段的数据还没到),预测也总是从你发送的最后一个 ds 的下一步开始。
- 最后一个观测值之后至多 3 个网格步(补值上限)的末尾空值保留在网格上,不再删除(决定
gap.masked_tail,类别fabricate,操作mask_for_model;同名问题与警告masked_tail;动作masked,reason: trailing_null)。这些位置不作为数据使用:不计入fed_points,不计费;该实体的model_input[]条目以masked_tail报告,响应的warnings[]中有一条trailing_values_missing。 - 末尾空值更长,或撤回
gap.masked_tail:<unique_id>时,以SERIES_DISCONTINUOUS拒绝(阻断trailing_gap_too_long,带count与max_steps),而不是返回一个比你要求更早开始的预测。请发送最新的观测值,或去掉末尾的空行。 strict下,gap.masked_tail与其他非结构性决定一样降为提议,可按id采纳。- 开头的空值仍按第 4.7 步删除。
2026-10与2026-11下末尾空值同样删除(edge_null),预测从最后一个非空y之后开始。
缺失判断规则(2026-13)
2026-13 保留 2026-12 的全部规则,替换第 4.10 步的缺失占比检查。更早的版本拒绝缺失占比达到 10% 的任何序列;2026-13 改看缺失的位置,因为紧挨预测起点的长缺口对预测的影响,远大于同样数量的零散缺失。缺口长度以序列的季节周期计:传了 seasonal_period 时用它,否则小时数据 24 步、30 分钟 48 步、15 分钟 96 步、日数据 7 步、周数据 52 步、月数据 12 步。为模型保留的末尾空值(masked_tail)不计入。
| 检查 | 拒绝(SERIES_DISCONTINUOUS) | 接受并给出警告 missing_pattern |
|---|---|---|
| 之后不足 0.5 个周期观测值的缺口(近期缺口) | 0.75 个周期及以上(reason: gap_near_origin_too_long) | 0.25 个周期及以上(gap_near_origin) |
| 其他缺口 | 不单独拒绝 | 2 个周期及以上(long_gap) |
| 缺失占比(缺口加空值) | 35% 及以上(reason: missing_share_too_high) | 20% 及以上(missing_share_high) |
没有季节周期时(例如频率不规则)只检查缺失占比。被拒绝的实体仍以 health_critical 阻断,并带 reason、reasons、period、near_gap_steps 与 far_gap_steps;caused_by 与之前一致。请补发缺失的近期数据,或只发送缺口之前的历史。
health.factors 列出健康分的各项扣分,格式为 {code, points, count?, ratio?},分数之和等于 100 − score:gap_near_origin、far_gap、missing_share(被接受的实体上合计至多 49 分)、conflicting_duplicates、outliers(有异常值时至少 1 分)、flat_runs、level_shifts,以及 blocked(使被拒绝的实体不高于 49 分)。等级与上表一致:拒绝为 Critical,警告为 Warning。
与 2026-12 的区别。 一部分因缺失达到 10% 而被 2026-12 拒绝的序列,现在会被接受(缺失达到 20% 时带 missing_pattern 提醒);一部分在预测起点前有长缺口、缺失不足 10% 而被 2026-12 接受的序列,现在会以 reason: gap_near_origin_too_long 拒绝。如需暂时保留原有行为,可固定 options.cleaning.version: "2026-12"(已弃用)。
6. strict 预设
strict 运行同版本 default 的全部规则,然后只保留结构性决定,其余 applied 的决定改为 proposed,请求以 422 拒绝并附带报告:
| 仍然自动执行 | 降为提议 |
|---|---|
time.reorder、值相同的 time.duplicates、grid.snap、grid.regrid、grid.business_days(2026-11 及之后)。API 不执行 window.context:超长实体返回 SERIES_TOO_LONG(见 §4.8) | gap.impute、gap.edge_trim、gap.split、grid.off_grid、值冲突的 time.duplicates、value.sentinel、value.tokens、value.dash_token、constraint.*(2026-11 及之后)、gap.masked_tail(2026-12) |
- 被降级的决定中有
time.*或grid.*时以TIMESTAMP_IRREGULAR拒绝,否则以SERIES_DISCONTINUOUS拒绝(阻断cleaning_required)。 - 把决定
id放进accept后该决定照常执行;所有被降级的决定都采纳后请求通过。 strict下报告的actions仍描述default会做的操作,以decisions的状态为准。
7. raw 预设
raw@2026-10 不清洗:不排序、不去重、不补点、不推断时区,只做结构校验,数据原样交给模型。要求 freq 必填且为固定步长,ds 严格为 YYYY-MM-DDTHH:MM[:SS[.ffffff]] 加 Z 或 ±HH:MM,每个实体严格递增且步长恰好等于 freq,每个 y 都是有限数值。不满足时返回 RAW_INPUT_INVALID。响应没有 cleaning_report,也不能使用 accept / decline 或任何清洗参数。完整说明见 raw 预设。
8. 读取结果:effective_policy、决定与采纳 / 拒绝
effective_policy.id是本次实际使用的策略;cleaning_report.policy是清洗服务解析后的完整参数(补值上限gap_fill_max_steps: 3、异常值阈值outlier_threshold: 3.5、重复处理duplicate_policy: "last"等),以及你传入的accept/decline。cleaning_report.decisions[]列出每一处改动数据的决定和未执行的提议。id格式为规则:unique_id,value.sentinel额外带数值选择器,例如value.sentinel:meter-001:-9999。status:applied已执行;proposed只提议、数据未改动;declined被你拒绝。accept让提议执行:value.sentinel、value.dash_token(按 0 处理)、gap.split,以及strict下被降级的任何决定。decline撤销reversible: true的决定:value.sentinel、gap.split、grid.business_days、constraint.structural_zero、constraint.nonnegative、constraint.bounds。撤回gap.masked_tail不会删除末尾空值,而是以trailing_gap_too_long拒绝请求。- 同一个
id不要同时放进两个列表。列出的id在本次数据中不存在时,报告附带decision_not_applicable警告,请求照常处理。 issues[]是发现的问题(带位置),warnings[]是不阻断请求的提醒,blocking[]是拒绝原因。请求被拒时,错误码由第一条阻断原因决定。
请求示例与各规则的前后对比见清洗策略与清洗报告。
9. 术语表
决定规则
| 规则 | 类别 | 操作 | 含义 | 可采纳 / 可拒绝 |
|---|---|---|---|---|
time.reorder | structural | stable_sort | 行没有按时间排序,已按时间稳定排序。 | — |
time.duplicates | structural / drop | keep_last | 同一时间戳有多行,只保留最后一行。值不同时为 drop。 | — |
grid.snap | structural | nearest_slot | 时间戳略偏离格点,已对齐到最近的格点。 | — |
grid.off_grid | drop | drop | 时间戳落在两个格点之间,该行已删除。 | — |
grid.business_days | structural | business_day_grid | 2026-11。只有工作日的日频数据,改用工作日网格 B,周末不算缺口。 | 可拒绝 |
gap.edge_trim | drop | drop | 序列首尾的空值已删除。 | — |
gap.masked_tail | fabricate | mask_for_model | 2026-12。至多 3 个末尾空值保留在网格上、不作为数据使用,预测仍从最后一个 ds 之后开始。 | 可撤回(撤回后请求以 trailing_gap_too_long 拒绝) |
window.context | drop | keep_latest | 历史长于模型最大上下文,只保留最近的部分。API 不会产生,此类序列返回 SERIES_TOO_LONG。 | — |
gap.split | drop | keep_latest_segment | 序列中有很长的缺口,只保留缺口之后的最新一段。 | 可采纳、可拒绝 |
grid.regrid | structural | insert_empty_slots | 网格上缺少的时间戳已作为空格点插入。 | — |
gap.impute | fabricate | linear / pchip / seasonal / mixed | 缺失值已补齐,操作为所用方法(2026-10 始终为 linear)。 | — |
constraint.structural_zero | fabricate | zero | 2026-11。几乎总为 0 的相位上,补值设为 0。 | 可拒绝 |
constraint.nonnegative | fabricate | clip_at_zero | 2026-11。非负序列的补值截到 0 以上。 | 可拒绝 |
constraint.bounds | fabricate | clip_to_bounds | 2026-11。补值截到声明的范围内。 | 可拒绝 |
value.sentinel | fabricate | null | 数值是常见的缺失值代码,已置为空值后补齐;证据不足时只提议。 | 可采纳、可拒绝 |
value.tokens | semantic | null | 文本单元格中的缺失标记(如 N/A)已置为空值。 | — |
value.dash_token | semantic | zero | 单独的破折号,提议按 0 处理;未采纳时按缺失处理。 | 可采纳 |
strict 预设下被降级的决定都可以采纳。
问题代码 issues[].code
| 代码 | 含义 |
|---|---|
timestamp_format | 时间戳不是 ISO 8601,或日月顺序是从数据推断的;报告写明读取所用的格式。 |
naive_timestamps_assumed_utc | 时间戳不带偏移且未传 options.timezone,已按 UTC 读取。 |
dst_missing | 夏令时开始时缺少的一小时(来自偏移变化,或对 UTC 数据的推测)。 |
dst_duplicate | 夏令时结束时重复的一小时。 |
dst_nonexistent_time | 该本地时间在所用时区中不存在(夏令时跳过的时段)。 |
mixed_timezone | 同一实体内 UTC 偏移发生了夏令时以外的变化,可能混用了时区。 |
non_numeric_token | 文本单元格是缺失标记(如 N/A),已置为空值。 |
dash_token | 文本单元格是单独的破折号,可能是 0 也可能是缺失。 |
sentinel_value | 缺失值代码已置为空值。 |
suspected_sentinel | 疑似缺失值代码,证据不足,保留原值;可按 id 采纳。 |
thousands_separator | 2026-11。带千位分隔的数字文本,保持缺失。 |
decimal_comma | 2026-11。使用小数逗号的数字文本,保持缺失。 |
ambiguous_separator | 2026-11。无法判断逗号是千位分隔还是小数点,保持缺失。 |
number_format_mixed | 2026-11。同一序列中混用了千位分隔与小数逗号。 |
non_numeric_value | 2026-11。不是数字的文本(如带单位),保持缺失。 |
missing_value | y 为空值。 |
business_days_pattern | 2026-11。数据只有工作日,已使用工作日网格;count 为跳过的周末天数。 |
business_days_not_applicable | 2026-11。要求使用工作日网格,但数据不是日频,未使用。 |
out_of_order | 有行没有按时间排序。 |
duplicate_timestamp | 同一时间戳出现多行;conflicting 为值不同的重复数。 |
entity_column_suspected | 大量值冲突的重复时间戳,可能多条序列混在同一个 unique_id 下。 |
timestamp_jitter | 时间戳略偏离格点,已对齐。 |
off_grid | 时间戳落在两个格点之间,已删除;ratio 为占比。 |
edge_null | 序列首尾的空值,已删除。 |
masked_tail | 2026-12。保留在网格上、不作为数据使用的末尾空值;count 为步数。 |
trailing_gap_too_long | 2026-12。末尾空值超过可保留的步数(max_steps),或撤回了 gap.masked_tail(declined: true)。 |
missing_pattern | 2026-13。缺失的位置会影响预测;reasons 列出触发的检查(见缺失判断规则)。被接受时严重度为 warning,被拒绝时为 error。 |
context_window | 保留;API 不会产生,此类序列直接返回 SERIES_TOO_LONG。 |
segment_split_skipped | 有很长的缺口,但拆分会丢弃过半观测值,未执行,改为补齐;可按 id 采纳拆分。 |
gap | 网格上缺少的时间戳。 |
long_gap | 连续缺失超过补值上限(3 步),仍已补齐。 |
outlier | 异常值,只标记,数值未修改。 |
constant_series | 2026-11。观测值从不变化,没有可供预测的信号。 |
all_zero_series | 2026-11。观测值全为 0,常意味着没有数据。 |
flat_run | 一段连续相同的非零值,可能是传感器卡住;只标记。 |
level_shift | 前后两段相差约 1000 倍,可能是单位换算错误;只标记。 |
negative_in_nonnegative | 2026-11。非负序列中出现负的观测值;只标记。 |
out_of_bounds | 2026-11。观测值超出声明的 bounds;只标记。 |
too_short | 清洗后点数不足模型的最小上下文,或没有任何数值。 |
警告 warnings[].code
| 代码 | 含义 |
|---|---|
freq_low_confidence | 推断频率的置信度在 70% 至 90% 之间,照常使用,建议显式传 freq。 |
duplicate_conflict | 重复时间戳的值不同,保留了最后一行。 |
entity_column_suspected | 同名问题的汇总。 |
off_grid_dropped | 删除了偏离网格的行。 |
segment_split | 已按长缺口拆分,丢弃了较早的数据。 |
segment_split_skipped | 同名问题的汇总。 |
dst_suspected | UTC 数据中疑似夏令时造成的缺失或重复,考虑传 options.timezone。 |
long_gap_filled | 补齐了超过补值上限的长缺口。 |
masked_tail | 2026-12。同名问题的汇总。 |
missing_pattern | 2026-13。同名问题的汇总,带 reasons。 |
outlier_flagged_not_modified | 标记了异常值,数值未修改。 |
decision_not_applicable | accept / decline 中的 id 在本次数据中不存在;ids 列出这些 id。 |
阻断原因 blocking[].code
| 代码 | 错误码 | 含义 |
|---|---|---|
unparseable_timestamp | VALIDATION_ERROR | 2026-11。有无法解析的时间戳,rows 列出所在行。 |
ambiguous_date_format | AMBIGUOUS_DATE_FORMAT | 无法从数据判断日月顺序。 |
freq_irregular | FREQ_INFERENCE_FAILED | 无法推断稳定的频率,或偏离网格的行超过 10%(reason: off_grid)。 |
freq_ambiguous | FREQ_AMBIGUOUS | 频率有多个候选,或各实体推断出不同频率。 |
freq_unsupported | FREQ_UNSUPPORTED | 频率无法识别。 |
all_null | SERIES_EMPTY | 实体没有任何数值型 y。 |
health_critical | SERIES_DISCONTINUOUS | 近期缺口或缺失占比未通过缺失判断规则,见 reason(已弃用的版本:缺失占比达到 10%)。带 caused_by 时,缺失主要由缺失值判定造成,按其中的 decline / accept 调整即可。 |
too_short_for_model | SERIES_TOO_SHORT | 清洗后点数少于模型的最小上下文。 |
trailing_gap_too_long | SERIES_DISCONTINUOUS | 2026-12。末尾空值超过可保留的步数,或撤回了 gap.masked_tail;count 与 max_steps 给出具体数值。 |
cleaning_required | TIMESTAMP_IRREGULAR / SERIES_DISCONTINUOUS | 需要修复,但 clean_series 为 false 或 strict 未采纳;reason 为 timestamp_irregular 或 series_discontinuous。 |
动作 actions[].code
| 代码 | method | 含义 |
|---|---|---|
reordered | stable_sort | 按时间重新排序。 |
deduplicated | last | 删除重复时间戳,保留最后一行。 |
snapped | nearest_slot | 时间戳对齐到格点。 |
dropped | grid_align / edge_trim / latest_segment | 删除数据;reason 为 off_grid、edge_null 或 long_gap_split。 |
regridded | insert_missing_stamps | 插入缺少的时间戳。 |
sentinel_to_null | token_table / sentinel_list | 缺失标记或缺失值代码置为空值。 |
imputed | linear / pchip / seasonal / mixed | 补齐缺失值;gaps[] 为每个缺口写明范围、方法、层级与原因。 |
masked | model_mask | 2026-12。为模型保留、不作为数据使用的末尾空值;reason 为 trailing_null。 |
补值原因 gaps[].reason
| 原因 | 版本 | 含义 |
|---|---|---|
within_gap_fill_max_steps | 2026-10 | 缺口不超过补值上限(3 步)。 |
no_seasonal_method | 2026-10 | 缺口超过补值上限;该版本没有季节补值,使用线性。 |
exceeds_long_gap_max | 2026-10 | 缺口长于 T2 上限。 |
short_gap | 2026-11 | 短缺口,两侧观测值充足,使用 PCHIP。 |
short_gap_few_neighbours | 2026-11 | 短缺口,一侧观测值不足 2 个,使用线性。 |
seasonal_period_accepted | 2026-11 | 季节周期被采用,使用季节补值。 |
no_seasonality:<原因> | 2026-11 | 季节周期未被采用,使用线性;原因见下表。 |
insufficient_history | 2026-11 | 同相位历史不足,回退为线性。 |
method_option | 2026-11 | 使用 impute_method 指定的方法。 |
seasonal_unavailable | 2026-11 | 指定了 seasonal,但没有可用周期,回退为线性。 |
季节性结论 seasonality.reason
| 原因 | 含义 |
|---|---|
accepted | 按频率得到的周期通过检验(至少 3 个周期,自相关至少 0.3)。 |
option | 使用 seasonal_period 指定的周期(至少 2 个周期)。 |
insufficient_cycles | 序列覆盖的周期数不足。 |
weak_autocorrelation | 滞后一个周期的自相关低于 0.3,或无法计算。 |
no_seasonal_period | 该频率没有候选周期。 |
缺口层级 gaps[].tier
| 层级 | 含义 |
|---|---|
T0 | 短缺口:不超过补值上限(3 步)。 |
T1 | 不超过一个季节周期。 |
T2 | 不超过 3 个季节周期或序列长度的 5%(取较大者)。 |
T3 | 更长。 |