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

AI摘要
该内容为技术分享,介绍接入印度股票行情数据(NSE/BSE)的REST与WebSocket接口方法,重点说明印度市场订阅格式为“代码$交易所$市场”三参数、需指定交易所、时区差异及毫秒时间戳等注意事项,并附完整Python监控脚本示例。

最近不少朋友在做新兴市场的量化策略,印度股市是绕不开的一个。NSE(印度国家证券交易所)和BSE(孟买证券交易所)的市值加起来排全球前列,而且增长速度快,很多策略在印度市场的表现跟美股完全不一样。
印度股票API接入
但接印度股票数据的时候,有几个跟美股、港股都不一样的地方——尤其是订阅格式和交易所指定。这篇记录一下接入印度股票行情的全过程。

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

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

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

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

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

REST拉取印度股票报价

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


import requests

API_BASE = "https://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 = "https://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交易所、交易时间跟国内有时差。这些细节不踩一遍坑很容易忽略。

参考文档:docs.itick.org/websocket/stocks

GitHub:https://github.com/itick-org/

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
92
粉丝
4
喜欢
8
收藏
8
排名:1733
访问:1619
私信
所有博文
社区赞助商