User

guide karo : असली, genuine-2 अलग Fixes चाहिए आपका-Watchlist-Data-Fix करना (established, Spellings सही करना, या-BSE-Only-Stocks-को-genuinely-Remove-करना) — यह-आपको-करना-होगा Code-Level-Fix (established, kotak_live_feed.py में) — \"Not-Found\"-Result-को-भी-

Asked by CNI Follower · 54 minutes ago · 11-09-2026

Haan, kotak_live_feed.py में negative caching implement करना चाहिए – यही सही fix है ताकि:

- गलत / BSE-only / typo symbols के लिए बार‑बार API hit न हो

- logs में बार‑बार वही “NOT FOUND” spam न आए

- watchlist cleaning (spelling fix + BSE-only हटाना) deterministic हो जाए

नीचे साफ‑सुथरा design + sample code level बदलाव दिए हैं।

---

1) Overall Design: Positive + Negative Cache

Goal:

- हर symbol को canonical form में key बनाना (uppercase, trimmed, etc.)

- Cache में दो तरह के entries:

- Valid data (status = "ok")

- Not found / invalid (status = "not_found")

Suggested cache structure (in‑memory):

```python

from dataclasses import dataclass

from time import time

@dataclass

class CacheEntry:

status: str # "ok" or "not_found"

data: dict | None

ts: float # timestamp when cached

```

```python

class KotakLiveFeed:

def __init__(self, cache_ttl_ok=5, cache_ttl_not_found=3600):

# cache_ttl_ok: seconds, live quotes short TTL

# cache_ttl_not_found: longer TTL for bad symbols

self._cache = {} # {canonical_symbol: CacheEntry}

self.cache_ttl_ok = cache_ttl_ok

self.cache_ttl_not_found = cache_ttl_not_found

```

---

2) Canonical Symbol Normalisation (Spelling / Case Fix)

इससे एक ही symbol key से cache hit होगा:

```python

def canonical_symbol(symbol: str) -> str:

# आप अपनी आवश्यकता अनुसार और normalization जोड़ सकते हैं

return symbol.strip().upper()

```

Use this everywhere जब आप symbol को cache या API में उपयोग करें:

```python

sym = canonical_symbol(symbol)

```

---

3) Cache Read Helper (Positive + Negative दोनों को Respect करें)

```python

def _get_from_cache(self, symbol: str) -> CacheEntry | None:

sym = canonical_symbol(symbol)

entry = self._cache.get(sym)

if not entry:

return None

now = time()

ttl = self.cache_ttl_ok if entry.status == "ok" else self.cache_ttl_not_found

if now - entry.ts > ttl:

# stale cache

self._cache.pop(sym, None)

return None

return entry

```

---

4) Main Fetch Function with Negative Caching

```python

def get_quote(self, symbol: str) -> dict | None:

sym = canonical_symbol(symbol)

# 1) Check cache first (positive + negative)

cached = self._get_from_cache(sym)

if cached:

if cached.status == "not_found":

# Negative cache hit – कोई नया API call नहीं

# जरूरत हो तो बस debug-level log करें

# logger.debug("Symbol %s is cached as NOT FOUND, skipping API call", sym)

return None

elif cached.status == "ok":

return cached.data

# 2) No cache / expired cache ⇒ call API once

resp = self._call_kotak_api(sym)

# 3) Parse and classify

if resp is None:

# network issue आदि; यहां आप चाहें तो cache न भी करें

return None

if self._is_symbol_not_found(resp):

# NEGATIVE CACHE ENTRY

self._cache[sym] = CacheEntry(

status="not_found",

data=None,

ts=time()

)

# एक बार warning log ठीक है; बार‑बार नहीं (क्योंकि अब cache हो गया)

# logger.warning("Symbol %s not found in Kotak API", sym)

return None

# 4) Valid data: Positive cache

quote = self._normalize_quote(resp)

self._cache[sym] = CacheEntry(

status="ok",

data=quote,

ts=time()

)

return quote

```

जहां helper functions कुछ ऐसे हो सकते हैं:

```python

def _call_kotak_api(self, symbol: str) -> dict | None:

# यहां आपका Kotak API integration होगा

# try/except आदि लगाकर JSON return करें

...

def _is_symbol_not_found(self, resp: dict) -> bool:

# यह Kotak API के exact response format पर depend करेगा

# Example logic (adjust to real API):

if resp.get("errorCode") in ("SYMBOL_NOT_FOUND", "INVALID_SYMBOL"):

return True

if resp.get("status") == "FAIL" and "not found" in str(resp.get("message", "")).lower():

return True

return False

def _normalize_quote(self, resp: dict) -> dict:

# यहां आप raw API response को अपनी internal schema में map करें

# e.g. LTP, bid/ask, volume, etc.

return {

"symbol": canonical_symbol(resp["symbol"]),

"ltp": float(resp["lastPrice"]),

"exchange": resp.get("exchange"),

# और फ़ील्ड्स …

}

```

---

5) BSE‑Only Stocks को Genuine तरीके से Remove करना

आपके 2nd fix के लिए: BSE-only stocks ko watchlist se निकालने के लिए:

1. Exchange field Kotak API response से निकालें (e.g. `"NSE"`, `"BSE"`).

2. Normalization के बाद logic कुछ ऐसा रखें:

```python

def get_quote(self, symbol: str) -> dict | None:

# ... ऊपर जैसा ही code ...

quote = self._normalize_quote(resp)

# अगर policy है कि केवल NSE allow है:

if quote.get("exchange") != "NSE":

# इस symbol को भी negative cache treat करें

self._cache[sym] = CacheEntry(

status="not_found",

data=None,

ts=time()

)

# Optional: कोई अलग flag भी ला सकते हैं, जैसे "bse_only"

# logger.info("Symbol %s is not tradable on NSE. Marking as not_found for watchlist.", sym)

return None

# नहीं तो normal positive cache

self._cache[sym] = CacheEntry(

status="ok",

data=quote,

ts=time()

)

return quote

```

3. Watchlist cleaning:

जहां पर आप पूरी watchlist resolve करते हैं, वहां simple rule रख सकते हैं:

```python

def refresh_watchlist(self, symbols: list[str]) -> dict:

result = {}

to_remove = []

for s in symbols:

q = self.get_quote(s)

if q is None:

# Either genuinely not found OR BSE-only OR invalid

to_remove.append(s)

else:

result[s] = q

# यहां DB / file में watchlist update कर के to_remove symbols हटा दें

self._remove_from_watchlist_storage(to_remove)

return result

```

इस तरह:

- Typos / invalid / delisted / BSE-only symbols → एक‑दो बार API से confirm होंगे,

फिर लंबे TTL के लिए negative cache में फ्रीज़ हो जाएंगे.

- Watchlist धीरे‑धीरे साफ होती जाएगी (सिर्फ genuinely valid NSE symbols बचेंगे).

- Repeated wasteful API calls और log spam दोनों बंद।

---

6) Logging Strategy (Optional but Recommended)

- API failure / symbol not found को सिर्फ पहली बार warning / error में लॉग करें

- Cache hit (positive या negative) पर ज़्यादा से ज़्यादा debug‑level log रखें या बिल्कुल न रखें

- symbol level पर `last_error_logged_at` track करना चाहें तो कर सकते हैं, ताकि हर घंटे में max 1 warning ही आए, etc.

---

7) Summary (Direct Answer)

- हाँ, kotak_live_feed.py में negative caching implement करना बिल्कुल सही और recommended fix है.

- “NOT FOUND” result को भी cache करें (लंबे TTL के साथ), जिससे:

- वही गलत / BSE-only / typo symbols के लिए बार‑बार API calls नहीं होंगे

- logs में बार‑बार वही error / warning नहीं आएगी

- Exchange check करके BSE-only scrips को भी negative cache जैसा treat कर सकते हैं और watchlist से सिस्टमेटिकली हटा सकते हैं.

If you have any further queries, please connect with us on 022-6290-10141 (Timings : 09.00 AM to 05.00 PM) or you can email us on info@cniinfoxchange.com