eshan6704 commited on
Commit
ac877b5
·
verified ·
1 Parent(s): 2fbe7eb

Update nsepython.py

Browse files
Files changed (1) hide show
  1. nsepython.py +193 -146
nsepython.py CHANGED
@@ -1,29 +1,61 @@
 
 
 
1
  import os, sys, requests, pandas as pd, json, random, datetime, time, logging, re, urllib.parse
2
  from collections import Counter
3
 
4
- mode = 'local'
5
 
6
- # ------------------------- NSE FETCH -------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  if mode == "vpn":
 
8
  def nsefetch(payload):
9
- def encode(url): return url if "%26" in url or "%20" in url else urllib.parse.quote(url, safe=":/?&=")
 
 
 
 
 
 
10
  def refresh_cookies():
11
  os.popen(f'curl -c cookies.txt "https://www.nseindia.com" {curl_headers}').read()
12
  os.popen(f'curl -b cookies.txt -c cookies.txt "https://www.nseindia.com/option-chain" {curl_headers}').read()
13
 
14
- if not os.path.exists("cookies.txt"): refresh_cookies()
 
 
15
  encoded = encode(payload)
16
  cmd = f'curl -b cookies.txt "{encoded}" {curl_headers}'
17
  raw = os.popen(cmd).read()
18
- try: return json.loads(raw)
 
 
19
  except:
20
  refresh_cookies()
21
  raw = os.popen(cmd).read()
22
- try: return json.loads(raw)
23
- except: return {}
 
 
 
 
24
 
25
- if mode == 'local':
26
  def nsefetch(payload):
 
 
 
27
  try:
28
  s = requests.Session()
29
  s.get("https://www.nseindia.com", headers=headers, timeout=10)
@@ -32,207 +64,222 @@ if mode == 'local':
32
  except:
33
  return {}
34
 
35
- # ------------------------- HEADERS -------------------------
 
 
 
 
36
  headers = {
37
- "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
38
- "accept-language": "en-US,en;q=0.9,en-IN;q=0.8,en-GB;q=0.7",
39
  "cache-control": "max-age=0",
40
- "priority": "u=0, i",
41
- "sec-ch-ua": '"Microsoft Edge";v="129","Not=A?Brand";v="8","Chromium";v="129"',
42
- "sec-ch-ua-mobile": "?0",
43
- "sec-ch-ua-platform": '"Windows"',
44
- "sec-fetch-dest": "document",
45
- "sec-fetch-mode": "navigate",
46
- "sec-fetch-site": "none",
47
- "sec-fetch-user": "?1",
48
- "upgrade-insecure-requests": "1",
49
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"
50
  }
51
 
52
  niftyindices_headers = {
53
- 'Connection': 'keep-alive',
54
- 'sec-ch-ua': '"Not;A Brand";v="99","Google Chrome";v="91","Chromium";v="91"',
55
- 'Accept': 'application/json,text/javascript,*/*;q=0.01',
56
- 'DNT': '1',
57
- 'X-Requested-With': 'XMLHttpRequest',
58
- 'sec-ch-ua-mobile': '?0',
59
- 'User-Agent': 'Mozilla/5.0',
60
- 'Content-Type': 'application/json; charset=UTF-8',
61
- 'Origin': 'https://niftyindices.com',
62
- 'Sec-Fetch-Site': 'same-origin',
63
- 'Sec-Fetch-Mode': 'cors',
64
- 'Sec-Fetch-Dest': 'empty',
65
- 'Referer': 'https://niftyindices.com/reports/historical-data',
66
- 'Accept-Language': 'en-US,en;q=0.9,hi;q=0.8'
67
  }
68
 
69
- curl_headers = ''' -H "authority: beta.nseindia.com" -H "cache-control: max-age=0" -H "dnt: 1" -H "upgrade-insecure-requests: 1" -H "user-agent: Mozilla/5.0" -H "sec-fetch-user: ?1" -H "accept: */*" -H "sec-fetch-site: none" -H "accept-language: en-US,en;q=0.9" --compressed'''
 
 
 
 
 
 
 
70
 
 
 
 
71
  run_time = datetime.datetime.now()
72
- indices = ['NIFTY','FINNIFTY','BANKNIFTY']
 
 
 
 
 
 
 
 
 
73
 
74
- # ------------------------- HELPERS -------------------------
75
- def nsesymbolpurify(s): return s.replace('&','%26')
76
 
77
  def flatten_dict(d, parent="", sep="."):
78
- items={}
79
- for k,v in d.items():
 
80
  nk = f"{parent}{sep}{k}" if parent else k
81
- if isinstance(v, dict): items.update(flatten_dict(v, nk, sep))
82
- else: items[nk] = v
 
 
83
  return items
84
 
 
85
  def flatten_nested(d, prefix=""):
86
- flat={}
87
- for k,v in d.items():
88
- nk = f"{prefix}{k}" if prefix=="" else f"{prefix}.{k}"
 
89
  if isinstance(v, dict):
90
  flat.update(flatten_nested(v, nk))
91
  elif isinstance(v, list):
92
  if v and isinstance(v[0], dict):
93
- for i,x in enumerate(v): flat.update(flatten_nested(x, f"{nk}.{i}"))
94
- else: flat[nk]=v
95
- else: flat[nk]=v
 
 
 
96
  return flat
97
 
 
98
  def rename_col(cols):
99
- child=[c.split('.')[-1] for c in cols]
100
- cnt=Counter(child)
101
- new=[]
102
- for c,ch in zip(cols,child):
103
- if cnt[ch]==1: new.append(ch)
 
 
104
  else:
105
- p=c.split('.')
106
- new.append(f"{p[-1]}_{p[-2]}" if len(p)>=2 else p[-1])
107
  return new
108
 
 
109
  def df_from_data(data):
110
- rows=[ flatten_nested(x) if isinstance(x,dict) else {"value":x} for x in data ]
111
- df=pd.DataFrame(rows)
112
- df.columns=rename_col(df.columns)
 
113
  return df
114
 
115
- # ------------------------- API FUNCTIONS -------------------------
 
 
 
 
116
  def indices():
117
- p=nsefetch("https://www.nseindia.com/api/allIndices")
118
- return {"data":pd.DataFrame(p.pop("data")), "dates":pd.DataFrame([p.pop("dates")]), "indices":pd.DataFrame([p])}
 
 
 
 
 
119
 
120
  def eq(symbol):
121
- symbol=nsesymbolpurify(symbol)
122
- df=nsefetch(f'https://www.nseindia.com/api/quote-equity?symbol={symbol}')
123
- pre=df.pop('preOpenMarket')
124
- out={
 
125
  "securityInfo": pd.DataFrame([df["securityInfo"]]),
126
  "priceInfo": pd.DataFrame([flatten_dict(df["priceInfo"])]),
127
  "industryInfo": pd.DataFrame([df["industryInfo"]]),
128
  "pdSectorIndAll": pd.DataFrame([df["metadata"].pop("pdSectorIndAll")]),
129
  "metadata": pd.DataFrame([df["metadata"]]),
130
  "info": pd.DataFrame([df["info"]]),
131
- "preOpen": pd.DataFrame(pre.pop('preopen')),
132
  "preOpenMarket": pd.DataFrame([pre])
133
  }
134
- return out
135
 
136
- def eq_fno(): return nsefetch('https://www.nseindia.com/api/equity-stockIndices?index=SECURITIES%20IN%20F%26O')
137
- def eq_der(symbol): return nsefetch('https://www.nseindia.com/api/quote-derivative?symbol='+nsesymbolpurify(symbol))
138
- def index_chain(symbol): return nsefetch('https://www.nseindia.com/api/option-chain-indices?symbol='+nsesymbolpurify(symbol))
139
- def eq_chain(symbol): return nsefetch('https://www.nseindia.com/api/option-chain-equities?symbol='+nsesymbolpurify(symbol))
140
- def nse_holidays(t="trading"): return nsefetch('https://www.nseindia.com/api/holiday-master?type='+t)
141
 
142
- def nse_results(index="equities",period="Quarterly"):
143
- if index in ["equities","debt","sme"] and period in ["Quarterly","Annual","Half-Yearly","Others"]:
144
- return pd.json_normalize(nsefetch(f'https://www.nseindia.com/api/corporates-financial-results?index={index}&period={period}'))
145
- print("Invalid Input")
146
 
147
- def nse_events(): return pd.json_normalize(nsefetch('https://www.nseindia.com/api/event-calendar'))
148
- def nse_past_results(symbol): return nsefetch('https://www.nseindia.com/api/results-comparision?symbol='+nsesymbolpurify(symbol))
149
- def nse_blockdeal(): return nsefetch('https://nseindia.com/api/block-deal')
150
- def nse_marketStatus(): return nsefetch('https://nseindia.com/api/marketStatus')
151
- def nse_circular(mode="latest"):
152
- return nsefetch('https://www.nseindia.com/api/latest-circular' if mode=="latest" else 'https://www.nseindia.com/api/circulars')
153
 
154
- def nse_fiidii(mode="pandas"):
155
-
156
- p=nsefetch('https://www.nseindia.com/api/fiidiiTradeReact')
157
- return pd.DataFrame(p)
158
 
159
- def nsetools_get_quote(symbol):
160
- p=nsefetch('https://www.nseindia.com/api/equity-stockIndices?index=SECURITIES%20IN%20F%26O')
161
- for x in p['data']:
162
- if x['symbol']==symbol.upper(): return x
163
 
164
- def nse_index():
165
- p=nsefetch('https://iislliveblob.niftyindices.com/jsonfiles/LiveIndicesWatch.json')
166
- return pd.DataFrame(p['data'])
167
 
168
- def index_history(sym,sd,ed):
169
- d={'cinfo':f"{{'name':'{sym}','startDate':'{sd}','endDate':'{ed}','indexName':'{sym}'}}"}
170
- p=json.loads(requests.post('https://niftyindices.com/Backpage.aspx/getHistoricaldatatabletoString', headers=niftyindices_headers, json=d).json()["d"])
171
- return pd.DataFrame.from_records(p)
172
 
173
- def index_pe_pb_div(sym,sd,ed):
174
- d={'cinfo':f"{{'name':'{sym}','startDate':'{sd}','endDate':'{ed}','indexName':'{sym}'}}"}
175
- p=json.loads(requests.post('https://niftyindices.com/Backpage.aspx/getpepbHistoricaldataDBtoString', headers=niftyindices_headers, json=d).json()["d"])
176
- return pd.DataFrame.from_records(p)
177
 
178
- def index_total_returns(sym,sd,ed):
179
- d={'cinfo':f"{{'name':'{sym}','startDate':'{sd}','endDate':'{ed}','indexName':'{sym}'}}"}
180
- p=json.loads(requests.post('https://niftyindices.com/Backpage.aspx/getTotalReturnIndexString', headers=niftyindices_headers, json=d).json()["d"])
181
- return pd.DataFrame.from_records(p)
182
 
 
 
183
 
184
- def nse_bulkdeals(): return pd.read_csv("https://archives.nseindia.com/content/equities/bulk.csv")
185
- def nse_blockdeals(): return pd.read_csv("https://archives.nseindia.com/content/equities/block.csv")
186
- #nse daily report
187
- def nse_bhavcopy(d): return pd.read_csv("https://archives.nseindia.com/products/content/sec_bhavdata_full_"+d.replace("-","")+".csv")
188
 
189
- def nse_highlow(d: str) -> pd.DataFrame:
190
- """
191
- NSE 52-week High/Low CSV
192
- Real header starts from row 3
193
- """
194
- date_str = d.replace("-", "")
195
- url = f"https://archives.nseindia.com/content/CM_52_wk_High_low_{date_str}.csv"
196
 
197
- df = pd.read_csv(
198
- url,
199
- skiprows=2, # 🔥 key fix
200
- engine="python"
201
- )
202
 
203
- df.columns = df.columns.str.strip()
204
- return df
205
 
206
 
 
 
207
 
208
 
209
- def nse_preopen(key="NIFTY"):
210
- p=nsefetch("https://www.nseindia.com/api/market-data-pre-open?key="+key)
211
- return {"data":df_from_data(p.pop("data")), "rem":df_from_data([p])}
212
 
213
- def nse_most_active(t="securities",s="value"):
214
- return pd.DataFrame(nsefetch(f"https://www.nseindia.com/api/live-analysis-most-active-{t}?index={s}")["data"])
215
 
216
- def nse_eq_symbols():
217
- return pd.read_csv('https://archives.nseindia.com/content/equities/EQUITY_L.csv')['SYMBOL'].tolist()
218
 
219
- def nse_price_band_hitters(b="both",v="AllSec"):
220
- p=nsefetch("https://www.nseindia.com/api/live-analysis-price-band-hitter")
221
- return {"data":pd.DataFrame(p[b][v]["data"]), "count":pd.DataFrame([p['count']])}
222
 
223
- def nse_largedeals(mode="bulk_deals"):
224
- p=nsefetch('https://www.nseindia.com/api/snapshot-capital-market-largedeal')
225
- return pd.DataFrame(p["BULK_DEALS_DATA" if mode=="bulk_deals" else "SHORT_DEALS_DATA" if mode=="short_deals" else "BLOCK_DEALS_DATA"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
- def nse_largedeals_historical(f,t,mode="bulk_deals"):
228
- m = "bulk-deals" if mode=="bulk_deals" else "short-selling" if mode=="short_deals" else "block-deals"
229
- p=nsefetch(f'https://www.nseindia.com/api/historical/{m}?from={f}&to={t}')
230
  return pd.DataFrame(p["data"])
231
 
232
- def nse_stock_hist(f,t,symbol,series="ALL"):
233
- url=f"https://www.nseindia.com/api/historical/securityArchives?from={f}&to={t}&symbol={symbol.upper()}&dataType=priceVolumeDeliverable&series={series}"
234
- return pd.DataFrame(nsefetch(url)['data'])
235
 
236
- def nse_index_live(name="NIFTY 50"):
237
- p=nsefetch(f"https://www.nseindia.com/api/equity-stockIndices?index={name.replace(' ','%20')}")
238
- return {"data":df_from_data(p.pop("data")) if "data" in p else pd.DataFrame(), "rem":df_from_data([p])}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ===============================================================
2
+ # Core imports (kept exactly as requested)
3
+ # ===============================================================
4
  import os, sys, requests, pandas as pd, json, random, datetime, time, logging, re, urllib.parse
5
  from collections import Counter
6
 
 
7
 
8
+ # ===============================================================
9
+ # Runtime mode
10
+ # - "local": direct requests.Session
11
+ # - "vpn" : curl + cookie based access
12
+ # ===============================================================
13
+ mode = "local"
14
+
15
+
16
+ # ===============================================================
17
+ # NSE FETCH HANDLER
18
+ # Single unified fetch function
19
+ # Auto-handles cookies, headers, and retries
20
+ # ===============================================================
21
+
22
  if mode == "vpn":
23
+
24
  def nsefetch(payload):
25
+ """
26
+ NSE fetch using curl + cookies (VPN-safe mode)
27
+ """
28
+
29
+ def encode(url):
30
+ return url if "%26" in url or "%20" in url else urllib.parse.quote(url, safe=":/?&=")
31
+
32
  def refresh_cookies():
33
  os.popen(f'curl -c cookies.txt "https://www.nseindia.com" {curl_headers}').read()
34
  os.popen(f'curl -b cookies.txt -c cookies.txt "https://www.nseindia.com/option-chain" {curl_headers}').read()
35
 
36
+ if not os.path.exists("cookies.txt"):
37
+ refresh_cookies()
38
+
39
  encoded = encode(payload)
40
  cmd = f'curl -b cookies.txt "{encoded}" {curl_headers}'
41
  raw = os.popen(cmd).read()
42
+
43
+ try:
44
+ return json.loads(raw)
45
  except:
46
  refresh_cookies()
47
  raw = os.popen(cmd).read()
48
+ try:
49
+ return json.loads(raw)
50
+ except:
51
+ return {}
52
+
53
+ else:
54
 
 
55
  def nsefetch(payload):
56
+ """
57
+ NSE fetch using requests.Session (local / HF safe)
58
+ """
59
  try:
60
  s = requests.Session()
61
  s.get("https://www.nseindia.com", headers=headers, timeout=10)
 
64
  except:
65
  return {}
66
 
67
+
68
+ # ===============================================================
69
+ # HTTP HEADERS
70
+ # ===============================================================
71
+
72
  headers = {
73
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
74
+ "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
75
  "cache-control": "max-age=0",
76
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
 
 
 
 
 
 
 
 
 
77
  }
78
 
79
  niftyindices_headers = {
80
+ "Accept": "application/json,text/javascript,*/*;q=0.01",
81
+ "Content-Type": "application/json; charset=UTF-8",
82
+ "Origin": "https://niftyindices.com",
83
+ "Referer": "https://niftyindices.com/reports/historical-data",
84
+ "User-Agent": "Mozilla/5.0"
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
+ curl_headers = '''
88
+ -H "authority: beta.nseindia.com"
89
+ -H "cache-control: max-age=0"
90
+ -H "user-agent: Mozilla/5.0"
91
+ -H "accept: */*"
92
+ --compressed
93
+ '''
94
+
95
 
96
+ # ===============================================================
97
+ # Runtime metadata
98
+ # ===============================================================
99
  run_time = datetime.datetime.now()
100
+ indices = ["NIFTY", "FINNIFTY", "BANKNIFTY"]
101
+
102
+
103
+ # ===============================================================
104
+ # Helper utilities
105
+ # ===============================================================
106
+
107
+ def nsesymbolpurify(s):
108
+ """Encode special NSE symbols"""
109
+ return s.replace("&", "%26")
110
 
 
 
111
 
112
  def flatten_dict(d, parent="", sep="."):
113
+ """Flatten nested dictionaries"""
114
+ items = {}
115
+ for k, v in d.items():
116
  nk = f"{parent}{sep}{k}" if parent else k
117
+ if isinstance(v, dict):
118
+ items.update(flatten_dict(v, nk, sep))
119
+ else:
120
+ items[nk] = v
121
  return items
122
 
123
+
124
  def flatten_nested(d, prefix=""):
125
+ """Flatten dicts + lists (deep NSE JSON support)"""
126
+ flat = {}
127
+ for k, v in d.items():
128
+ nk = f"{prefix}{k}" if prefix == "" else f"{prefix}.{k}"
129
  if isinstance(v, dict):
130
  flat.update(flatten_nested(v, nk))
131
  elif isinstance(v, list):
132
  if v and isinstance(v[0], dict):
133
+ for i, x in enumerate(v):
134
+ flat.update(flatten_nested(x, f"{nk}.{i}"))
135
+ else:
136
+ flat[nk] = v
137
+ else:
138
+ flat[nk] = v
139
  return flat
140
 
141
+
142
  def rename_col(cols):
143
+ """Resolve duplicate column names after flattening"""
144
+ child = [c.split(".")[-1] for c in cols]
145
+ cnt = Counter(child)
146
+ new = []
147
+ for c, ch in zip(cols, child):
148
+ if cnt[ch] == 1:
149
+ new.append(ch)
150
  else:
151
+ p = c.split(".")
152
+ new.append(f"{p[-1]}_{p[-2]}" if len(p) >= 2 else p[-1])
153
  return new
154
 
155
+
156
  def df_from_data(data):
157
+ """Convert NSE JSON array into clean DataFrame"""
158
+ rows = [flatten_nested(x) if isinstance(x, dict) else {"value": x} for x in data]
159
+ df = pd.DataFrame(rows)
160
+ df.columns = rename_col(df.columns)
161
  return df
162
 
163
+
164
+ # ===============================================================
165
+ # API WRAPPERS (No name changes)
166
+ # ===============================================================
167
+
168
  def indices():
169
+ p = nsefetch("https://www.nseindia.com/api/allIndices")
170
+ return {
171
+ "data": pd.DataFrame(p.pop("data")),
172
+ "dates": pd.DataFrame([p.pop("dates")]),
173
+ "indices": pd.DataFrame([p])
174
+ }
175
+
176
 
177
  def eq(symbol):
178
+ symbol = nsesymbolpurify(symbol)
179
+ df = nsefetch(f"https://www.nseindia.com/api/quote-equity?symbol={symbol}")
180
+ pre = df.pop("preOpenMarket")
181
+
182
+ return {
183
  "securityInfo": pd.DataFrame([df["securityInfo"]]),
184
  "priceInfo": pd.DataFrame([flatten_dict(df["priceInfo"])]),
185
  "industryInfo": pd.DataFrame([df["industryInfo"]]),
186
  "pdSectorIndAll": pd.DataFrame([df["metadata"].pop("pdSectorIndAll")]),
187
  "metadata": pd.DataFrame([df["metadata"]]),
188
  "info": pd.DataFrame([df["info"]]),
189
+ "preOpen": pd.DataFrame(pre.pop("preopen")),
190
  "preOpenMarket": pd.DataFrame([pre])
191
  }
 
192
 
 
 
 
 
 
193
 
194
+ def eq_fno():
195
+ return nsefetch("https://www.nseindia.com/api/equity-stockIndices?index=SECURITIES%20IN%20F%26O")
 
 
196
 
 
 
 
 
 
 
197
 
198
+ def eq_der(symbol):
199
+ return nsefetch("https://www.nseindia.com/api/quote-derivative?symbol=" + nsesymbolpurify(symbol))
 
 
200
 
 
 
 
 
201
 
202
+ def index_chain(symbol):
203
+ return nsefetch("https://www.nseindia.com/api/option-chain-indices?symbol=" + nsesymbolpurify(symbol))
 
204
 
 
 
 
 
205
 
206
+ def eq_chain(symbol):
207
+ return nsefetch("https://www.nseindia.com/api/option-chain-equities?symbol=" + nsesymbolpurify(symbol))
 
 
208
 
 
 
 
 
209
 
210
+ def nse_holidays(t="trading"):
211
+ return nsefetch("https://www.nseindia.com/api/holiday-master?type=" + t)
212
 
 
 
 
 
213
 
214
+ def nse_results(index="equities", period="Quarterly"):
215
+ if index in ["equities", "debt", "sme"] and period in ["Quarterly", "Annual", "Half-Yearly", "Others"]:
216
+ return pd.json_normalize(
217
+ nsefetch(f"https://www.nseindia.com/api/corporates-financial-results?index={index}&period={period}")
218
+ )
219
+ print("Invalid Input")
 
220
 
 
 
 
 
 
221
 
222
+ def nse_events():
223
+ return pd.json_normalize(nsefetch("https://www.nseindia.com/api/event-calendar"))
224
 
225
 
226
+ def nse_past_results(symbol):
227
+ return nsefetch("https://www.nseindia.com/api/results-comparision?symbol=" + nsesymbolpurify(symbol))
228
 
229
 
230
+ def nse_blockdeal():
231
+ return nsefetch("https://nseindia.com/api/block-deal")
 
232
 
 
 
233
 
234
+ def nse_marketStatus():
235
+ return nsefetch("https://nseindia.com/api/marketStatus")
236
 
 
 
 
237
 
238
+ def nse_circular(mode="latest"):
239
+ return nsefetch(
240
+ "https://www.nseindia.com/api/latest-circular"
241
+ if mode == "latest"
242
+ else "https://www.nseindia.com/api/circulars"
243
+ )
244
+
245
+
246
+ def nse_fiidii(mode="pandas"):
247
+ return pd.DataFrame(nsefetch("https://www.nseindia.com/api/fiidiiTradeReact"))
248
+
249
+
250
+ def nsetools_get_quote(symbol):
251
+ p = nsefetch("https://www.nseindia.com/api/equity-stockIndices?index=SECURITIES%20IN%20F%26O")
252
+ for x in p["data"]:
253
+ if x["symbol"] == symbol.upper():
254
+ return x
255
 
256
+
257
+ def nse_index():
258
+ p = nsefetch("https://iislliveblob.niftyindices.com/jsonfiles/LiveIndicesWatch.json")
259
  return pd.DataFrame(p["data"])
260
 
 
 
 
261
 
262
+ # ===============================================================
263
+ # Historical / CSV endpoints
264
+ # ===============================================================
265
+
266
+ def nse_bhavcopy(d):
267
+ return pd.read_csv(
268
+ "https://archives.nseindia.com/products/content/sec_bhavdata_full_" + d.replace("-", "") + ".csv"
269
+ )
270
+
271
+
272
+ def nse_highlow(d: str) -> pd.DataFrame:
273
+ date_str = d.replace("-", "")
274
+ url = f"https://archives.nseindia.com/content/CM_52_wk_High_low_{date_str}.csv"
275
+ df = pd.read_csv(url, skiprows=2, engine="python")
276
+ df.columns = df.columns.str.strip()
277
+ return df
278
+
279
+
280
+ def nse_bulkdeals():
281
+ return pd.read_csv("https://archives.nseindia.com/content/equities/bulk.csv")
282
+
283
+
284
+ def nse_blockdeals():
285
+ return pd.read_csv("https://archives.nseindia.com/content/equities/block.csv")