Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/cotdata/registry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Equities:
cftc_code: "239742"
hist_codes:
- "23977A"
# Held-out generalization markets (never in the deploy selection) — collected here
# so the strategy can be scored on them; cot-analyzer flags them role: heldout.
EMD: # E-mini S&P MidCap 400 (CME)
cftc_code: "33874A"
NKD: # Nikkei 225 ($-denominated, CME)
cftc_code: "240741"

Metals:
GC:
Expand Down Expand Up @@ -43,6 +49,18 @@ Grains:
cftc_code: "007601"
ZW:
cftc_code: "001602"
# Held-out generalization grains (new symbols, never in the deploy selection).
ZO: # Oats (CBOT)
cftc_code: "004603"
KE: # KC HRW Wheat (Kansas City, CME)
cftc_code: "001612"

# Dairy — a genuinely new asset class for the held-out generalization test: real
# commercial hedgers, never touched CMR selection. Collected here; cot-analyzer
# flags it role: heldout.
Dairy:
DC: # Class III Milk (CME)
cftc_code: "052641"

Currencies:
6E:
Expand Down
11 changes: 7 additions & 4 deletions tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# ── loading & basic shape ────────────────────────────────────────────────────
def test_registry_loads_all_symbols():
symbols = all_symbols()
assert len(symbols) == 42, f"Expected 42 symbols, got {len(symbols)}"
assert len(symbols) == 47, f"Expected 47 symbols, got {len(symbols)}"


def test_basic_symbol_loading():
Expand Down Expand Up @@ -49,17 +49,20 @@ def test_hist_code_scales_normalization():

def test_by_asset_class():
equities = by_asset_class("Equities")
assert len(equities) == 4
assert len(equities) == 6 # ES NQ YM RTY + held-out EMD, NKD
assert all(eq.is_equity for eq in equities)

dairy = by_asset_class("Dairy") # new held-out class
assert [d.internal for d in dairy] == ["DC"]

crypto = by_asset_class("Crypto")
assert [c.internal for c in crypto] == ["BTC", "ETH"]


# ── hashability (frozen dataclass must stay hashable, incl. scaled hist_codes) ─
def test_symbols_are_hashable():
# Would raise TypeError: unhashable type 'list' if hist_codes held a list.
assert len(set(all_symbols())) == 42
assert len(set(all_symbols())) == 47
assert symbol("LBR") in {symbol("LBR")}
hash(symbol("LBR")) # scaled hist_codes — the tricky one

Expand Down Expand Up @@ -148,5 +151,5 @@ def test_golden_identity_checksum():
(registry.yaml carries FIXED identity only; unintended drift is a bug)."""
ident = sorted((s.internal, s.cftc_code, s.asset_class) for s in all_symbols())
digest = hashlib.md5(repr(ident).encode()).hexdigest()
assert digest == "e14ab3bad0f67741a95f721d4eff5ada", (
assert digest == "427c5d59ee4a2e5a09fd7dc6f8b5103a", (
"registry identity facts changed; update the expected checksum if intended")
Loading