WebSocket error 1006 even though my API app is showing as 'Active

GuruprasadTitu
I am getting repeated WebSocket error 1006 even though my API app is showing as 'Active', and this script is working for historical/test API calls.
I have pasted my concise logic below for review. Can you check if my account is fully enabled for live trading and WebSocket streaming access?

Kindly confirm if anything is wrong on the code/API enablement side

import datetime as dt
import time
import threading
import queue
from collections import defaultdict
import pandas as pd
from kiteconnect import KiteConnect, KiteTicker
from ta.trend import EMAIndicator, ADXIndicator
from ta.momentum import RSIIndicator

# --- ZERODHA KITE CONNECT CONFIGURATION ---
api_key = "YOUR_API_KEY" # <-- Replace with your actual API key
access_token = open("access_token.txt").read().strip()
kite = KiteConnect(api_key=api_key)
kite.set_access_token(access_token)

qty = 75
ema_fast, ema_slow = 8, 21
adx_threshold, rsi_threshold = 20, 60
target_points, stoploss_points = 6, 8
max_trades_per_day = 6

# --- STATE ---
ce_token = pe_token = ce_symbol = pe_symbol = None
history = {}
positions = {}
trades_today = {}
adx_above = {}
rsi_above = {}
signal_state = {}
minute_candles = defaultdict(list)
tick_queue = queue.Queue()

def adx_is_rising(df, n=3):
adx = df["adx"].dropna()
if len(adx) < n+1: return False
return all(adx.iloc[-1] > adx.iloc[-(i+2)] for i in range(n))

def tick_worker():
while True:
token, ts, price = tick_queue.get()
m = ts.replace(second=0, microsecond=0)
minute_candles[(token, m)].append(price)
tick_queue.task_done()

def candle_worker():
last = None
while True:
now = dt.datetime.now().replace(second=0, microsecond=0)
if now != last:
for (token, m), prices in list(minute_candles.items()):
if prices and m < now:
o, h, l, c = prices[0], max(prices), min(prices), prices[-1]
row = pd.DataFrame([[m,o,h,l,c]],columns=["timestamp","open","high","low","close"])
if token not in history: history[token]=pd.DataFrame(columns=row.columns)
history[token] = pd.concat([history[token],row],ignore_index=True).tail(100)
check_and_trade(history[token].copy(), token)
del minute_candles[(token, m)]
last = now
time.sleep(1)

def get_dynamic_itm_tokens():
global ce_token, pe_token, ce_symbol, pe_symbol
spot = kite.ltp("NSE:NIFTY 50")["NSE:NIFTY 50"]["last_price"]
instr = pd.DataFrame(kite.instruments("NFO"))
nifty_opts = instr[(instr["name"]=="NIFTY") & instr["instrument_type"].isin(["CE","PE"])]
expiry = pd.to_datetime(nifty_opts["expiry"]).sort_values().iloc[0]
strike = int(round(spot/50)*50)
ce = nifty_opts[(nifty_opts["expiry"]==expiry)&(nifty_opts["strike"]<=spot)&(nifty_opts["instrument_type"]=="CE")].sort_values("strike",ascending=False).iloc[0]
pe = nifty_opts[(nifty_opts["expiry"]==expiry)&(nifty_opts["strike"]>=spot)&(nifty_opts["instrument_type"]=="PE")].sort_values("strike").iloc[0]
ce_token, pe_token = ce["instrument_token"], pe["instrument_token"]
ce_symbol, pe_symbol = ce["tradingsymbol"], pe["tradingsymbol"]

def check_and_trade(df, token):
if len(df) < ema_slow+4: return
df = df.set_index("timestamp").sort_index()
df["ema8"] = EMAIndicator(df["close"], ema_fast).ema_indicator()
df["ema21"] = EMAIndicator(df["close"], ema_slow).ema_indicator()
df["rsi"] = RSIIndicator(df["close"],14).rsi()
df["adx"] = ADXIndicator(df["high"],df["low"],df["close"],14).adx()
df = df.dropna()
if len(df) < 4: return
latest, prev = df.iloc[-1], df.iloc[-2]

# ADX & RSI cross logic
adx_above[token] = (adx_above.get(token,False) or (prev["adx"]=adx_threshold)) and latest["adx"]>=adx_threshold
rsi_above[token] = (rsi_above.get(token,False) or (prev["rsi"]=rsi_threshold)) and latest["rsi"]>=rsi_threshold
crossover = prev["ema8"] < prev["ema21"] and latest["ema8"] > latest["ema21"]
adx_rising = adx_is_rising(df, 3)

ts = df.index[-1]
now_time = ts.time()
trade_window = dt.time(9,30)<=now_time<=dt.time(15,20)
trade_count = trades_today.get(token, (ts.date(),0))[1]
open_pos = positions.get(token,None)

# Fresh signal logic (all true just became true, or 2 were true and 3rd flipped, and ADX rising)
if token not in signal_state: signal_state[token] = {'crossover':False,'adx':False,'rsi':False}
prev_state = signal_state[token].copy()
now_state = {'crossover':crossover, 'adx':adx_above[token], 'rsi':rsi_above[token]}
signal_state[token]=now_state
all_true = all(now_state.values())
two_true_flip = sum(prev_state.values())==2 and sum(now_state.values())==3

if (not open_pos) and trade_window and adx_rising and ((all_true and not all(prev_state.values())) or two_true_flip) and trade_count<max_trades_per_day:
entry = latest["close"]
positions[token] = {'entry': entry, 'timestamp': ts, 'target': entry+target_points, 'stop': entry-stoploss_points}
trades_today[token]=(ts.date(), trade_count+1)
symbol = ce_symbol if token==ce_token else pe_symbol
print(f"BUY {symbol} {entry:.2f} @ {ts}")
try:
kite.place_order(variety="regular", exchange="NFO", tradingsymbol=symbol,
transaction_type="BUY", quantity=qty, order_type="MARKET", product="MIS")
except Exception as e:
print(f"Order Error: {e}")

if open_pos:
entry, target, stop = open_pos["entry"], open_pos["target"], open_pos["stop"]
ltp = latest["close"]
symbol = ce_symbol if token==ce_token else pe_symbol
if ltp >= target or ltp <= stop:
action = "TARGET HIT" if ltp>=target else "STOPLOSS HIT"
print(f"{action} {symbol} {entry:.2f} -> {ltp:.2f} @ {ts}")
try:
kite.place_order(variety="regular", exchange="NFO", tradingsymbol=symbol,
transaction_type="SELL", quantity=qty, order_type="MARKET", product="MIS")
except Exception as e:
print(f"Exit Error: {e}")
positions[token]=None

def on_ticks(ws, ticks):
for tick in ticks:
token = tick["instrument_token"]
price = tick.get("last_price")
if price:
tick_queue.put((token, tick.get("timestamp",dt.datetime.now()), float(price)))

def on_connect(ws, response):
ws.subscribe([ce_token, pe_token])
ws.set_mode(ws.MODE_FULL, [ce_token, pe_token])

def on_close(ws, code, reason):
print(f"WebSocket closed: {code} | {reason}")
time.sleep(5)
try:
if not kws.is_connected():
kws.connect(threaded=True)
except: pass

def on_error(ws, code, reason):
print(f"WebSocket Error: {code} | {reason}")

# --- MAIN ---
get_dynamic_itm_tokens()
history = {ce_token: pd.DataFrame(columns=["timestamp","open","high","low","close"]),
pe_token: pd.DataFrame(columns=["timestamp","open","high","low","close"])}
positions = {ce_token:None, pe_token:None}
adx_above = {ce_token:False, pe_token:False}
rsi_above = {ce_token:False, pe_token:False}
signal_state = {ce_token:{'crossover':False,'adx':False,'rsi':False},
pe_token:{'crossover':False,'adx':False,'rsi':False}}

kws = KiteTicker(api_key, access_token)
kws.on_ticks = on_ticks
kws.on_connect = on_connect
kws.on_close = on_close
kws.on_error = on_error

threading.Thread(target=tick_worker,daemon=True).start()
threading.Thread(target=candle_worker,daemon=True).start()

try:
kws.connect(threaded=True)
while True: time.sleep(60)
except KeyboardInterrupt:
if kws.is_connected(): kws.close()
except Exception as e:
print(f"Fatal Error: {e}")
if kws.is_connected(): kws.close()
  • Nivas
    If you've created the Kite Connect app (paid version), you should be able to access market data via WebSocket. You might find this thread helpful as it relates to your error.
Sign In or Register to comment.