Money, Timings & Holidays
Lakhs vs millions, 9:15 IST vs 9:30 ET - the everyday units and clocks of Indian and US markets, expressed in code.
- ·Lakh & crore vs million
- ·Formatting Indian money
- ·Market hours IST vs ET
- ·Time zones in Python
- ·Trading holidays
- ·Sessions & pre-open
Two small things trip up almost everyone writing code for Indian markets, and neither is hard - they're just different from the US defaults most software assumes. The first is units: India counts in lakhs and crores, grouped 2-2-3, not in millions grouped in threes. The second is the clock: the market runs 9:15 to 3:30 on its own time zone, skips weekends, and closes on a long list of holidays. Get these right and your numbers and timestamps will always make sense to an Indian trader.
Lakhs and crores
Indian numbering groups digits 2-2-3 from the right - so 656800 is written 6,56,800 (six lakh, fifty-six thousand, eight hundred), not the Western 656,800. A lakh is 1,00,000 and a crore is 1,00,00,000. Python's built-in :, gives Western grouping, so for Indian style you write a small helper:
def indian_format(n):
"""Format a whole number with Indian 2-2-3 digit grouping (lakh/crore style)."""
s = f"{int(round(n)):d}"
if len(s) <= 3:
return s
last3, rest = s[-3:], s[:-3]
parts = []
while len(rest) > 2: # group the rest in twos, from the right
parts.insert(0, rest[-2:])
rest = rest[:-2]
if rest:
parts.insert(0, rest)
return ",".join(parts) + "," + last3
# The same numbers, Western grouping vs Indian grouping.
for n in [1313, 656800, 18016237, 1500000000]:
print(f"Western {n:>14,} -> Indian Rs {indian_format(n)}")Western 1,313 -> Indian Rs 1,313 Western 656,800 -> Indian Rs 6,56,800 Western 18,016,237 -> Indian Rs 1,80,16,237 Western 1,500,000,000 -> Indian Rs 1,50,00,00,000
The function peels off the last three digits, then groups the rest in twos. The difference is stark on big numbers: a Reliance lot's value is 6,56,800 to an Indian reader, and a billion rupees is 1,50,00,00,000 - 150 crore. Whenever you display rupee figures to Indian users, reach for this grouping; the Western commas look subtly wrong to a local eye.
Indian numbers group 2-2-3 from the right: lakh = 1,00,000 (10^5), crore = 1,00,00,000 (10^7). Python's :, does Western grouping, so use a small helper for Indian style. One crore = 100 lakh = 10 million.
Market hours across time zones
The NSE cash session runs 09:15 to 15:30 IST, weekdays only; the US runs 09:30 to 16:00 ET. To reason about both safely, attach a real time zone to your datetimes with Python's zoneinfo, and convert with astimezone:
from datetime import datetime, time
from zoneinfo import ZoneInfo
ist = ZoneInfo("Asia/Kolkata")
et = ZoneInfo("America/New_York")
# One fixed moment - 11:00 on a Thursday in Mumbai - shown in two time zones.
moment = datetime(2026, 6, 25, 11, 0, tzinfo=ist)
print("Mumbai (IST):", moment.strftime("%a %H:%M %Z"))
print("New York (ET) :", moment.astimezone(et).strftime("%a %H:%M %Z"))
print()
# NSE cash session is 09:15 to 15:30 IST, on weekdays only.
def nse_open(dt):
dt = dt.astimezone(ist)
return dt.weekday() < 5 and time(9, 15) <= dt.time() <= time(15, 30)
for label, m in [("Thu 11:00 IST", datetime(2026, 6, 25, 11, 0, tzinfo=ist)),
("Thu 16:00 IST", datetime(2026, 6, 25, 16, 0, tzinfo=ist)),
("Sun 11:00 IST", datetime(2026, 6, 28, 11, 0, tzinfo=ist))]:
print(f"{label}: NSE open? {nse_open(m)}")Mumbai (IST): Thu 11:00 IST New York (ET) : Thu 01:30 EDT Thu 11:00 IST: NSE open? True Thu 16:00 IST: NSE open? False Sun 11:00 IST: NSE open? False
The output makes the gap concrete: 11:00 in Mumbai is 01:30 the previous night in New York. That's why, on an IST clock, the US market only comes alive in your evening. The nse_open check combines the weekday test from Chapter 23 with a time-zone-aware conversion, so it's correct no matter where the code runs.
IST is UTC+5:30 - one of the world's few half-hour time zones. Most zones are whole hours off UTC; India (with Sri Lanka) sits on a thirty-minute offset, and the entire country uses this single zone despite spanning nearly two hours of real sunrise difference. The lesson for code: never assume whole-hour offsets or that "local time" means one thing - always attach a real zone with zoneinfo and let it do the arithmetic.
Holidays and special sessions
Weekends are easy (weekday() >= 5), but markets also close on a long list of trading holidays - Republic Day, Holi, Diwali, Independence Day and more - that don't follow any simple rule. There's no formula; you check the date against the exchange's published holiday list for the year. The day also has structure beyond the bell: a pre-open auction from 09:00 to 09:15 sets the opening price before continuous trading begins.
Once a year, the Indian market opens at night - on Diwali. On Diwali evening the NSE and BSE hold a special one-hour session called Muhurat Trading, considered an auspicious moment to begin the new Samvat (the traditional accounting year). It's the only scheduled trading on what is otherwise a holiday, and many traders place a small symbolic buy for good fortune. A centuries-old ritual, conducted on a modern electronic exchange - a very Indian blend of the ancient and the algorithmic.
Try it yourself
- Format
12345678and99000withindian_format. Read them aloud in lakhs and crores. - Convert
datetime(2026, 6, 25, 9, 30, tzinfo=et)(US open) into IST - what evening time does the US market open for an Indian trader? - Add a check to
nse_openthat also rejects a hard-coded holiday date of your choice (e.g.dt.date() == date(2026, 1, 26)).
Recap
- Indian numbers group 2-2-3 (lakh 10^5, crore 10^7); use a small helper since
:,is Western. - NSE trades 09:15-15:30 IST (pre-open from 09:00); the US trades 09:30-16:00 ET - barely overlapping on an IST clock.
- Attach real time zones with
zoneinfoand convert withastimezone; IST is UTC+5:30. - Markets close on weekends and holidays (no simple rule - check the published list).
You can now speak the market's language of money and time. It's finally time to look closely at the unit of market data itself - the bar that every chart is built from. The next chapter dissects OHLCV data: open, high, low, close and volume, and the candle they form.