Skip to content

[research·parked] A second market-data provider the engine can fail over to on its own #638

Description

@atomchung

Status

Research — parked by owner ruling, 2026-07-30. Not this cycle. Split out of #629 so that issue can proceed on the agent-side recovery without this question blocking it.

未来我们可以去探讨有没有第二个数据源来替代 Yahoo Finance,但这一期不用讨论。

Milestone

None — deferred. Revisit when Yahoo's failure rate becomes the binding constraint on review availability, or when someone measures that it already is.

The question

market_data.py has exactly one retrieval source, Yahoo via yfinance. When it is unavailable the engine degrades and #629 has the agent recover the prices by hand. Should the engine instead carry a second provider it can fail over to on its own?

Why it is worth revisiting later, not now

The case for a second provider is stronger than it looks, which is why this is parked rather than rejected:

The case against, and the reason it is not this cycle:

What would make this decidable

  1. Measure the failure rate. How often does a real prepare/consider hit provider_missing, transport_failed, or empty_response? The gap codes already exist and are stable (market_data.GAP_CODES); nothing records them over time.
  2. Decide whether a second source must agree with the first, and what happens when they disagree. A disagreement on a close is a real signal, and silently preferring one is the shape of defect this repository keeps paying for.
  3. Name the normalization contract once. If a second provider lands, its closes, splits and FX have to enter through price_feed.parse exactly as a supplied envelope does — the same single lane [architecture·implementation] One market-data resolver — minimum Yahoo calls, one fact bundle for prepare and consider #605 established — rather than as a parallel adapter with its own basis rules.

Related

#629 (the agent-side recovery, this cycle's answer — proceeds independently), #605 (one resolver, one dated bundle — the ruling whose premise this reopens), #583 / #558 / #550 (the split-basis divergences that make a second normalization path expensive), #603 (measure per route before bounding it).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions