Live Market Depth Feed isn't implemented in Python SDK

Live Market Depth Feed isn’t implemented in Python SDK. Can I have the python code for parsing the binary data packet? I tried Java implementation (you can check out the code at DhanHQ-java/src/main/java/co/dhan/http/LiveMarketDepthTransformer.java at main · karthiks/DhanHQ-java · GitHub) but not getting bid/asks buy/sell values right making me wonder what I missed in the binary parsing of the packets received.

cc/ @Hardik @PravinJ

I checked the javascript code from tv.dhan and found the packet structure (as I understand it) is totally different from that of the API Doc (that in itself is inconsistent).

Can you guys please confirm the right structure of 2-level Market Data Packet sent as byte-array on websockets?

@PravinJ @Hardik Got a chance to look into this? Can you confirm the binary data packet structure of 20-level depth feed and fix the inconsistencies in the API docs. Would love to know what is in your mind.

Hello @kartz

The python code is still in development, will be out by next week.

Coming to API Docs being inconsistent, can you highlight the point which you found to be incorrect, will get to it. Rest, I know a lot of our users have already started using 20-Depth over websockets, so nothing major should be incorrect in documentation.

Hi @Hardik, thanks for your response. Realized that I have posted the details in 20-Market Depth Documentation is incomplete and it has no implementation in this python SDK. · Issue #55 · dhan-oss/DhanHQ-py · GitHub. But to repeat it here,

The API Doc for 20 Market Depth reference to Feed Response Code in Annexure is incomplete. The same further is repeated in Depth section of the doc on the same page.
This needs correction, for establishing right contract with the API users.

Per Dhan API -20 Level Market Depth’s response has 2 parts ResponseHeader and Payload.

  • The doc reads ResponseHeader is 8 bytes size but shows 12 bytes (= 2+1+1+4+4 bytes) in size in the table :frowning:
  • The doc reads DepthPayload is said to be 10 bytes and then again in the table to be 16 bytes and 32 bytes each. This inconsistency irks. Though, I believe it has to be 16 bytes. This assumption still fails, as I’m not seeing expected values in deserializing the values :frowning:

Update: My bad the doc is not showing 32 but 320 bytes with the ZERO overflowing to next row thus causing confusion. 320 bytes makes sense as 20 units of 16 bytes packet each is 20*16 = 320 bytes.

Now the questions is, every message comes stating that its message length is 332 but the actual length is different sometimes greater and sometimes lesser. Why?

Please see the logs of one such entry for the sake of debugging an equity instrument subscription for 20-level depth:

2025-02-07 10:46:43 DEBUG c.d.http.LiveMarketDepthTransformer - LiveMarketDepthTransformer.onMessage(..)
2025-02-07 10:46:43 DEBUG c.d.http.LiveMarketDepthTransformer - bytes size = 1328
2025-02-07 10:46:43 DEBUG c.d.http.LiveMarketDepthTransformer - byteResponseCode = 41, exchangeSegmentCode = 1, securityID = 27176, ignoreSegment = 0, messageLength = 332
2025-02-07 10:46:43 DEBUG co.dhan.dto.LiveDepth - ByteBuffer's current position is 12
Bid(price=110.88, qty=9, orders=3)
Bid(price=110.87, qty=1263, orders=2)
Bid(price=110.86, qty=366, orders=5)
Bid(price=110.85, qty=1953, orders=10)
Bid(price=110.84, qty=509, orders=4)
Bid(price=110.83, qty=533, orders=3)
Bid(price=110.82, qty=563, orders=7)
Bid(price=110.81, qty=637, orders=3)
Bid(price=110.80, qty=3074, orders=23)
Bid(price=110.79, qty=555, orders=3)
Bid(price=110.78, qty=204, orders=3)
Bid(price=110.77, qty=1185, orders=5)
Bid(price=110.76, qty=197, orders=2)
Bid(price=110.75, qty=973, orders=7)
Bid(price=110.74, qty=1034, orders=4)
Bid(price=110.73, qty=290, orders=2)
Bid(price=110.72, qty=415, orders=5)
Bid(price=110.71, qty=1499, orders=8)
Bid(price=110.70, qty=3296, orders=12)
Bid(price=110.69, qty=517, orders=3)
Bid(price=0.00, qty=0, orders=-171798692)
Bid(price=0.00, qty=1, orders=-858993459)
Bid(price=0.00, qty=1, orders=-1546188227)
Bid(price=0.00, qty=4, orders=2061584302)
Bid(price=0.00, qty=5, orders=1374389535)
Bid(price=0.00, qty=1, orders=687194767)
Bid(price=0.00, qty=8, orders=0)
Bid(price=0.00, qty=13, orders=-687194767)
Bid(price=0.00, qty=2, orders=-1374389535)
Bid(price=0.00, qty=4, orders=-2061584302)
Bid(price=0.00, qty=2, orders=1546188227)
Bid(price=0.00, qty=2, orders=858993459)
Bid(price=0.00, qty=7, orders=171798692)
Bid(price=0.00, qty=3, orders=-515396076)
Bid(price=0.00, qty=3, orders=-1202590843)
Bid(price=0.00, qty=3, orders=-1889785610)
Bid(price=0.00, qty=3, orders=1717986918)
Bid(price=0.00, qty=9, orders=1030792151)
Bid(price=0.00, qty=5, orders=343597384)
Bid(price=0.00, qty=5, orders=-343597384)
Bid(price=0.00, qty=4, orders=19464524)
Bid(price=0.00, qty=-343597384, orders=1079752785)
Bid(price=0.00, qty=343597384, orders=1079752622)
Bid(price=0.00, qty=1030792151, orders=1079752458)
Bid(price=0.00, qty=1717986918, orders=1079752294)
Bid(price=0.00, qty=-1889785610, orders=1079752130)
Bid(price=0.00, qty=-1202590843, orders=1079751966)
Bid(price=0.00, qty=-515396076, orders=1079751802)
Bid(price=0.00, qty=171798692, orders=1079751639)
Bid(price=0.00, qty=858993459, orders=1079751475)
Bid(price=0.00, qty=1546188227, orders=1079751311)
Bid(price=0.00, qty=-2061584302, orders=1079751147)
Bid(price=0.00, qty=-1374389535, orders=1079750983)
Bid(price=0.00, qty=-687194767, orders=1079750819)
Bid(price=0.00, qty=0, orders=1079750656)
Bid(price=0.00, qty=687194767, orders=1079750492)
Bid(price=0.00, qty=1374389535, orders=1079750328)
Bid(price=0.00, qty=2061584302, orders=1079750164)
Bid(price=0.00, qty=-1546188227, orders=1079750000)
Bid(price=0.00, qty=-858993459, orders=1079749836)
Bid(price=0.00, qty=-171798692, orders=1079749672)
Bid(price=0.00, qty=20119884, orders=27176)
Bid(price=-17835455233755740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079753768, orders=67)
Bid(price=-92559641157289310000000000000000000000000000000000000000000000.00, qty=1079753932, orders=13)
Bid(price=-0.00, qty=1079754096, orders=516)
Bid(price=80298907385281020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079754260, orders=673)
Bid(price=427698049712232440000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079754424, orders=56)
Bid(price=0.00, qty=1079754588, orders=1604)
Bid(price=0.00, qty=1079754752, orders=3874)
Bid(price=-1972024648733286600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079754915, orders=502)
Bid(price=-0.00, qty=1079755079, orders=762)
Bid(price=-0.00, qty=1079755243, orders=558)
Bid(price=9070949719158507000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079755407, orders=110)
Bid(price=0.00, qty=1079755571, orders=838)
Bid(price=0.00, qty=1079755735, orders=729)
Bid(price=-41614939728028970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079755898, orders=205)
Bid(price=-0.00, qty=1079756062, orders=707)
Bid(price=-0.00, qty=1079756226, orders=733)
Bid(price=190359804756584800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079756390, orders=2077)
Bid(price=0.00, qty=1079756554, orders=1360)
Bid(price=0.00, qty=1079756718, orders=1223)
Bid(price=-867922223097222000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00, qty=1079756881, orders=792)
2025-02-07 10:46:43 DEBUG co.dhan.dto.LiveDepth - Loop Iteration Count for Bids = 82
2025-02-07 10:46:43 DEBUG c.d.a.s.ManualTest_LiveDepthFeed - LiveMarketDepthListener.onBidsArrival(..), size 50 for securityID 27176
2025-02-07 10:46:43 DEBUG c.d.a.s.ManualTest_LiveDepthFeed - [Bid(price=110.88, quantity=9, orders=3), Bid(price=110.87, quantity=1263, orders=2), Bid(price=110.86, quantity=366, orders=5), Bid(price=110.85, quantity=1953, orders=10), Bid(price=110.84, quantity=509, orders=4), Bid(price=110.83, quantity=533, orders=3), Bid(price=110.82, quantity=563, orders=7), Bid(price=110.81, quantity=637, orders=3), Bid(price=110.8, quantity=3074, orders=23), Bid(price=110.79, quantity=555, orders=3), Bid(price=110.78, quantity=204, orders=3), Bid(price=110.77, quantity=1185, orders=5), Bid(price=110.76, quantity=197, orders=2), Bid(price=110.75, quantity=973, orders=7), Bid(price=110.74, quantity=1034, orders=4), Bid(price=110.73, quantity=290, orders=2), Bid(price=110.72, quantity=415, orders=5), Bid(price=110.71, quantity=1499, orders=8), Bid(price=110.7, quantity=3296, orders=12), Bid(price=110.69, quantity=517, orders=3), Bid(price=1.095483297543E-311, quantity=4, orders=2061584302), Bid(price=1.4286366368054E-311, quantity=5, orders=1374389535), Bid(price=1.19365233861E-312, quantity=1, orders=687194767), Bid(price=1.18460712133E-311, quantity=2, orders=1546188227), Bid(price=2.339530070587E-312, quantity=2, orders=858993459), Bid(price=1.7787659429624E-311, quantity=7, orders=171798692), Bid(price=1.5559563852347E-311, quantity=3, orders=1717986918), Bid(price=4.407918728373E-311, quantity=9, orders=1030792151), Bid(price=2.886447746332E-311, quantity=5, orders=343597384), Bid(price=1.6811541372253E-311, quantity=4, orders=19464524), Bid(price=6.3659873773E-314, quantity=343597384, orders=1079752622), Bid(price=4.243992206E-314, quantity=1030792151, orders=1079752458), Bid(price=1.06099791357E-313, quantity=1717986918, orders=1079752294), Bid(price=1.4853970815E-313, quantity=171798692, orders=1079751639), Bid(price=6.3659876876E-314, quantity=858993459, orders=1079751475), Bid(price=4.8805904711E-313, quantity=1546188227, orders=1079751311), Bid(price=1.48539710175E-313, quantity=687194767, orders=1079750492), Bid(price=8.4879836747E-314, quantity=1374389535, orders=1079750328), Bid(price=4.243991725E-314, quantity=2061584302, orders=1079750164), Bid(price=6.3659876283E-314, quantity=20119884, orders=27176), Bid(price=8.029890738528102E283, quantity=1079754260, orders=673), Bid(price=4.2769804971223244E86, quantity=1079754424, orders=56), Bid(price=2.262040593967417E-111, quantity=1079754588, orders=1604), Bid(price=4.0E-323, quantity=1079754752, orders=3874), Bid(price=9.070949719158507E135, quantity=1079755407, orders=110), Bid(price=4.667260716554628E-62, quantity=1079755571, orders=838), Bid(price=2.3934347268026047E-259, quantity=1079755735, orders=729), Bid(price=1.903598047565848E185, quantity=1079756390, orders=2077), Bid(price=9.458744551493777E-13, quantity=1079756554, orders=1360), Bid(price=5.110135058468759E-210, quantity=1079756718, orders=1223)]

After Bid(price=110.69, qty=517, orders=3) you would see the Bids having garbage values. This leaves me with the question, as to why does the real message length different when the messageLength in the message remains at 332 as mentioned in the API docs? What am I missing here @Hardik @PravinJ ?

Is your 20-level Message structure like below as mentioned in the docs:
Message (332 bytes) = ResponseHeader (12 bytes) + Payload (320 bytes)

Or is it like below:
Message (12*PayloadArraySize) = ResponseHeader (12 bytes) + Array of Payloads (320 bytes each)

Payload could be Ask/Bid sharing same structure and thus same size. And per the docs the payload is either Ask/Bid, given that both are sent as separate messages.

@Hardik @PravinJ @tradernoob

@tradernoob Thanks for your response and confirmation that the message structure is array of 332 bytes (12+320). What baffles me here is that I do see price, order and quantities in negative values for some bids/asks, which IMHO is impossible?

Example debug log I got below:

Ask(price=0.00, qty=4, orders=-2061584302)
Ask(price=3.44, qty=20, orders=1)
Ask(price=190232055819272200.00, qty=1079767695, orders=2371)
Ask(price=0.00, qty=858993459, orders=1079767859)
Ask(price=0.00, qty=10, orders=171798692)
Ask(price=3.44, qty=801, orders=3)
Ask(price=-230215357595645900000.00, qty=1079768186, orders=2252)
Ask(price=0.00, qty=-1202590843, orders=1079768350)

cc/ @Hardik @PravinJ

Most likely you are using the wrong data types or your indexing is wrong in the bytearray.

1 Like

@tradernoob Thanks for confirming the schema and responding pretty fast. The rest is now cracked.

1 Like

how did you solve this? I am having the same issue

Check out the code in my Java SDK for this that is open-sourced in github.