Realtime (WebSocket)
Use AsyncTTConnect for WebSocket subscribe/unsubscribe.
Minimal example
import asyncio
from tt_connect import AsyncTTConnect
from tt_connect.instruments import Equity
from tt_connect.enums import Exchange
from tt_connect import Tick
async def on_tick(tick: Tick) -> None:
print(tick.instrument.symbol, tick.ltp, tick.timestamp)
async def main() -> None:
config = {"api_key": "...", "access_token": "..."}
async with AsyncTTConnect("zerodha", config) as broker:
watch = [
Equity(exchange=Exchange.NSE, symbol="RELIANCE"),
Equity(exchange=Exchange.NSE, symbol="SBIN"),
]
await broker.subscribe(watch, on_tick)
await asyncio.sleep(30)
await broker.unsubscribe(watch)
asyncio.run(main())
Feed health callbacks
Subscribe accepts two optional callbacks that fire when the feed goes silent or recovers:
import asyncio
from tt_connect import AsyncTTConnect
from tt_connect.instruments import Equity
from tt_connect.enums import Exchange
from tt_connect import Tick
async def on_tick(tick: Tick) -> None:
print(tick.instrument.symbol, tick.ltp)
async def on_stale() -> None:
# No tick received for 30 seconds — alert or pause your algo
print("Feed is stale — no data")
async def on_recovered() -> None:
# Ticks are flowing again after a stale period
print("Feed recovered — resuming")
async def main() -> None:
config = {"api_key": "...", "access_token": "..."}
async with AsyncTTConnect("angelone", config) as broker:
watch = [Equity(exchange=Exchange.NSE, symbol="RELIANCE")]
await broker.subscribe(
watch,
on_tick,
on_stale=on_stale,
on_recovered=on_recovered,
)
await asyncio.sleep(120)
asyncio.run(main())
on_stale fires once when the feed crosses the 30-second silence threshold.
on_recovered fires on the first tick after a stale period.
Both callbacks work identically on Zerodha and AngelOne.
Feed state
Check broker.feed_state at any point to read the current stream health:
from tt_connect.enums import FeedState
if broker.feed_state == FeedState.STALE:
print("No data — market may be closed or connection degraded")
if broker.feed_state == FeedState.CONNECTED:
print("Stream is healthy")
| State | Meaning |
|---|---|
CONNECTING |
Initial state before first connect |
CONNECTED |
Ticks are flowing normally |
STALE |
Connected but no tick for 30+ seconds |
RECONNECTING |
Connection lost — reconnect attempt in progress |
CLOSED |
Client was closed or unsubscribe called |
Per-instrument last tick time
Check when a specific instrument last produced a tick:
from datetime import datetime, timezone, timedelta
IST = timezone(timedelta(hours=5, minutes=30))
age = (datetime.now(IST) - broker.last_tick_at(reliance)).total_seconds()
if age > 60:
print(f"RELIANCE tick is {age:.0f}s old")
Returns None if no tick has been received yet for that instrument.
Reliability behavior
- Reconnect is automatic with exponential backoff (cap: 60 seconds)
- All subscriptions are restored after every reconnect
on_stale/on_recoveredcontinue to work across reconnects
Callback best practices
- Keep callbacks fast and non-blocking
- Push heavy work (DB writes, HTTP calls) to a queue/worker
- Catch your own business logic errors inside callbacks — unhandled exceptions are logged but do not crash the stream