Skip to content

fix: upsert scoped Norgate metadata instead of replacing whole table#22

Merged
mspinola merged 1 commit into
mainfrom
claude/priceless-yalow-4d2142
Jul 16, 2026
Merged

fix: upsert scoped Norgate metadata instead of replacing whole table#22
mspinola merged 1 commit into
mainfrom
claude/priceless-yalow-4d2142

Conversation

@mspinola

Copy link
Copy Markdown
Owner

Bug

cotdata-update --metadata --symbols DC ZO KE EMD NKD replaced the entire metadata/contract_specs.parquet with only those 5 rows, dropping the other 42 markets' contract specs (Norgate_Symbol, tick/point value, margin, …). This broke contract-spec lookups (position sizing, cost calc) across the deploy book. Confirmed: 42 rows → 5 after that run.

Root cause

Contract specs live in one Symbol-keyed table (unlike prices/COT, which are one parquet per symbol). norgate.update_metadata(symbols=…) built a specs frame for only the requested symbols and wrote it via store.write_metadata, which atomically replaces the whole file. A subset write therefore erased every unlisted market.

Fix

  • store.upsert_metadata — read existing → replace/add requested Symbols → keep the rest → write the union (manifest reflects the union count).
  • norgate.update_metadata — a scoped run (symbols given) now upserts by Symbol; a no-symbols run still regenerates the full registry and replaces the table.

Other writers checked

write_prices and the COT writers all write per-symbol/per-name files, so they have no replace-vs-merge exposure — contract_specs was the only single-table-for-all-symbols writer.

Tests (55 pass)

  • scoped update preserves unlisted markets (the regression)
  • scoped update_metadata upserts end-to-end through a tmp store
  • no-symbols update still replaces the table
  • upsert on an empty store behaves like a plain write

Operational note

Immediate recovery (already done): re-run cotdata-update --metadata with no --symbols on the Norgate/Windows box → regenerates all 47. This change prevents recurrence.

🤖 Generated with Claude Code

A scoped `cotdata-update --metadata --symbols DC ZO KE EMD NKD` run REPLACED
the entire metadata/contract_specs.parquet with only those rows, dropping the
other 42 markets' contract specs (Norgate_Symbol, tick/point value, margin,
…) and breaking position-sizing / cost lookups across the deploy book.

Contract specs live in ONE Symbol-keyed table (unlike prices/COT, which are
one parquet per symbol), so a subset write must upsert, not overwrite.

- store.upsert_metadata: read existing → replace/add requested Symbols → keep
  the rest → write the union (manifest reflects the union count).
- norgate.update_metadata: scoped run (`symbols` given) upserts by Symbol;
  no-symbols run still regenerates the full registry and replaces the table.
- Tests: scoped update preserves unlisted markets; full update replaces;
  upsert on empty store behaves like a plain write.

Other metadata writers (prices, COT) are per-symbol files, so they have no
replace-vs-merge exposure — only contract_specs shares one table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mspinola
mspinola merged commit ee48a9b into main Jul 16, 2026
5 checks passed
@mspinola
mspinola deleted the claude/priceless-yalow-4d2142 branch July 16, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant