Skip to main content

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.

Why so little lives here

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.

GroupSymbols
BullionGOLD, GOLDM, GOLDGUINEA, GOLDPETAL, GOLDTENGOLD; SILVER, SILVERM, SILVERMIC, SILVER100SILVER
EnergyCRUDEOIL, CRUDEOILMCRUDEOIL; NATURALGAS, NATGASMININATURALGAS
Base metalsALUMINIUM/ALUMINI, COPPER/COPPERM, ZINC/ZINCMINI, LEAD/LEADMINI, NICKEL/NICKELM
AgriCOTTON/COTTONCNDY, COTTONOIL, KAPAS, CARDAMOM, CASTORSEED, MENTHAOIL, CPO, RUBBER
IndustrialSTEELREBAR, ELECDMBL
IndicesMCXBULLDEX, 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.

SymbolpricequoteMeaning
GOLD10.0Quoted per 10 grams
GOLDM10.0Quoted per 10 grams
GOLDTEN10.0Quoted per 10 grams
SILVER10010.0Quoted per 10 grams
GOLDGUINEA8.0Quoted per 8 grams
everything else1.0Quoted 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

FunctionUsed 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