Kotak-Neo / kotak-neo-api

100 stars 86 forks source link

Need a good working demo & design architecture issues. #65

Open geek-coder opened 10 months ago

geek-coder commented 10 months ago

Hi,

My few cents,

1) You need to decouple a) autorization , sesssion creation from b) socket callbacks. This is needed, so that once session object is created it can be re-used from another m/c. User does not need to re-authinticate .

2) subscribe call to be made unblocking. Ideally, there can be a web-socket blocking thread which receives callback and notifications. You can have a start_websocket api to do that. From another thread one could subscribe, unsubscribe place orders and do anything else. It could be either different thread or different instance altogether. This websock will receive all those notifications.

3) You need to document that ExpiryTime sent for options is IBM BIOS epoch , instead of typical unix epoch time.

4) typically in a app you would keep fdevent handler or blocking call in the end, now if subscribe is blocking, how do I unsubscribe and change it without exiting app.

5) Another minor observation, even your quotes api implemetation and usage of websock to receive callback seems a overkill. This could be simple rest api . This is different from order update callback which needs a websock connection to send updates later on.

You can look at shoonya, 5paisa, prostocks sample program. All are well written. All cater to issues pointed out here.

geek-coder commented 10 months ago

If I call quotes api , while subscribe is in progress. It hangs, and sometimes websocket closes. scenario is , Have subscribed to few options, then want to check price of some other option, while initial subscribed token is streaming live. If you make get_quotes or quotes a RESP API and decouple from websocket, it will start working.

geek-coder commented 10 months ago

Look at this code in neo_api quotes.

    self.NeoWebSocketQuotes.get_quotes(instrument_tokens=instrument_tokens, quote_type=quote_type, isIndex=isIndex,
                                 callback=callback)

    if not response:
        pass

    return response

Here get_quotes is non-blocking and later response will come as callback, How do you ensure that callback is recevied before returning response? There are multiple issues in github mentioning quotes api returning blank etc, which are closed without being addressed properly.

You need to use threading.Event() to sync and wait for response. You also need to put a timeout , just like a rest api and return.

As a sidenote zerodha get_quotes api returns a data 1 min older, they don't multiplex on user created websocket. It is simple rest api. Now with your websock mechanism it will be latest data, but you need to address all issues around it.

geek-coder commented 9 months ago

There are many problems in this codebase primarity due to use of asyncio for giving REST like interface. Multiple race conditions. Main issues with quotes api, unsubscribe api .

Subscribe works well, you just subscribe to a token then updates can happen without any socket disconnect for hours. But it fails when you try to do few api calls with quotes, or do a sub unsub without restarting app . This is because neo_api.py, NeoWebSocket.py are poorly written modules.

( So quotes api mentioned in prev comment is a blocking call). Now I have fixed neo-api quotes/sub/unsub api issues on my local m/c . Will raise a pull request with all fixes. Best would be totaly rewrite of neo_api and NeoWebSocket , but that will take time. So just trying to use holiday to make quotes/sub/unsub work in a pytthon app without any restarts.

PROS Good thing about this codebase is use of telecom style packet formation and parsing i.e HSWebSocketLib.py is well written. This will definitely help in achiving better throughput when compared with pure REST based server by other brokers. I am spending time fixing this code-base just because, this kind of server can help to make this best algo platform for live streaming if we fix client.