ADR-0007 §7.5: delete the price surface, keep databento - #105
Merged
Conversation
cotdata is CFTC positioning now. Gone: prices.py (with the derived propadj
tier), providers/norgate.py, providers/yfinance.py, the get_prices/roll_dates
exports, store.{write,upsert,read}_metadata, the --prices/--metadata/
--prices-yahoo/--require-final/--final-cutoff/--full flags, the norgate and
yahoo extras, and the `packaging` dependency that existed only for norgatedata.
Bars come from marketdata.get_bars against $MARKETDATA_STORE.
Deleted rather than deprecated. A shim left importable would read a store the
nightly job no longer fills, and stale data is much harder to notice than an
AttributeError -- the failure is a number that looks right and is months old.
A test asserts the names stay gone.
DATABENTO STAYS, and with it store.write_prices/read_prices, config.prices_dir
and the `prices` manifest half it writes through. It has no marketdata
equivalent, and deleting it would destroy a validated provider-different
alternative (ADR-0006) plus the only intraday-capable source in the fleet. So
the CONSUMER bar API left and the store-level pair the retained producer needs
did not -- read its output with store.read_prices. cotdata-prices survives,
scoped to --ingest-databento/--build-databento. Worth stating plainly: "COT
only" is now true of the public API and not yet of the store.
The `metadata` manifest domain stays DECLARED with no writer, so stores written
before this still migrate and reconcile their entries instead of stranding them
in the legacy aggregate.
Three things the deletion exposed rather than caused, each fixed first:
* finals_ready() had no caller. It was ported in §7.1 but never wired to a
CLI flag, so --require-final here was the only way to reach it -- deleting
it would have left the Windows nightly job ungated, and a fetch before
Norgate settles writes a provisional bar over a real one silently. Fixed as
marketdata #13; this deletion was not safe without it.
* Six behaviours had tests only here: volume reconstruction, the volume-rank
pick, the incremental window, full=True, the NDU-down abort, the all-null
spec-row skip. §7.1 ported the provider and not its tests. A file-count
check would have missed it -- the test FILES existed on both sides, with
zero name overlap and a real gap underneath. Ported in the same PR.
* Two harnesses read the Norgate store by PATH, so no call-site grep finds
them. validate_databento_vs_norgate.py and investigate_databento_roll_rule
.py now read bars/futures/norgate/ first and fall back to the old layout,
so the ADR-0006 parity gate still runs across the split.
test_every_action_flag_is_assigned_to_a_half was reading a list copied beside
the parser, which stayed green through this change while naming three flags
that no longer exist -- so it could not have caught a fourth being added
either. It now derives the flags from the parser, which needed update.main's
argparse block extracted into _parser().
Known breakage, deliberate: crowdmon (frozen, archived) and npf's
docs/crowdmon/reproduce_forced_flow_mechanism.py still call get_prices. Both
are point-in-time records under their repos' doc lifecycle; §8.2 of the work
order already voided the crowdmon repoint on the same grounds.
Verified: ruff clean; 254 pass here. npf's full suite run against this branch
and against main gives byte-identical failure sets (38/38, all pre-existing
sibling-checkout gaps in this sandbox), and its contract-specs loader now
resolves unambiguously to marketdata instead of warning that both packages
could answer.
Written against a stale clone. `--require-final` was wired into `marketdata-update` by PR #12, which merged while this branch was being built, and a duplicate written here converged on the same design independently hours apart. #12 is the better of the two -- it also keeps `--final-cutoff` accepted and ignored, so a scheduler still carrying cotdata's flag does not break on it, and it prints a per-reference defer table. Worth recording rather than quietly fixing: two passes reaching for the same gate is evidence the deletion could not proceed without it, which is the point §8.5 was making. #13 is now only the ported producer tests, which nothing else covers.
mspinola
marked this pull request as ready for review
August 9, 2026 13:49
This was referenced Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes ADR-0007 step 2 §7.5. cotdata is CFTC positioning now; bars are
marketdata.get_barsagainst$MARKETDATA_STORE.Merge marketdata#13 first (the producer tests this deletion would otherwise orphan — see "What this exposed"). The
--require-finalprerequisite is already satisfied: marketdata#12 landed it.Gone
prices.py(with the derivedpropadjtier) ·providers/norgate.py·providers/yfinance.py·get_prices/roll_dates·store.{write,upsert,read}_metadata·--prices/--metadata/--prices-yahoo/--require-final/--final-cutoff/--full· thenorgateandyahooextras · thepackagingdependency that existed only fornorgatedata. Migration table is in the CHANGELOG.Deleted rather than deprecated. A shim left importable would read a store the nightly job no longer fills, and stale data is much harder to notice than an
AttributeError— the failure is a number that looks right and is months old. A test asserts the names stay gone.roll_datesis dropped outright rather than ported: a sweep of the four consumer repos found no caller. npf'sroll_datesis its own function (a threshold on the back-adjustment offset, not aDelivery Monthchange) and is unaffected.What stayed, and why it is worth saying out loud
databento stays, and with it
store.write_prices/read_prices,config.prices_dir()and thepricesmanifest half it writes through. It has no marketdata equivalent, and deleting it would destroy a validated provider-different alternative (ADR-0006) plus the only intraday-capable source in the fleet. So the consumer bar API left and the store-level pair the retained producer needs did not — read its output withstore.read_prices.cotdata-pricessurvives, scoped to--ingest-databento/--build-databento.That means "cotdata is COT-only" is now true of the public API and not yet of the store. ADR-0007 needs to record databento as a live exception to its own boundary rather than a step still to do.
The
metadatamanifest domain stays declared with no writer, so stores written before this still migrate and reconcile their entries instead of stranding them in the legacy aggregate.What the deletion exposed (not caused)
Three gaps §7.1 left, invisible while cotdata still held a copy:
finals_ready()had no caller. Ported in §7.1 but never wired to a CLI flag —cotdata-update --prices --require-finalwas the only way to reach it. Deleting that would have left the Windows nightly job ungated, and a fetch run before Norgate settles writes a provisional bar over a real one with nothing in the store to say so. Already fixed by marketdata#12. Worth recording that fix: make PEP 604 union annotations import-safe on Python 3.9 #12 and a duplicate written from this branch converged on the same design independently, hours apart: a second pass reaching for the same gate is evidence the deletion could not proceed without it.Six behaviours had tests only here — volume reconstruction, the volume-rank pick (the GC/SI case), the incremental window,
full=True, the NDU-down abort, the all-null spec-row skip. §7.1 ported the provider and not its tests. A file-count check would have missed this entirely: the test files existed on both sides, with zero name overlap across 30 deleted tests and a real coverage gap underneath. Ported in marketdata#13, which is why that should merge first.Two harnesses read the Norgate store by path, so no call-site grep finds them — the same class of coupling as the work order's §8.3, one layer out.
validate_databento_vs_norgate.pyandinvestigate_databento_roll_rule.pynow trybars/futures/norgate/first and fall back to the old layout, so the ADR-0006 parity gate still runs across the split.A test that could not do its job
test_every_action_flag_is_assigned_to_a_halfcompared_HALF_ACTIONSagainst a list copied beside the parser. It stayed green through this change while naming three flags that no longer exist — so it could not have caught a fourth being added either. It now derives the flag set from the parser, which neededmain's argparse block extracted into_parser().Docs
README, CHANGELOG (0.4.0, breaking),
WINDOWS_SCHEDULING,WINDOWS_SETUP,LINUX_SCHEDULING,SYNCING,CONTRIBUTING, the Windows/Linux example wrapper scripts, and the databento parity record. The Windows nightly task is retargeted tomarketdata-update --bars --domain futures --require-final— same box, same time, same restart-on-failure trick; every operational fact about NDU and deferred exit codes is unchanged.Two design records get a banner rather than a rewrite, per the doc lifecycle:
finals_ready_data_driven.md(mechanism moved) andreading-the-store.md§4–§5 (updated to the new API but kept here — they are naming-and-composition traps a reader arriving from a COT question walks straight into).crowdmon_step2_normalisation.mdis left untouched as a point-in-time proposal.Known breakage, accepted
crowdmon(frozen, archived) andnpf/docs/crowdmon/reproduce_forced_flow_mechanism.pystill callcotdata.get_prices. Both are point-in-time records under their repos' doc lifecycle; §8.2 of the work order already voided the crowdmon repoint on the same grounds.Verification
ruff check src tests scriptsclean; 254 pass (from 289 — the delta is the deleted Norgate/yfinance/propadj files, whose behaviours are now covered in marketdata).--pricesis refused with a non-zero exit, and the nothing-to-do message namesmarketdata-update --bars.main: byte-identical failure sets, 38/38, zero new. Those 38 are pre-existing sibling-checkout gaps in this sandbox, not regressions. npf's CI checks out cotdata's default branch with noref:, so it becomes the real integration test on merge.specs source -> marketdata.store.read_metadata, also available: ()), instead of warning that both packages could answer — the ADR-0007 fallback it was built for, working.