印度股票API接入:NSE/BSE行情数据与实时订阅实战

用户头像Fxdund
2026-10-10 发布

最近不少朋友在做新兴市场的量化策略,印度股市是绕不开的一个。NSE(印度国家证券交易所)和BSE(孟买证券交易所)的市值加起来排全球前列,而且增长速度快,很多策略在印度市场的表现跟美股完全不一样。
印度股票API接入.jpg

但接印度股票数据的时候,有几个跟美股、港股都不一样的地方——尤其是订阅格式和交易所指定。这篇记录一下接入印度股票行情的全过程。

印度市场跟其他市场有什么不一样

刚开始接的时候我以为跟美股一样,直接传个代码和region就行,结果发现根本不是那么回事。

第一,印度有两个主要交易所:NSE和BSE。 同一只股票在两个交易所都可能上市,代码一样但交易所不同。所以接印度股票的时候,必须指定交易所,不然返回的数据可能不是你想要的那个。

第二,WebSocket订阅格式不一样。 美股是两个参数:AAPL$US(代码市场)。印度是三个参数:`RELIANCENSEIN`(代码交易所$市场)。一开始我按美股的格式传,结果订阅一直失败。

第三,region代码是 IN。 不是 US、HK 那种,印度市场传 IN。

REST拉取印度股票报价

先从REST开始,确认数据格式对不对。

import requests

API_BASE = "//api.itick.org"
TOKEN = "your_token_here"
headers = {"accept": "application/json", "token": TOKEN}

# 拉印度股票的实时报价
def get_india_stock_quote(code, exchange="NSE"):
    resp = requests.get(
        f"{API_BASE}/stock/quote",
        headers=headers,
        params={
            "region": "IN",
            "code": code,
            "exchange": exchange
        }
    )
    return resp.json()["data"]


# 拉几只印度大盘股
stocks = [
    ("RELIANCE", "NSE"),   # 信实工业
    ("TCS", "NSE"),        # 塔塔咨询
    ("INFY", "NSE"),       # 印孚瑟斯
]

for code, exchange in stocks:
    q = get_india_stock_quote(code, exchange)
    sign = "+" if q["chp"] >= 0 else ""
    print(f"{code}({exchange}): {q['ld']} ({sign}{q['chp']}%)")

返回字段跟其他市场基本一致:ld最新价、chp涨跌幅、o/h/l开高低、v成交量。做行情看板这些字段够用了。

注意:印度股票的代码是字母形式(RELIANCE、TCS),不是数字。跟港股的数字代码(700)不一样。

WebSocket订阅印度股票(重点)

这是印度市场最容易踩坑的地方——订阅格式跟其他市场不一样。

其他市场(美股、港股、外汇)都是两个参数:代码$市场,比如 AAPL$US。

印度市场是三个参数:代码$交易所$市场,比如 RELIANCE$NSE$IN。

import json
import threading
import time
import websocket

WS_URL = "wss://api.itick.org/stock"
TOKEN = "your_token_here"
authenticated = False

def on_message(ws, message):
    global authenticated
    payload = json.loads(message)

    # 先等鉴权成功
    if payload.get("resAc") == "auth" and payload.get("code") == 1 and not authenticated:
        authenticated = True
        # 印度股票订阅格式:代码$交易所$市场
        ws.send(json.dumps({
            "ac": "subscribe",
            "params": "RELIANCE$NSE$IN,TCS$NSE$IN",
            "types": "quote"
        }))
        return

    if payload.get("resAc") == "pong":
        return

    data = payload.get("data") or {}
    if data.get("type") == "quote":
        sign = "+" if data["chp"] >= 0 else ""
        print(f"{data['s']}: {data['ld']} ({sign}{data['chp']}%)")

为什么印度要多一个交易所参数? 因为同一只股票在NSE和BSE都可能上市,价格可能不一样。指定交易所才能确保你拿到的是你想要的那个交易所的数据。

K线数据获取

K线接口跟其他市场一样,只是多了个exchange参数。

def get_india_kline(code, exchange="NSE", k_type=8, limit=100):
    """
    k_type: 1=1分钟 2=5分钟 5=1小时 8=日K 9=周K 10=月K
    """
    resp = requests.get(
        f"{API_BASE}/stock/kline",
        headers=headers,
        params={
            "region": "IN",
            "code": code,
            "exchange": exchange,
            "kType": k_type,
            "limit": limit
        }
    )
    return resp.json()["data"]


# 拉RELIANCE最近100根日K
daily = get_india_kline("RELIANCE", "NSE", k_type=8, limit=100)
closes = [bar["c"] for bar in daily]

# 算20日均线
ma20 = sum(closes[-20:]) / 20
print(f"RELIANCE最新收盘: {closes[-1]}, 20日均线: {ma20:.2f}")

K线返回标准OHLCV:t时间戳、o/h/l/c开高低收、v成交量。做技术分析直接用这些字段。

印度市场接入的特殊注意事项

订阅格式别搞错。 这是最容易踩的坑。印度是三个参数:RELIANCE$NSE$IN,不是两个参数。一开始我按美股格式传 RELIANCE$IN,结果订阅一直失败。

交易所要指定。 印度有NSE和BSE两个交易所,同一只股票在两个交易所都可能上市。REST接口要传 exchange=NSE 或 exchange=BSE,WebSocket订阅要在params里带上交易所代码。

交易时间跟国内不一样。 印度股市的交易时间是印度标准时间(IST),比北京时间晚2.5小时。做实时监控的时候要注意时区转换。

股票代码是字母。 印度股票代码是字母形式(RELIANCE、TCS、INFY),不是数字。跟港股的数字代码(700)不一样。

时间戳是毫秒。 所有返回的时间戳都是毫秒,直接当秒数处理会得到一个很远的未来时间,记得除以1000。

完整脚本:印度股票行情监控

把前面几块拼起来,最终的完整脚本:

import json, time, threading, requests, websocket

API_BASE = "//api.itick.org"
WS_URL = "wss://api.itick.org/stock"
TOKEN = "your_token_here"
headers = {"accept": "application/json", "token": TOKEN}

# 印度股票监控列表
watchlist = [
    ("RELIANCE", "NSE"),
    ("TCS", "NSE"),
    ("INFY", "NSE"),
]

# 启动时拉快照
print("=== 印度股票快照 ===")
for code, exchange in watchlist:
    r = requests.get(f"{API_BASE}/stock/quote",
                     headers=headers,
                     params={"region": "IN", "code": code, "exchange": exchange}).json()["data"]
    sign = "+" if r["chp"] >= 0 else ""
    print(f"  {code}({exchange}): {r['ld']} ({sign}{r['chp']}%)")

# WebSocket实时推送
authenticated = False

def on_message(ws, message):
    global authenticated
    payload = json.loads(message)
    if payload.get("resAc") == "auth" and payload.get("code") == 1 and not authenticated:
        authenticated = True
        # 印度股票订阅格式:代码$交易所$市场
        params = ",".join(f"{c}${e}$IN" for c, e in watchlist)
        ws.send(json.dumps({
            "ac": "subscribe",
            "params": params,
            "types": "quote"
        }))
        threading.Thread(target=heartbeat, args=(ws,), daemon=True).start()
        return
    if payload.get("resAc") == "pong":
        return
    data = payload.get("data") or {}
    if data.get("type") == "quote":
        sign = "+" if data["chp"] >= 0 else ""
        print(f"[实时] {data['s']}: {data['ld']} ({sign}{data['chp']}%)")

def heartbeat(ws):
    while True:
        time.sleep(30)
        ws.send(json.dumps({"ac": "ping", "params": str(int(time.time() * 1000))}))

ws = websocket.WebSocketApp(WS_URL, header=[f"token: {TOKEN}"], on_message=on_message)
ws.run_forever()

这个脚本跑起来之后,开盘前先看到一组印度股票的快照,盘中实时更新价格和涨跌幅。

小结

接印度股票数据的技术框架跟美股、港股差不多——REST做快照和历史数据,WebSocket做实时推送。但有几个特殊点:订阅格式是三个参数(代码交易所市场)、必须指定NSE或BSE交易所、交易时间跟国内有时差。这些细节不踩一遍坑很容易忽略。

参考文档:https://docs.itick.org/websocket/stocks
GitHub:https://github.com/itick-org/

评论