Azhagesan
(Azhagesan S)
September 25, 2026, 5:09am
1
TBT 50-level depth bug in fyers-apiv3 — Depth._addDepth() ignores num
Hi team,
Found a bug in fyers-apiv3 (up to 3.1.18), FyersWebsocket/tbt_ws.py — Depth._addDepth() writes levels using the loop index instead of level.num.value.
Snapshots look fine, but partial diffs (only changed levels) get packed into 0..N-1 instead of their true 0-49 positions, so the order book corrupts after the first diff.
Fix is one rule: index by num, skip if missing/out-of-range. Full details + corrected code here:
opened 02:17AM - 25 Sep 26 UTC
## TBT `Depth._addDepth()` ignores `num` field — 50-level depth corrupted on par… tial diffs
**Package:** `fyers-apiv3` 3.1.18
**Module:** `fyers_apiv3.FyersWebsocket.tbt_ws` — class `Depth`, method `_addDepth()`
**Socket:** `FyersTbtSocket` with `SubscriptionModes.DEPTH`
### Description
Depth **snapshots** (all 50 levels) render correctly. Partial **diffs** (only changed levels) are written to the wrong array indices: `_addDepth()` uses the loop counter instead of the protobuf `num` field, which carries each level's true position (0–49). After the first diff, the order book is corrupted.
### Steps to reproduce
1. Connect `FyersTbtSocket` and subscribe with `SubscriptionModes.DEPTH`.
2. Log `Depth.askprice` / `Depth.bidprice` on every message.
3. Compare a `snapshot=0` message against the raw protobuf `depth.asks[].num.value`.
### Expected behavior
Each level is written at its `num` position:
```python
self.askprice[level.num.value] = level.price.value / 100
```
Raw capture shows scattered positions, e.g. `num = [0, 1, 5, 12, 47, 48, 49]`.
### Actual behavior
Levels are packed into `0..N-1`:
```python
for i, level in enumerate(currdata.depth.asks):
self.askprice[i] = level.price.value / 100
```
A diff containing 37 changed levels overwrites indices `0..36` and leaves stale data everywhere else. The book shows phantom price changes and wrong quantities until the next full snapshot.
### Root cause
`_addDepth()` treats diffs as if they were full snapshots. `num` is always populated and correct on the wire — only the SDK's indexing is wrong.
### Suggested fix
Index by `num`, guard against missing/out-of-range values:
```python
def _addDepth(self, currdata, isSnapshot):
if currdata.HasField("depth"):
self.snapshot = isSnapshot
if currdata.depth.HasField("tbq"):
self.tbq = currdata.depth.tbq.value
if currdata.depth.HasField("tsq"):
self.tsq = currdata.depth.tsq.value
for level in currdata.depth.asks:
if not level.HasField("num"):
continue
idx = level.num.value
if not 0 <= idx < 50:
continue
if level.HasField("price"):
self.askprice[idx] = level.price.value / 100
if level.HasField("qty"):
self.askqty[idx] = level.qty.value
if level.HasField("nord"):
self.askordn[idx] = level.nord.value
for level in currdata.depth.bids:
if not level.HasField("num"):
continue
idx = level.num.value
if not 0 <= idx < 50:
continue
if level.HasField("price"):
self.bidprice[idx] = level.price.value / 100
if level.HasField("qty"):
self.bidqty[idx] = level.qty.value
if level.HasField("nord"):
self.bidordn[idx] = level.nord.value
self.timestamp = currdata.feed_time.value
self.sendtime = currdata.send_time.value
self.seqNo = currdata.sequence_no
```
Levels without `num` are skipped — there is no fallback to the loop index, as that would reintroduce the bug.
### Impact
Every consumer of 50-level TBT depth gets a corrupted order book on each diff. Snapshots mask the issue until the next diff arrives.
Requesting an official fix in the next fyers-apiv3 release. Thanks.
Tags: api, python, websocket, market-depth