quantmod 0.1.1__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quantmod-0.1.1 → quantmod-0.1.2}/PKG-INFO +1 -1
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/derivatives/nse.py +24 -109
- quantmod-0.1.2/quantmod/version.py +1 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/PKG-INFO +1 -1
- quantmod-0.1.1/quantmod/version.py +0 -1
- {quantmod-0.1.1 → quantmod-0.1.2}/LICENSE.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/README.md +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/_version.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/charts/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/charts/plotting.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/charts/themes.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/datasets/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/datasets/data/nifty50.csv +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/datasets/data/spx.csv +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/datasets/dataloader.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/derivatives/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/indicators/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/indicators/indicators.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/main.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/markets/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/markets/bb.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/markets/yahoo.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/models/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/models/binomial.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/models/blackscholes.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/models/montecarlo.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/models/optioninputs.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/risk/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/risk/var.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/risk/varbacktest.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/risk/varinputs.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/timeseries/__init__.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/timeseries/performance.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/timeseries/timeseries.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod/utils.py +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/SOURCES.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/dependency_links.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/entry_points.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/not-zip-safe +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/requires.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/quantmod.egg-info/top_level.txt +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/setup.cfg +0 -0
- {quantmod-0.1.1 → quantmod-0.1.2}/setup.py +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
#
|
|
2
|
-
# to be used only for tutorial purposes
|
|
3
|
-
# for production use, please reach out to NSE India
|
|
1
|
+
# updated to new nse api changes on 10th Dec 2025
|
|
4
2
|
import os, sys
|
|
5
3
|
import requests
|
|
6
4
|
import numpy as np
|
|
@@ -83,89 +81,6 @@ def nsefetch(payload: str):
|
|
|
83
81
|
# --- Utility constants ---
|
|
84
82
|
indices = ["NIFTY", "FINNIFTY", "BANKNIFTY"]
|
|
85
83
|
|
|
86
|
-
# # Constants
|
|
87
|
-
# indices = ["NIFTY", "FINNIFTY", "BANKNIFTY"]
|
|
88
|
-
|
|
89
|
-
# headers = {
|
|
90
|
-
# "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",
|
|
91
|
-
# "accept-language": "en-US,en;q=0.9,en-IN;q=0.8,en-GB;q=0.7",
|
|
92
|
-
# "cache-control": "max-age=0",
|
|
93
|
-
# "priority": "u=0, i",
|
|
94
|
-
# "sec-ch-ua": '"Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
|
|
95
|
-
# "sec-ch-ua-mobile": "?0",
|
|
96
|
-
# "sec-ch-ua-platform": '"Windows"',
|
|
97
|
-
# "sec-fetch-dest": "document",
|
|
98
|
-
# "sec-fetch-mode": "navigate",
|
|
99
|
-
# "sec-fetch-site": "none",
|
|
100
|
-
# "sec-fetch-user": "?1",
|
|
101
|
-
# "upgrade-insecure-requests": "1",
|
|
102
|
-
# "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",
|
|
103
|
-
# }
|
|
104
|
-
|
|
105
|
-
# # Curl headers
|
|
106
|
-
# 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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" -H "sec-fetch-user: ?1" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-site: none" -H "sec-fetch-mode: navigate" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9,hi;q=0.8" --compressed"""
|
|
107
|
-
|
|
108
|
-
# # https://ipapi.co/json
|
|
109
|
-
# # https://ipinfo.io/json
|
|
110
|
-
|
|
111
|
-
# try:
|
|
112
|
-
# # Try ipapi.co
|
|
113
|
-
# response = requests.get("https://ipapi.co/json/", timeout=5)
|
|
114
|
-
# if response.status_code == 200:
|
|
115
|
-
# data = response.json()
|
|
116
|
-
# country_code = data.get('country_code', '').upper()
|
|
117
|
-
# mode = "local" if country_code == "IN" else "vpn"
|
|
118
|
-
# else:
|
|
119
|
-
# # Fallback to ipinfo.io
|
|
120
|
-
# response = requests.get("https://ipinfo.io/json", timeout=5)
|
|
121
|
-
# if response.status_code == 200:
|
|
122
|
-
# data = response.json()
|
|
123
|
-
# country_code = data.get('country', '').upper()
|
|
124
|
-
# mode = "local" if country_code == "IN" else "vpn"
|
|
125
|
-
# else:
|
|
126
|
-
# mode = "local"
|
|
127
|
-
|
|
128
|
-
# except Exception:
|
|
129
|
-
# mode = "local"
|
|
130
|
-
|
|
131
|
-
# # Force local mode only if you’re sure your machine is in India
|
|
132
|
-
# mode = "local"
|
|
133
|
-
# def nsefetch(payload):
|
|
134
|
-
# if mode == "vpn":
|
|
135
|
-
# if ("%26" in payload) or ("%20" in payload):
|
|
136
|
-
# encoded_url = payload
|
|
137
|
-
# else:
|
|
138
|
-
# encoded_url = urllib.parse.quote(payload, safe=":/?&=")
|
|
139
|
-
# payload_var = 'curl -b cookies.txt "' + encoded_url + '"' + curl_headers + ""
|
|
140
|
-
# try:
|
|
141
|
-
# output = os.popen(payload_var).read()
|
|
142
|
-
# output = json.loads(output)
|
|
143
|
-
# except ValueError: # includes simplejson.decoder.JSONDecodeError:
|
|
144
|
-
# payload2 = "https://www.nseindia.com"
|
|
145
|
-
# output2 = os.popen(
|
|
146
|
-
# 'curl -c cookies.txt "' + payload2 + '"' + curl_headers + ""
|
|
147
|
-
# ).read()
|
|
148
|
-
|
|
149
|
-
# output = os.popen(payload_var).read()
|
|
150
|
-
# output = json.loads(output)
|
|
151
|
-
# return output
|
|
152
|
-
|
|
153
|
-
# else: # mode == "local":
|
|
154
|
-
# try:
|
|
155
|
-
# output = requests.get(payload, headers=headers).json()
|
|
156
|
-
# # print(output)
|
|
157
|
-
# except ValueError:
|
|
158
|
-
# s = requests.Session()
|
|
159
|
-
# try:
|
|
160
|
-
# output = s.get("http://nseindia.com/option-chain", headers=headers)
|
|
161
|
-
# output = s.get(payload, headers=headers).json()
|
|
162
|
-
# except ValueError:
|
|
163
|
-
# output = s.get("https://www.nseindia.com", headers=headers)
|
|
164
|
-
# output = output.json()
|
|
165
|
-
# # output = s.get("https://www.nseindia.com/option-chain", headers=headers) # replaced http://nseindia.com with https://www.nseindia.com/option-chain
|
|
166
|
-
# output = s.get(payload, headers=headers).json()
|
|
167
|
-
# return output
|
|
168
|
-
|
|
169
84
|
|
|
170
85
|
class OptionData:
|
|
171
86
|
"""
|
|
@@ -232,16 +147,15 @@ class OptionData:
|
|
|
232
147
|
"""
|
|
233
148
|
if any(x in self.symbol for x in indices):
|
|
234
149
|
payload = nsefetch(
|
|
235
|
-
"https://www.nseindia.com/api/option-chain-
|
|
236
|
-
+ self.symbol
|
|
150
|
+
f"https://www.nseindia.com/api/option-chain-v3?type=Indices&symbol={self.symbol}&expiry={self.expiry_dt}"
|
|
237
151
|
)
|
|
238
152
|
else:
|
|
239
153
|
payload = nsefetch(
|
|
240
|
-
"https://www.nseindia.com/api/option-chain-
|
|
241
|
-
+ self.symbol
|
|
154
|
+
f"https://www.nseindia.com/api/option-chain-v3?type=Equity&symbol={self.symbol}&expiry={self.expiry_dt}"
|
|
242
155
|
)
|
|
243
156
|
return payload
|
|
244
157
|
|
|
158
|
+
|
|
245
159
|
def get_option_quote(self, strikePrice, optionType, intent=""):
|
|
246
160
|
"""
|
|
247
161
|
Get option quote for specific strike price and option type.
|
|
@@ -254,9 +168,9 @@ class OptionData:
|
|
|
254
168
|
Type of option, either 'CE' (Call) or 'PE' (Put)
|
|
255
169
|
intent : str, optional
|
|
256
170
|
Quote type:
|
|
257
|
-
- '' (default)
|
|
258
|
-
- 'sell' for
|
|
259
|
-
- 'buy' for
|
|
171
|
+
- '' (default) lastPrice
|
|
172
|
+
- 'sell' for sellPrice1
|
|
173
|
+
- 'buy' for buyPrice1
|
|
260
174
|
|
|
261
175
|
Returns
|
|
262
176
|
-------
|
|
@@ -264,16 +178,15 @@ class OptionData:
|
|
|
264
178
|
Option price based on the specified intent
|
|
265
179
|
"""
|
|
266
180
|
for x in range(len(self.payload["records"]["data"])):
|
|
267
|
-
if (self.payload["records"]["data"][x]["strikePrice"] == strikePrice)
|
|
268
|
-
self.payload["records"]["data"][x]["expiryDate"] == self.expiry_dt
|
|
269
|
-
):
|
|
181
|
+
if (self.payload["records"]["data"][x]["strikePrice"] == strikePrice):
|
|
270
182
|
if intent == "":
|
|
271
183
|
return self.payload["records"]["data"][x][optionType]["lastPrice"]
|
|
272
184
|
if intent == "sell":
|
|
273
|
-
return self.payload["records"]["data"][x][optionType]["
|
|
185
|
+
return self.payload["records"]["data"][x][optionType]["sellPrice1"]
|
|
274
186
|
if intent == "buy":
|
|
275
|
-
return self.payload["records"]["data"][x][optionType]["
|
|
187
|
+
return self.payload["records"]["data"][x][optionType]["buyPrice1"]
|
|
276
188
|
|
|
189
|
+
|
|
277
190
|
def _get_option_pcr(self):
|
|
278
191
|
"""
|
|
279
192
|
Calculate Put-Call Ratio based on open interest.
|
|
@@ -286,14 +199,14 @@ class OptionData:
|
|
|
286
199
|
ce_oi = 0
|
|
287
200
|
pe_oi = 0
|
|
288
201
|
for i in self.payload["records"]["data"]:
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
pass
|
|
202
|
+
try:
|
|
203
|
+
ce_oi += i["CE"]["openInterest"]
|
|
204
|
+
pe_oi += i["PE"]["openInterest"]
|
|
205
|
+
except KeyError:
|
|
206
|
+
pass
|
|
295
207
|
return round(pe_oi / ce_oi, 2)
|
|
296
208
|
|
|
209
|
+
|
|
297
210
|
def get_synthetic_future_price(self, strike):
|
|
298
211
|
"""
|
|
299
212
|
Calculate synthetic futures price using put-call parity.
|
|
@@ -315,6 +228,7 @@ class OptionData:
|
|
|
315
228
|
)
|
|
316
229
|
return synthetic_futures
|
|
317
230
|
|
|
231
|
+
|
|
318
232
|
def _get_call_option_data(self):
|
|
319
233
|
"""
|
|
320
234
|
Get call options data for current expiry.
|
|
@@ -327,10 +241,11 @@ class OptionData:
|
|
|
327
241
|
ce_values = [
|
|
328
242
|
data["CE"]
|
|
329
243
|
for data in self.payload["records"]["data"]
|
|
330
|
-
if "CE" in data and data["expiryDate"] == self.expiry_dt
|
|
331
244
|
]
|
|
332
245
|
return pd.DataFrame(ce_values).sort_values(["strikePrice"])
|
|
333
|
-
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
334
249
|
def _get_put_option_data(self):
|
|
335
250
|
"""
|
|
336
251
|
Get put options data for current expiry.
|
|
@@ -343,10 +258,10 @@ class OptionData:
|
|
|
343
258
|
pe_values = [
|
|
344
259
|
data["PE"]
|
|
345
260
|
for data in self.payload["records"]["data"]
|
|
346
|
-
if "PE" in data and data["expiryDate"] == self.expiry_dt
|
|
347
261
|
]
|
|
348
262
|
return pd.DataFrame(pe_values).sort_values(["strikePrice"])
|
|
349
|
-
|
|
263
|
+
|
|
264
|
+
|
|
350
265
|
def _get_maximum_pain_strike(self):
|
|
351
266
|
"""
|
|
352
267
|
Calculate maximum pain strike price.
|
|
@@ -367,4 +282,4 @@ class OptionData:
|
|
|
367
282
|
for expiry_price in strikes
|
|
368
283
|
]
|
|
369
284
|
|
|
370
|
-
return strikes[np.argmin(total_pain)]
|
|
285
|
+
return strikes[np.argmin(total_pain)]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "0.1.2"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "0.1.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|