NSEPython Documentation

logo

NSEPython is a Python library to get publicly available data on the current NSEIndia and NIFTY Indices site by communicating with their REST APIs.

logo

Support and Beta Functions

Versions

There are two versions of NSEPython depending on the execution environment. While it’s technically feasible to combine these versions into a single program, doing so could introduce latency. Given the financial nature of this program, time is of the essence.

NSEPython Edition Compatibility Tested Environments
Local Edition Laptops (Windows 9, 10) Windows 9, Windows 10
Server Edition Servers (AWS, Google Colab, DigitalOcean) AWS, Google Colab, DigitalOcean

Installation

Use the package manager pip to install nsepython.

NSEPython Local Edition

Access NSEPython for laptops, specifically tailored for Windows 9 and Windows 10 compatibility.

pip install nsepython

NSEPython Server Edition

Leverage NSEPython designed for server environments, seamlessly functioning on AWS, Google Colab, and DigitalOcean.

pip install nsepythonserver

Cross Library Migration

All the functions from the two renowned packages, NsepY and NSETools, have been migrated here with the same function names. Both of these packages had been left unmaintained for a considerable period.

Advanced Usecases

Mastering AlgoTrading: A Beginner’s Guide using NSEPython

Designing an Index Fund From Scratch in Indian Share Market

Coding Heatmap and ORB

Markov Chain

Leverage

In Leverage, a plethora of trader-focused tools has been meticulously crafted using NSEPython.

Here’s an illustration of a Sectoral Heatmap, showcasing the extent of complexity that NSEPython API can effortlessly handle.

logo

2 Likes

A post was split to a new topic: NSEPython 1.0 Release Logs

3 posts were split to a new topic: NSEPython 2.0 Release Logs

2 posts were split to a new topic: NSEPython Server Version

Added new version 2.3

is_market_open(segment = "FO"): #COM,CD,CB,CMOT,COM,FO,IRD,MF,NDM,NTRP,SLBS

Did it quickly because I needed it myself for another project

Version 2.6 Release Log

Fixed Functions of

  • nse_expirydetails_by_symbol()
  • nse_quote_ltp()
  • nse_expirydetails()
  • nse_optionchain_ltp()

Read more on → Changed the nse_quote_ltp() function - #4 by dexter

No change of Syntax in the earlier functions. Documentation will not be updated.

Previously as documented here NSEPy Functions - Unofficed

symbol = "SBIN"
start_date = "15-05-2020"
end_date ="15-06-2021"

print(expiry_history(symbol,start_date,end_date))
print(expiry_history(symbol,start_date))
print(expiry_history(symbol))

used to give

['28-May-2020', '25-Jun-2020', '30-Jul-2020', '27-Aug-2020', '24-Sep-2020', '29-Oct-2020', '26-Nov-2020', '31-Dec-2020', '28-Jan-2021', '25-Feb-2021', '25-Mar-2021', '29-Apr-2021', '27-May-2021', '24-Jun-2021', '29-Jul-2021', '26-Aug-2021']

['28-May-2020', '25-Jun-2020', '30-Jul-2020', '27-Aug-2020', '24-Sep-2020', '29-Oct-2020', '26-Nov-2020', '31-Dec-2020', '28-Jan-2021', '25-Feb-2021', '25-Mar-2021', '29-Apr-2021', '27-May-2021', '24-Jun-2021', '29-Jul-2021', '26-Aug-2021']

['27-May-2021', '24-Jun-2021', '29-Jul-2021', '26-Aug-2021']

Now if we do this, We get

['30-Jan-2020', '27-Feb-2020', '26-Mar-2020', '30-Apr-2020', '28-May-2020', '25-Jun-2020', '30-Jul-2020', '27-Aug-2020', '24-Sep-2020', '29-Oct-2020', '26-Nov-2020', '31-Dec-2020', '28-Jan-2021', '25-Feb-2021', '25-Mar-2021', '29-Apr-2021', '27-May-2021', '24-Jun-2021', '29-Jul-2021', '26-Aug-2021', '30-Sep-2021', '28-Oct-2021', '25-Nov-2021', '30-Dec-2021']
['30-Jan-2020', '27-Feb-2020', '26-Mar-2020', '30-Apr-2020', '28-May-2020', '25-Jun-2020', '30-Jul-2020', '27-Aug-2020', '24-Sep-2020', '29-Oct-2020', '26-Nov-2020', '31-Dec-2020', '28-Jan-2021', '25-Feb-2021', '25-Mar-2021', '29-Apr-2021', '27-May-2021', '24-Jun-2021', '29-Jul-2021', '26-Aug-2021', '30-Sep-2021', '28-Oct-2021', '25-Nov-2021', '30-Dec-2021', '27-Jan-2022', '24-Feb-2022', '31-Mar-2022', '28-Apr-2022', '26-May-2022', '30-Jun-2022', '28-Jul-2022', '25-Aug-2022', '29-Sep-2022', '27-Oct-2022', '24-Nov-2022', '29-Dec-2022', '25-Jan-2023', '23-Feb-2023', '29-Mar-2023', '27-Apr-2023', '04-May-2023', '11-May-2023', '18-May-2023', '25-May-2023', '01-Jun-2023', '28-Jun-2023', '29-Jun-2023', '27-Jul-2023', '31-Aug-2023', '21-Sep-2023', '28-Sep-2023', '05-Oct-2023', '12-Oct-2023', '19-Oct-2023', '26-Oct-2023', '30-Nov-2023']
['25-Jan-2023', '23-Feb-2023', '29-Mar-2023', '27-Apr-2023', '04-May-2023', '11-May-2023', '18-May-2023', '25-May-2023', '01-Jun-2023', '28-Jun-2023', '29-Jun-2023', '27-Jul-2023', '31-Aug-2023', '21-Sep-2023', '28-Sep-2023', '05-Oct-2023', '12-Oct-2023', '19-Oct-2023', '26-Oct-2023', '30-Nov-2023']

In short, it does not check start_date, end_date

But it does check the start_year.

Also the data structure changed

Also FUTSTK for stock FUTIDX for index

We can not just do [0] because it has { instead of [

I thought to do the data thing fixed inside the code. But the wrapper should give the data that NSE is giving.

So, did this as of now -


def expiry_history(symbol,start_date="",end_date="",type="options"):
    if(end_date==""):end_date=end_date
    nsefetch_url = "https://www.nseindia.com/api/historical/fo/derivatives/meta?&from="+start_date+"&to="+end_date+"&symbol="+symbol+""
    payload = nsefetch(nsefetch_url)
    for key, value in payload['expiryDatesByInstrument'].items():
      if type.lower() == "options" and "OPT" in key:
          return (payload['expiryDatesByInstrument'][key])
      elif type.lower() == "futures" and "FUT" in key:
          return (payload['expiryDatesByInstrument'][key])

Now, We can check futures expiry separately.

Then I thought… screw it. Add it. It will save me extra work

def expiry_history(symbol,start_date="",end_date="",type="options"):
    if(end_date==""):end_date=end_date
    nsefetch_url = "https://www.nseindia.com/api/historical/fo/derivatives/meta?&from="+start_date+"&to="+end_date+"&symbol="+symbol+""
    payload = nsefetch(nsefetch_url)

    print(payload)

    for key, value in payload['expiryDatesByInstrument'].items():
      if type.lower() == "options" and "OPT" in key:
          payload_data = payload['expiryDatesByInstrument'][key]
          break
      elif type.lower() == "futures" and "FUT" in key:
          payload_data =  payload['expiryDatesByInstrument'][key]
          break
    
    # Convert start_date and end_date to datetime objects
    start_date = datetime.datetime.strptime(start_date, "%d-%m-%Y")
    end_date = datetime.datetime.strptime(end_date, "%d-%m-%Y")

    # Initialize an empty list to store filtered dates
    filtered_date_payload = []

    # Initialize a flag to check if the first date after end_date has been added
    added_after_end_date = False    

    # Iterate through date_payload and filter dates within the range
    for date_str in payload_data:
        date_obj = datetime.datetime.strptime(date_str, "%d-%b-%Y")
        if start_date <= date_obj <= end_date:
            filtered_date_payload.append(date_str)
        elif date_obj > end_date and not added_after_end_date:
            filtered_date_payload.append(date_str)
            added_after_end_date = True
    
    return filtered_date_payload

Then I scanned for this -


symbol = "BANKNIFTY"

start_date = "1-09-2023"

end_date ="25-09-2023"

print(expiry_history(symbol,start_date,end_date))

The output is -

{'data': [['FUTIDX', 'OPTIDX'], ['CE', 'PE'], ['05-Jan-2023', '12-Jan-2023', '19-Jan-2023', '25-Jan-2023', '02-Feb-2023', '09-Feb-2023', '16-Feb-2023', '23-Feb-2023', '02-Mar-2023', '09-Mar-2023', '16-Mar-2023', '23-Mar-2023', '29-Mar-2023', '06-Apr-2023', '13-Apr-2023', '20-Apr-2023', '27-Apr-2023', '04-May-2023', '11-May-2023', '18-May-2023', '25-May-2023', '01-Jun-2023', '08-Jun-2023', '15-Jun-2023', '22-Jun-2023', '28-Jun-2023', '29-Jun-2023', '06-Jul-2023', '13-Jul-2023', '20-Jul-2023', '27-Jul-2023', '03-Aug-2023', '10-Aug-2023', '17-Aug-2023', '24-Aug-2023', '31-Aug-2023', '06-Sep-2023', '07-Sep-2023', '13-Sep-2023', '14-Sep-2023', '20-Sep-2023', '21-Sep-2023', '28-Sep-2023', '04-Oct-2023', '05-Oct-2023', '11-Oct-2023', '18-Oct-2023', '26-Oct-2023', '01-Nov-2023', '30-Nov-2023', '28-Dec-2023', '28-Mar-2024', '27-Jun-2024'], ['0.00', '31500.00', '33000.00', '34500.00', '36000.00', '37500.00', '38000.00', '38500.00', '39000.00', '39500.00', '40000.00', '40500.00', '41000.00', '41400.00', '41500.00', '41600.00', '41700.00', '41800.00', '41900.00', '42000.00', '42100.00', '42200.00', '42300.00', '42400.00', '42500.00', '42600.00', '42700.00', '42800.00', '42900.00', '43000.00', '43100.00', '43200.00', '43300.00', '43400.00', '43500.00', '43600.00', '43700.00', '43800.00', '43900.00', '44000.00', '44100.00', '44200.00', '44300.00', '44400.00', '44500.00', '44600.00', '44700.00', '44800.00', '44900.00', '45000.00', '45100.00', '45200.00', '45300.00', '45400.00', '45500.00', '45600.00', '45700.00', '45800.00', '45900.00', '46000.00', '46100.00', '46200.00', '46300.00', '46400.00', '46500.00', '46600.00', '46700.00', '46800.00', '46900.00', '47000.00', '47100.00', '47200.00', '47300.00', '47400.00', '47500.00', '47600.00', '47700.00', '47800.00', '47900.00', '48000.00', '48100.00', '48200.00', '48300.00', '48400.00', '48500.00', '48600.00', '48700.00', '49000.00', '49500.00', '50000.00', '50500.00', '51000.00', '51500.00', '52000.00', '52500.00', '54000.00']], 'years': {'2023': ['06-Sep-2023', '07-Sep-2023', '13-Sep-2023', '14-Sep-2023', '20-Sep-2023', '21-Sep-2023', '28-Sep-2023', '04-Oct-2023', '05-Oct-2023', '11-Oct-2023', '18-Oct-2023', '26-Oct-2023', '01-Nov-2023', '30-Nov-2023', '28-Dec-2023'], '2024': ['28-Mar-2024', '27-Jun-2024'], 'all': ['2023', '2024']}, 'expiryDatesByInstrument': {'FUTIDX': ['25-Jan-2023', '23-Feb-2023', '29-Mar-2023', '27-Apr-2023', '25-May-2023', '28-Jun-2023', '29-Jun-2023', '27-Jul-2023', '31-Aug-2023', '28-Sep-2023', '26-Oct-2023', '30-Nov-2023'], 'OPTIDX': ['05-Jan-2023', '12-Jan-2023', '19-Jan-2023', '25-Jan-2023', '02-Feb-2023', '09-Feb-2023', '16-Feb-2023', '23-Feb-2023', '02-Mar-2023', '09-Mar-2023', '16-Mar-2023', '23-Mar-2023', '29-Mar-2023', '06-Apr-2023', '13-Apr-2023', '20-Apr-2023', '27-Apr-2023', '04-May-2023', '11-May-2023', '18-May-2023', '25-May-2023', '01-Jun-2023', '08-Jun-2023', '15-Jun-2023', '22-Jun-2023', '28-Jun-2023', '29-Jun-2023', '06-Jul-2023', '13-Jul-2023', '20-Jul-2023', '27-Jul-2023', '03-Aug-2023', '10-Aug-2023', '17-Aug-2023', '24-Aug-2023', '31-Aug-2023', '06-Sep-2023', '07-Sep-2023', '13-Sep-2023', '14-Sep-2023', '20-Sep-2023', '21-Sep-2023', '28-Sep-2023', '04-Oct-2023', '05-Oct-2023', '11-Oct-2023', '18-Oct-2023', '26-Oct-2023', '01-Nov-2023', '30-Nov-2023', '28-Dec-2023', '28-Mar-2024', '27-Jun-2024']}, 'yearsByInstrument': {'FUTIDX': {'2023': ['25-Jan-2023', '23-Feb-2023', '29-Mar-2023', '27-Apr-2023', '25-May-2023', '28-Jun-2023', '29-Jun-2023', '27-Jul-2023', '31-Aug-2023', '28-Sep-2023', '26-Oct-2023', '30-Nov-2023'], 'all': ['2023']}, 'OPTIDX': {'2023': ['05-Jan-2023', '12-Jan-2023', '19-Jan-2023', '25-Jan-2023', '02-Feb-2023', '09-Feb-2023', '16-Feb-2023', '23-Feb-2023', '02-Mar-2023', '09-Mar-2023', '16-Mar-2023', '23-Mar-2023', '29-Mar-2023', '06-Apr-2023', '13-Apr-2023', '20-Apr-2023', '27-Apr-2023', '04-May-2023', '11-May-2023', '18-May-2023', '25-May-2023', '01-Jun-2023', '08-Jun-2023', '15-Jun-2023', '22-Jun-2023', '28-Jun-2023', '29-Jun-2023', '06-Jul-2023', '13-Jul-2023', '20-Jul-2023', '27-Jul-2023', '03-Aug-2023', '10-Aug-2023', '17-Aug-2023', '24-Aug-2023', '31-Aug-2023', '06-Sep-2023', '07-Sep-2023', '13-Sep-2023', '14-Sep-2023', '20-Sep-2023', '21-Sep-2023', '28-Sep-2023', '04-Oct-2023', '05-Oct-2023', '11-Oct-2023', '18-Oct-2023', '26-Oct-2023', '01-Nov-2023', '30-Nov-2023', '28-Dec-2023'], '2024': ['28-Mar-2024', '27-Jun-2024'], 'all': ['2023', '2024']}}, 'from': '01-Sep-2023', 'to': '25-Sep-2023', 'symbol': 'BANKNIFTY'}
['06-Sep-2023', '07-Sep-2023', '13-Sep-2023', '14-Sep-2023', '20-Sep-2023', '21-Sep-2023', '28-Sep-2023']

So, it is telling there is Banknifty expiry in both 6th and 7th.

I am looking for paracetamols and also having thoughts to get the coders who code this monosyllabic piece of shit API datastream for NSE killed.

Found another error and fixed

def derivative_history_virgin(symbol,start_date,end_date,instrumentType,expiry_date,strikePrice="",optionType=""):

    instrumentType = instrumentType.lower()

    if(instrumentType=="options"):
        instrumentType="OPTSTK"
        if("NIFTY" in symbol): instrumentType="OPTIDX"
        
    if(instrumentType=="futures"):
        instrumentType="FUTSTK"
        if("NIFTY" in symbol): instrumentType="FUTIDX"
        

    #if(((instrumentType=="OPTIDX")or (instrumentType=="OPTSTK")) and (expiry_date!="")):
    if(strikePrice!=""):
        strikePrice = "%.2f" % strikePrice
        strikePrice = str(strikePrice)

    nsefetch_url = "https://www.nseindia.com/api/historical/fo/derivatives?&from="+str(start_date)+"&to="+str(end_date)+"&optionType="+optionType+"&strikePrice="+strikePrice+"&expiryDate="+expiry_date+"&instrumentType="+instrumentType+"&symbol="+symbol+""
    payload = nsefetch(nsefetch_url)
    logging.info(nsefetch_url)
    logging.info(payload)
    return pd.DataFrame.from_records(payload["data"])

It would have thrown error for index options.