mcx_specs.py — Contract Specifications
Holds only the contract properties that are genuinely static — everything else is read off each day's bhavcopy instead of hardcoded.
unit (KGS / GRMS / BBL / mmBtu / MWH / MT / BALES / UNIT)
and lotsize are not in this file — both come straight from each day's
bhavcopy:
unit = suffix of "Volume(In 000's)" # "225.810 KGS" -> KGS
lotsize = (Volume(In 000's) * 1000) / Volume(Lots) # verified: SILVER -> 30
MCX revises lot sizes between contract cycles, so a hardcoded table would go
stale silently. lotsize is stored per row in scr_mcxfo_eod, not in
the master — same reasoning as scr_nsefo_eod.lotsize in nseeod. Putting
it in the master would overwrite history on every revision.
COMMODITY_FAMILY: Dict[str, str]
Maps a tradable symbol to its analytics-only family grouping (e.g. GOLD,
GOLDM, GOLDGUINEA, GOLDPETAL, GOLDTEN all group under "GOLD"). A
symbol absent from the map is treated as its own family.
This is not the underly masid. Every tradable symbol is its own
underlying (typ=20) — the same way an NSE contract's underly points at
its own spot instrument, never at a shared parent. An earlier version made
the family the underlying, which hung ALUMINI (1,000 kg lot) off
ALUMINIUM (5,000 kg lot) — different lot sizes and prices made
ALUMINI-I ambiguous. Minis are never collapsed into their parent here.
| Group | Symbols |
|---|---|
| Bullion | GOLD, GOLDM, GOLDGUINEA, GOLDPETAL, GOLDTEN → GOLD; SILVER, SILVERM, SILVERMIC, SILVER100 → SILVER |
| Energy | CRUDEOIL, CRUDEOILM → CRUDEOIL; NATURALGAS, NATGASMINI → NATURALGAS |
| Base metals | ALUMINIUM/ALUMINI, COPPER/COPPERM, ZINC/ZINCMINI, LEAD/LEADMINI, NICKEL/NICKELM |
| Agri | COTTON/COTTONCNDY, COTTONOIL, KAPAS, CARDAMOM, CASTORSEED, MENTHAOIL, CPO, RUBBER |
| Industrial | STEELREBAR, ELECDMBL |
| Indices | MCXBULLDEX, MCXMETLDEX, MCXENRGDEX |
get_family(symbol) → str
COMMODITY_FAMILY.get(clean, clean) — returns the symbol itself when unmapped.
PRICE_QUOTATION: Dict[str, float]
The number of physical units the quoted price refers to. Default is 1.0.
| Symbol | pricequote | Meaning |
|---|---|---|
GOLD | 10.0 | Quoted per 10 grams |
GOLDM | 10.0 | Quoted per 10 grams |
GOLDTEN | 10.0 | Quoted per 10 grams |
SILVER100 | 10.0 | Quoted per 10 grams |
GOLDGUINEA | 8.0 | Quoted per 8 grams |
| everything else | 1.0 | Quoted per 1 unit |
get_price_quotation(symbol) → float
PRICE_QUOTATION.get(clean, 1.0).
Every value here was verified against the 2026-08-04 bhavcopy by checking, for traded futures rows only:
pricequote = (qty_k * 1000 * close) / (Value(Lacs) * 100000)
Filter with InstrumentName.isin(['FUTCOM', 'FUTIDX']) — not
.str.contains('FUT'), which also matches OPTFUT and produces garbage from
option premiums.
MCX_INDEX_SYMBOLS: frozenset
{"MCXBULLDEX", "MCXMETLDEX", "MCXENRGDEX"} — MCX index symbols, which drive
typ 23 (FUTIDX) / 24 (OPTIDX) instead of the ordinary 21/22 commodity
codes.
is_index(symbol) → bool
Membership test against MCX_INDEX_SYMBOLS. Used by
McxProcessor._classify() in mcx_downloader.py.
Consumers
| Function | Used in |
|---|---|
get_family() | process_bhavcopy_data(), resolve_masids() (new typ=20 rows) |
get_price_quotation() | process_bhavcopy_data() — feeds the avgprice formula |
is_index() | McxProcessor._classify() — routes typ to 23/24 vs 21/22 |