Build a watchlist manager
A watchlist is just a named set of instrument tokens your bot tracks — for signals, alerts, or WebSocket subscription (chapter 37). Keep it as a small, explicit config rather than scattering symbol strings through strategy code.
# watchlist.py
import json
from pathlib import Path
class Watchlist:
def __init__(self, path: str = "data/watchlist.json"):
self.path = Path(path)
self.symbols: dict[str, int] = {} # "NSE:INFY" -> instrument_token
if self.path.exists():
self.symbols = json.loads(self.path.read_text())
def add(self, exchange: str, tradingsymbol: str, instrument_token: int):
self.symbols[f"{exchange}:{tradingsymbol}"] = instrument_token
self._save()
def remove(self, exchange: str, tradingsymbol: str):
self.symbols.pop(f"{exchange}:{tradingsymbol}", None)
self._save()
def tokens(self) -> list[int]:
return list(self.symbols.values())
def _save(self):
self.path.parent.mkdir(exist_ok=True)
self.path.write_text(json.dumps(self.symbols, indent=2))
wl = Watchlist()
wl.add("NSE", "INFY", 408065)
wl.add("NSE", "RELIANCE", 738561)
print(wl.tokens()) # feed directly into kws.subscribe(...)
Build it from a rule, not just manually
For anything beyond a handful of hand-picked names — e.g. "top 50 by volume," "all NIFTY constituents," "all stocks with F&O available" — generate the watchlist programmatically from the instrument master (chapter 21) plus a filter, and refresh it periodically rather than maintaining it by hand:
def nifty50_watchlist(nse_df: pd.DataFrame, constituents: list[str]) -> dict[str, int]:
subset = nse_df[nse_df.tradingsymbol.isin(constituents)]
return {f"NSE:{row.tradingsymbol}": row.instrument_token for row in subset.itertuples()}
(NIFTY 50 constituents change periodically on index rebalancing — source the current list from NSE rather than hardcoding it long-term.)