jugaad-py / jugaad-trader

Unofficial python client for Zerodha
https://marketsetup.in/documentation/jugaad-trader/
151 stars 107 forks source link

Getting Bad Request on Kite.ltp("NSE:INFY") #59

Open AtulShinde94 opened 1 month ago

AtulShinde94 commented 1 month ago

Started seeing this error since 21st May : Getting HTTP 400 on Quotes Endpoint

Code snippet d = kite.ltp("NSE:INFY")

Error { "name": "InputException", "message": "Bad Request", "stack": "[text] 0m: Bad Request" }

iampankajkumar commented 1 month ago

I'm also facing the same.

Get Outlook for Androidhttps://aka.ms/AAb9ysg


From: Atul @.> Sent: Wednesday, May 22, 2024 10:34:29 AM To: jugaad-py/jugaad-trader @.> Cc: Subscribed @.***> Subject: [jugaad-py/jugaad-trader] Getting Bad Request on Kite.ltp("NSE:INFY") (Issue #59)

Started seeing this error since 21st May : Getting HTTP 400 on Quotes Endpoint

Code snippet d = kite.ltp("NSE:INFY")

Error { "name": "InputException", "message": "Bad Request", "stack": "[text] 0m: Bad Request" }

— Reply to this email directly, view it on GitHubhttps://github.com/jugaad-py/jugaad-trader/issues/59, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AG5WQVW5BR4IWM2ZB65ZEYLZDQRN3AVCNFSM6AAAAABIC3GOO6VHI2DSMVQWIX3LMV43ASLTON2WKOZSGMYDSNJXG42DONI. You are receiving this because you are subscribed to this thread.Message ID: @.***>

darshanpavan commented 1 month ago

Zerodha is blocking users without api key Need to find workaround

iampankajkumar commented 1 month ago

Alternatively we can use yahoo library to get the price information.

import yfinance as yf

yf.Ticker("ITBEES.NS").history(period="1d")['Close'].iloc[0]

All other kite APIs working fine, like AMO, GTT, Orders etc. Seems, only price data APIs are blocked

zerodha.quote(), zerodha.ltp() and so on, these are blocked

satishgv1985 commented 1 month ago

Alternatively we can use yahoo library to get the price information.

import yfinance as yf

yf.Ticker("ITBEES.NS").history(period="1d")['Close'].iloc[0]

All other kite APIs working fine, like AMO, GTT, Orders etc. Seems, only price data APIs are blocked

zerodha.quote(), zerodha.ltp() and so on, these are blocked

will this work for multiple instruments? Did you try?

iampankajkumar commented 1 month ago

It won't work with multiple instruments at once, you can loop through the instruments.

Something like this:

    def quote(self, nse_instruments):
        ticker_prices = {}
        for nse_instrument in nse_instruments:
             closing_price = yf.Ticker(nse_instrument).history(period="1d")['Close'].iloc[0]
             ticker_prices[nse_instrument] = {"last_price": closing_price}
        return ticker_prices; 

Though it is slow, but It is at least unblocking to earn money. :-P

AtulShinde94 commented 1 month ago

@iampankajkumar Infy was just for example. I actually need quotes/ltp on FnO instruments.

iampankajkumar commented 1 month ago

@AtulShinde94 , No idea for FnO.

A project can be created using AngelOne APIs, they all are free to use.

aneesh2312 commented 1 month ago

I think websocket still works. You can use that for price

iampankajkumar commented 1 month ago

@aneesh2312 Any code reference?

AtulShinde94 commented 1 month ago

@aneesh2312 I need to calculate spread of FnO instruments for which I need bid and ask price. Is it possible to get that from ticker? Also, last time I checked ticker from jugaad-trader was not working. This was few months back. If you are able to make it work properly, can you share the working code snippet?

aneesh2312 commented 1 month ago

Yes, ticker was not working. You need to make this change in the ticker function in https://github.com/jugaad-py/jugaad-trader/blob/master/jugaad_trader/zerodha.py#L217, instead of the existing return (will raise PR at some point, or you can raise after confirming):

        return KiteTicker(
            api_key=api_key,
            access_token="&user_id="
            + self.user_id
            + "&enctoken="
            + urllib.parse.quote(self.enc_token),
            root="wss://ws.zerodha.com",
        )

As for bid and ask price, I don't know - I guess you can try subscribing to the tokens you want in MODE_FULL - I think the Kite Ticker documentation will be more helpful.

ssheikh098 commented 1 month ago

in ticket method replace the WebSocket URL as zerodha updated this.

return KiteTicker(api_key=api_key, access_token=urllib.parse.quote_plus(self.enc_token) + '&user_id=' + self.user_id,

root='wss://ws.zerodha.com')

                      root="wss://ws.kite.trade")

You can add below code in Zerodha.py at the end of Zerodha(KiteConnect):

 def on_ticks(self, ws, ticks):
    global instrument
    # for tick in ticks:
    #     instrument_token = tick['instrument_token']
    #     last_price = tick['last_price']
    self.last_price = next((d['last_price'] for d in ticks if d['instrument_token'] == instrument), None)
    # print(f"Last traded price for instrument {instrument_token}: {last_price}")
    # print(f"Last traded price for instrument {instrument_token}: {ltp}")

def on_connect(self, ws, response):
    pass  # No need to subscribe initially

def on_close(self, kws, code, reason):
    kws.stop()

def subscribe_instrument(self, kws, instrument_token):
    global instrument
    instrument = int(instrument_token)
    if kws.is_connected():
        kws.subscribe([instrument])
        # Wait for the first tick to be received
        while self.last_price is None:
            time.sleep(0.1)
        return self.last_price
        # kws.set_mode(kws.MODE_LTP, instrument_token)
    else:
        print("WebSocket is not connected.")

def zerodha_socket(self):
    kws = self.ticker()
    # Assign the callbacks.
    kws.on_ticks = self.on_ticks
    kws.on_connect = self.on_connect
    kws.on_close = self.on_close
    # Start the WebSocket connection in the main thread.
    if not kws.is_connected():
        kws.connect(threaded=True)
        # Wait for the connection to be established
        while not kws.is_connected():
            time.sleep(0.1)
    return kws

def unsubscribe(self, kws, instrument_token):
    global instrument
    instrument_token = int(instrument_token)
    kws.unsubscribe([instrument_token])
    self.last_price = None
    instrument = None

def quote(self, kws, symb):
    ltp1 = None
    ltp1 = self.subscribe_instrument(kws, symb)
    print(self.last_price)
    print("I am here")
    self.unsubscribe(kws, symb)
    return ltp1

Then calling as kws = kite.zerodha_socket()

for token in list_tokens: buy_ltp1 = kite.quote(kws, token)

Please review, this might provide you some idea... I wont be able to assist further.