Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

OpenContractID (OCID)

OpenContractID is an open specification and Python reference implementation for deterministic, reversible, UUIDv8-based identifiers for financial instruments and contracts.

OCID treats the identifier itself as the stable identity. A broker ID, database sequence, FIGI, ISIN, Yahoo symbol, IBKR conId, or other provider identifier is an alias or metadata rather than the source of truth.

Current status

This repository is the unreleased initial implementation. The package version remains 0.1.0 until the first publication. The protocol is explicitly versioned by an OCID schema nibble so future incompatible layouts can coexist.

Design

Two public value types define the Python API:

  • Contract: immutable domain value object and human-readable representation.
  • ContractUUID: a subclass of Python's uuid.UUID, carrying the deterministic OCID identity.

Contract is not a persistence entity. No contracts table is required to recover the core identity fields.

Contract
│ encode
▼
ContractUUID (uuid.UUID subclass)
│ decode
▼
Contract

For options, print(), str() and repr() use OCC/OSI 21-character option symbology. ContractUUID deliberately retains normal UUID string behavior.

Schema 1 payload

OCID uses UUIDv8 as a 128-bit container. UUID version and variant consume 6 fixed bits. The remaining 122 payload bits are:

FieldBitsSchema 1 meaning
schema4OCID schema version (1)
market8canonical market namespace
asset_type4equity / ETF / option / ...
symbol54reversible symbol code, max 10 canonical chars
expiry16days since 2000-01-01; zero means none
right2none / call / put
strike30fixed-point strike * 1000
reserved4zero in Schema 1

Canonical symbol alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-

Install

Development checkout:

python -m pip install -e '.[dev]'

After the package is published:

pip install opencontractid

Python API

Create an option

strike accepts either Decimal or a numeric string. Floating-point strikes are intentionally rejected.

fromdecimalimportDecimalfromocidimportContractcontract=Contract.option(
"INTC",
market="US",
expiry="2026-08-21",
right="C",
strike="150",
)
print(contract)
# INTC 260821C00150000assertcontract.strike==Decimal("150")

Equivalent construction with Decimal:

contract=Contract.option(
"INTC",
expiry="2026-08-21",
right="CALL",
strike=Decimal("150.125"),
)

Convert to UUID

fromuuidimportUUIDcid=contract.to_uuid()
assertisinstance(cid, UUID)
print(cid)
# standard UUID text, UUID version 8

ContractUUID extends Python's standard uuid.UUID, so it can generally be passed directly to PostgreSQL drivers, SQLAlchemy UUID columns, Pydantic UUID fields and APIs expecting a UUID.

Aliases are provided where external SDK conventions make them convenient:

contract.to_uuid()
contract.toUUID()
contract.to_id()
contract.toID()
contract.idcontract.uuid

Decode without a registry or database

fromocidimportContractrestored=Contract.from_uuid(cid)
assertrestored==contract

Accepted OCID inputs include ContractUUID, uuid.UUID, UUID string, 16-byte UUID bytes and integer UUID values through ContractUUID.parse().

Contract.from_uuid(cid)
Contract.fromUUID(cid)
Contract.from_id(str(cid))
Contract.fromID(str(cid))
cid.to_contract()
cid.toContract()

OCC / OSI

Options render as the OCC/OSI 21-character format:

contract=Contract.from_osi("INTC 260821C00150000")
str(contract)
# 'INTC 260821C00150000'repr(contract)
# 'INTC 260821C00150000'contract.to_osi()
# 'INTC 260821C00150000'

OSI conversion is a human/exchange representation. OCID remains the identity. str(contract.id) always remains standard UUID text.

Equities

fromocidimportContractintel=Contract.equity("intc", market="US")
str(intel)
# 'INTC'intel.id# ContractUUID(...)

US share/class separators are normalized into the OCID canonical form:

Contract.equity("BRK-B").symbol# 'BRK.B'

Numeric markets

Market decorators normalize exchange conventions before encoding:

Contract.equity("700", market="HK").symbol# '00700'Contract.equity("1", market="CN").symbol# '000001'

Market decorators

The UUID layout is global. Markets normally customize only canonicalization and validation.

fromocidimportMarket, contract_market@contract_market(Market.US)classUSMarketRules:
@staticmethoddefnormalize_symbol(symbol: str) ->str:
returnsymbol.strip().upper().replace("-", ".")

Do not create a separate UUID codec for every exchange. A market decorator should adapt its symbology into the global canonical contract model.

Built-in namespaces currently include US, HK, CN, JP, GB, DE, FR, NL, CH, CA, AU, SG, GLOBAL, FX and CRYPTO.

CLI

Encode:

ocid encode \
--market US \
--asset OPTION \
--symbol INTC \
--expiry 2026-08-21 \
--right CALL \
--strike 150

Decode:

ocid decode <uuid>

Parse OSI and emit OCID:

ocid osi 'INTC 260821C00150000'

Provider identity

Keep provider identifiers outside the core identity:

OCID / ContractUUID deterministic internal identity
FIGI / ISIN external industry identity
IBKR conId broker identity
Yahoo/Futu symbol provider alias
exchange metadata / venue

A persistence system may store queryable metadata keyed by OCID, but the metadata record does not own the identity.

Agent skills

The repository includes skills under skills/:

  • opencontractid-python-api/SKILL.md: how an agent should consume OCID from Python applications.
  • opencontractid-development/SKILL.md: how an agent should safely modify the implementation and protocol.

The Python API skill is deliberately usage-oriented: construction, conversion, parsing, persistence boundaries, safe strike handling and provider integration.

Repository layout

src/ocid/
model.py Contract + enums
uuid8.py ContractUUID + UUIDv8 free-bit mapping
codec.py Schema 1 packing and validation
symbol_codec.py reversible symbol encoding
registry.py decorator-based market registration
markets/ market canonicalization rules
cli.py command-line interface
docs/SPEC.md protocol specification
docs/ARCHITECTURE.md domain and integration architecture
skills/ Python API and development agent skills
tests/ behavior and protocol tests
AGENTS.md coding-agent repository rules

Development and release

python -m pip install -e '.[dev]'
pytest
ruff check .
mypy src/ocid
python -m build
python -m twine check dist/*

The package is configured for PyPI as opencontractid and imports as ocid. The first production publication should occur only after the Schema 1 golden vectors are intentionally frozen.

Intentional Schema 1 constraints

  • Canonical symbol: at most 10 characters from A-Z0-9.-.
  • Option strike input: Decimal or numeric str; no float.
  • Strike precision: at most 0.001.
  • OCID encoded strike maximum: (2^30 - 1) / 1000.
  • OCC/OSI rendering additionally requires a root that fits 6 characters and an 8-digit scaled strike.
  • Expiry: uint16 day offset from 2000-01-01 with zero reserved for no expiry.
  • Corporate-action renames produce a new symbol-derived identity in Schema 1; metadata can link identities.
  • Complex adjusted options, exotic derivatives and exceptional long symbols are deferred.

License

Apache-2.0. See LICENSE.

About

Deterministic and reversible UUIDv8 contract identifiers for equities, options and other financial instruments, with OCC/OSI support.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages