Constructing valid symbol using APIs

Team,

I am trying to find valid symbol providing details ex: if I provide `SENSEX 78800 CE` , It should return SENSEX2521178800CE. (with nearest expiry ). I am trying the following code, /v3/data/symbol . Not sure what is missing. can some how help me or provide an alternative.

import requests
import datetime
import re
import os
import sys
import re

parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(parent_dir)
import credentials as cr

# FYERS API V3 Credentials
FYERS_ACCESS_TOKEN = cr.access_token  # Replace with your valid V3 access token
FYERS_SYMBOL_API = "https://api.fyers.in/v3/data/symbol"
FYERS_OPTION_CHAIN_API = "https://api.fyers.in/v3/data/options-chain"

def extract_symbol_details(input_symbol):
    """
    Extracts the underlying symbol, strike price, and option type from the input string.
    Example input: "SENSEX 78800 CE"
    """
    match = re.match(r"([A-Za-z]+)\s+(\d+)\s+(CE|PE)", input_symbol)
    if not match:
        raise ValueError("Invalid symbol format. Use format: 'SYMBOL STRIKE CE/PE'")

    symbol, strike_price, option_type = match.groups()
    return symbol.upper(), int(strike_price), option_type.upper()

def identify_exchange(symbol):
    """
    Identifies the exchange for the given symbol using FYERS Security Master API.
    """
    headers = {
        "Authorization": f"Bearer {FYERS_ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    
    payload = {"symbol": symbol}  # Only the symbol, without NSE: or BSE:

    try:
        response = requests.put(FYERS_SYMBOL_API, headers=headers, json=payload)
        print("FYERS Symbol API Response:", response.text)  # Debugging

        if response.status_code != 200:
            raise Exception(f"HTTP Error: {response.status_code}")

        data = response.json()

        if data.get('s') != "ok":
            raise Exception(f"Error fetching exchange: {data.get('message', 'Unknown error')}")

        # Extract exchange from response
        return data['data']['exchange']

    except requests.exceptions.RequestException as e:
        raise Exception(f"API request failed: {e}")
    except Exception as e:
        raise Exception(f"Error processing response: {e}")


def get_next_expiry(symbol, exchange):
    """
    Fetches the next expiry date for the given symbol from FYERS API V3.
    """
    headers = {
        "Authorization": f"Bearer {FYERS_ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    
    fyers_symbol = f"{exchange}:{symbol}-INDEX"  # Proper format for FYERS API
    
    payload = {"symbol": fyers_symbol}

    try:
        response = requests.put(FYERS_OPTION_CHAIN_API, headers=headers, json=payload)
        print("FYERS Option Chain API Response:", response.text)  # Debugging

        if response.status_code != 200:
            raise Exception(f"HTTP Error: {response.status_code}")

        data = response.json()

        if data.get('s') != "ok":
            raise Exception(f"Error fetching expiry: {data.get('message', 'Unknown error')}")

        # Extract expiry dates
        expiry_dates = sorted(data['data']['expiry_dates'])
        if not expiry_dates:
            raise Exception("No expiry dates found for the given symbol.")

        return expiry_dates[0]  # Return the nearest expiry date

    except requests.exceptions.RequestException as e:
        raise Exception(f"API request failed: {e}")
    except Exception as e:
        raise Exception(f"Error processing response: {e}")


def construct_fyers_symbol(symbol, strike_price, option_type, expiry_date, exchange):
    """
    Constructs the FYERS-compliant option symbol using expiry date.
    FYERS Format: EXCHANGE:SYMBOLYYMDDSTRIKEOPTION
    """
    expiry_obj = datetime.datetime.strptime(expiry_date, "%Y-%m-%d")
    yy = expiry_obj.strftime('%y')  # Last two digits of the year
    m = expiry_obj.strftime('%b')[0].upper()  # First letter of the month
    dd = expiry_obj.strftime('%d')  # Day
    strike = f"{strike_price:05d}"  # Format strike price

    fyers_symbol = f"{exchange}:{symbol}{yy}{m}{dd}{strike}{option_type}"
    return fyers_symbol

def generate_fyers_symbol(input_symbol):
    """
    Full pipeline to extract details, identify exchange, get expiry, and construct the final FYERS symbol.
    """
    try:
        # Step 1: Extract details from input
        symbol, strike_price, option_type = extract_symbol_details(input_symbol)
        print(f"Extracted Details -> Symbol: {symbol}, Strike: {strike_price}, Type: {option_type}")

        # Step 2: Identify the correct exchange
        exchange = identify_exchange(symbol)
        print(f"Identified Exchange: {exchange}")

        # Step 3: Get the next expiry date
        next_expiry = get_next_expiry(symbol, exchange)
        print(f"Next Expiry Date: {next_expiry}")

        # Step 4: Construct the complete FYERS option symbol
        fyers_symbol = construct_fyers_symbol(symbol, strike_price, option_type, next_expiry, exchange)
        print(f"FYERS Symbol for Order: {fyers_symbol}")

        return fyers_symbol  # This symbol can be used in place_orders API

    except Exception as e:
        print(f"Error: {e}")
        return None

if __name__ == "__main__":
    input_symbol = "SENSEX 78800 CE"  # Example input
    final_symbol = generate_fyers_symbol(input_symbol)
3 replies