全部文章

替代数据:当拦截被误认为数据点

相比糟糕的模型,替代数据 pipeline 因静默采集失败造成的损失更大。本文将探讨被拦截的页面如何变成虚假信号,以及如何防范。

零售商的产品页面返回了 200 状态码,但没有任何内容。管道没有记录到拦截。它记录了一个空货架。

这是替代数据领域中无人能预料的失败。不是缺失数据集,也不是供应商速度慢。而是一个采集层不断向你提供数据行,却在暗中测量与你正在研究的公司无关的指标。

挑战

2026 年 1 月,Exabel 对美国、英国、新加坡和香港的 100 位基本面投资组合经理和分析师进行了调查,他们管理着约 6100 亿美元的资产。71% 的人认为将不同来源的数据组合在一起是使用替代数据时最令人沮丧的部分,而 94% 的人表示他们已经在研究过程中的某个环节运行了 AI 或机器学习。

将这两个数字放在一起看,问题的轮廓就显现出来了。建模方面人员配备充足。而底层的管道则不然。

从网络收集的面板数据 (价格、库存状态、招聘页面、评论数量、市场分类) 首先是一个时间序列。每个时间序列都带有一个无人写入规范的假设:今天的观察结果是以与昨天相同的方式收集的。高调地打破这个假设,你会得到一个警报。悄悄地打破它,你就会得到一个信号。

几乎所有从网络收集的面板数据中都会出现这三种悄无声息的破坏。

非内容的 200。 机器人防御系统很久以前就不再返回干净的 403 了。挑战页面、同意墙或空结果模板会以成功状态到达,而你的解析器将其读取为零结果。列表变少看起来和需求减少完全一样。

观察点发生了移动。 价格、货币、产品分类、促销横幅,有时甚至包括页面是否呈现:零售商根据 request 似乎来自的地理位置来决定这一切。如果周一的收集在德国退出,而周四的在波兰退出,那么你的序列中就会出现一个属于你,而不是零售商的阶跃。

接受首次响应的轮换。 在不告诉收集器什么是成功的情况下轮换退出节点,它会在第一个响应的节点停止。拒绝也是一种 response。因此,数据行落地了,作业变绿了,没有人会再看一眼。

这些都不会抛出异常。摄取过程计算行数,仪表板保持绿色,分析师得到一张图表。然后,模型花了一个季度来学习你收集基础设施的行为,而不是业务的行为。

方法

将数据完整性视为 request 的属性,而不是下游解析器的属性。必须满足三个条件。

**1. 定义真实页面的特征。**采集器无法自行判断。提供仅真实内容包含的字符串,以及几个仅拒绝响应包含的字符串,验证页面就不会再被计为有效观察。我们在 validate 规则发布时介绍过这一点:request 本身决定了何为成功。

import requests

r = requests.post(
    "https://api.foura.ai/api/proxy",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "maxTries": 8,
        "exitCountries": ["DE"],
        "request": {
            "method": "GET",
            "url": "https://retailer.example/p/12345",
            "validate": {
                "status": {"accept": [200]},
                "data": {
                    "accept": ["data-testid=\"price\""],
                    "fail": ["Access Denied", "Just a moment"]
                }
            }
        }
    }
).json()

observation = r["data"]        # content your rules accepted, or nothing
exit_id = r["proxy"]           # opaque ID of the exit that delivered it
served_from = r["exitCountry"] # verify it against what you asked for

轮换(Rotation)现在有了“完成”的明确定义。它会不断尝试出口,直到某个出口返回符合你规则的内容,而不是返回它遇到的第一个看起来像网页的对象。

2. 保持视角稳定。 exitCountries是目标可见国家代码的严格允许列表,未知地理位置的出口会被排除,而不是被替换。在基于此构建之前,有两点需要说明的注意事项。国家元数据是周期性刷新的(通常在10分钟左右),因此它不是在请求时的实时查找,这正是响应中包含exitCountry供你检查的原因。当资源池中没有与你请求的作用域匹配的资源时,调用会返回HTTP 200和一个包含错误信息的包封,而不是抛出异常。请读取body,而不是状态码。保留该作用域并在稍后重试,而不是扩大它,因为扩大作用域会破坏数据系列的连续性。

3. 保持出口标识。 proxy字段是一个不透明的ID,而不是地址。在随后的Single或Browser调用中将其传回,详细信息页面就会来自与找到它的搜索页面相同的视角(如何重用出口)。将该ID和X-FourA-Request-Id header与每一行数据一起存储。当分析师在六周后对数据激增提出质疑时,“这是真实的吗?”这个问题就变成了一次查询,而不是一场争论。

对于正在接入但尚未完全了解的数据源,Auto是寻找可用路径的最快方法:它会从低成本到高成本逐级尝试,告诉你哪一级成功了,并返回生效的会话。用它来寻找路线,然后将生产环境的流量放在直接引擎上。在不需要渲染的地方通过Single重放该会话,在确实需要渲染的地方通过Browser重放。寻路和稳态收集是不同的工作。

结果

当这三个特性得到保证时,在跨越十几个零售商、每天数千个产品页面的面板上会发生什么变化(基于行业基准的示例场景):

  • 缺失就是缺失,不是猜测。 被拒绝的请求永远不会以零的形式进入面板,因此空结果集意味着零售商没有显示任何内容,你的缺失信号就具有交易价值。
  • 可比较的数据行。 一个系列中的每次观察都来自该系列定义的国家,因此价格变动就是真实的价格变动。
  • 可复现的历史记录。 每行的出口ID加上request ID意味着任何有争议的数据点都可以追溯到产生它的具体调用。
  • 每行可用数据的成本更低。 那些原本会产生废弃观察结果的request会在收集时进行重试,而不是先付费、解析、存储,然后在回测时被清理掉。

但最后一点往往被研究团队低估。一行无效数据并不因为它获取成本低就是免费的。它会消耗一个研究周期,有时还会让必须批准该信号的人失去信心。

核心要点

替代数据买家会根据覆盖率、延迟和历史深度来评估提供商。几乎没有人会问这个决定面板是否可交易的问题:当数据源拒绝响应时,这个数据集会表现如何?

直接丢弃该行的供应商是诚实的。将提示页面作为观察结果返回的供应商,实际上向你出售的是对他们自身基础设施的测量数据,你将在回测中为此付出代价,这种回测直到失效前看似都是正常的。这个问题应该列入所有的数据尽职调查清单中,并且应该首先出现在你自己的 pipeline 中,因为如果你自己在收集数据,你就是供应商。